This option works analogous to --verify-signatures for git-merge by
checking that the commits, that are rebased onto, have good GPG
signatures.

Additionally, git-pull now forwards --verify-signatures to rebase as
well.

Signed-off-by: Alexander 'z33ky' Hirsch <1ze...@gmail.com>
---

I'm unsure if the opt_verify_signatures check in builtin/pull.c should
be moved up to the "/* Shared options */" now.

The output strings from the GPG check are identical to the ones in
builtin/merge.c; I am unsure about the implications for l10n.

The test is mostly copied from t7612-merge-verify-signatures.sh.

 Documentation/git-rebase.txt        |  6 ++++
 builtin/pull.c                      |  2 ++
 git-rebase.sh                       | 44 +++++++++++++++++++++++++
 t/t3427-rebase-verify-signatures.sh | 65 +++++++++++++++++++++++++++++++++++++
 4 files changed, 117 insertions(+)
 create mode 100755 t/t3427-rebase-verify-signatures.sh

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 6cca8bb..959b12b 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -292,6 +292,12 @@ which makes little sense.
        specified, `-s recursive`.  Note the reversal of 'ours' and
        'theirs' as noted above for the `-m` option.
 
+--verify-signatures::
+--no-verify-signatures::
+       Verify that the commits in the branch the rebase is onto, but not
+       present in the working branch, have good GPG signatures and abort the
+       operation in case they do not.
+
 -S[<keyid>]::
 --gpg-sign[=<keyid>]::
        GPG-sign commits. The `keyid` argument is optional and
diff --git a/builtin/pull.c b/builtin/pull.c
index bf3fd3f..37ec0f8 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -774,6 +774,8 @@ static int run_rebase(const unsigned char *curr_head,
                argv_array_push(&args, "--preserve-merges");
        if (opt_diffstat)
                argv_array_push(&args, opt_diffstat);
+       if (opt_verify_signatures)
+               argv_array_push(&args, opt_verify_signatures);
        argv_array_pushv(&args, opt_strategies.argv);
        argv_array_pushv(&args, opt_strategy_opts.argv);
        if (opt_gpg_sign)
diff --git a/git-rebase.sh b/git-rebase.sh
index af7ba5f..dcfbc3a 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -38,6 +38,7 @@ whitespace=!       passed to 'git apply'
 ignore-whitespace! passed to 'git apply'
 C=!                passed to 'git apply'
 S,gpg-sign?        GPG-sign commits
+verify-signatures  verify that the commits of onto have valid GPG signatures
  Actions:
 continue!          continue
 abort!             abort and check out the original branch
@@ -88,6 +89,7 @@ autosquash=
 keep_empty=
 test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t
 gpg_sign_opt=
+verify_signatures=
 
 read_basic_state () {
        test -f "$state_dir/head-name" &&
@@ -339,6 +341,12 @@ do
        --gpg-sign=*)
                gpg_sign_opt="-S${1#--gpg-sign=}"
                ;;
+       --verify-signatures)
+               verify_signatures=t
+               ;;
+       --no-verify-signatures)
+               verify_signatures=
+               ;;
        --)
                shift
                break
@@ -594,6 +602,42 @@ then
        fi
 fi
 
+if test "$verify_signatures"
+then
+       if test -n "$rebase_root"
+       then
+               foreign_revisions="$orig_head..$onto"
+       else
+               foreign_revisions="$orig_head..${restrict_revision-$upstream}"
+       fi
+
+       for cmt in $(git rev-list --reverse "$foreign_revisions")
+       do
+               if ! git log -1 --pretty=format:'%G?%n%GS' "$cmt" |
+               (
+                       read cmt_sig
+                       read cmt_signer
+                       case "$cmt_sig" in
+                       'G')
+                               ;;
+                       'U')
+                               die "$(gettext "Commit $cmt has an untrusted 
GPG signature, allegedly by $cmt_signer.")"
+                               ;;
+                       'B')
+                               die "$(gettext "Commit $cmt has a bad GPG 
signature allegedly by $cmt_signer.")"
+                               ;;
+                       *) #'N'
+                               die "$(gettext "Commit $cmt does not have a GPG 
signature.")"
+                               ;;
+                       esac
+                       test "$verbose" && test 'G' = "$cmt_sig" && echo 
"Commit $cmt has a good GPG signature by $cmt_signer."
+               )
+               then
+                       exit 1
+               fi
+       done
+fi
+
 # If a hook exists, give it a chance to interrupt
 run_pre_rebase_hook "$upstream_arg" "$@"
 
diff --git a/t/t3427-rebase-verify-signatures.sh 
b/t/t3427-rebase-verify-signatures.sh
new file mode 100755
index 0000000..1bd0a4d
--- /dev/null
+++ b/t/t3427-rebase-verify-signatures.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+test_description='rebase signature verification tests'
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-gpg.sh"
+
+test_expect_success GPG 'create signed commits' '
+       echo 1 >file && git add file &&
+       test_tick && git commit -m initial &&
+       git tag initial &&
+
+       git checkout -b side-signed &&
+       echo 3 >elif && git add elif &&
+       test_tick && git commit -S -m "signed on side" &&
+       git checkout initial &&
+
+       git checkout -b side-unsigned &&
+       echo 3 >foo && git add foo &&
+       test_tick && git commit -m "unsigned on side" &&
+       git checkout initial &&
+
+       git checkout -b side-bad &&
+       echo 3 >bar && git add bar &&
+       test_tick && git commit -S -m "bad on side" &&
+       git cat-file commit side-bad >raw &&
+       sed -e "s/bad/forged bad/" raw >forged &&
+       git hash-object -w -t commit forged >forged.commit &&
+       git checkout initial &&
+
+       git checkout -b side-untrusted &&
+       echo 3 >baz && git add baz &&
+       test_tick && git commit -SB7227189 -m "untrusted on side" &&
+
+       git checkout master
+'
+
+test_expect_success GPG 'rebase unsigned commit with verification' '
+       test_must_fail git rebase --verify-signatures side-unsigned 
2>rebaseerror &&
+       test_i18ngrep "does not have a GPG signature" rebaseerror
+'
+
+test_expect_success GPG 'rebase commit with bad signature with verification' '
+       test_must_fail git rebase --verify-signatures $(cat forged.commit) 
2>rebaseerror &&
+       test_i18ngrep "has a bad GPG signature" rebaseerror
+'
+
+test_expect_success GPG 'rebase commit with untrusted signature with 
verification' '
+       test_must_fail git rebase --verify-signatures side-untrusted 
2>rebaseerror &&
+       test_i18ngrep "has an untrusted GPG signature" rebaseerror
+'
+
+test_expect_success GPG 'rebase signed commit with verification' '
+       git rebase --verbose --verify-signatures side-signed >rebaseoutput &&
+       test_i18ngrep "has a good GPG signature" rebaseoutput
+'
+
+test_expect_success GPG 'rebase commit with bad signature without verification 
(implicit)' '
+       git rebase $(cat forged.commit)
+'
+
+test_expect_success GPG 'rebase commit with bad signature without verification 
(explicit)' '
+       git rebase --no-verify-signatures $(cat forged.commit)
+'
+
+test_done
-- 
2.6.3

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to