# [204][S1][11] Study GIT submodule ID update issue
###### tags: `SMC` `Git` `Submodule` `Jenkins`
###### Task Description
> jenkins script was updated to very old version which does not support ARM64 SUM building.
>
> To study which situation will cause that the submodule to be updated to old version.
>
> Commit the submodule on the old branch then cherry-pick to current branch?
>
> [Max] May need to investigate user cases
>
> preventative measure:
> 1. git hook post-checkout to update submodule when switching branch: git submodule update script/jenkins
> 1. git hook pre-commit to disable commit script/jenkins with other file changes
>
> guideline: do we still need a guideline?
###### Teams msg
> [12/9 上午 11:12] Sean Zheng - TW (SW)
> 
> Please make sure your commit did not change submodule unintended, it will broke our jenkins build for latest SUM.if you are not using script/jenkins locally, please deinit it.
> like 3 人 sad 1 人
> git submodule deinit script/jenkins
## Task Start
編譯的時候 CMakeLists.txt 中會將我們的客製化 Script 搬移至 .git 中以利 git 指令執行:

#### Example:
pre-commit
```
#!/bin/bash
# Put this file at: .git/hooks/post-checkout
# and make it executable
# You can install it system wide too, see http://stackoverflow.com/a/2293578/685587
PREV_COMMIT=$1
POST_COMMIT=$2
NOCOLOR='\e[0m'
REDCOLOR='\e[37;41m'
if [[ -f composer.lock ]]; then
DIFF=`git diff --shortstat $PREV_COMMIT..$POST_COMMIT composer.lock`
if [[ $DIFF != "" ]]; then
echo -e "$REDCOLOR composer.lock has changed. You must run composer install$NOCOLOR"
fi
fi
echo -e "$REDCOLOR Hello post-checkout hooker!$NOCOLOR"
```

---
## Dealing Strings in the Hook
to get every submodule's name:
```
git config --file .gitmodules --get-regexp path | awk '{ print $2 }'
```

https://stackoverflow.com/questions/12641469/list-submodules-in-a-git-repository
---
## 重點結論與參考連結
##### What is a subproject commit?
https://stackoverflow.com/questions/21088781/what-is-a-subproject-commit
##### get submodule names:
`git config --file .gitmodules --get-regexp path | awk '{ print $2 }'`
https://stackoverflow.com/questions/12641469/list-submodules-in-a-git-repository
##### post checkout:
`git submodule update script/jenkins`
##### pre commit:
`git diff --cached mySubModule/`
https://stackoverflow.com/questions/1587846/how-do-i-show-the-changes-which-have-been-staged
#### 同時處理全部 submodules:
```
git config --file .gitmodules --get-regexp path | awk '{ print $2 }' | xargs -n1 git diff --cached
```
https://blog.gtwang.org/linux/xargs-command-examples-in-linux-unix/
#### 擷取不包含 submodules 的 git status:
`git status -s -uno --ignore-submodules`
https://git-scm.com/docs/git-status#Documentation/git-status.txt---ignore-submodulesltwhengt
#### testing code in hooks (shell):
```
cecho "TESTING HERE" $red
readonly A=$(git config --file .gitmodules --get-regexp path | awk '{ print $2 }' | xargs -n1 git diff --cached)
readonly B=$(git status -s -uno --ignore-submodules)
echo A:$A:
echo B:$B:
if [[ -z $A ]]; then
echo "-z A"
fi
if [[ -z $B ]]; then
echo "-z B"
fi
if [[ -n $A ]]; then
echo "-n A"
fi
if [[ -n $B ]]; then
echo "-n B"
fi
```
https://www.ltsplus.com/linux/shell-script-check-empty-variable
---
#### 問題與方案
1. git restore 的時候會用到 Checkout 觸發 hook: git submodule update script/jenkins --> 觸發失敗沒關係
1. 沒有 init submodule script/jenkins 時的觸發失敗 --> 觸發失敗沒關係
---
Last code:
post-checkout
```
#!/usr/bin/env bash
# SUM code re-format before commit script
# USAGE: Copy this script to .git/hooks/
readonly UTIL_SCRIPT_PATH=$(dirname "$(readlink -f "$0")")/util.sh
source "$UTIL_SCRIPT_PATH"
cecho "Testing Hook..." $yello
git config --file .gitmodules --get-regexp path | awk '{ print $2 }' | xargs -n1 git submodule update
```

