[PATCH] Use git-update-ref in scripts.

Subsystems: the rest

DORMANTno replies

6 messages, 2 authors, 2016-06-15 · open the first message on its own page

[PATCH] Use git-update-ref in scripts.

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:42:07

This uses the git-update-ref command in scripts for safer updates.
Also places where we used to read HEAD ref by using "cat" were fixed
to use git-rev-parse.  This will matter when we start using symbolic
references.

Signed-off-by: Junio C Hamano <redacted>

---

 * Requesting extra sets of eyeballs from the list for stupid
   mistakes.

 git-applypatch.sh |    5 +++--
 git-commit.sh     |    4 +++-
 git-fetch.sh      |   34 ++++++++++++++++++----------------
 git-merge.sh      |    9 +++++----
 git-octopus.sh    |    2 +-
 git-pull.sh       |    6 +++---
 git-rebase.sh     |    5 +++--
 git-reset.sh      |    2 +-
 git-resolve.sh    |    4 ++--
 9 files changed, 39 insertions(+), 32 deletions(-)

7bae83d5754a1afb8e64f9de17f1dc34d0022f0a
diff --git a/git-applypatch.sh b/git-applypatch.sh
--- a/git-applypatch.sh
+++ b/git-applypatch.sh
@@ -108,9 +108,10 @@ fi
 
 tree=$(git-write-tree) || exit 1
 echo Wrote tree $tree
-commit=$(git-commit-tree $tree -p $(cat "$GIT_DIR"/HEAD) < "$final") || exit 1
+parent=$(git-rev-parse --verify HEAD) &&
+commit=$(git-commit-tree $tree -p $parent <"$final") || exit 1
 echo Committed: $commit
-echo $commit > "$GIT_DIR"/HEAD
+git-update-ref HEAD $commit $parent || exit
 
 if test -x "$GIT_DIR"/hooks/post-applypatch
 then
diff --git a/git-commit.sh b/git-commit.sh
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -159,7 +159,9 @@ if [ ! -r "$GIT_DIR/HEAD" ]; then
 		exit 1
 	fi
 	PARENTS=""
+	current=
 else
+	current=$(git-rev-parse --verify HEAD)
 	if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
 		PARENTS="-p HEAD "`sed -e 's/^/-p /' "$GIT_DIR/MERGE_HEAD"`
 	fi
@@ -220,7 +222,7 @@ if test -s .cmitchk
 then
 	tree=$(git-write-tree) &&
 	commit=$(cat .cmitmsg | git-commit-tree $tree $PARENTS) &&
-	echo $commit > "$GIT_DIR/HEAD" &&
+	git-update-ref HEAD $commit $current &&
 	rm -f -- "$GIT_DIR/MERGE_HEAD"
 else
 	echo >&2 "* no commit message?  aborting commit."
