update a few Porcelain-ish for ref lock safety.
authorJunio C Hamano <junkio@cox.net>
Wed, 27 Sep 2006 09:06:31 +0000 (02:06 -0700)
committerJunio C Hamano <junkio@cox.net>
Wed, 27 Sep 2006 09:06:31 +0000 (02:06 -0700)
This updates the use of git-update-ref in git-branch, git-tag
and git-commit to make them safer in a few corner cases as
demonstration.

 - git-tag makes sure that the named tag does not exist, allows
   you to edit tag message and then creates the tag.  If a tag
   with the same name was created by somebody else in the
   meantime, it used to happily overwrote it.  Now it notices
   the situation.

 - git-branch -d and git-commit (for the initial commit) had the
   same issue but with smaller race window, which is plugged
   with this.

Signed-off-by: Junio C Hamano <junkio@cox.net>
git-branch.sh
git-commit.sh
git-tag.sh

index 2600e9c..4379a07 100755 (executable)
@@ -42,8 +42,7 @@ If you are sure you want to delete it, run 'git branch -D $branch_name'."
            esac
            ;;
        esac
-       rm -f "$GIT_DIR/logs/refs/heads/$branch_name"
-       rm -f "$GIT_DIR/refs/heads/$branch_name"
+       git update-ref -d "refs/heads/$branch_name" "$branch"
        echo "Deleted branch $branch_name."
     done
     exit 0
@@ -112,6 +111,7 @@ rev=$(git-rev-parse --verify "$head") || exit
 git-check-ref-format "heads/$branchname" ||
        die "we do not like '$branchname' as a branch name."
 
+prev=''
 if git-show-ref --verify --quiet -- "refs/heads/$branchname"
 then
        if test '' = "$force"
@@ -121,10 +121,11 @@ then
        then
                die "cannot force-update the current branch."
        fi
+       prev=`git rev-parse --verify "refs/heads/$branchname"`
 fi
 if test "$create_log" = 'yes'
 then
        mkdir -p $(dirname "$GIT_DIR/logs/refs/heads/$branchname")
        touch "$GIT_DIR/logs/refs/heads/$branchname"
 fi
-git update-ref -m "branch: Created from $head" "refs/heads/$branchname" $rev
+git update-ref -m "branch: Created from $head" "refs/heads/$branchname" "$rev" "$prev"
index 5a4c659..ee5a165 100755 (executable)
@@ -547,15 +547,15 @@ then
                PARENTS=$(git-cat-file commit HEAD |
                        sed -n -e '/^$/q' -e 's/^parent /-p /p')
        fi
-       current=$(git-rev-parse --verify HEAD)
+       current="$(git-rev-parse --verify HEAD)"
 else
        if [ -z "$(git-ls-files)" ]; then
                echo >&2 Nothing to commit
                exit 1
        fi
        PARENTS=""
-       current=
        rloga='commit (initial)'
+       current=''
 fi
 
 if test -z "$no_edit"
@@ -631,7 +631,7 @@ then
        fi &&
        commit=$(cat "$GIT_DIR"/COMMIT_MSG | git-commit-tree $tree $PARENTS) &&
        rlogm=$(sed -e 1q "$GIT_DIR"/COMMIT_MSG) &&
-       git-update-ref -m "$rloga: $rlogm" HEAD $commit $current &&
+       git-update-ref -m "$rloga: $rlogm" HEAD $commit "$current" &&
        rm -f -- "$GIT_DIR/MERGE_HEAD" &&
        if test -f "$NEXT_INDEX"
        then
index a0afa25..2bde3c0 100755 (executable)
@@ -63,8 +63,11 @@ done
 
 name="$1"
 [ "$name" ] || usage
-if [ -e "$GIT_DIR/refs/tags/$name" -a -z "$force" ]; then
-    die "tag '$name' already exists"
+prev=0000000000000000000000000000000000000000
+if test -e "$GIT_DIR/refs/tags/$name"
+then
+    test -n "$force" || die "tag '$name' already exists"
+    prev=`git rev-parse "refs/tags/$name"`
 fi
 shift
 git-check-ref-format "tags/$name" ||
@@ -109,4 +112,4 @@ fi
 
 leading=`expr "refs/tags/$name" : '\(.*\)/'` &&
 mkdir -p "$GIT_DIR/$leading" &&
-echo $object > "$GIT_DIR/refs/tags/$name"
+GIT_DIR="$GIT_DIR" git update-ref "refs/tags/$name" "$object" "$prev"