Merge branch 'jc/commit-tree-ignore-commit-gpgsign'
authorJunio C Hamano <gitster@pobox.com>
Fri, 13 May 2016 20:18:27 +0000 (13:18 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 13 May 2016 20:18:27 +0000 (13:18 -0700)
"git commit-tree" plumbing command required the user to always sign
its result when the user sets the commit.gpgsign configuration
variable, which was an ancient mistake. Rework "git rebase" that
relied on this mistake so that it reads commit.gpgsign and pass (or
not pass) the -S option to "git commit-tree" to keep the end-user
expectation the same, while teaching "git commit-tree" to ignore
the configuration variable. This will stop requiring the users to
sign commit objects used internally as an implementation detail of
"git stash".

* jc/commit-tree-ignore-commit-gpgsign:
commit-tree: do not pay attention to commit.gpgsign

1  2 
Documentation/git-commit-tree.txt
builtin/commit-tree.c
git-rebase.sh
t/t7510-signed-commit.sh
index 48c33d7ed7323c7fc4776ffeb98aad9b41b23744,eb273c3d8a0972fb32cdb9c61949e2b3f0e0953c..cb69faab686285050d121b1bd64f509a0b561f3e
@@@ -9,7 -9,7 +9,7 @@@ git-commit-tree - Create a new commit o
  SYNOPSIS
  --------
  [verse]
 -'git commit-tree' <tree> [(-p <parent>)...] < changelog
 +'git commit-tree' <tree> [(-p <parent>)...]
  'git commit-tree' [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...]
                  [(-F <file>)...] <tree>
  
@@@ -56,13 -56,11 +56,13 @@@ OPTION
  
  -S[<keyid>]::
  --gpg-sign[=<keyid>]::
 -      GPG-sign commit.
 +      GPG-sign commits. The `keyid` argument is optional and
 +      defaults to the committer identity; if specified, it must be
 +      stuck to the option without a space.
  
  --no-gpg-sign::
-       Countermand `commit.gpgSign` configuration variable that is
-       set to force each and every commit to be signed.
+       Do not GPG-sign commit, to countermand a `--gpg-sign` option
+       given earlier on the command line.
  
  
  Commit Information
diff --combined builtin/commit-tree.c
index 3feeffeab1ccd51a5e30098c31b4daa62e7ef684,15de7e8f2203f884d88ec8497f123ca1c713b844..8a674bc9e759116a06f7464222ec591472b65610
  #include "utf8.h"
  #include "gpg-interface.h"
  
 -static const char commit_tree_usage[] = "git commit-tree [(-p <sha1>)...] [-S[<keyid>]] [-m <message>] [-F <file>] <sha1> <changelog";
 +static const char commit_tree_usage[] = "git commit-tree [(-p <sha1>)...] [-S[<keyid>]] [-m <message>] [-F <file>] <sha1>";
  
  static const char *sign_commit;
  
  static void new_parent(struct commit *parent, struct commit_list **parents_p)
  {
 -      unsigned char *sha1 = parent->object.sha1;
 +      struct object_id *oid = &parent->object.oid;
        struct commit_list *parents;
        for (parents = *parents_p; parents; parents = parents->next) {
                if (parents->item == parent) {
 -                      error("duplicate parent %s ignored", sha1_to_hex(sha1));
 +                      error("duplicate parent %s ignored", oid_to_hex(oid));
                        return;
                }
                parents_p = &parents->next;
@@@ -33,10 -33,6 +33,6 @@@ static int commit_tree_config(const cha
        int status = git_gpg_config(var, value, NULL);
        if (status)
                return status;
-       if (!strcmp(var, "commit.gpgsign")) {
-               sign_commit = git_config_bool(var, value) ? "" : NULL;
-               return 0;
-       }
        return git_default_config(var, value, cb);
  }
  
diff --combined git-rebase.sh
index 0bf41ee72b79953dbb8fdab44e275c027174f5b7,4d466622a6c39141572d80d8e307687a3e659371..44ede367ae0e24ad80ba91608d26ad3bd4bbd8da
@@@ -14,7 -14,7 +14,7 @@@ git-rebase --continue | --abort | --ski
   Available options are
  v,verbose!         display a diffstat of what changed upstream
  q,quiet!           be quiet. implies --no-stat
 -autostash!         automatically stash/stash pop before and after
 +autostash          automatically stash/stash pop before and after
  fork-point         use 'merge-base --fork-point' to refine upstream
  onto=!             rebase onto given branch instead of upstream
  p,preserve-merges! try to recreate merges instead of ignoring them
@@@ -87,7 -87,10 +87,10 @@@ preserve_merges
  autosquash=
  keep_empty=
  test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t
- gpg_sign_opt=
+ case "$(git config --bool commit.gpgsign)" in
+ true) gpg_sign_opt=-S ;;
+ *)    gpg_sign_opt= ;;
+ esac
  
  read_basic_state () {
        test -f "$state_dir/head-name" &&
@@@ -176,7 -179,7 +179,7 @@@ You can run "git stash pop" or "git sta
  
  finish_rebase () {
        apply_autostash &&
 -      git gc --auto &&
 +      { git gc --auto || true; } &&
        rm -rf "$state_dir"
  }
  
@@@ -202,9 -205,9 +205,9 @@@ run_specific_rebase () 
  
  run_pre_rebase_hook () {
        if test -z "$ok_to_skip_pre_rebase" &&
 -         test -x "$GIT_DIR/hooks/pre-rebase"
 +         test -x "$(git rev-parse --git-path hooks/pre-rebase)"
        then
 -              "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} ||
 +              "$(git rev-parse --git-path hooks/pre-rebase)" ${1+"$@"} ||
                die "$(gettext "The pre-rebase hook refused to rebase.")"
        fi
  }
@@@ -248,7 -251,6 +251,7 @@@ d
                ;;
        --exec=*)
                cmd="${cmd}exec ${1#--exec=}${LF}"
 +              test -z "$interactive_rebase" && interactive_rebase=implied
                ;;
        --interactive)
                interactive_rebase=explicit
        --autostash)
                autostash=true
                ;;
 +      --no-autostash)
 +              autostash=false
 +              ;;
        --verbose)
                verbose=t
                diffstat=t
  done
  test $# -gt 2 && usage
  
 -if test -n "$cmd" &&
 -   test "$interactive_rebase" != explicit
 -then
 -      die "$(gettext "The --exec option must be used with the --interactive option")"
 -fi
 -
  if test -n "$action"
  then
        test -z "$in_progress" && die "$(gettext "No rebase in progress?")"
