From 59e70ab7c156fb22855d91d7541db307749ff259 Mon Sep 17 00:00:00 2001 From: Miao Wang Date: Wed, 11 Oct 2023 22:34:39 +0800 Subject: [PATCH] git-recursive: change the way to iterate submoudles --- git-recursive.sh | 107 ++++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/git-recursive.sh b/git-recursive.sh index ff6ff6d..42d7ea8 100755 --- a/git-recursive.sh +++ b/git-recursive.sh @@ -27,7 +27,7 @@ fi depth=0 function echon() { - echo depth $depth $@ + echo depth "$depth" "$@" } function repo_init() { @@ -42,7 +42,7 @@ function update_linux_git() { cd "$working_dir" echon "==== SYNC $upstream START ====" git remote set-url origin "$upstream" - /usr/bin/timeout -s INT 3600 git remote -v update -p + "timeout" -s INT 3600 git remote -v update -p local ret=$? [[ $ret -ne 0 ]] && echon "git update failed with rc=$ret" local head=$(git remote show origin | awk '/HEAD branch:/ {print $NF}') @@ -60,60 +60,63 @@ function git_sync() { local working_dir=$2 if [[ ! -f "$working_dir/HEAD" ]]; then echon "Initializing $upstream mirror" - repo_init $1 $2 + repo_init "$upstream" "$working_dir" return $? fi - update_linux_git $1 $2 + update_linux_git "$upstream" "$working_dir" } function checkout_repo() { local repo_dir="$1" local work_tree="$2" local commit="$3" - echon "Checkout $repo_dir to $work_tree" - rm -rf $work_tree - git clone "$repo_dir" "$work_tree" - local ret=$? - if [[ $ret -ne 0 ]]; then - echon "git clone failed with rc=$ret" - return $ret - fi - if [[ ! -z "$commit" ]]; then - echon "Worktree $work_tree switch to commit $commit" - git -C $work_tree checkout $commit - fi + if [[ -z "$commit" ]]; then + commit="HEAD" + fi + echon "Considering $repo_dir on commit $commit" + local commit_obj_type=$(git -C "$repo_dir" cat-file -t "$commit") + local rc=$? + if [[ $rc -ne 0 ]] || [[ "$commit_obj_type" != "commit" ]]; then + echon "Commit $commit is not a valid commit object" + return 1 + fi local repo_dir_no_git=${repo_dir%%.git} - local gitmodules="$work_tree/.gitmodules" - if [[ -f "$gitmodules" ]]; then - local paths_str=$(cat $gitmodules | grep path | cut -d '=' -f 2 | sed 's/^[[:blank:]]*//') - local urls_str=$(cat $gitmodules | grep url | cut -d '=' -f 2 | sed 's/^[[:blank:]]*//') - local -a paths - local -a urls - readarray -t paths <<<"$paths_str" - readarray -t urls <<<"$urls_str" - local -i i - for ((i=0;i<${#paths[@]};i++)); do - local path=${paths[$i]} - # ignore empty .gitmodules - if [[ "$path" == "" ]]; then + if git -C "$repo_dir" cat-file -e "$commit:.gitmodules" 2>/dev/null; then + echon "Find submodules for $repo_dir" + local -a submodules + IFS= readarray -d '' submodules < <( + git -C "$repo_dir" config --null --blob "$commit:.gitmodules" --name-only --get-regexp "^submodule\." | sed --null-data 's/\.[^.]*$//' | sort --zero-terminated --unique + ) + for submoudle in "${submodules[@]}"; do + local submodule_path=$(git -C "$repo_dir" config --blob "$commit:.gitmodules" --get "$submoudle.path") + local submodule_url=$(git -C "$repo_dir" config --blob "$commit:.gitmodules" --get "$submoudle.url") + if [[ -z "$submodule_path" ]] || [[ -z "$submodule_url" ]]; then continue fi - local commit=$(git -C $work_tree submodule status $path | cut -d ' ' -f 1 | cut -d '-' -f 2) - local git_path=$repo_dir_no_git/$path.git - mkdir -p $git_path - local mirror_url=$(echo $git_path | sed "s#$WORKING_DIR_BASE#$MIRROR_BASE_URL#") + local submodule_path_parent=$(dirname -- "$submodule_path") + if [[ "$submodule_path_parent" = "." ]]; then + submodule_path_parent="" + fi + local submodule_commit=$(git -C "$repo_dir" ls-tree -d -z --format="%(path)/%(objectname)" "$commit:$submodule_path_parent" | fgrep --null-data "$(basename -- "$submodule_path")/" | head --zero-terminated --lines 1 | cut -d '/' -f 2 | tr -d '\0' ) + if [[ -z "$submodule_commit" ]]; then + echon "Cannot find submodule commit for $submodule_path" + continue + fi + local submodule_git_path="$repo_dir_no_git/$submodule_path.git" + mkdir -p -- "$submodule_git_path" + local submodule_mirror_url=$(echo "$submodule_git_path" | sed "s#$WORKING_DIR_BASE#$MIRROR_BASE_URL#") script_append "cat >>.git/config <