#!/bin/bash set -e shopt -s nullglob PROGRAM="$0" MODULES=(tock libtock-rs) success() { echo -e "\r\e[1;32mDone:\e[m $1" exit 0 } fail() { echo -e "\r\e[1;31mError:\e[m $1" exit 1 } commit() { local message="$1" git add . git commit -qm"${message}" } get_root() { local module="$1" git ls-tree HEAD:third_party | sed -En 's/^.* ([^ ]+)\t'"${module}"'$/\1/p' } get_head() { git rev-parse HEAD } help() { local root="$(get_root)" cat < edit 3. For each edited submodule, create a fix commit per affected patch by repeating the following commands until there are no more files to add: git add -p git commit -m'fix ' 4. For each edited submodule, merge the fixes into their patches by moving their line below their patch and changing their "edit" into "fixup": git rebase -i ${root} 5. Save the changes: cd ../.. ${PROGRAM} save 6. Either continue repeating steps 2 to 5, or return to the normal state: ${PROGRAM} restore EOF exit 0 } apply_module() { local root="$1" module="$2" file git checkout -q "${root}" if [[ "${module}" == tock ]]; then cp -a ../../boards . commit '00-boards' fi for file in ../../patches/"${module}"/*; do git apply "${file}" commit "$(basename "${file}" .patch)" echo -n . done } apply() { for module in "${MODULES[@]}"; do local root="$(get_root "${module}")" ( set -e cd third_party/"${module}" git reset -q --hard git clean -qfxd apply_module "${root}" "${module}" ) done } save() { for module in "${MODULES[@]}"; do local root="$(get_root "${module}")" ( set -e cd third_party/"${module}" [[ -z "$(git status -s)" ]] \ || fail "The ${module} submodule is not clean." rm -rf ../../patches/"${module}" mkdir ../../patches/"${module}" for file in $(git format-patch "${root}"); do sed -n '/^diff/,$p' "${file}" \ | sed '/^-- $/,$d' > "../../patches/${module}/${file#*-}" done git clean -qfxd local top="$(get_head)" git checkout -q "${root}" if [[ "${module}" == tock ]]; then rm -r boards git apply --whitespace=nowarn ../../patches/"${module}"/00-boards.patch rm ../../patches/tock/00-boards.patch rm -r ../../boards cp -a boards ../.. fi git reset -q --hard git clean -qfxd git checkout -q "${top}" ) done } check() { # Overwrite the commit function to do nothing. commit() { true; } for module in "${MODULES[@]}"; do local root="$(get_root "${module}")" ( set -e cd third_party/"${module}" git commit --allow-empty -qmi git add . git commit --allow-empty -qmx local top="$(get_head)" apply_module "${root}" "${module}" git add . git commit --allow-empty -qmy # We need to cleanup (and not exit) regardless of a diff. local r; if git diff "${top}" --quiet; then r=0; else r=1; fi git checkout -q "${top}" git reset -q HEAD~ git reset -q --soft HEAD~ [[ "${r}" -eq 0 ]] \ || fail "The ${module} submodule differs from its patches." ) done } grep -q third_party/tock .gitmodules 2>/dev/null \ || fail 'Not running from OpenSK directory.' [[ $# -eq 1 ]] || help case $1 in apply) apply success 'Applied the patches to the submodules.' ;; save) save success 'Saved the submodules to the patches.' ;; restore) # Overwrite the commit function to do nothing. commit() { true; } apply success 'Restored the submodules.' ;; check) check success 'The submodules and patches are in sync.' ;; *) fail 'Unexpected argument. Run without argument for help.' ;; esac