#!/bin/sh set -e fail () { echo >&2 "$0: $*"; exit 1; } case "$#.$1" in 2.edit|2.done) mode="$1"; arg="$2" ;; 3.gitfetchinfo) mode="$1"; arg="$2"; remote="$3" ;; ?.-*) fail "no options understood" ;; *) fail "usage: tartree-edit edit|done DIRECTORY|TARBALL tartree-edit gitfetchinfo DIRECTORY|TARBALL REMOTE" ;; esac case "$arg" in *.tar) base=${arg%.tar} ;; *.edit) base=${arg%.edit} ;; *) base=${arg} ;; esac tryat_pre () { local b="$1" rm -rf "$b.tmp" if test -f "$b.tar" && test -f "$b.edit"; then echo "$b.edit exists, deleting possibly-obsolete $b.tar" rm "$b.tar" fi } tryat_edit () { local b="$1" if test -d "$b.edit"; then echo "$b.edit already exists" exit 0 fi if test -f "$b.tar"; then mkdir "$b.tmp" (set -e; cd "$b.tmp"; tar xf "$b.tar") mv "$b.tmp" "$b.edit" rm "$b.tar" echo "$b.edit ready" exit 0 fi } gitfetchinfo_perhaps_commit () { local m="$1" set +e git diff --cached --quiet --exit-code HEAD local rc=$? set -e case "$rc" in 0) return ;; 1) git commit --allow-empty --author='tartree-edit <>' -m "$m" ;; *) fail "git diff failed ($rc)" ;; esac } tryat_gitfetchinfo () { local wd=$(pwd) case "$wd" in *.edit) fail "bad idea to run gitfetchinfo into a .edit tree!" ;; esac local play=.git/tartree-edit-work rm -rf $play mkdir $play if test -d "$b.edit"; then cp -a "$b.edit"/. "$play"/. else exec 3<"$b.tar" tar -C $play -f - <&3 -x exec 3<&- fi local innerwd=$play/* git remote remove "$remote" 2>/dev/null ||: git remote add "$remote" $innerwd git fetch --no-tags -p "$remote" \ +"HEAD:refs/remotes/$remote/HEAD" cd $innerwd git checkout -b WORKTREE gitfetchinfo_perhaps_commit INDEX git add -Af . gitfetchinfo_perhaps_commit WORKTREE cd ../../.. git fetch --no-tags "$remote" --refmap \ +"refs/*:refs/remotes/$remote/*" \ +"refs/*:refs/remotes/$remote/*" exit 0 } tryat_done () { local b="$1" if test -d "$b.edit"; then (set -e; cd "$b.edit"; tar cf "$b.tmp" *) mv "$b.tmp" "$b.tar" mv "$b.edit" "$b.tmp" rm -rf "$b.tmp" echo "$b.tar regenerated" exit 0 fi if test -f "$b.tar"; then echo "$b.tar already exists and $b.edit doesn't" exit 0 fi } tryat () { local b="$1" if ! test -f "$b.tar" && ! test -d "$b.edit"; then return fi tryat_pre "$b" tryat_$mode "$b" fail "unexpected situation in $b.*" } case "$arg" in /*) tryat "$base" ;; *) pwd=`pwd` tryat "$pwd/$base" tryat "$pwd/git-srcs/$base" tryat "$pwd/tests/git-srcs/$base" fail "could not find $base..." ;; esac