Git fork

Merge branch 'pw/subtree-gpg-sign'

"git subtree" (in contrib/) learns to grok GPG signing its commits.

* pw/subtree-gpg-sign:
contrib/subtree: add -S/--gpg-sign
contrib/subtree: parse using --stuck-long

+158 -40
+13 -6
contrib/subtree/git-subtree.adoc
··· 9 9 SYNOPSIS 10 10 -------- 11 11 [verse] 12 - 'git subtree' [<options>] -P <prefix> add <local-commit> 13 - 'git subtree' [<options>] -P <prefix> add <repository> <remote-ref> 14 - 'git subtree' [<options>] -P <prefix> merge <local-commit> [<repository>] 15 - 'git subtree' [<options>] -P <prefix> split [<local-commit>] 12 + 'git subtree' [<options>] -P <prefix> [-S[<keyid>]] add <local-commit> 13 + 'git subtree' [<options>] -P <prefix> [-S[<keyid>]] add <repository> <remote-ref> 14 + 'git subtree' [<options>] -P <prefix> [-S[<keyid>]] merge <local-commit> [<repository>] 15 + 'git subtree' [<options>] -P <prefix> [-S[<keyid>]] split [<local-commit>] 16 16 17 17 [verse] 18 - 'git subtree' [<options>] -P <prefix> pull <repository> <remote-ref> 19 - 'git subtree' [<options>] -P <prefix> push <repository> <refspec> 18 + 'git subtree' [<options>] -P <prefix> [-S[<keyid>]] pull <repository> <remote-ref> 19 + 'git subtree' [<options>] -P <prefix> [-S[<keyid>]] push <repository> <refspec> 20 20 21 21 DESCRIPTION 22 22 ----------- ··· 148 148 Specify the path in the repository to the subtree you 149 149 want to manipulate. This option is mandatory 150 150 for all commands. 151 + 152 + -S[<keyid>]:: 153 + --gpg-sign[=<keyid>]:: 154 + --no-gpg-sign:: 155 + GPG-sign commits. The `keyid` argument is optional and 156 + defaults to the committer identity; `--no-gpg-sign` is useful to 157 + countermand a `--gpg-sign` option given earlier on the command line. 151 158 152 159 OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull', 'split --rejoin', AND 'push --rejoin') 153 160 -----------------------------------------------------------------------------------
+32 -34
contrib/subtree/git-subtree.sh
··· 26 26 fi 27 27 28 28 OPTS_SPEC="\ 29 - git subtree add --prefix=<prefix> <commit> 30 - git subtree add --prefix=<prefix> <repository> <ref> 31 - git subtree merge --prefix=<prefix> <commit> 32 - git subtree split --prefix=<prefix> [<commit>] 33 - git subtree pull --prefix=<prefix> <repository> <ref> 34 - git subtree push --prefix=<prefix> <repository> <refspec> 29 + git subtree add --prefix=<prefix> [-S[=<key-id>]] <commit> 30 + git subtree add --prefix=<prefix> [-S[=<key-id>]] <repository> <ref> 31 + git subtree merge --prefix=<prefix> [-S[=<key-id>]] <commit> 32 + git subtree split --prefix=<prefix> [-S[=<key-id>]] [<commit>] 33 + git subtree pull --prefix=<prefix> [-S[=<key-id>]] <repository> <ref> 34 + git subtree push --prefix=<prefix> [-S[=<key-id>]] <repository> <refspec> 35 35 -- 36 36 h,help! show the help 37 37 q,quiet! quiet ··· 46 46 options for 'add' and 'merge' (also: 'pull', 'split --rejoin', and 'push --rejoin') 47 47 squash merge subtree changes as a single commit 48 48 m,message!= use the given message as the commit message for the merge commit 49 + S,gpg-sign?key-id GPG-sign commits. The keyid argument is optional and defaults to the committer identity 49 50 " 50 51 51 52 indent=0 ··· 115 116 then 116 117 set -- -h 117 118 fi 118 - set_args="$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)" 119 + set_args="$(echo "$OPTS_SPEC" | git rev-parse --parseopt --stuck-long -- "$@" || echo exit $?)" 119 120 eval "$set_args" 120 121 . git-sh-setup 121 122 require_work_tree ··· 131 132 opt="$1" 132 133 shift 133 134 case "$opt" in 134 - --annotate|-b|-P|-m|--onto) 135 - shift 136 - ;; 137 135 --rejoin) 138 136 arg_split_rejoin=1 139 137 ;; ··· 171 169 arg_split_annotate= 172 170 arg_addmerge_squash= 173 171 arg_addmerge_message= 172 + arg_gpg_sign= 174 173 while test $# -gt 0 175 174 do 176 175 opt="$1" 177 176 shift 178 177 179 178 case "$opt" in 180 - -q) 179 + --quiet) 181 180 arg_quiet=1 182 181 ;; 183 - -d) 182 + --debug) 184 183 arg_debug=1 185 184 ;; 186 - --annotate) 185 + --annotate=*) 187 186 test -n "$allow_split" || die_incompatible_opt "$opt" "$arg_command" 188 - arg_split_annotate="$1" 189 - shift 187 + arg_split_annotate="${opt#*=}" 190 188 ;; 191 189 --no-annotate) 192 190 test -n "$allow_split" || die_incompatible_opt "$opt" "$arg_command" 193 191 arg_split_annotate= 194 192 ;; 195 - -b) 193 + --branch=*) 196 194 test -n "$allow_split" || die_incompatible_opt "$opt" "$arg_command" 197 - arg_split_branch="$1" 198 - shift 195 + arg_split_branch="${opt#*=}" 199 196 ;; 200 - -P) 201 - arg_prefix="${1%/}" 202 - shift 197 + --prefix=*) 198 + arg_prefix="${opt#*=}" 203 199 ;; 204 - -m) 200 + --message=*) 205 201 test -n "$allow_addmerge" || die_incompatible_opt "$opt" "$arg_command" 206 - arg_addmerge_message="$1" 207 - shift 202 + arg_addmerge_message="${opt#*=}" 208 203 ;; 209 204 --no-prefix) 210 205 arg_prefix= 211 206 ;; 212 - --onto) 207 + --onto=*) 213 208 test -n "$allow_split" || die_incompatible_opt "$opt" "$arg_command" 214 - arg_split_onto="$1" 215 - shift 209 + arg_split_onto="${opt#*=}" 216 210 ;; 217 211 --no-onto) 218 212 test -n "$allow_split" || die_incompatible_opt "$opt" "$arg_command" ··· 240 234 test -n "$allow_addmerge" || die_incompatible_opt "$opt" "$arg_command" 241 235 arg_addmerge_squash= 242 236 ;; 237 + --gpg-sign=* | --gpg-sign | --no-gpg-sign) 238 + arg_gpg_sign="$opt" 239 + ;; 243 240 --) 244 241 break 245 242 ;; ··· 272 269 debug "quiet: {$arg_quiet}" 273 270 debug "dir: {$dir}" 274 271 debug "opts: {$*}" 272 + debug "gpg-sign: {$arg_gpg_sign}" 275 273 debug 276 274 277 275 "cmd_$arg_command" "$@" ··· 537 535 printf "%s" "$arg_split_annotate" 538 536 cat 539 537 ) | 540 - git commit-tree "$2" $3 # reads the rest of stdin 538 + git commit-tree $arg_gpg_sign "$2" $3 # reads the rest of stdin 541 539 ) || die "fatal: can't copy commit $1" 542 540 } 543 541 ··· 683 681 if test -n "$old" 684 682 then 685 683 squash_msg "$dir" "$oldsub" "$newsub" | 686 - git commit-tree "$tree" -p "$old" || exit $? 684 + git commit-tree $arg_gpg_sign "$tree" -p "$old" || exit $? 687 685 else 688 686 squash_msg "$dir" "" "$newsub" | 689 - git commit-tree "$tree" || exit $? 687 + git commit-tree $arg_gpg_sign "$tree" || exit $? 690 688 fi 691 689 } 692 690 ··· 925 923 then 926 924 rev=$(new_squash_commit "" "" "$rev") || exit $? 927 925 commit=$(add_squashed_msg "$rev" "$dir" | 928 - git commit-tree "$tree" $headp -p "$rev") || exit $? 926 + git commit-tree $arg_gpg_sign "$tree" $headp -p "$rev") || exit $? 929 927 else 930 928 revp=$(peel_committish "$rev") || exit $? 931 929 commit=$(add_msg "$dir" $headrev "$rev" | 932 - git commit-tree "$tree" $headp -p "$revp") || exit $? 930 + git commit-tree $arg_gpg_sign "$tree" $headp -p "$revp") || exit $? 933 931 fi 934 932 git reset "$commit" || exit $? 935 933 ··· 1080 1078 if test -n "$arg_addmerge_message" 1081 1079 then 1082 1080 git merge --no-ff -Xsubtree="$arg_prefix" \ 1083 - --message="$arg_addmerge_message" "$rev" 1081 + --message="$arg_addmerge_message" $arg_gpg_sign "$rev" 1084 1082 else 1085 - git merge --no-ff -Xsubtree="$arg_prefix" $rev 1083 + git merge --no-ff -Xsubtree="$arg_prefix" $arg_gpg_sign $rev 1086 1084 fi 1087 1085 } 1088 1086
+113
contrib/subtree/t/t7900-subtree.sh
··· 11 11 12 12 TEST_DIRECTORY=$(pwd)/../../../t 13 13 . "$TEST_DIRECTORY"/test-lib.sh 14 + . "$TEST_DIRECTORY"/lib-gpg.sh 14 15 15 16 # Use our own wrapper around test-lib.sh's test_create_repo, in order 16 17 # to set log.date=relative. `git subtree` parses the output of `git ··· 1560 1561 git subtree split --prefix folder_subtree/ --branch subtree_tip $defaultBranch && 1561 1562 git subtree split --prefix folder_subtree/ --branch subtree_branch branch && 1562 1563 test $(git rev-list --count subtree_tip..subtree_branch) = 0 1564 + ) 1565 + ' 1566 + 1567 + test_expect_success GPG 'add subproj with GPG signing using -S flag' ' 1568 + subtree_test_create_repo "$test_count" && 1569 + subtree_test_create_repo "$test_count/sub proj" && 1570 + test_create_commit "$test_count" main1 && 1571 + test_create_commit "$test_count/sub proj" sub1 && 1572 + ( 1573 + cd "$test_count" && 1574 + git fetch ./"sub proj" HEAD && 1575 + git subtree add --prefix="sub dir" -S FETCH_HEAD && 1576 + git verify-commit HEAD && 1577 + test "$(last_commit_subject)" = "Add '\''sub dir/'\'' from commit '\''$(git rev-parse FETCH_HEAD)'\''" 1578 + ) 1579 + ' 1580 + 1581 + test_expect_success GPG 'add subproj with GPG signing using --gpg-sign flag' ' 1582 + subtree_test_create_repo "$test_count" && 1583 + subtree_test_create_repo "$test_count/sub proj" && 1584 + test_create_commit "$test_count" main1 && 1585 + test_create_commit "$test_count/sub proj" sub1 && 1586 + ( 1587 + cd "$test_count" && 1588 + git fetch ./"sub proj" HEAD && 1589 + git subtree add --prefix="sub dir" --gpg-sign FETCH_HEAD && 1590 + git verify-commit HEAD && 1591 + test "$(last_commit_subject)" = "Add '\''sub dir/'\'' from commit '\''$(git rev-parse FETCH_HEAD)'\''" 1592 + ) 1593 + ' 1594 + 1595 + test_expect_success GPG 'add subproj with GPG signing using specific key ID' ' 1596 + subtree_test_create_repo "$test_count" && 1597 + subtree_test_create_repo "$test_count/sub proj" && 1598 + test_create_commit "$test_count" main1 && 1599 + test_create_commit "$test_count/sub proj" sub1 && 1600 + ( 1601 + cd "$test_count" && 1602 + git fetch ./"sub proj" HEAD && 1603 + git subtree add --prefix="sub dir" -S"$GIT_COMMITTER_EMAIL" FETCH_HEAD && 1604 + git verify-commit HEAD && 1605 + test "$(last_commit_subject)" = "Add '\''sub dir/'\'' from commit '\''$(git rev-parse FETCH_HEAD)'\''" 1606 + ) 1607 + ' 1608 + 1609 + test_expect_success GPG 'merge with GPG signing' ' 1610 + subtree_test_create_repo "$test_count" && 1611 + subtree_test_create_repo "$test_count/sub proj" && 1612 + test_create_commit "$test_count" main1 && 1613 + test_create_commit "$test_count/sub proj" sub1 && 1614 + ( 1615 + cd "$test_count" && 1616 + git fetch ./"sub proj" HEAD && 1617 + git subtree add --prefix="sub dir" FETCH_HEAD 1618 + ) && 1619 + test_create_commit "$test_count/sub proj" sub2 && 1620 + ( 1621 + cd "$test_count" && 1622 + git fetch ./"sub proj" HEAD && 1623 + git subtree merge --prefix="sub dir" -S FETCH_HEAD && 1624 + git verify-commit HEAD 1625 + ) 1626 + ' 1627 + 1628 + test_expect_success GPG 'split with GPG signing and --rejoin' ' 1629 + subtree_test_create_repo "$test_count" && 1630 + subtree_test_create_repo "$test_count/sub proj" && 1631 + test_create_commit "$test_count" main1 && 1632 + test_create_commit "$test_count/sub proj" sub1 && 1633 + ( 1634 + cd "$test_count" && 1635 + git fetch ./"sub proj" HEAD && 1636 + git subtree add --prefix="sub dir" FETCH_HEAD 1637 + ) && 1638 + test_create_commit "$test_count" "sub dir/main-sub1" && 1639 + ( 1640 + cd "$test_count" && 1641 + git subtree split --prefix="sub dir" --rejoin -S && 1642 + git verify-commit HEAD 1643 + ) 1644 + ' 1645 + 1646 + test_expect_success GPG 'add with --squash and GPG signing' ' 1647 + subtree_test_create_repo "$test_count" && 1648 + subtree_test_create_repo "$test_count/sub proj" && 1649 + test_create_commit "$test_count" main1 && 1650 + test_create_commit "$test_count/sub proj" sub1 && 1651 + ( 1652 + cd "$test_count" && 1653 + git fetch ./"sub proj" HEAD && 1654 + git subtree add --prefix="sub dir" --squash -S FETCH_HEAD && 1655 + git verify-commit HEAD && 1656 + # With --squash, the commit subject should reference the squash commit (first parent of merge) 1657 + squash_commit=$(git rev-parse HEAD^2) && 1658 + test "$(last_commit_subject)" = "Merge commit '\''$squash_commit'\'' as '\''sub dir'\''" 1659 + ) 1660 + ' 1661 + 1662 + test_expect_success GPG 'pull with GPG signing' ' 1663 + subtree_test_create_repo "$test_count" && 1664 + subtree_test_create_repo "$test_count/sub proj" && 1665 + test_create_commit "$test_count" main1 && 1666 + test_create_commit "$test_count/sub proj" sub1 && 1667 + ( 1668 + cd "$test_count" && 1669 + git subtree add --prefix="sub dir" ./"sub proj" HEAD 1670 + ) && 1671 + test_create_commit "$test_count/sub proj" sub2 && 1672 + ( 1673 + cd "$test_count" && 1674 + git subtree pull --prefix="sub dir" -S ./"sub proj" HEAD && 1675 + git verify-commit HEAD 1563 1676 ) 1564 1677 ' 1565 1678