Skip to content

Commit

Permalink
GPG対応
Browse files Browse the repository at this point in the history
  • Loading branch information
soramimi committed Jan 18, 2024
1 parent 73a14a8 commit 64e4b98
Show file tree
Hide file tree
Showing 10 changed files with 273 additions and 55 deletions.
2 changes: 2 additions & 0 deletions Guitar.pri
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ macx {
}

SOURCES += \
$$PWD/src/CommitDetailGetter.cpp \
src/AboutDialog.cpp \
src/AbstractProcess.cpp \
src/AbstractSettingForm.cpp \
Expand Down Expand Up @@ -251,6 +252,7 @@ SOURCES += \
src/coloredit/RingSlider.cpp

HEADERS += \
$$PWD/src/CommitDetailGetter.h \
filetype/filetype.h \
src/AboutDialog.h \
src/AbstractProcess.h \
Expand Down
117 changes: 117 additions & 0 deletions src/CommitDetailGetter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#include "CommitDetailGetter.h"

CommitDetailGetter::~CommitDetailGetter()
{
stop();
}

void CommitDetailGetter::start(GitPtr git)
{
interrupted_ = false;
git_ = git;
thread_ = std::make_shared<std::thread>([&](){
while (1) {
Item item;
{
std::unique_lock lock(mutex_);
if (interrupted_) return;
condition_.wait(lock);
if (interrupted_) return;
for (size_t i = 0; i < requests_.size(); i++) {
if (!requests_[i].done && !requests_[i].busy) {
requests_[i].busy = true;
item = requests_[i];
break;
}
}
}
if (item.id) {
auto c = git_->log_signature(item.id);
if (c) {
bool ok = false;
Git::CommitItem const &commit = *c;
item.value = commit.sign.verify;
item.done = true;
item.busy = false;
{
std::lock_guard lock(mutex_);
for (size_t i = 0; i < requests_.size(); i++) {
if (item.id == requests_[i].id) {
requests_.erase(requests_.begin() + i);
requests_.push_back(item);
requests_[i] = item;
ok = true;
break;
}
}
}
if (ok) {
emit ready();
}
}
}
}
});
}

void CommitDetailGetter::stop()
{
{
std::lock_guard lock(mutex_);
interrupted_ = true;
condition_.notify_all();
}
if (thread_) {
if (thread_->joinable()) {
thread_->join();
}
thread_.reset();
}
interrupted_ = false;
}

CommitDetailGetter::Item CommitDetailGetter::request(Git::CommitID id)
{
if (id.isValid()) {
std::lock_guard lock(mutex_);
for (size_t i = 0; i < requests_.size(); i++) {
if (id == requests_[i].id) {
if (requests_[i].done) {
Item item = requests_[i];
requests_.erase(requests_.begin() + i);
requests_.push_back(item);
return item;
}
}
}

Item item;
item.id = id;
requests_.push_back(item);

size_t n = requests_.size();
if (n > 100) {
n -= 100;
requests_.erase(requests_.begin(), requests_.begin() + n);
}

condition_.notify_all();
}
return {};
}

void CommitDetailGetter::apply(Git::CommitItemList *logs)
{
std::lock_guard lock(mutex_);
for (size_t i = 0; i < requests_.size(); i++) {
if (requests_[i].done) {
Git::CommitID const &id = requests_[i].id;
for (size_t j = 0; j < logs->size(); j++) {
if (id == (*logs)[j].commit_id) {
(*logs)[j].sign.verify = requests_[i].value;
break;
}
}
}
}
}
44 changes: 44 additions & 0 deletions src/CommitDetailGetter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifndef COMMITDETAILGETTER_H
#define COMMITDETAILGETTER_H

#include "Git.h"
#include <QObject>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <thread>

class CommitDetailGetter : public QObject {
Q_OBJECT
private:
std::mutex mutex_;
std::condition_variable condition_;
std::shared_ptr<std::thread> thread_;
bool interrupted_ = false;

struct Item {
bool done = false;
bool busy = false;
Git::CommitID id;
int value = 0;
operator bool () const
{
return done;
}
};
std::vector<Item> requests_;

GitPtr git_;

public:
CommitDetailGetter() = default;
virtual ~CommitDetailGetter();
void start(GitPtr git);
void stop();
CommitDetailGetter::Item request(Git::CommitID id);
void apply(Git::CommitItemList *logs);
signals:
void ready();
};

#endif // COMMITDETAILGETTER_H
11 changes: 6 additions & 5 deletions src/Git.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,9 @@ bool Git::chdirexec(std::function<bool()> const &fn)
return ok;
}

