subgit

Simple git-submodule alternative with versioning and multiple remotes
git clone https://git.sinitax.com/sinitax/subgit
Log | Files | Refs | sfeed.txt

commit 3394c5fa78844f646ce036858ccafb6cb2e1ebe8
parent f62f4dbd6dabaf7e889714f60d48ea3fa8696e47
Author: Louis Burda <quent.burda@gmail.com>
Date:   Fri, 10 May 2024 01:54:45 +0200

Separate out subgit-update and source commands

Diffstat:
MMakefile | 2+-
Msubgit | 20++++++++++++++++++--
Msubgit-clone | 25+++++++++----------------
Msubgit-init | 53+++++++++++++++++++----------------------------------
Msubgit-run | 15++-------------
Asubgit-update | 17+++++++++++++++++
Msubgit-write | 38++++++++++++++++----------------------
7 files changed, 82 insertions(+), 88 deletions(-)

diff --git a/Makefile b/Makefile @@ -2,7 +2,7 @@ DESTDIR ?= PREFIX ?= /usr/local BINDIR ?= /bin -BINS = subgit subgit-run subgit-init subgit-write subgit-clone +BINS = subgit subgit-run subgit-init subgit-update subgit-write subgit-clone all: diff --git a/subgit b/subgit @@ -1,13 +1,23 @@ -#!/bin/sh +#!/bin/bash set -e +if [ "$1" = "-d" ]; then + set -x + shift +fi + if [ "$1" = "-C" ]; then cd "$2" shift shift fi +die() { + echo "$@" 2>&1 + exit 1 +} + cmd="$1" shift @@ -15,4 +25,10 @@ if [ "$cmd" = "--" ]; then cmd="run" fi -exec "subgit-$cmd" "$@" +if [ -z "$(which "subgit-$cmd" 2>/dev/null)" ]; then + echo "Unknown command $cmd" 1>&2 + exit 1 +fi + +trap 'echo "Error at during $cmd"' ERR +( source "subgit-$cmd" "$@"; ) diff --git a/subgit-clone b/subgit-clone @@ -1,13 +1,6 @@ #!/bin/bash -set -xe - -die() { - echo "$@" 2>&1 - exit 1 -} - -[ $# -lt 2 ] && die "Usage: subgit-clone OPT.. REMOTE PATH" +[ $# -lt 2 ] && die "Usage: subgit clone [GIT-OPT..] REMOTE PATH" repo=$(realpath "$(git rev-parse --show-toplevel)") subrepo=$(realpath "${@: -1}") @@ -23,19 +16,19 @@ fi [ -e "$repo/$subrepo" ] && die "Subrepo $subrepo already exists" -#trap '[ ! -z "$repo" -a ! -z "$subrepo" ] && rm -rf "$repo/$subrepo"' exit -trap 'echo "$repo/$subrepo"' exit +trap '[ ! -z "$repo" -a ! -z "$subrepo" ] && rm -rf "$repo/$subrepo"' exit git clone "$@" + [ ! -e "$repo/$subrepo" ] && die "Subrepo $subrepo missing" +mkdir -p $(dirname "$repo/.subgit/$subrepo") +mv "$repo/$subrepo/.git" "$repo/.subgit/$subrepo" + subgit[$subrepo]=1 -subgitinfo[$subrepo/remote]=$(git -C "$repo/$subrepo" remote get-url origin) -subgitinfo[$subrepo/branch]=$(git -C "$repo/$subrepo" branch --show-current) -subgitinfo[$subrepo/commit]=$(git -C "$repo/$subrepo" rev-parse --verify HEAD) +subgitinfo[$subrepo/remote]=$(git -C "$repo/.subgit/$subrepo" remote get-url origin) +subgitinfo[$subrepo/branch]=$(git -C "$repo/.subgit/$subrepo" branch --show-current) +subgitinfo[$subrepo/commit]=$(git -C "$repo/.subgit/$subrepo" rev-parse --verify HEAD) source subgit-write -mkdir -p $(dirname "$repo/.subgit/$subrepo") -mv "$repo/$subrepo/.git" "$repo/.subgit/$subrepo" - trap - exit diff --git a/subgit-init b/subgit-init @@ -1,50 +1,35 @@ #!/bin/bash -set -xe +if [ "$1" = "-r" ]; then + recursive=-r + shift +fi -die() { - echo "$@" 2>&1 - exit 1 -} - -recursive=0 -update=0 -while [ $# -ge 1 ]; do - if [ "$1" = "-r" ]; then - recursive=1 - shift - elif [ "$1" = "-u" ]; then - update=1 - shift - else - die "Unknown opt: $1" - fi -done - -[ $# -ne 0 ] && die "Usage: subgit-init" +[ $# -ne 0 ] && die "Usage: subgit init" repo=$(realpath "$(git rev-parse --show-toplevel)") source "$repo/.subgitrc" for subrepo in ${!subgit[@]}; do path="$repo/.subgit/$subrepo" + [ -d "$repo/$subrepo" ] || mkdir -p "$repo/$subrepo" if [ ! -d "$path" ]; then mkdir -p "$(dirname "$path")" - git clone --bare --single-branch -b "${subgitinfo[$subrepo/branch]}" \ + branch_args=() + if [ ! -z "${subgitinfo[$subrepo/branch]}" ]; then + branch_args+=(--single-branch -b "${subgitinfo[$subrepo/branch]}") + fi + git clone --bare "${branch_args[@]}" \ "${subgitinfo[$subrepo/remote]}" "$path" git -C "$path" config --local --bool core.bare false + subgit -C "$repo/$subrepo" -- git reset --hard "${subgitinfo[$subrepo/commit]}" + elif [ ! -z "${subgitinfo[$subrepo/branch]}" ]; then + subgit -C "$repo/$subrepo" -- git checkout "${subgitinfo[$subrepo/branch]}" + subgit -C "$repo/$subrepo" -- git reset "${subgitinfo[$subrepo/commit]}" + else + subgit -C "$repo/$subrepo" -- git checkout "${subgitinfo[$subrepo/commit]}" fi - [ -d "$repo/$subrepo" ] || mkdir -p "$repo/$subrepo" - subgit -C "$repo/$subrepo" -- git checkout "${subgitinfo[$subrepo/branch]}" - if [ $update -ne 0 ]; then - subgitinfo[$subrepo/remote]=$(git -C "$path" remote get-url origin) - subgitinfo[$subrepo/branch]=$(git -C "$path" branch --show-current) - subgitinfo[$subrepo/commit]=$(git -C "$path" rev-parse --verify HEAD) - fi - subgit -C "$repo/$subrepo" -- git reset "${subgitinfo[$subrepo/commit]}" - if [ $recursive -ne 0 -a -e "$repo/$subrepo/.subgitrc" ]; then - subgit -C "$repo/$subrepo" -- subgit-init + if [ ! -z "$recursive" -a -e "$repo/$subrepo/.subgitrc" ]; then + subgit -C "$repo/$subrepo" -- subgit init "$recursive" fi done - -source subgit-write diff --git a/subgit-run b/subgit-run @@ -1,17 +1,6 @@ -#!/bin/sh +#!/bin/bash -set -e - -die() { - echo "$@" 1>&2 - exit 1 -} - -if [ "$1" = "-C" ]; then - cd "$2" - shift - shift -fi +[ $# -eq 0 ] && die "Usage: subgit run CMD [ARG..]" repo=$(realpath "$(git rev-parse --show-toplevel)") [ "${PWD#$repo/}" != "$PWD" ] || die "Bad path $repo > $PWD" diff --git a/subgit-update b/subgit-update @@ -0,0 +1,17 @@ +#!/bin/bash + +[ $# -ne 0 ] && die "Usage: subgit update" + +repo=$(realpath "$(git rev-parse --show-toplevel)") +source "$repo/.subgitrc" + +for subrepo in ${!subgit[@]}; do + if [ ! -d "$repo/.subgit/$subrepo" -o ! -d "$repo/$subrepo" ]; then + die "Subrepo $subrepo uninitialized" + fi + subgitinfo[$subrepo/remote]=$(git -C "$repo/.subgit/$subrepo" remote get-url origin) + subgitinfo[$subrepo/branch]=$(git -C "$repo/.subgit/$subrepo" branch --show-current) + subgitinfo[$subrepo/commit]=$(git -C "$repo/.subgit/$subrepo" rev-parse --verify HEAD) +done + +source subgit-write diff --git a/subgit-write b/subgit-write @@ -1,28 +1,22 @@ #!/bin/bash -subgit-write-inner() { - set -e +[ $# -ne 0 ] && die "Usage: subgit init" - repo=$(realpath "$(git rev-parse --show-toplevel)") +repo=$(realpath "$(git rev-parse --show-toplevel)") - echo -e "#!/bin/bash\n" > "$repo/.subgitrc" - echo -e "declare -A subgit subgitinfo\n" >> "$repo/.subgitrc" +echo -e "#!/bin/bash\n" > "$repo/.subgitrc" +echo -e "declare -A subgit subgitinfo\n" >> "$repo/.subgitrc" - for subrepo in ${!subgit[@]}; do - echo "subgit[$subrepo]=1" - echo "subgitinfo[$subrepo/remote]='${subgitinfo[$subrepo/remote]}'" - echo "subgitinfo[$subrepo/branch]='${subgitinfo[$subrepo/branch]}'" - echo "subgitinfo[$subrepo/commit]='${subgitinfo[$subrepo/commit]}'" - echo "" - done >> "$repo/.subgitrc" +for subrepo in ${!subgit[@]}; do + echo "subgit[$subrepo]=1" + echo "subgitinfo[$subrepo/remote]='${subgitinfo[$subrepo/remote]}'" + echo "subgitinfo[$subrepo/branch]='${subgitinfo[$subrepo/branch]}'" + echo "subgitinfo[$subrepo/commit]='${subgitinfo[$subrepo/commit]}'" + echo "" +done >> "$repo/.subgitrc" - if [ ! -e "$repo/.gitignore" ]; then - echo "/.gitignore" > "$repo/.gitignore" - fi - cat "$repo/.gitignore" | grep -q "^/.subgit$" \ - || echo "/.subgit" >> "$repo/.gitignore" -} - -( subgit-write-inner "$@"; ) - -unset subgit-write-inner +if [ ! -e "$repo/.gitignore" ]; then + echo "/.gitignore" > "$repo/.gitignore" +fi +cat "$repo/.gitignore" | grep -q "^/.subgit$" \ + || echo "/.subgit" >> "$repo/.gitignore"