关于git:使用Bash将.gitmodules转换为可解析的格式以进行迭代

Convert .gitmodules into a parsable format for iteration using Bash

背景

我想做一个shell函数,它接受.gitmodules并根据每个子模块的属性(例如对每个模块执行某些命令进行迭代。

??.gitmodules的默认格式:

1
2
3
4
5
6
7
[submodule"PATH"]
    path = <PATH>
    url = <URL>
[submodule"PATH"]
    path = <PATH>
    url = <URL>
    branch = <BRANCH>

?Pseudocode:

1
2
3
4
5
6
7
8
9
10
11
def install_modules() {
    modules = new list

    fill each index of the modules list with each submodule & its properties

    iteratate over modules
       if module @ 'path' contains a specified 'branch':
          git submodule add -b 'branch' 'url' 'path'
       else:
          git submodule add 'url' 'path'
}

??当前install_modules()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# currently works for grabbing the first line of the file
# doesn't work for each line after.
install_modules() {
    declare -A regex

    regex["module"]='\[submodule"(.*)"\]'
    regex["url"]='url ="(.*)"'
    regex["branch"]='branch ="(.*)"'

    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    cat <".gitmodules" | while read -r LINE; do
        if [[ $LINE =~ ${regex[module]} ]]; then
            PATH=${BASH_REMATCH[1]}

            echo"$PATH"
        fi
    done
}


.gitmodules是一个.gitconfig类文件,因此您可以使用git config来读取它。例如,读取.gitmodules中的所有值,按=拆分值(key=value),按.拆分键:

1
git config -f .gitmodules -l | awk '{split($0, a, /=/); split(a[1], b, /\./); print b[1], b[2], b[3], a[2]}'

git config -f .gitmodules -l打印的

1
2
submodule.native/inotify_simple.path=native/inotify_simple
submodule.native/inotify_simple.url=https://github.com/chrisjbillington/inotify_simple

awk的输出将是

1
2
submodule native/inotify_simple path native/inotify_simple
submodule native/inotify_simple url https://github.com/chrisjbillington/inotify_simple


在@phd的一点帮助下,并从.gitmodules中恢复git子模块(这是@phd向我指出的),我能够构建我需要的功能。

install_submodules()

??注:假设$REPO_PATH已声明并初始化。

?我的答案是改编自https://stackoverflow.com/a/53269641/5290011。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
install_submodules() {
    git -C"${REPO_PATH}" config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
        while read -r KEY MODULE_PATH
        do
            # If the module's path exists, remove it.
            # This is done b/c the module's path is currently
            # not a valid git repo and adding the submodule will cause an error.
            [ -d"${MODULE_PATH}" ] && sudo rm -rf"${MODULE_PATH}"

            NAME="$(echo"${KEY}" | sed 's/\submodule\.\(.*\)\.path$/\1/')"

            url_key="$(echo"${KEY}" | sed 's/\.path$/.url/')"
            branch_key="$(echo"${KEY}" | sed 's/\.path$/.branch/')"

            URL="$(git config -f .gitmodules --get"${url_key}")"
            BRANCH="$(git config -f .gitmodules --get"${branch_key}" || echo"master")"

            git -C"${REPO_PATH}" submodule add --force -b"${BRANCH}" --name"${NAME}""${URL}""${MODULE_PATH}" || continue
        done

    git -C"${REPO_PATH}" submodule update --init --recursive
}