diff --combined t/t7510-signed-commit.sh
index 18e5cf06630273a6131d13d9a82f085d33f15153,7b365ee115432322d2da9eeea31788c6f8d3c9b6..4177a8609acac433cbc3f87d9ddec9c02672963c
@@@ -45,12 -45,18 +45,18 @@@ test_expect_success GPG 'create signed 
        git tag seventh-signed &&
  
        echo 8 >file && test_tick && git commit -a -m eighth -SB7227189 &&
-       git tag eighth-signed-alt
+       git tag eighth-signed-alt &&
+       # commit.gpgsign is still on but this must not be signed
+       git tag ninth-unsigned $(echo 9 | git commit-tree HEAD^{tree}) &&
+       # explicit -S of course must sign.
+       git tag tenth-signed $(echo 9 | git commit-tree -S HEAD^{tree})
  '
  
  test_expect_success GPG 'verify and show signatures' '
        (
-               for commit in initial second merge fourth-signed fifth-signed sixth-signed seventh-signed
+               for commit in initial second merge fourth-signed \
+                       fifth-signed sixth-signed seventh-signed tenth-signed
                do
                        git verify-commit $commit &&
                        git show --pretty=short --show-signature $commit >actual &&
@@@ -60,7 -66,8 +66,8 @@@
                done
        ) &&
        (
-               for commit in merge^2 fourth-unsigned sixth-unsigned seventh-unsigned
+               for commit in merge^2 fourth-unsigned sixth-unsigned \
+                       seventh-unsigned ninth-unsigned
                do
                        test_must_fail git verify-commit $commit &&
                        git show --pretty=short --show-signature $commit >actual &&
        )
  '
  
 +test_expect_success GPG 'verify-commit exits success on untrusted signature' '
 +      git verify-commit eighth-signed-alt 2>actual &&
 +      grep "Good signature from" actual &&
 +      ! grep "BAD signature from" actual &&
 +      grep "not certified" actual
 +'
 +
 +test_expect_success GPG 'verify signatures with --raw' '
 +      (
 +              for commit in initial second merge fourth-signed fifth-signed sixth-signed seventh-signed
 +              do
 +                      git verify-commit --raw $commit 2>actual &&
 +                      grep "GOODSIG" actual &&
 +                      ! grep "BADSIG" actual &&
 +                      echo $commit OK || exit 1
 +              done
 +      ) &&
 +      (
 +              for commit in merge^2 fourth-unsigned sixth-unsigned seventh-unsigned
 +              do
 +                      test_must_fail git verify-commit --raw $commit 2>actual &&
 +                      ! grep "GOODSIG" actual &&
 +                      ! grep "BADSIG" actual &&
 +                      echo $commit OK || exit 1
 +              done
 +      ) &&
 +      (
 +              for commit in eighth-signed-alt
 +              do
 +                      git verify-commit --raw $commit 2>actual &&
 +                      grep "GOODSIG" actual &&
 +                      ! grep "BADSIG" actual &&
 +                      grep "TRUST_UNDEFINED" actual &&
 +                      echo $commit OK || exit 1
 +              done
 +      )
 +'
 +
  test_expect_success GPG 'show signed commit with signature' '
        git show -s initial >commit &&
        git show -s --show-signature initial >show &&