diff --git a/git-fetch.sh b/git-fetch.sh
--- a/git-fetch.sh
+++ b/git-fetch.sh
@@ -105,14 +105,16 @@ fast_forward_local () {
 	else
 		echo >&2 "* $1: storing $3"
 	fi
-	echo "$2" >"$GIT_DIR/$1" ;;
+	git-update-ref "$1" "$2" 
+	;;
 
     refs/heads/*)
-	# NEEDSWORK: use the same cmpxchg protocol here.
-	echo "$2" >"$GIT_DIR/$1.lock"
-	if test -f "$GIT_DIR/$1"
+	# $1 is the ref being updated.
+	# $2 is the new value for the ref.
+	local=$(git-rev-parse --verify "$1^0" 2>/dev/null)
+	if test "$local"
 	then
-	    local=$(git-rev-parse --verify "$1^0") &&
+	    # Require fast-forward.
 	    mb=$(git-merge-base "$local" "$2") &&
 	    case "$2,$mb" in
 	    $local,*)
@@ -120,34 +122,34 @@ fast_forward_local () {
 		;;
 	    *,$local)
 		echo >&2 "* $1: fast forward to $3"
+		git-update-ref "$1" "$2" "$local"
 		;;
 	    *)
 		false
 		;;
 	    esac || {
 		echo >&2 "* $1: does not fast forward to $3;"
-		case "$force,$single_force" in
-		t,* | *,t)
+		case ",$force,$single_force," in
+		*,t,*)
 			echo >&2 "  forcing update."
+			git-update-ref "$1" "$2" "$local"
 			;;
 		*)
-			mv "$GIT_DIR/$1.lock" "$GIT_DIR/$1.remote"
-			echo >&2 "  leaving it in '$1.remote'"
+			echo >&2 "  not updating."
 			;;
 		esac
 	    }
 	else
-		echo >&2 "* $1: storing $3"
+	    echo >&2 "* $1: storing $3"
+	    git-update-ref "$1" "$2"
 	fi
-	test -f "$GIT_DIR/$1.lock" &&
-	    mv "$GIT_DIR/$1.lock" "$GIT_DIR/$1"
 	;;
     esac
 }
 
 case "$update_head_ok" in
 '')
-	orig_head=$(cat "$GIT_DIR/HEAD" 2>/dev/null)
+	orig_head=$(git-rev-parse --verify HEAD 2>/dev/null)
 	;;
 esac
 
@@ -184,7 +186,7 @@ do
     rsync://*)
 	TMP_HEAD="$GIT_DIR/TMP_HEAD"
 	rsync -L -q "$remote/$remote_name" "$TMP_HEAD" || exit 1
-	head=$(git-rev-parse TMP_HEAD)
+	head=$(git-rev-parse --verify TMP_HEAD)
 	rm -f "$TMP_HEAD"
 	test "$rsync_slurped_objects" || {
 	    rsync -av --ignore-existing --exclude info \
@@ -261,10 +263,10 @@ case ",$update_head_ok,$orig_head," in
 *,, | t,* )
 	;;
 *)
-	curr_head=$(cat "$GIT_DIR/HEAD" 2>/dev/null)
+	curr_head=$(git-rev-parse --verify HEAD 2>/dev/null)
 	if test "$curr_head" != "$orig_head"
 	then
-		echo "$orig_head" >$GIT_DIR/HEAD
+	    	git-update-ref HEAD "$orig_head"
 		die "Cannot fetch into the current branch."
 	fi
 	;;
diff --git a/git-merge.sh b/git-merge.sh
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -114,8 +114,9 @@ case "$#,$common" in
 	# Again the most common case of merging one remote.
 	echo "Updating from $head to $1."
 	git-update-index --refresh 2>/dev/null
-	git-read-tree -u -m $head "$1" || exit 1
-	git-rev-parse --verify "$1^0" > "$GIT_DIR/HEAD"
+	git-read-tree -u -m $head "$1" &&
+	new_head=$(git-rev-parse --verify "$1^0") &&
+	git-update-ref HEAD "$new_head" "$head" || exit 1
 	summary "$1"
 	dropsave
 	exit 0
@@ -218,9 +219,9 @@ then
     do
         parents="$parents -p $remote"
     done
-    result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree $parents)
+    result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree $parents) || exit
     echo "Committed merge $result_commit, made by $wt_strategy."
-    echo $result_commit >"$GIT_DIR/HEAD"
+    git-update-ref HEAD $result_commit $head
     summary $result_commit
     dropsave
     exit 0
diff --git a/git-octopus.sh b/git-octopus.sh
--- a/git-octopus.sh
+++ b/git-octopus.sh
@@ -86,5 +86,5 @@ esac
 result_commit=$(git-fmt-merge-msg <"$GIT_DIR/FETCH_HEAD" |
 		git-commit-tree $MRT $PARENT)
 echo "Committed merge $result_commit"
-echo $result_commit >"$GIT_DIR"/HEAD
+git-update-ref HEAD $result_commit $head
 git-diff-tree -p $head $result_commit | git-apply --stat
diff --git a/git-pull.sh b/git-pull.sh
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -6,10 +6,10 @@
 
 . git-sh-setup || die "Not a git archive"
 
-orig_head=$(cat "$GIT_DIR/HEAD") || die "Pulling into a black hole?"
+orig_head=$(git-rev-parse --verify HEAD) || die "Pulling into a black hole?"
 git-fetch --update-head-ok "$@" || exit 1
 
-curr_head=$(cat "$GIT_DIR/HEAD")
+curr_head=$(git-rev-parse --verify HEAD)
 if test "$curr_head" != "$orig_head"
 then
 	# The fetch involved updating the current branch.
@@ -38,4 +38,4 @@ case "$merge_head" in
 esac
 
 merge_name=$(git-fmt-merge-msg <"$GIT_DIR/FETCH_HEAD")
-git-resolve "$(cat "$GIT_DIR"/HEAD)" $merge_head "$merge_name"
+git-resolve "$curr_head" $merge_head "$merge_name"
diff --git a/git-rebase.sh b/git-rebase.sh
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -33,7 +33,8 @@ test "$different1$different2" = "" ||
 die "Your working tree does not match $ours_symbolic."
 
 git-read-tree -m -u $ours $upstream &&
-git-rev-parse --verify "$upstream^0" >"$GIT_DIR/HEAD" || exit
+new_head=$(git-rev-parse --verify "$upstream^0") &&
+git-update-ref HEAD "$new_head" || exit
 
 tmp=.rebase-tmp$$
 fail=$tmp-fail
@@ -50,7 +51,7 @@ do
 		continue ;;
 	esac
 	echo >&2 "* Applying: $msg"
-	S=`cat "$GIT_DIR/HEAD"` &&
+	S=$(git-rev-parse --verify HEAD) &&
 	git-cherry-pick --replay $commit || {
 		echo >&2 "* Not applying the patch and continuing."
 		echo $commit >>$fail
diff --git a/git-reset.sh b/git-reset.sh
--- a/git-reset.sh
+++ b/git-reset.sh
@@ -60,7 +60,7 @@ then
 else
 	rm -f "$GIT_DIR/ORIG_HEAD"
 fi
-echo "$rev" >"$GIT_DIR/HEAD"
+git-update-ref HEAD "$rev"
 
 case "$reset_type" in
 --hard )
diff --git a/git-resolve.sh b/git-resolve.sh
--- a/git-resolve.sh
+++ b/git-resolve.sh
@@ -45,7 +45,7 @@ case "$common" in
 "$head")
 	echo "Updating from $head to $merge."
 	git-read-tree -u -m $head $merge || exit 1
-	echo $merge > "$GIT_DIR"/HEAD
+	git-update-ref HEAD "$merge"
 	git-diff-tree -p $head $merge | git-apply --stat
 	dropheads
 	exit 0
@@ -99,6 +99,6 @@ if [ $? -ne 0 ]; then
 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
+git-update-ref HEAD "$result_commit"
 git-diff-tree -p $head $result_commit | git-apply --stat
 dropheads

Re: [PATCH] Use git-update-ref in scripts.

From: Linus Torvalds <torvalds@osdl.org>
Date: 2016-06-15 22:42:07


On Tue, 27 Sep 2005, Junio C Hamano wrote:
This uses the git-update-ref command in scripts for safer updates.
Looks good.

git-resolve might want to verify the old head. On the other hand, it looks 
like it's being phased out, so maybe nobody cares?

		Linus

Re: [PATCH] Use git-update-ref in scripts.

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:42:07

Linus Torvalds [off-list ref] writes:
git-resolve might want to verify the old head. On the other hand, it looks 
like it's being phased out, so maybe nobody cares?
It was my mistake -- git-merge does it, and I should do the
same in git-resolve.  Thanks for pointing it out.

Have you had a chance to look at the git-merge change to remove
the stupid clean-tree requirements?  I have been planning to
inflict the 'use git-merge instead of git-resolve' change on you
sometime soonish (like today ;-).  Having said that, I myself
would vote against phasing out 'git-resolve' -- being able to
say 'git resolve master hold fast' to fast forward the master
head to topic branch head of 'hold' (my topic branches are often
rebased to allow this) is quite useful.

I have one unrelated request.

Could I have a copy of .git/{branches,remotes,refs}/* from the
primary repository you do your kernel work please?

Re: [PATCH] Use git-update-ref in scripts.

From: Linus Torvalds <torvalds@osdl.org>
Date: 2016-06-15 22:42:07


On Wed, 28 Sep 2005, Junio C Hamano wrote:
Have you had a chance to look at the git-merge change to remove
the stupid clean-tree requirements?  I have been planning to
inflict the 'use git-merge instead of git-resolve' change on you
sometime soonish (like today ;-).
I don't like doing the diff before-hand, but it looked like the default 
was to try just one strategy, and avoid the diff in that case.

Actually, my preference would be to have a unconditional simple case
first. If there's only one possible base, and the trivial merge succeeds
(ie no three-way merges needed at all, just a single git-read-tree), do
that part unconditionally.

That actually matches 90% of all merges I do, and I'd be much happier with 
git-merge if it did that first and if it then does something more complex 
(including diffs etc) afterwards, I'm much less likely to worry.
Could I have a copy of .git/{branches,remotes,refs}/* from the
primary repository you do your kernel work please?
Heh. My kernel has none of that. Well, it obviously has refs, but even 
there it literally has just one head: "master". The rest are the standard 
tags you see in public.

So if you clone the public kernel,. you'll actually have a superset of 
what I have, since you'll have the "origin" thing ;)

			Linus

Re: [PATCH] Use git-update-ref in scripts.

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:42:07

Linus Torvalds [off-list ref] writes:
On Wed, 28 Sep 2005, Junio C Hamano wrote:
quoted
I don't like doing the diff before-hand, but it looked like the default 
was to try just one strategy, and avoid the diff in that case.
By 'diff before-hand' I take it to mean the savestate for later
rounds to keep the pre-merge state.  You are correct that it is
not done in a single strategy case, and 'git pull' by default
would use only one of Daniel's git-merge-resolve or in the
multi-remote case git-merge-octopus, depending on the number of
heads being merged.  BTW, I decided not to use diff, just in
case somebody has binary blob we cannot reproduce with diff and
patch.
Actually, my preference would be to have a unconditional simple case
first. If there's only one possible base, and the trivial merge succeeds
(ie no three-way merges needed at all, just a single git-read-tree), do
that part unconditionally.

That actually matches 90% of all merges I do, and I'd be much happier with 
git-merge if it did that first and if it then does something more complex 
(including diffs etc) afterwards, I'm much less likely to worry.
Hmph.  That sort of makes sense but to make the unconditional
simple case really fast it should use read-tree -m -u which
_would_ smudge if things do not go well, which implies you need
savestate before that which would make it slower -- wouldn't it?

I think using Daniel's git-merge-resolve and nothing else by
default would be equivalent of having that unconditional simple
case upfront.

Re: [PATCH] Use git-update-ref in scripts.

From: Linus Torvalds <torvalds@osdl.org>
Date: 2016-06-15 22:42:07


On Wed, 28 Sep 2005, Junio C Hamano wrote:
Hmph.  That sort of makes sense but to make the unconditional
simple case really fast it should use read-tree -m -u which
_would_ smudge if things do not go well, which implies you need
savestate before that which would make it slower -- wouldn't it?
Yeah, we'd have to do something like this.. (untested, surprise, surprise)

NOTE! Even if you don't take this, I noticed what looks like a missing 
"continue" in the "--head" case. That just can't work without it, afaik. 

Not that I know what "--head" is supposed to do.. 

		Linus
---
diff --git a/read-tree.c b/read-tree.c
--- a/read-tree.c
+++ b/read-tree.c
@@ -13,6 +13,8 @@
 static int merge = 0;
 static int update = 0;
 static int index_only = 0;
+static int nontrivial_merge = 0;
+static int trivial_merges_only = 0;
 
 static int head_idx = -1;
 static int merge_size = 0;
@@ -275,6 +277,9 @@ static int unpack_trees(merge_fn_t fn)
 	if (unpack_trees_rec(posns, len, "", fn, &indpos))
 		return -1;
 
+	if (trivial_merges_only && nontrivial_merge)
+		die("Merge requires file-level merging");
+
 	check_updates(active_cache, active_nr);
 	return 0;
 }
@@ -460,6 +465,8 @@ static int threeway_merge(struct cache_e
 		verify_uptodate(index);
 	}
 
+	nontrivial_merge = 1;
+
 	/* #2, #3, #4, #6, #7, #9, #11. */
 	count = 0;
 	if (!head_match || !remote_match) {
@@ -629,9 +636,15 @@ int main(int argc, char **argv)
 			continue;
 		}
 
+		if (!strcmp(arg, "--trivial")) {
+			trivial_merges_only = 1;
+			continue;
+		}
+
 		if (!strcmp(arg, "--head")) {
 			head_idx = stage - 1;
 			fn = threeway_merge;
+			continue;
 		}
 
 		/* "-m" stands for "merge", meaning we start in stage 1 */
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help