Skip to content

Commit

Permalink
Add support for GPG-signed commits (mystor#46)
Browse files Browse the repository at this point in the history
GPG-sign commits if option -S/--gpg-sign is given, or if configurations
revise.gpgSign or commit.gpgSign are set to true.

In contrast to git-commit's options, the keyid used for signing cannot
(yet) be specified explicitly but by user.signingKey to prevent using
the committer signature as fallback.

A call of `git-revise COMMIT --gpg-sign` w/o any changes in the index
does not cause (re)creation of GPG commit signatures.

Signed-off-by: Nicolas Schier <nicolas@fjasle.eu>
  • Loading branch information
Nicolas Schier committed Sep 4, 2020
1 parent 7176273 commit 2c20ffc
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 2 deletions.
14 changes: 14 additions & 0 deletions git-revise.1
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ Reset target commit\(aqs author to the current user.
.B \-\-ref <gitref>
Working branch to update; defaults to \fBHEAD\fP\&.
.UNINDENT
.INDENT 0.0
.TP
\fB\-\-gpg-sign\fR, \fB\-S\fR, \fB\-\-no\-gpg\-sign
GPG-sign commits. To override the \fIcommit.gpgSign\fR git configuration, use
\fI\-\-no\-gpg\-sign\fR.
.UNINDENT
.SS Main modes of operation
.INDENT 0.0
.TP
Expand Down Expand Up @@ -147,6 +153,14 @@ If set to true, imply \fI\%\-\-autosquash\fP whenever \fI\%\-\-interactive\fP
is specified. Overridden by \fI\%\-\-no\-autosquash\fP\&. Defaults to false. If
not set, the value of \fBrebase.autoSquash\fP is used instead.
.UNINDENT
.INDENT 0.0
.TP
.B revise.gpgSign
If set to true, GPG-sign new commits; defaults to false. This setting
overrides the original git configuration \fBcommit.gpgSign\fR and may be
overridden by the command line options \fI\-\-gpg\-sign\fR and
\fI\-\-no\-gpg\-sign\fR.
.UNINDENT
.SH CONFLICT RESOLUTION
.sp
When a conflict is encountered, \fBgit revise\fP will attempt to resolve
Expand Down
51 changes: 49 additions & 2 deletions gitrevise/odb.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
Tuple,
cast,
)
import subprocess
from sys import stderr, exit
from types import TracebackType
from pathlib import Path
from enum import Enum
Expand Down Expand Up @@ -134,6 +136,15 @@ class Repository:
index: "Index"
"""current index state"""

sign_commits: False
"""sign commits with gpg"""

key_id: ""
"""key ID to be used for commit signing"""

gpg: "gpg"
"""path to GnuPG binary"""

_objects: Dict[int, Dict[Oid, "GitObj"]]
_catfile: Popen
_tempdir: Optional[TemporaryDirectory]
Expand All @@ -144,6 +155,9 @@ class Repository:
"default_author",
"default_committer",
"index",
"sign_commits",
"key_id",
"gpg",
"_objects",
"_catfile",
"_tempdir",
Expand All @@ -162,6 +176,22 @@ def __init__(self, cwd: Optional[Path] = None):

self.index = Index(self)

self.sign_commits = self.bool_config(
"revise.gpgSign", default=self.bool_config("commit.gpgSign", default=False)
)

self.key_id = self.default_committer.name
if self.default_committer.email:
if self.key_id:
self.key_id += b" "
self.key_id += b"<" + self.default_committer.email + b">"
else:
self.key_id = self.default_committer.email

self.key_id = self.bool_config("user.signingKey", default=self.key_id)

self.gpg = self.config("gpg.program", default="gpg")

self._catfile = Popen(
["git", "cat-file", "--batch"],
bufsize=-1,
Expand Down Expand Up @@ -270,8 +300,25 @@ def new_commit(
body += b"parent " + parent.oid.hex().encode() + b"\n"
body += b"author " + author + b"\n"
body += b"committer " + committer + b"\n"
body += b"\n"
body += message

body_tail = b"\n" + message

if self.sign_commits:
p = subprocess.run(
[self.gpg, "-bsau", self.key_id],
capture_output=True,
input=body + body_tail,
)
if not p.stdout:
print(p.stderr.decode(), file=stderr, end="")
print("gpg failed to sign commit", file=stderr)
exit(1)

body += b"gpgsig " + p.stdout.replace(b"\n", b"\n ")
body = body[:-1]

body += body_tail

return Commit(self, body)

def new_tree(self, entries: Mapping[bytes, "Entry"]) -> "Tree":
Expand Down
11 changes: 11 additions & 0 deletions gitrevise/tui.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ def build_parser() -> ArgumentParser:
action="store_true",
help="interactively cut a commit into two smaller commits",
)

mode_group = parser.add_mutually_exclusive_group()
mode_group.add_argument(
"--gpg-sign", "-S", action="store_true", default=None, help="GPG sign commits",
)
index_group.add_argument(
"--no-gpg-sign", action="store_false", help="do not GPG sign commits",
)
return parser


Expand Down Expand Up @@ -192,6 +200,9 @@ def inner_main(args: Namespace, repo: Repository):
if args.patch:
repo.git("add", "-p")

if args.gpg_sign != None:
repo.sign_commits = args.gpg_sign

# Create a commit with changes from the index
staged = None
if not args.no_index:
Expand Down

0 comments on commit 2c20ffc

Please sign in to comment.