From 4f11a32aca4f229d7d843e87e54d1241574422c9 Mon Sep 17 00:00:00 2001 From: yasuda Date: Wed, 7 Feb 2024 10:11:08 +0900 Subject: [PATCH 1/4] Store submodule commits bounded for `HEAD` of top repository --- git-archive-all.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git-archive-all.sh b/git-archive-all.sh index b72dc4d..13e01e6 100755 --- a/git-archive-all.sh +++ b/git-archive-all.sh @@ -249,9 +249,9 @@ fi if [ $VERBOSE -eq 1 ]; then echo -n "archiving submodules..." fi -git submodule >>"$TMPLIST" +git submodule status --recursive --cached >> "$TMPLIST" while read path; do - TREEISH=$(grep "^ .*${path%/} " "$TMPLIST" | cut -d ' ' -f 2) # git submodule does not list trailing slashes in $path + TREEISH=$(sed -nr -e 's@^[ +-]@@' -e 's@ +\(.*\)$@@' -e 's@([^ ]+) +'"${path%/}"'$@\1@ p' "$TMPLIST") # git submodule does not list trailing slashes in $path cd "$path" rm -f "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT git archive --format=$FORMAT --prefix="${PREFIX}$path" $ARCHIVE_OPTS ${TREEISH:-HEAD} > "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT From 388a0a45e304be2e8025d2a5f642d7754fab6d57 Mon Sep 17 00:00:00 2001 From: yasuda Date: Thu, 8 Feb 2024 15:42:22 +0900 Subject: [PATCH 2/4] Store exact submodule commits for direct submodule. --- git-archive-all.sh | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/git-archive-all.sh b/git-archive-all.sh index 13e01e6..739b064 100755 --- a/git-archive-all.sh +++ b/git-archive-all.sh @@ -249,9 +249,27 @@ fi if [ $VERBOSE -eq 1 ]; then echo -n "archiving submodules..." fi + +TOP_TREEISH=$TREEISH +TOP_TREEISH_HASH=$(git rev-parse "$TOP_TREEISH") +TOP_HEAD_HASH=$(git rev-parse HEAD) git submodule status --recursive --cached >> "$TMPLIST" while read path; do - TREEISH=$(sed -nr -e 's@^[ +-]@@' -e 's@ +\(.*\)$@@' -e 's@([^ ]+) +'"${path%/}"'$@\1@ p' "$TMPLIST") # git submodule does not list trailing slashes in $path + # git submodule does not list trailing slashes in $path. Remove it in $TREEISH search. + TREEISH=$(git ls-tree "${TOP_TREEISH}" "${path%/}" | awk '{ print $3 }') + if [ -z "$TREEISH" ]; then + if [ "$TOP_TREEISH_HASH" != "$TOP_HEAD_HASH" ]; then + echo >&2 -e "\e[33;1mWarning:\e[22m Submodule \"${path%/}\" hash for top repo's ${TOP_TREEISH} was not obtained. Use the commit for top repo's HEAD.\e[m" + fi + + TREEISH=$(sed -nr -e 's@^[ +-]@@' -e 's@ +\(.*\)$@@' -e 's@([^ ]+) +'"${path%/}"'$@\1@ p' "$TMPLIST") + if [ -z "$TREEISH" ]; then + echo >&2 -e "\e[33;1mWarning:\e[22m Submodule \"${path%/}\" hash for top repo's HEAD was not obtained. Use the commit for the submodule's HEAD.\e[m" + TREEISH=HEAD + fi + fi + echo >&2 "Submodule \"${path%/}\" commit for top repo's ${TOP_TREEISH}: ${TREEISH:-HEAD} ($(git -C ${path} name-rev --name-only "${TREEISH}"))" + cd "$path" rm -f "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT git archive --format=$FORMAT --prefix="${PREFIX}$path" $ARCHIVE_OPTS ${TREEISH:-HEAD} > "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT From 1c522f9b4aeb3b1a11407c1a36cde8001f697b60 Mon Sep 17 00:00:00 2001 From: yasuda Date: Thu, 8 Feb 2024 18:30:16 +0900 Subject: [PATCH 3/4] Try to search non-direct submodule's exact commit --- git-archive-all.sh | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/git-archive-all.sh b/git-archive-all.sh index 739b064..e93094d 100755 --- a/git-archive-all.sh +++ b/git-archive-all.sh @@ -257,17 +257,40 @@ git submodule status --recursive --cached >> "$TMPLIST" while read path; do # git submodule does not list trailing slashes in $path. Remove it in $TREEISH search. TREEISH=$(git ls-tree "${TOP_TREEISH}" "${path%/}" | awk '{ print $3 }') + + if [ -z "$TREEISH" ]; then + # It is not top repo's direct submodule. + ppath=${path%/}; ppath=${ppath%/*} + pathbase=${path%/}; pathbase=${pathbase##*/} + while [ -n "${ppath}" ]; do + PARENT_TREEISH=$(sed -nr -e 's@^[ +-]@@' -e 's@ +\(.*\)$@@' -e 's@([^ ]+) +'"${ppath}"'$@\1@ p' "$TMPLIST" | tail -n1) + if [ -n "$PARENT_TREEISH" ]; then + TREEISH=$(git -C "${ppath}" ls-tree "${PARENT_TREEISH}" "${pathbase}" | awk '{ print $3 }') + if [ -n "${TREEISH}" ]; then + break; + fi + fi + if [ ${ppath} == ${ppath%/*} ]; then + break + else + pathbase="${ppath##*/}/${pathbase}" + ppath=${ppath%/*} + fi + done + fi + if [ -z "$TREEISH" ]; then if [ "$TOP_TREEISH_HASH" != "$TOP_HEAD_HASH" ]; then echo >&2 -e "\e[33;1mWarning:\e[22m Submodule \"${path%/}\" hash for top repo's ${TOP_TREEISH} was not obtained. Use the commit for top repo's HEAD.\e[m" fi - TREEISH=$(sed -nr -e 's@^[ +-]@@' -e 's@ +\(.*\)$@@' -e 's@([^ ]+) +'"${path%/}"'$@\1@ p' "$TMPLIST") + TREEISH=$(sed -nr -e 's@^[ +-]@@' -e 's@ +\(.*\)$@@' -e 's@([^ ]+) +'"${path%/}"'$@\1@ p' "$TMPLIST" | tail -n1) if [ -z "$TREEISH" ]; then echo >&2 -e "\e[33;1mWarning:\e[22m Submodule \"${path%/}\" hash for top repo's HEAD was not obtained. Use the commit for the submodule's HEAD.\e[m" TREEISH=HEAD fi fi + echo " ${TREEISH} ${path%/}" >> "${TMPLIST}" # Update the chosen commit echo >&2 "Submodule \"${path%/}\" commit for top repo's ${TOP_TREEISH}: ${TREEISH:-HEAD} ($(git -C ${path} name-rev --name-only "${TREEISH}"))" cd "$path" From acfe11d3fadb4f0e9a8154a5f6d67b8cbc6b6981 Mon Sep 17 00:00:00 2001 From: yasuda Date: Fri, 9 Feb 2024 09:40:11 +0900 Subject: [PATCH 4/4] Use `git rev-parse --show-toplevel` to get each submodule's top dir in exact commit search --- git-archive-all.sh | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/git-archive-all.sh b/git-archive-all.sh index e93094d..8d57cd1 100755 --- a/git-archive-all.sh +++ b/git-archive-all.sh @@ -260,23 +260,13 @@ while read path; do if [ -z "$TREEISH" ]; then # It is not top repo's direct submodule. - ppath=${path%/}; ppath=${ppath%/*} - pathbase=${path%/}; pathbase=${pathbase##*/} - while [ -n "${ppath}" ]; do - PARENT_TREEISH=$(sed -nr -e 's@^[ +-]@@' -e 's@ +\(.*\)$@@' -e 's@([^ ]+) +'"${ppath}"'$@\1@ p' "$TMPLIST" | tail -n1) - if [ -n "$PARENT_TREEISH" ]; then - TREEISH=$(git -C "${ppath}" ls-tree "${PARENT_TREEISH}" "${pathbase}" | awk '{ print $3 }') - if [ -n "${TREEISH}" ]; then - break; - fi - fi - if [ ${ppath} == ${ppath%/*} ]; then - break - else - pathbase="${ppath##*/}/${pathbase}" - ppath=${ppath%/*} - fi - done + ppath=$(realpath --relative-base="${PWD}" "$(git -C "${path%/*/}" rev-parse --show-toplevel)") + pathbase=$(realpath --relative-base="${ppath}" "${path%/}") + + PARENT_TREEISH=$(sed -nr -e 's@^[ +-]@@' -e 's@ +\(.*\)$@@' -e 's@([^ ]+) +'"${ppath}"'$@\1@ p' "$TMPLIST" | tail -n1) + if [ -n "$PARENT_TREEISH" ]; then + TREEISH=$(git -C "${ppath}" ls-tree "${PARENT_TREEISH}" "${pathbase}" | awk '{ print $3 }') + fi fi if [ -z "$TREEISH" ]; then