submodule: teach set-branch subcommand
authorDenton Liu <liu.denton@gmail.com>
Fri, 8 Feb 2019 11:21:34 +0000 (03:21 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 10 Apr 2019 03:07:16 +0000 (12:07 +0900)
This teaches git-submodule the set-branch subcommand which allows the
branch of a submodule to be set through a porcelain command without
having to manually manipulate the .gitmodules file.

Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-submodule.txt
contrib/completion/git-completion.bash
git-submodule.sh
t/t7419-submodule-set-branch.sh [new file with mode: 0755]
index 4150148fa3ff5d054037f90d4fc3ecea5dd6d529..4daf14418074abe1b0c3cb5b720afe15e2576561 100644 (file)
@@ -14,6 +14,7 @@ SYNOPSIS
 'git submodule' [--quiet] init [--] [<path>...]
 'git submodule' [--quiet] deinit [-f|--force] (--all|[--] <path>...)
 'git submodule' [--quiet] update [<options>] [--] [<path>...]
+'git submodule' [--quiet] set-branch [<options>] [--] <path>
 'git submodule' [--quiet] summary [<options>] [--] [<path>...]
 'git submodule' [--quiet] foreach [--recursive] <command>
 'git submodule' [--quiet] sync [--recursive] [--] [<path>...]
@@ -168,6 +169,12 @@ submodule with the `--init` option.
 If `--recursive` is specified, this command will recurse into the
 registered submodules, and update any nested submodules within.
 --
+set-branch ((-d|--default)|(-b|--branch <branch>)) [--] <path>::
+       Sets the default remote tracking branch for the submodule. The
+       `--branch` option allows the remote branch to be specified. The
+       `--default` option removes the submodule.<name>.branch configuration
+       key, which causes the tracking branch to default to 'master'.
+
 summary [--cached|--files] [(-n|--summary-limit) <n>] [commit] [--] [<path>...]::
        Show commit summary between the given commit (defaults to HEAD) and
        working tree/index. For a submodule in question, a series of commits
index 499e56f83d0a0592abd53686612c79358780eef2..8b3b5a9d34590fbf025753d87c5a69ec77945239 100644 (file)
@@ -2573,7 +2573,7 @@ _git_submodule ()
 {
        __git_has_doubledash && return
 
-       local subcommands="add status init deinit update summary foreach sync"
+       local subcommands="add status init deinit update set-branch summary foreach sync"
        local subcommand="$(__git_find_on_cmdline "$subcommands")"
        if [ -z "$subcommand" ]; then
                case "$cur" in
@@ -2604,6 +2604,9 @@ _git_submodule ()
                        --force --rebase --merge --reference --depth --recursive --jobs
                "
                ;;
+       set-branch,--*)
+               __gitcomp "--default --branch"
+               ;;
        summary,--*)
                __gitcomp "--cached --files --summary-limit"
                ;;
index b5f2beee60ab59a04b5b236da8df39403009db1b..470f6815730fe08aa112fde630b301b814f31571 100755 (executable)
@@ -10,6 +10,7 @@ USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <re
    or: $dashless [--quiet] init [--] [<path>...]
    or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...)
    or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]
+   or: $dashless [--quiet] set-branch (--default|--branch <branch>) [--] <path>
    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
    or: $dashless [--quiet] foreach [--recursive] <command>
    or: $dashless [--quiet] sync [--recursive] [--] [<path>...]
@@ -684,6 +685,72 @@ cmd_update()
        }
 }
 
