From 2121ce36cf4eb02385255cbd5b0bbd1dcc803113 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Thu, 8 Nov 2012 18:47:18 -0500 Subject: [PATCH] git-submodule foreach: export .gitmodules settings as variables This makes it easy to access per-submodule variables. For example, git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull' can now be reduced to git submodule foreach 'git checkout $submodule_branch && git pull' Every submodule.. setting from .gitmodules is available as a $submodule_ variable. These variables are not propagated recursively into nested submodules. Signed-off-by: W. Trevor King Based-on-patch-by: Phil Hord --- Documentation/git-submodule.txt | 3 +++ git-sh-setup.sh | 20 ++++++++++++++++++++ git-submodule.sh | 16 ++++++++++++++++ t/t7407-submodule-foreach.sh | 29 +++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+) mode change 100644 => 100755 git-sh-setup.sh diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt index cbec363a4..9a99826d5 100644 --- a/Documentation/git-submodule.txt +++ b/Documentation/git-submodule.txt @@ -175,6 +175,9 @@ foreach:: $path is the name of the submodule directory relative to the superproject, $sha1 is the commit as recorded in the superproject, and $toplevel is the absolute path to the top-level of the superproject. + In addition, every submodule.. setting from .gitmodules + is available as the variable $submodule_. These + variables are not propagated recursively into nested submodules. Any submodules defined in the superproject but not checked out are ignored by this command. Unless given `--quiet`, foreach prints the name of each submodule before evaluating the command. diff --git a/git-sh-setup.sh b/git-sh-setup.sh old mode 100644 new mode 100755 index ee0e0bc04..179a92010 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -222,6 +222,26 @@ clear_local_git_env() { unset $(git rev-parse --local-env-vars) } +# Remove any suspect characters from a user-generated variable name. +sanitize_variable_name() { + VAR_NAME="$1" + printf '%s' "$VAR_NAME" | + sed -e 's/^[^a-zA-Z]/_/' -e 's/[^a-zA-Z0-9]/_/g' +} + +# Return a command for setting a new variable. +# Neither the variable name nor the variable value passed to this +# function need to be sanitized. You need to eval the returned +# string, because new variables set by the function itself don't +# effect the calling process. +set_user_variable() { + VAR_NAME="$1" + VAR_VALUE="$2" + VAR_NAME=$(sanitize_variable_name "$VAR_NAME") + VAR_VALUE=$(printf '%s' "$VAR_VALUE" | + sed -e 's/\\/\\\\/g' -e 's/"/\\"/g') + printf '%s=%s;\n' "$VAR_NAME" "\"$VAR_VALUE\"" +} # Platform specific tweaks to work around some commands case $(uname -s) in diff --git a/git-submodule.sh b/git-submodule.sh index bc33112ab..e4d26f9a9 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -434,8 +434,24 @@ cmd_foreach() clear_local_git_env # we make $path available to scripts ... path=$sm_path + + # make all submodule variables available to scripts + eval $( + git config -f .gitmodules --get-regexp "^submodule\.${name}\..*" | + sed -e "s|^submodule\.${name}\.||" | + while read VAR_NAME VAR_VALUE ; do + VAR_NAME=$(printf '%s' "$VAR_NAME" | tr A-Z a-z) + set_user_variable "submodule_${VAR_NAME}" "$VAR_VALUE" + done) + UNSET_CMD=$(set | + sed -n -e 's|^\(submodule_[a-z_]*\)=.*$|\1|p' | + while read VAR_NAME ; do + printf 'unset %s;\n' "$VAR_NAME" + done) + cd "$sm_path" && eval "$@" && + eval "$UNSET_CMD" && if test -n "$recursive" then cmd_foreach "--recursive" "$@" diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh index 9b69fe2e1..46ac74611 100755 --- a/t/t7407-submodule-foreach.sh +++ b/t/t7407-submodule-foreach.sh @@ -313,4 +313,33 @@ test_expect_success 'command passed to foreach --recursive retains notion of std test_cmp expected actual ' +cat > expect < ../actual + ) && + test_i18ncmp expect actual +' +# +#"echo \$toplevel-\$name-\$submodule_path-\$submodule_url" + test_done -- 2.26.2