All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Santi Béjar" <sbejar@gmail.com>
To: Git Mailing List <git@vger.kernel.org>
Subject: [PATCH] git-fetch: Split fetch and merge logic
Date: Wed, 07 Mar 2007 13:25:28 +0100	[thread overview]
Message-ID: <87fy8h5jgn.fsf@gmail.com> (raw)


It makes git-parse-remote.sh, git-fetch--tool and almost all git-fetch
independent of the merge logic.

git-fetch fetches the branches from the remote and saves this
information in .git/FETCH_FETCHED (a temporary file), and at the end it
generates the file .git/FETCH_HEAD.

The current merge behaviour is unchanged.

Signed-off-by: Santi Béjar <sbejar@gmail.com>
---
Hi *,

 this time the net effect is to add 10 lines :(

 This applies to next.

 Regards,

 Santi

 builtin-fetch--tool.c |   49 ++++++++++--------------------
 git-fetch.sh          |   78 +++++++++++++++++++++++++++++++++++++++++-------
 git-parse-remote.sh   |   65 ++++++++++++-----------------------------
 3 files changed, 101 insertions(+), 91 deletions(-)

diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c
index e9d6764..2cee058 100644
--- a/builtin-fetch--tool.c
+++ b/builtin-fetch--tool.c
@@ -138,8 +138,7 @@ static int update_local_ref(const char *name,
 
 static int append_fetch_head(FILE *fp,
 			     const char *head, const char *remote,
-			     const char *remote_name, const char *remote_nick,
-			     const char *local_name, int not_for_merge,
+			     const char *remote_name, const char *local_name,
 			     int verbose, int force)
 {
 	struct commit *commit;
@@ -151,8 +150,6 @@ static int append_fetch_head(FILE *fp,
 	if (get_sha1(head, sha1))
 		return error("Not a valid object name: %s", head);
 	commit = lookup_commit_reference(sha1);
-	if (!commit)
-		not_for_merge = 1;
 
 	if (!strcmp(remote_name, "HEAD")) {
 		kind = "";
@@ -189,9 +186,9 @@ static int append_fetch_head(FILE *fp,
 		note_len += sprintf(note + note_len, "'%s' of ", what);
 	}
 	note_len += sprintf(note + note_len, "%.*s", remote_len, remote);
-	fprintf(fp, "%s\t%s\t%s\n",
+	fprintf(fp, "%s\t%s:%s\t%s\n",
 		sha1_to_hex(commit ? commit->object.sha1 : sha1),
-		not_for_merge ? "not-for-merge" : "",
+		remote_name, local_name,
 		note);
 	return update_local_ref(local_name, head, note, verbose, force);
 }
@@ -211,14 +208,14 @@ static void remove_keep_on_signal(int signo)
 }
 
 static char *find_local_name(const char *remote_name, const char *refs,
-			     int *force_p, int *not_for_merge_p)
+			     int *force_p)
 {
 	const char *ref = refs;
 	int len = strlen(remote_name);
 
 	while (ref) {
 		const char *next;
-		int single_force, not_for_merge;
+		int single_force;
 
 		while (*ref == '\n')
 			ref++;
@@ -226,19 +223,11 @@ static char *find_local_name(const char *remote_name, const char *refs,
 			break;
 		next = strchr(ref, '\n');
 
-		single_force = not_for_merge = 0;
+		single_force = 0;
 		if (*ref == '+') {
 			single_force = 1;
 			ref++;
 		}
-		if (*ref == '.') {
-			not_for_merge = 1;
-			ref++;
-			if (*ref == '+') {
-				single_force = 1;
-				ref++;
-			}
-		}
 		if (!strncmp(remote_name, ref, len) && ref[len] == ':') {
 			const char *local_part = ref + len + 1;
 			char *ret;
@@ -252,7 +241,6 @@ static char *find_local_name(const char *remote_name, const char *refs,
 			memcpy(ret, local_part, retlen);
 			ret[retlen] = 0;
 			*force_p = single_force;
-			*not_for_merge_p = not_for_merge;
 			return ret;
 		}
 		ref = next;
@@ -262,7 +250,6 @@ static char *find_local_name(const char *remote_name, const char *refs,
 
 static int fetch_native_store(FILE *fp,
 			      const char *remote,
-			      const char *remote_nick,
 			      const char *refs,
 			      int verbose, int force)
 {
@@ -276,7 +263,7 @@ static int fetch_native_store(FILE *fp,
 		int len;
 		char *cp;
 		char *local_name;
-		int single_force, not_for_merge;
+		int single_force;
 
 		for (cp = buffer; *cp && !isspace(*cp); cp++)
 			;
@@ -298,12 +285,11 @@ static int fetch_native_store(FILE *fp,
 		}
 
 		local_name = find_local_name(cp, refs,
-					     &single_force, &not_for_merge);
+					     &single_force);
 		if (!local_name)
 			continue;
 		err |= append_fetch_head(fp,
-					 buffer, remote, cp, remote_nick,
-					 local_name, not_for_merge,
+					 buffer, remote, cp, local_name,
 					 verbose, force || single_force);
 	}
 	return err;
@@ -336,8 +322,6 @@ static int parse_reflist(const char *reflist)
 			break;
 		for (next = ref; *next && !isspace(*next); next++)
 			;
-		if (*ref == '.')
-			ref++;
 		if (*ref == '+')
 			ref++;
 		colon = strchr(ref, ':');
@@ -460,12 +444,11 @@ int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
 		int result;
 		FILE *fp;
 
-		if (argc != 8)
-			return error("append-fetch-head takes 6 args");
-		fp = fopen(git_path("FETCH_HEAD"), "a");
+		if (argc != 6)
+			return error("append-fetch-head takes 4 args");
+		fp = fopen(git_path("FETCH_FETCHED"), "a");
 		result = append_fetch_head(fp, argv[2], argv[3],
 					   argv[4], argv[5],
-					   argv[6], !!argv[7][0],
 					   verbose, force);
 		fclose(fp);
 		return result;
@@ -474,10 +457,10 @@ int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
 		int result;
 		FILE *fp;
 
-		if (argc != 5)
-			return error("fetch-native-store takes 3 args");
-		fp = fopen(git_path("FETCH_HEAD"), "a");
-		result = fetch_native_store(fp, argv[2], argv[3], argv[4],
+		if (argc != 4)
+			return error("fetch-native-store takes 2 args");
+		fp = fopen(git_path("FETCH_FETCHED"), "a");
+		result = fetch_native_store(fp, argv[2], argv[3],
 					    verbose, force);
 		fclose(fp);
 		return result;
diff --git a/git-fetch.sh b/git-fetch.sh
index 9d45dd2..58cbef1 100755
--- a/git-fetch.sh
+++ b/git-fetch.sh
@@ -79,9 +79,9 @@ do
 	shift
 done
 
+origin=$(get_default_remote)
 case "$#" in
 0)
-	origin=$(get_default_remote)
 	test -n "$(get_remote_url ${origin})" ||
 		die "Where do you want to fetch from today?"
 	set x $origin ; shift ;;
@@ -103,6 +103,8 @@ if test "" = "$append"
 then
 	: >"$GIT_DIR/FETCH_HEAD"
 fi
+: >"$GIT_DIR/FETCH_FETCHED"
+trap 'rm -f "$GIT_DIR"/FETCH_FETCHED' 0 1 2 3 15
 
 # Global that is reused later
 ls_remote_result=$(git ls-remote $exec "$remote") ||
@@ -145,7 +147,7 @@ then
 		  git-show-ref --exclude-existing=refs/tags/ |
 	          while read sha1 name
 		  do
-			echo ".${name}:${name}"
+			echo "${name}:${name}"
 		  done` || exit
 	if test "$#" -gt 1
 	then
@@ -182,7 +184,7 @@ fetch_native () {
 	test -n "$force" && flags="$flags -f"
 	GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION" \
 		git-fetch--tool $flags native-store \
-			"$remote" "$remote_nick" "$refs"
+			"$remote" "$refs"
       )
     ) || exit
 
@@ -199,13 +201,6 @@ fetch_dumb () {
 
       # These are relative path from $GIT_DIR, typically starting at refs/
       # but may be HEAD
-      if expr "z$ref" : 'z\.' >/dev/null
-      then
-	  not_for_merge=t
-	  ref=$(expr "z$ref" : 'z\.\(.*\)')
-      else
-	  not_for_merge=
-      fi
       if expr "z$ref" : 'z+' >/dev/null
       then
 	  single_force=t
@@ -283,7 +278,7 @@ fetch_dumb () {
       esac
 
       append_fetch_head "$head" "$remote" \
-	  "$remote_name" "$remote_nick" "$local_name" "$not_for_merge" || exit
+	  "$remote_name" "$remote_nick" "$local_name" || exit
 
   done
 
@@ -316,7 +311,7 @@ case "$no_tags$tags" in
 		do
 			git-cat-file -t "$sha1" >/dev/null 2>&1 || continue
 			echo >&2 "Auto-following $name"
-			echo ".${name}:${name}"
+			echo "${name}:${name}"
 		done)
 	esac
 	case "$taglist" in
@@ -344,3 +339,62 @@ case "$orig_head" in
 	fi
 	;;
 esac
+# Generate $GIT_DIR/FETCH_HEAD
+case ",$#,$remote_nick," in
+,1,$origin,)
+	# Fetch default: merge the branches in branch.*.merge that match
+	#                the fetched ones or the first one
+	curr_branch=$(git-symbolic-ref -q HEAD | sed -e 's|^refs/heads/||')
+	merge_branches=$(git-config \
+		--get-all "branch.${curr_branch}.merge" | sort -u)
+	fetch_branches=$(get_remote_default_refs_for_fetch -n $remote_nick |
+		sed -e 's/:.*$//g' -e 's/^+//' | sort -u)
+	test -n "$merge_branches" && test -n "$fetch_branches" &&
+	merge_branches=$(printf '%s\n%s' "$merge_branches" "$fetch_branches" |
+		sort | uniq -d)
+
+	[ -z "$merge_branches" ] ||
+	test "$(get_data_source $remote_nick)" = branches && merge_first=yes;;
+,1,$remote,)
+	# Remote is a URL, merge the default branch HEAD
+	merge_branches=HEAD;;
+,1,*)
+	# Remote is a shorthand diferent from the default,
+	# merge the first fetched branch
+	merge_first=yes ;;
+*)
+	# Merge the branches given in the command line
+	merge_branches=$(for ref in $(get_remote_refs_for_fetch "$@") ; do
+		expr "z$ref" : 'z.*:' >/dev/null || ref="${ref}:"
+		echo "$(expr "z$ref" : 'z\([^:]*\):')"; done);;
+esac
+
+if test "$merge_first" = "yes" ; then
+    merge_branches=
+    # Do not merge the first branch if it was specified with a glob
+    test "$(get_remote_default_refs_for_fetch -t $remote_nick)" != "explicit" &&
+    merge_first=
+else
+    merge_branches=$(canon_refs_list_for_fetch $merge_branches | sed 's/:.*$//g')
+fi
+
+while IFS='	' read hash ref note ; do
+	# 2.6.11-tree tag would not be happy to be fed to resolve.
+	if git-cat-file commit "$hash" >/dev/null 2>&1
+	then
+		hashc=$(git-rev-parse --verify "$hash^0") || exit
+		remote_branch=$(expr "z$ref" : 'z\([^:]*\):')
+		for merge_branch in $merge_branches ; do
+			[ "$merge_branch" = "$remote_branch" ] &&
+			echo "$hashc		$note" && continue 2
+		done
+	else
+		echo "$hash	not-for-merge	$note" && continue
+	fi
+	if ! test "$merge_first" || test "$merge_first" = "done" ; then
+		echo "$hash	not-for-merge	$note"
+	else
+		echo "$hash		$note"
+		merge_first=done
+	fi
+done < "$GIT_DIR"/FETCH_FETCHED >> "$GIT_DIR/FETCH_HEAD"
diff --git a/git-parse-remote.sh b/git-parse-remote.sh
index c46131f..99e7184 100755
--- a/git-parse-remote.sh
+++ b/git-parse-remote.sh
@@ -70,8 +70,7 @@ get_remote_default_refs_for_push () {
 	esac
 }
 
-# Called from canon_refs_list_for_fetch -d "$remote", which
-# is called from get_remote_default_refs_for_fetch to grok
+# Called from get_remote_default_refs_for_fetch to grok
 # refspecs that are retrieved from the configuration, but not
 # from get_remote_refs_for_fetch when it deals with refspecs
 # supplied on the command line.  $ls_remote_result has the list
@@ -87,30 +86,6 @@ expand_refs_wildcard () {
 
 # Subroutine to canonicalize remote:local notation.
 canon_refs_list_for_fetch () {
-	# If called from get_remote_default_refs_for_fetch
-	# leave the branches in branch.${curr_branch}.merge alone,
-	# or the first one otherwise; add prefix . to the rest
-	# to prevent the secondary branches to be merged by default.
-	merge_branches=
-	curr_branch=
-	if test "$1" = "-d"
-	then
-		shift ; remote="$1" ; shift
-		set $(expand_refs_wildcard "$remote" "$@")
-		is_explicit="$1"
-		shift
-		if test "$remote" = "$(get_default_remote)"
-		then
-			curr_branch=$(git-symbolic-ref -q HEAD | \
-			    sed -e 's|^refs/heads/||')
-			merge_branches=$(git-config \
-			    --get-all "branch.${curr_branch}.merge")
-		fi
-		if test -z "$merge_branches" && test $is_explicit != explicit
-		then
-			merge_branches=..this.will.never.match.any.ref..
-		fi
-	fi
 	for ref
 	do
 		force=
@@ -123,18 +98,6 @@ canon_refs_list_for_fetch () {
 		expr "z$ref" : 'z.*:' >/dev/null || ref="${ref}:"
 		remote=$(expr "z$ref" : 'z\([^:]*\):')
 		local=$(expr "z$ref" : 'z[^:]*:\(.*\)')
-		dot_prefix=.
-		if test -z "$merge_branches"
-		then
-			merge_branches=$remote
-			dot_prefix=
-		else
-			for merge_branch in $merge_branches
-			do
-			    [ "$remote" = "$merge_branch" ] &&
-			    dot_prefix= && break
-			done
-		fi
 		case "$remote" in
 		'' | HEAD ) remote=HEAD ;;
 		refs/heads/* | refs/tags/* | refs/remotes/*) ;;
@@ -153,32 +116,42 @@ canon_refs_list_for_fetch () {
 		   git-check-ref-format "$local_ref_name" ||
 		   die "* refusing to create funny ref '$local_ref_name' locally"
 		fi
-		echo "${dot_prefix}${force}${remote}:${local}"
+		echo "${force}${remote}:${local}"
 	done
 }
 
 # Returns list of src: (no store), or src:dst (store)
 get_remote_default_refs_for_fetch () {
+	test "$1" = -t && type=yes && shift
+	test "$1" = -n && canon=no && shift
 	data_source=$(get_data_source "$1")
 	case "$data_source" in
 	'')
-		echo "HEAD:" ;;
+		set explicit "HEAD:" ;;
 	config)
-		canon_refs_list_for_fetch -d "$1" \
-			$(git-config --get-all "remote.$1.fetch") ;;
+		set $(expand_refs_wildcard "$1" \
+			$(git-config --get-all "remote.$1.fetch")) ;;
 	branches)
 		remote_branch=$(sed -ne '/#/s/.*#//p' "$GIT_DIR/branches/$1")
 		case "$remote_branch" in '') remote_branch=master ;; esac
-		echo "refs/heads/${remote_branch}:refs/heads/$1"
+		set explicit "refs/heads/${remote_branch}:refs/heads/$1"
 		;;
 	remotes)
-		canon_refs_list_for_fetch -d "$1" $(sed -ne '/^Pull: */{
-						s///p
-					}' "$GIT_DIR/remotes/$1")
+		set $(expand_refs_wildcard "$1" $(sed -ne '/^Pull: */s///p'\
+					"$GIT_DIR/remotes/$1"))
 		;;
 	*)
 		die "internal error: get-remote-default-ref-for-push $1" ;;
 	esac
+	if test "$type" = yes ; then
+		echo $1
+	elif test "$canon" = no ; then
+		shift
+		for ref ; do echo "$ref" ; done
+	else
+		shift
+		canon_refs_list_for_fetch "$@"
+	fi
 }
 
 get_remote_refs_for_push () {
-- 
1.5.0.3.897.g91a70-dirty

             reply	other threads:[~2007-03-07 12:25 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-03-07 12:25 Santi Béjar [this message]
  -- strict thread matches above, loose matches on Subject: below --
2007-02-24  9:50 [PATCH] git-fetch: Split fetch and merge logic Santi Béjar
2007-02-24 10:23 ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87fy8h5jgn.fsf@gmail.com \
    --to=sbejar@gmail.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.