pre-commit
```
#!/usr/bin/env bash
# SUM code re-format before commit script
# USAGE: Copy this script to .git/hooks/
readonly UTIL_SCRIPT_PATH=$(dirname "$(readlink -f "$0")")/util.sh
source "$UTIL_SCRIPT_PATH"
readonly branch=`git rev-parse --abbrev-ref HEAD`
if [ "$branch" == "1.6.0_production" ] || [ "$branch" == "1.6.1_sun" ] ||
[ "$branch" == "1.6.2" ] || [ "$branch" == "1.7.0" ] ||
[ "$branch" == "2.0.1_sun" ] || [ "$branch" == "hii" ] ||
[ "$branch" == "master" ]; then
exit 0 # Prevent legacy branch from clang-format
fi
readonly os=`uname`
if [ "$os" != "Linux" ]; then
exit 0 # Skip non-Linux OS
fi
# check if clang-format is installed
# check clang-format version
clang_format_version=`clang-format --version 2>&1`
if [[ ! $clang_format_version =~ "version 6.0" ]] &&
[[ ! $clang_format_version =~ "version 14" ]]; then
echo "Current clang-format version is : $clang_format_version"
cecho "SUM re-format only works with clang-format version 14" $red
exit 1
fi
clang_format_6=0
if [[ ! $clang_format_version =~ "version 14" ]]; then
echo "Current clang-format version is : $clang_format_version"
cecho "Warning: please upgrade clang-format to 14, clang-format-6.0 will be denied soon." $yellow
clang_format_6=1
fi
readonly SKIPPATH1="libBase/src/util/cryptopp"
readonly SKIPPATH2="libBase/src/util/Jsoncpp"
readonly SKIPPATH3="libBase/src/util/openssl"
readonly SKIPPATH4="libBase/src/util/gzip"
readonly SKIPPATH5="tpm_iso"
readonly SKIPPATH6="windows_driver"
readonly SKIPPATH7="cmake"
readonly SKIPPATH8="libBase/src/util/acpica"
listSkipPath="$SKIPPATH1 $SKIPPATH2 $SKIPPATH3 $SKIPPATH4 $SKIPPATH5 $SKIPPATH6 $SKIPPATH7 $SKIPPATH8"
readonly CLANGFORMAT6SKIPFILE=(
"libBase/src/exception/CException.cpp"
"libBase/src/util/Jsoncpp/src/lib_json/json_writer.cpp"
"libBase/src/util/tools/CRoTImageParser.cpp"
"libBase/src/util/xml/pugixml.cpp"
"libBiosCfg/src/bioscfg/compress/LZMA/SDK/C/LzFind.cpp"
"libBiosCfg/src/bioscfg/compress/LZMA/SDK/C/LzmaDec.cpp"
"libBiosCfg/src/bioscfg/compress/LZMA/SDK/C/LzmaEnc.cpp"
"libBiosCfg/src/bioscfg/romparser/ffsengine.cpp"
"scebioscfg/src/CSumMThreadCmd.cpp"
"scebioscfg/src/GroupApp/CSumCmdLocateServerUid.cpp"
"scebioscfg/src/GroupApp/RemoteUpdate/misc.cpp"
"scebioscfg/src/GroupCMM/CSumCmdSwitchBase.cpp"
"scebioscfg_lib/src/ipmi/CBmcTaskAdapter.cpp"
)
fileReformat=0
format_file() {
echo "format file $1"
clang-format -style=file -i -fallback-style=none $1
git add $1
fileReformat=1
}
for file in `git commit --short | grep '^M' | grep -E "\.(h|c|hpp|cpp)$" | cut -d ' ' -f 3`
do
skip_format=0
for skipPath in $listSkipPath
do
if [[ ${file} =~ $skipPath ]]; then
skip_format=1
break
fi
done
if [ "$skip_format" -eq "1" ]; then
continue
fi
if [ "$clang_format_6" -eq "1" ]; then
if [[ "${CLANGFORMAT6SKIPFILE[*]}" =~ "${file}" ]]; then
cecho "format file ${file} SKIP for clang-format-6.0, file NOT formated." $yellow
continue
fi
fi
format_file "${file}"
done
if [ "$fileReformat" -eq "1" ]; then
# Allows us to read user input below, assigns stdin to keyboard
exec < /dev/tty
cecho " clang-format re-format your commit files." $yellow
cecho " Please make sure there is not compile error before pushing it." $yellow
while true; do
read -p "Press Enter to continue " Enter_key
if [ "$Enter_key" = "" ]; then
break;
fi
done
fi
# check if submodule is modified and cached
# bolcked if the major project is also modified
readonly submoduleDiffs=$(git config --file .gitmodules --get-regexp path | awk '{ print $2 }' | xargs -n1 git diff --cached)
readonly submoduleIgnoredStatus=$(git status -s -uno --ignore-submodules)
cecho "Testing Hook..." $red
if [[ -n $submoduleDiffs ]]; then
echo "$submoduleDiffs"
if [[ -n submoduleIgnoredStatus ]]; then
echo "$submoduleIgnoredStatus"
cecho "Error: please make sure your commit did not change submodule unintended. Please deinit it if you are not using the submodule locally." $red
exit 1
fi
fi
exit 1
```
