submodule update: Add --commit option wtk/submodule-commit
authorW. Trevor King <wking@tremily.us>
Thu, 29 Nov 2012 13:05:06 +0000 (08:05 -0500)
committerW. Trevor King <wking@tremily.us>
Thu, 29 Nov 2012 21:36:01 +0000 (16:36 -0500)
This option triggers automatic commits when `submodule update` changes
any gitlinked submodule SHA-1s.  The commit message contains a
`shortlog` summary of the changes for each changed submodule.

git-submodule.sh
t/t7406-submodule-update.sh

index ab6b1107b6090494f192f361471ed5748ffa7dc1..d9a59af1001d9fd527594f3e94f4c702e9cbc24b 100755 (executable)
@@ -8,7 +8,7 @@ dashless=$(basename "$0" | sed -e 's/-/ /')
 USAGE="[--quiet] add [-b branch] [-f|--force] [--reference <repository>] [--] <repository> [<path>]
    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] init [--] [<path>...]
-   or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
+   or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--commit] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
    or: $dashless [--quiet] foreach [--recursive] <command>
    or: $dashless [--quiet] sync [--] [<path>...]"
@@ -21,6 +21,7 @@ require_work_tree
 command=
 branch=
 force=
+commit=
 reference=
 cached=
 recursive=
@@ -239,6 +240,52 @@ module_clone()
        (clear_local_git_env; cd "$sm_path" && GIT_WORK_TREE=. git config core.worktree "$rel/$b")
 }
 
+#
+# Commit changed submodule gitlinks
+#
+# $1 = name-a;sha1-a;subsha1-a\n[name-b;sha1-b;subsha1-b\n...]
+#
+commit_changes()
+{
+       echo "commiting $1"
+       OIFS="$IFS"
+       IFS=";"
+       paths=$(echo "$1" |
+               while read name sm_path sha1 subsha1
+               do
+                       echo "$sm_path"
+               done
+               )
+       names=$(echo "$1" |
+               while read name sm_path sha1 subsha1
+               do
+                       printf ' %s' "$name"
+               done
+               )
+       summary="$(eval_gettext "Updated submodules:")$names"
+       body=$(echo "$1" |
+               while read name sm_path sha1 subsha1
+               do
+                       if test "$name" = "$sm_path"
+                       then
+                               printf 'Changes to %s:\n\n' "$name"
+                       else
+                               printf 'Changes to %s (%s):\n\n' "$name" "$sm_path"
+                       fi
+                       (
+                               clear_local_git_env
+                               cd "$sm_path" &&
+                               git shortlog "${sha1}..${subsha1}" ||
+                               die "$(eval_gettext "Unable to generate shortlog in submodule path '\$sm_path'")"
+                       )
+               done
+               )
+       IFS="$OIFS"
+       message="$(printf '%s\n\n%s\n' "$summary" "$body")"
+       echo "message: [$message]"
+       git commit -m "$message" $paths
+}
+
 #
 # Add a new submodule to the working tree, .gitmodules and the index
 #
@@ -515,6 +562,9 @@ cmd_update()
                -f|--force)
                        force=$1
                        ;;
+               --commit)
+                       commit=1
+                       ;;
                -r|--rebase)
                        update="rebase"
                        ;;
@@ -557,6 +607,7 @@ cmd_update()
        fi
 
        cloned_modules=
+       changed_modules=
        module_list "$@" | {
        err=
        while read mode sha1 stage sm_path
@@ -660,6 +711,15 @@ Maybe you want to use 'update --init'?")"
                                err="${err};$die_msg"
                                continue
                        fi
+
+                       subsha1=$(clear_local_git_env; cd "$sm_path" &&
+                               git rev-parse --verify HEAD) ||
+                       die "$(eval_gettext "Unable to find new revision in submodule path '\$sm_path'")"
+
+                       if test "$subsha1" != "$sha1"
+                       then
+                               changed_modules=$(printf '%s%s\n' "$changed_modules" "$name;$sm_path;$sha1;$subsha1")
+                       fi
                fi
 
                if test -n "$recursive"
@@ -680,6 +740,11 @@ Maybe you want to use 'update --init'?")"
                fi
        done
 
+       if test -z "$err" -a -n "$commit" -a -n "$changed_modules"
+       then
+               commit_changes "$changed_modules"
+       fi
+
        if test -n "$err"
        then
                OIFS=$IFS
index 15426530e49ef2e42cda2528f4a72a784eb40cd9..7f9abcbf2aab6d75d0e8dd89174c437f5deb7570 100755 (executable)
@@ -163,6 +163,24 @@ test_expect_success 'submodule update --merge staying on master' '
        )
 '
 
+test_expect_success 'submodule update --commit --rebase should commit gitlink changes' '
+       (cd super/submodule &&
+        git reset --hard HEAD~1 &&
+        echo "local change" > local-file &&
+        git add local-file &&
+        test_tick &&
+        git commit -m "local change"
+       ) &&
+       (cd super &&
+        git submodule update --commit --rebase submodule &&
+        test "$(git log -1 --oneline)" = "cd69713 Updated submodules: submodule"
+       ) &&
+       (cd submodule &&
+        git remote add super-submodule ../super/submodule &&
+        git pull super-submodule master
+       )
+'
+
 test_expect_success 'submodule update - rebase in .git/config' '
        (cd super &&
         git config submodule.submodule.update rebase