bool Git::git(QString const &arg, bool chdir, bool errout, AbstractPtyProcess *pty, QString const &prefix)
bool Git::git_(QString const &arg, bool chdir, bool log, bool errout, AbstractPtyProcess *pty, QString const &prefix)
{
qDebug() << "git: " << arg;
// qDebug() << "git: " << arg;
QFileInfo info(gitCommand());
if (!info.isExecutable()) {
qDebug() << "Invalid git command: " << gitCommand();
Expand Down Expand Up @@ -281,7 +281,7 @@ bool Git::git(QString const &arg, bool chdir, bool errout, AbstractPtyProcess *p
cmd += QString("\"%1\" --no-pager ").arg(gitCommand());
cmd += arg;

if (m->info.fn_log_writer_callback) {
if (log && m->info.fn_log_writer_callback) {
QByteArray ba;
ba.append("> git ");
ba.append(arg.toUtf8());
Expand Down Expand Up @@ -755,6 +755,7 @@ std::optional<Git::CommitItem> Git::parseCommitItem(QString const &line)
item.commit_id = val;
} else if (key == "gpg") { // %G? 署名検証結果
item.sign.verify = *val.utf16();
item.sign.sg = Git::evaluateSignature(item.sign.verify);
} else if (key == "key") { // %GF 署名フィンガープリント
sign_fp = val.toStdString();
} else if (key == "trust") {
Expand Down Expand Up @@ -804,7 +805,7 @@ Git::CommitItemList Git::log_all(CommitID const &id, int maxcount)

QString cmd = "log --pretty=format:\"id:%H#parent:%P#author:%an#mail:%ae#date:%ci##%s\" --all -%1 %2";
cmd = cmd.arg(maxcount).arg(id.toQString());
git(cmd);
git_(cmd, true, false, false, nullptr, {});
if (getProcessExitCode() == 0) {
QString text = resultQString().trimmed();
QStringList lines = misc::splitLines(text);
Expand All @@ -829,7 +830,7 @@ std::optional<Git::CommitItem> Git::log_signature(CommitID const &id)
{
QString cmd = "log -1 --show-signature --pretty=format:\"id:%H#gpg:%G?#key:%GF#sub:%GP#trust:%GT##%s\" %1";
cmd = cmd.arg(id.toQString());
git(cmd);
git_(cmd, true, false, false, nullptr, {});
if (getProcessExitCode() == 0) {
QString gpgtext;
QString text = resultQString().trimmed();
Expand Down
33 changes: 21 additions & 12 deletions src/Git.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ class Git : QObject {
if (!valid && !other.valid) return 0;
return memcmp(id, other.id, sizeof(id));
}
operator bool () const
{
return isValid();
}
};
class Context {
public:
Expand Down Expand Up @@ -93,6 +97,15 @@ class Git : QObject {
}
};

enum class SignatureGrade {
NoSignature,
Unknown,
Good,
Dubious,
Missing,
Bad,
};

struct CommitItem {
CommitID commit_id;
QList<CommitID> parent_ids;
Expand All @@ -107,6 +120,7 @@ class Git : QObject {
char verify = 0; // git log format:%G?
std::vector<uint8_t> key_fingerprint;
QString trust;
SignatureGrade sg;
} sign;
bool has_child = false;
int marker_depth = -1;
Expand Down Expand Up @@ -160,18 +174,9 @@ class Git : QObject {
void makeForSingleFile(Git::Diff *diff, QString const &id_a, QString const &id_b, QString const &path, QString const &mode);
};

enum class SignatureGrade {
NoSignature,
Unknown,
Good,
Dubious,
Missing,
Bad,
};

static SignatureGrade evaluateSignature(char s)
static SignatureGrade evaluateSignature(char c)
{
switch (s) {
switch (c) {
case 'G':
return SignatureGrade::Good;
case 'U':
Expand Down Expand Up @@ -366,7 +371,11 @@ class Git : QObject {
std::string resultStdString() const;
QString resultQString() const;
bool chdirexec(std::function<bool ()> const &fn);
bool git(QString const &arg, bool chdir, bool errout = false, AbstractPtyProcess *pty = nullptr, const QString &prefix = {});
bool git_(QString const &arg, bool chdir, bool log = true, bool errout = false, AbstractPtyProcess *pty = nullptr, const QString &prefix = {});
bool git(QString const &arg, bool chdir, bool errout = false, AbstractPtyProcess *pty = nullptr, const QString &prefix = {})
{
return git_(arg, chdir, true, errout, pty, prefix);
}
bool git(QString const &arg)
{
return git(arg, true);
Expand Down
10 changes: 5 additions & 5 deletions src/LogTableWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class LogTableWidgetDelegate : public MyTableWidgetDelegate {

Git::CommitItem const *commit = frame()->commitItem(index.row());
if (commit) {
QIcon icon = frame()->verifiedIcon(commit->sign.verify);
QIcon icon = frame()->signatureVerificationIcon(commit->sign.verify, index.row());
if (!icon.isNull()) {
QRect r = opt.rect.adjusted(6, 3, 0, -3);
int h = r.height();
Expand All @@ -75,7 +75,6 @@ class LogTableWidgetDelegate : public MyTableWidgetDelegate {
int row = index.row();
auto icon = frame()->committerIcon(row, {w, h});
if (!icon.isNull()) {

painter->save();
painter->setOpacity(0.5); // 半透明で描画
painter->drawImage(QRect(x, y, w, h), icon);
Expand Down Expand Up @@ -127,9 +126,9 @@ class LogTableWidgetDelegate : public MyTableWidgetDelegate {
QRect r(x0, y0, x1 - x0, y1 - y0);

// ラベル枠の描画
auto DrawLabelFrame = [&](int dx, int dy, QColor const &color){
painter->setBrush(color);
painter->drawRoundedRect(r.adjusted((int)lround(dx + 3), (int)lround(dy + 3), (int)lround(dx - 3), (int)lround(dy - 3)), 3, 3);
auto DrawLabelFrame = [&](int dx, int dy, QColor const &color){
painter->setBrush(color);
painter->drawRoundedRect(r.adjusted((int)lround(dx + 3), (int)lround(dy + 3), (int)lround(dx - 3), (int)lround(dy - 3)), 3, 3);
};

QColor color = BranchLabel::color(label.kind); // ラベル表面の色
Expand Down Expand Up @@ -188,6 +187,7 @@ class LogTableWidgetDelegate : public MyTableWidgetDelegate {
drawAvatar(painter, option, index);
}


// ラベルの描画
if (index.column() == Message) {
QString current_branch = frame()->currentBranchName();
Expand Down
Loading

0 comments on commit 64e4b98

Please sign in to comment.