Sometimes (often actually) I do: cp -Rl tree1 tree2 # new tree with implied CoW semantics cd tree2 cg-update # or similar
the latter well frob .git/HEAD or similar by doing echo foo > bar which obviously breaks the intended CoW semantics. How would people feel about something like the patch below be? (RFC purposes only, please eyeball this before blidnly applying anything. I may have missed spots or goofed, you never know). diff --git a/cg-Xlib b/cg-Xlib --- a/cg-Xlib +++ b/cg-Xlib @@ -21,6 +21,12 @@ usage() { die "usage: $USAGE" } +echo_to_file() { + TMPFILE=`mktemp "$2.tmp-XXXXXXX"` + echo "$1" > "$TMPFILE" + mv "$TMPFILE" "$2" +} + pager () { local line # Invoke pager only if there's any actual output @@ -101,7 +107,7 @@ tree_timewarp () { fi git-read-tree -m "$branch" || die "$branch: bad commit" - [ "$no_head_update" ] || echo "$branch" > $_git/HEAD + [ "$no_head_update" ] || echo_to_file "$branch" $_git/HEAD # Kill gone files git-diff-tree -z -r $base $branch | xargs -0 bash -c ' diff --git a/cg-branch-add b/cg-branch-add --- a/cg-branch-add +++ b/cg-branch-add @@ -50,4 +50,4 @@ mkdir -p $_git/branches [ -s "$_git/branches/$name" ] && die "branch already exists" [ -s "$_git/refs/heads/$name" ] && echo "warning: I already have head of this branch" >&2 -echo "$location" >$_git/branches/$name +echo_to_file "$location" $_git/branches/$name diff --git a/cg-branch-chg b/cg-branch-chg --- a/cg-branch-chg +++ b/cg-branch-chg @@ -14,4 +14,4 @@ location=$2 ([ "$name" ] && [ "$location" ]) || usage [ -s "$_git/branches/$name" ] || die "branch does not exist" -echo "$location" >$_git/branches/$name +echo_to_file "$location" $_git/branches/$name diff --git a/cg-commit b/cg-commit --- a/cg-commit +++ b/cg-commit @@ -331,7 +331,7 @@ fi if [ "$newhead" ]; then echo "Committed as $newhead." - echo $newhead >$_git/HEAD + echo_to_file $newhead $_git/HEAD [ "$merging" ] && rm $_git/merging $_git/merging-sym $_git/merge-base # Trigger the postcommit hook diff --git a/cg-init b/cg-init --- a/cg-init +++ b/cg-init @@ -44,7 +44,7 @@ mkdir $_git/branches touch $_git/refs/heads/master if [ "$uri" ]; then - echo "$uri" >$_git/branches/origin + echo_to_file "$uri" $_git/branches/origin cg-pull origin || die "pull failed" cp $_git/refs/heads/origin $_git/refs/heads/master diff --git a/cg-seek b/cg-seek --- a/cg-seek +++ b/cg-seek @@ -44,8 +44,8 @@ fi if [ "$seek_mode" = "away" ]; then rm $_git/HEAD - echo "$dstcommit" >$_git/HEAD - [ -s $_git/blocked ] || echo "seeked from $_git_head" >$_git/blocked + echo_to_file "$dstcommit" $_git/HEAD + [ -s $_git/blocked ] || echo_to_file "seeked from $_git_head" $_git/blocked else rm $_git/HEAD ln -s "refs/heads/$_git_head" $_git/HEAD diff --git a/cg-tag b/cg-tag --- a/cg-tag +++ b/cg-tag @@ -79,5 +79,5 @@ SIGEND rm -rf "$tagdir" else - echo "$id" >$_git/refs/tags/$name + echo_to_file "$id" $_git/refs/tags/$name fi diff --git a/git-branch-script b/git-branch-script --- a/git-branch-script +++ b/git-branch-script @@ -8,4 +8,4 @@ rev=$(git-rev-parse --verify --default H [ -z "$branchname" ] && die "git branch: I want a branch name" [ -e "$GIT_DIR/refs/heads/$branchname" ] && die "$branchname already exists" -echo $rev > "$GIT_DIR/refs/heads/$branchname" +echo_to_file $rev "$GIT_DIR/refs/heads/$branchname" diff --git a/git-checkout-script b/git-checkout-script --- a/git-checkout-script +++ b/git-checkout-script @@ -67,7 +67,7 @@ fi # if [ "$?" -eq 0 ]; then if [ "$newbranch" ]; then - echo $new > "$GIT_DIR/refs/heads/$newbranch" + echo_to_file $new "$GIT_DIR/refs/heads/$newbranch" branch="$newbranch" fi [ "$branch" ] && ln -sf "refs/heads/$branch" "$GIT_DIR/HEAD" diff --git a/git-commit-script b/git-commit-script --- a/git-commit-script +++ b/git-commit-script @@ -97,7 +97,7 @@ grep -v '^#' < .editmsg | git-stripspace [ -s .cmitmsg ] && tree=$(git-write-tree) && commit=$(cat .cmitmsg | git-commit-tree $tree $PARENTS) && - echo $commit > "$GIT_DIR/HEAD" && + echo_to_file $commit "$GIT_DIR/HEAD" && rm -f -- "$GIT_DIR/MERGE_HEAD" ret="$?" rm -f .cmitmsg .editmsg diff --git a/git-fetch-script b/git-fetch-script --- a/git-fetch-script +++ b/git-fetch-script @@ -30,4 +30,4 @@ rsync://*) ;; esac || exit 1 git-rev-parse --verify "$head" > /dev/null || exit 1 -echo "$head" > "$GIT_DIR/$destination" +echo_to_file "$head" "$GIT_DIR/$destination" diff --git a/git-rebase-script b/git-rebase-script --- a/git-rebase-script +++ b/git-rebase-script @@ -21,7 +21,7 @@ case "$#" in esac git-read-tree -m -u $junio $linus && -echo "$linus" >"$GIT_DIR/HEAD" || exit +echo_to_file "$linus" "$GIT_DIR/HEAD" || exit tmp=.rebase-tmp$$ fail=$tmp-fail diff --git a/git-resolve-script b/git-resolve-script --- a/git-resolve-script +++ b/git-resolve-script @@ -24,8 +24,8 @@ if [ -z "$head" -o -z "$merge" -o -z "$m fi dropheads -echo $head > "$GIT_DIR"/ORIG_HEAD -echo $merge > "$GIT_DIR"/LAST_MERGE +echo_to_file $head "$GIT_DIR"/ORIG_HEAD +echo_to_file $merge "$GIT_DIR"/LAST_MERGE common=$(git-merge-base $head $merge) if [ -z "$common" ]; then @@ -40,7 +40,7 @@ fi if [ "$common" == "$head" ]; then echo "Updating from $head to $merge." git-read-tree -u -m $head $merge || exit 1 - echo $merge > "$GIT_DIR"/HEAD + echo_to_file $merge "$GIT_DIR"/HEAD git-diff-tree -p $head $merge | git-apply --stat dropheads exit 0 @@ -52,13 +52,13 @@ if [ $? -ne 0 ]; then echo "Simple merge failed, trying Automatic merge" git-merge-cache -o git-merge-one-file-script -a if [ $? -ne 0 ]; then - echo $merge > "$GIT_DIR"/MERGE_HEAD + echo_to_file $merge "$GIT_DIR"/MERGE_HEAD die "Automatic merge failed, fix up by hand" fi result_tree=$(git-write-tree) || exit 1 fi result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree -p $head -p $merge) echo "Committed merge $result_commit" -echo $result_commit > "$GIT_DIR"/HEAD +echo_to_file $result_commit "$GIT_DIR"/HEAD git-diff-tree -p $head $result_commit | git-apply --stat dropheads - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html