+#
+# Configures a submodule's default branch
+#
+# $@ = requested path
+#
+cmd_set_branch() {
+       unset_branch=false
+       branch=
+
+       while test $# -ne 0
+       do
+               case "$1" in
+               -q|--quiet)
+                       # we don't do anything with this but we need to accept it
+                       ;;
+               -d|--default)
+                       unset_branch=true
+                       ;;
+               -b|--branch)
+                       case "$2" in '') usage ;; esac
+                       branch=$2
+                       shift
+                       ;;
+               --)
+                       shift
+                       break
+                       ;;
+               -*)
+                       usage
+                       ;;
+               *)
+                       break
+                       ;;
+               esac
+               shift
+       done
+
+       if test $# -ne 1
+       then
+               usage
+       fi
+
+       # we can't use `git submodule--helper name` here because internally, it
+       # hashes the path so a trailing slash could lead to an unintentional no match
+       name="$(git submodule--helper list "$1" | cut -f2)"
+       if test -z "$name"
+       then
+               exit 1
+       fi
+
+       test -n "$branch"; has_branch=$?
+       test "$unset_branch" = true; has_unset_branch=$?
+
+       if test $((!$has_branch != !$has_unset_branch)) -eq 0
+       then
+               usage
+       fi
+
+       if test $has_branch -eq 0
+       then
+               git submodule--helper config submodule."$name".branch "$branch"
+       else
+               git submodule--helper config --unset submodule."$name".branch
+       fi
+}
+
 #
 # Show commit summary for submodules in index or working tree
 #
@@ -983,7 +1050,7 @@ cmd_absorbgitdirs()
 while test $# != 0 && test -z "$command"
 do
        case "$1" in
-       add | foreach | init | deinit | update | status | summary | sync | absorbgitdirs)
+       add | foreach | init | deinit | update | set-branch | status | summary | sync | absorbgitdirs)
                command=$1
                ;;
        -q|--quiet)
@@ -1024,8 +1091,8 @@ then
     fi
 fi
 
-# "-b branch" is accepted only by "add"
-if test -n "$branch" && test "$command" != add
+# "-b branch" is accepted only by "add" and "set-branch"
+if test -n "$branch" && (test "$command" != add || test "$command" != set-branch)
 then
        usage
 fi
@@ -1036,4 +1103,4 @@ then
        usage
 fi
 
-"cmd_$command" "$@"
+"cmd_$(echo $command | sed -e s/-/_/g)" "$@"
diff --git a/t/t7419-submodule-set-branch.sh b/t/t7419-submodule-set-branch.sh
new file mode 100755 (executable)
index 0000000..c4b370e
--- /dev/null
@@ -0,0 +1,93 @@
+#!/bin/sh
+#
+# Copyright (c) 2019 Denton Liu
+#
+
+test_description='Test submodules set-branch subcommand
+
+This test verifies that the set-branch subcommand of git-submodule is working
+as expected.
+'
+
+TEST_NO_CREATE_REPO=1
+. ./test-lib.sh
+
+test_expect_success 'submodule config cache setup' '
+       mkdir submodule &&
+       (cd submodule &&
+               git init &&
+               echo a >a &&
+               git add . &&
+               git commit -ma &&
+               git checkout -b topic &&
+               echo b >a &&
+               git add . &&
+               git commit -mb
+       ) &&
+       mkdir super &&
+       (cd super &&
+               git init &&
+               git submodule add ../submodule &&
+               git commit -m "add submodule"
+       )
+'
+
+test_expect_success 'ensure submodule branch is unset' '
+       (cd super &&
+               test_must_fail grep branch .gitmodules
+       )
+'
+
+test_expect_success 'test submodule set-branch --branch' '
+       (cd super &&
+               git submodule set-branch --branch topic submodule &&
+               grep "branch = topic" .gitmodules &&
+               git submodule update --remote &&
+               cat <<-\EOF >expect &&
+               b
+               EOF
+               git -C submodule show -s --pretty=%s >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'test submodule set-branch --default' '
+       (cd super &&
+               git submodule set-branch --default submodule &&
+               test_must_fail grep branch .gitmodules &&
+               git submodule update --remote &&
+               cat <<-\EOF >expect &&
+               a
+               EOF
+               git -C submodule show -s --pretty=%s >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'test submodule set-branch -b' '
+       (cd super &&
+               git submodule set-branch -b topic submodule &&
+               grep "branch = topic" .gitmodules &&
+               git submodule update --remote &&
+               cat <<-\EOF >expect &&
+               b
+               EOF
+               git -C submodule show -s --pretty=%s >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'test submodule set-branch -d' '
+       (cd super &&
+               git submodule set-branch -d submodule &&
+               test_must_fail grep branch .gitmodules &&
+               git submodule update --remote &&
+               cat <<-\EOF >expect &&
+               a
+               EOF
+               git -C submodule show -s --pretty=%s >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_done