All of lore.kernel.org
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: Ingo Molnar <mingo@elte.hu>
Cc: Bruce Stephens <bruce.stephens@isode.com>, git@vger.kernel.org
Subject: [PATCH 1/3] Refactor "tracking statistics" code used by "git checkout"
Date: Wed, 02 Jul 2008 00:51:18 -0700	[thread overview]
Message-ID: <7vvdzoenbd.fsf@gitster.siamese.dyndns.org> (raw)
In-Reply-To: 7vlk0lmn32.fsf@gitster.siamese.dyndns.org

People seem to like "Your branch is ahead by N commit" report made by
"git checkout", but the interface into the statistics function was a bit
clunky.  This splits the function into three parts:

 * The core "commit counting" function that takes "struct branch" and
   returns number of commits to show if we are ahead, behind or forked;

 * Convenience "stat formating" function that takes "struct branch" and
   formats the report into a given strbuf, using the above function;

 * "checkout" specific function that takes "branch_info" (type that is
   internal to checkout implementation), calls the above function and
   print the formatted result.

in the hope that the former two can be more easily reusable.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin-checkout.c |   94 +++----------------------------------------
 remote.c           |  113 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 remote.h           |    4 ++
 3 files changed, 123 insertions(+), 88 deletions(-)

diff --git a/builtin-checkout.c b/builtin-checkout.c
index 93ea69b..d6641c2 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -305,97 +305,15 @@ static int merge_working_tree(struct checkout_opts *opts,
 	return 0;
 }
 
-static void report_tracking(struct branch_info *new, struct checkout_opts *opts)
+static void report_tracking(struct branch_info *new)
 {
-	/*
-	 * We have switched to a new branch; is it building on
-	 * top of another branch, and if so does that other branch
-	 * have changes we do not have yet?
-	 */
-	char *base;
-	unsigned char sha1[20];
-	struct commit *ours, *theirs;
-	char symmetric[84];
-	struct rev_info revs;
-	const char *rev_argv[10];
-	int rev_argc;
-	int num_ours, num_theirs;
-	const char *remote_msg;
+	struct strbuf sb = STRBUF_INIT;
 	struct branch *branch = branch_get(new->name);
 
-	/*
-	 * Nothing to report unless we are marked to build on top of
-	 * somebody else.
-	 */
-	if (!branch || !branch->merge || !branch->merge[0] || !branch->merge[0]->dst)
-		return;
-
-	/*
-	 * If what we used to build on no longer exists, there is
-	 * nothing to report.
-	 */
-	base = branch->merge[0]->dst;
-	if (!resolve_ref(base, sha1, 1, NULL))
+	if (!format_tracking_info(branch, &sb))
 		return;
-
-	theirs = lookup_commit(sha1);
-	ours = new->commit;
-	if (!hashcmp(sha1, ours->object.sha1))
-		return; /* we are the same */
-
-	/* Run "rev-list --left-right ours...theirs" internally... */
-	rev_argc = 0;
-	rev_argv[rev_argc++] = NULL;
-	rev_argv[rev_argc++] = "--left-right";
-	rev_argv[rev_argc++] = symmetric;
-	rev_argv[rev_argc++] = "--";
-	rev_argv[rev_argc] = NULL;
-
-	strcpy(symmetric, sha1_to_hex(ours->object.sha1));
-	strcpy(symmetric + 40, "...");
-	strcpy(symmetric + 43, sha1_to_hex(theirs->object.sha1));
-
-	init_revisions(&revs, NULL);
-	setup_revisions(rev_argc, rev_argv, &revs, NULL);
-	prepare_revision_walk(&revs);
-
-	/* ... and count the commits on each side. */
-	num_ours = 0;
-	num_theirs = 0;
-	while (1) {
-		struct commit *c = get_revision(&revs);
-		if (!c)
-			break;
-		if (c->object.flags & SYMMETRIC_LEFT)
-			num_ours++;
-		else
-			num_theirs++;
-	}
-
-	if (!prefixcmp(base, "refs/remotes/")) {
-		remote_msg = " remote";
-		base += strlen("refs/remotes/");
-	} else {
-		remote_msg = "";
-	}
-
-	if (!num_theirs)
-		printf("Your branch is ahead of the tracked%s branch '%s' "
-		       "by %d commit%s.\n",
-		       remote_msg, base,
-		       num_ours, (num_ours == 1) ? "" : "s");
-	else if (!num_ours)
-		printf("Your branch is behind the tracked%s branch '%s' "
-		       "by %d commit%s,\n"
-		       "and can be fast-forwarded.\n",
-		       remote_msg, base,
-		       num_theirs, (num_theirs == 1) ? "" : "s");
-	else
-		printf("Your branch and the tracked%s branch '%s' "
-		       "have diverged,\nand respectively "
-		       "have %d and %d different commit(s) each.\n",
-		       remote_msg, base,
-		       num_ours, num_theirs);
+	fputs(sb.buf, stdout);
+	strbuf_release(&sb);
 }
 
 static void update_refs_for_switch(struct checkout_opts *opts,
@@ -441,7 +359,7 @@ static void update_refs_for_switch(struct checkout_opts *opts,
 	remove_branch_state();
 	strbuf_release(&msg);
 	if (!opts->quiet && (new->path || !strcmp(new->name, "HEAD")))
-		report_tracking(new, opts);
+		report_tracking(new);
 }
 
 static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
diff --git a/remote.c b/remote.c
index ff2c802..bd5c3be 100644
--- a/remote.c
+++ b/remote.c
@@ -1,6 +1,9 @@
 #include "cache.h"
 #include "remote.h"
 #include "refs.h"
+#include "commit.h"
+#include "diff.h"
+#include "revision.h"
 
 static struct refspec s_tag_refspec = {
 	0,
@@ -1222,3 +1225,113 @@ int resolve_remote_symref(struct ref *ref, struct ref *list)
 		}
 	return 1;
 }
+
+/*
+ * Return true if there is anything to report, otherwise false.
+ */
+int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs)
+{
+	unsigned char sha1[20];
+	struct commit *ours, *theirs;
+	char symmetric[84];
+	struct rev_info revs;
+	const char *rev_argv[10], *base;
+	int rev_argc;
+
+	/*
+	 * Nothing to report unless we are marked to build on top of
+	 * somebody else.
+	 */
+	if (!branch ||
+	    !branch->merge || !branch->merge[0] || !branch->merge[0]->dst)
+		return 0;
+
+	/*
+	 * If what we used to build on no longer exists, there is
+	 * nothing to report.
+	 */
+	base = branch->merge[0]->dst;
+	if (!resolve_ref(base, sha1, 1, NULL))
+		return 0;
+	theirs = lookup_commit(sha1);
+	if (!theirs)
+		return 0;
+
+	if (!resolve_ref(branch->refname, sha1, 1, NULL))
+		return 0;
+	ours = lookup_commit(sha1);
+	if (!ours)
+		return 0;
+
+	/* are we the same? */
+	if (theirs == ours)
+		return 0;
+
+	/* Run "rev-list --left-right ours...theirs" internally... */
+	rev_argc = 0;
+	rev_argv[rev_argc++] = NULL;
+	rev_argv[rev_argc++] = "--left-right";
+	rev_argv[rev_argc++] = symmetric;
+	rev_argv[rev_argc++] = "--";
+	rev_argv[rev_argc] = NULL;
+
+	strcpy(symmetric, sha1_to_hex(ours->object.sha1));
+	strcpy(symmetric + 40, "...");
+	strcpy(symmetric + 43, sha1_to_hex(theirs->object.sha1));
+
+	init_revisions(&revs, NULL);
+	setup_revisions(rev_argc, rev_argv, &revs, NULL);
+	prepare_revision_walk(&revs);
+
+	/* ... and count the commits on each side. */
+	*num_ours = 0;
+	*num_theirs = 0;
+	while (1) {
+		struct commit *c = get_revision(&revs);
+		if (!c)
+			break;
+		if (c->object.flags & SYMMETRIC_LEFT)
+			(*num_ours)++;
+		else
+			(*num_theirs)++;
+	}
+	return 1;
+}
+
+/*
+ * Return true when there is anything to report, otherwise false.
+ */
+int format_tracking_info(struct branch *branch, struct strbuf *sb)
+{
+	int num_ours, num_theirs;
+	const char *base, *remote_msg;
+
+	if (!stat_tracking_info(branch, &num_ours, &num_theirs))
+		return 0;
+
+	base = branch->merge[0]->dst;
+	if (!prefixcmp(base, "refs/remotes/")) {
+		remote_msg = " remote";
+		base += strlen("refs/remotes/");
+	} else {
+		remote_msg = "";
+	}
+	if (!num_theirs)
+		strbuf_addf(sb, "Your branch is ahead of the tracked%s branch '%s' "
+			    "by %d commit%s.\n",
+			    remote_msg, base,
+			    num_ours, (num_ours == 1) ? "" : "s");
+	else if (!num_ours)
+		strbuf_addf(sb, "Your branch is behind the tracked%s branch '%s' "
+			    "by %d commit%s,\n"
+			    "and can be fast-forwarded.\n",
+			    remote_msg, base,
+			    num_theirs, (num_theirs == 1) ? "" : "s");
+	else
+		strbuf_addf(sb, "Your branch and the tracked%s branch '%s' "
+			    "have diverged,\nand respectively "
+			    "have %d and %d different commit(s) each.\n",
+			    remote_msg, base,
+			    num_ours, num_theirs);
+	return 1;
+}
diff --git a/remote.h b/remote.h
index 8eed87b..091b1d0 100644
--- a/remote.h
+++ b/remote.h
@@ -129,4 +129,8 @@ enum match_refs_flags {
 	MATCH_REFS_MIRROR	= (1 << 1),
 };
 
+/* Reporting of tracking info */
+int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs);
+int format_tracking_info(struct branch *branch, struct strbuf *sb);
+
 #endif
-- 
1.5.6.1.156.ge903b

  parent reply	other threads:[~2008-07-02  7:52 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-01  9:13 [OT] Your branch is ahead of the tracked remote branch 'origin/master' by 50 commits Ingo Molnar
2008-07-01  9:26 ` Bruce Stephens
2008-07-01 10:14   ` Ingo Molnar
2008-07-01 11:41     ` SZEDER Gábor
2008-07-01 12:47       ` Jakub Narebski
2008-07-01 19:16     ` Junio C Hamano
2008-07-02  7:50       ` [PATCH 0/3] Making remote tracking statistics available to other tools Junio C Hamano
2008-07-03 16:26         ` Olivier Marin
2008-07-03 19:07           ` Junio C Hamano
2008-07-03 19:25             ` Olivier Marin
2008-07-02  7:51       ` Junio C Hamano [this message]
2008-07-02  7:52       ` [PATCH 2/3] git-status: show the remote tracking statistics Junio C Hamano
2008-07-02  7:52       ` [PATCH 3/3] git-branch -v: " Junio C Hamano
2008-07-02  8:23         ` Johannes Sixt
2008-07-02  8:33           ` Karl Hasselström
2008-07-02 14:44             ` Brian Gernhardt
2008-07-02  8:42           ` Junio C Hamano
2008-07-02 15:44         ` Johannes Schindelin
2008-07-01 12:44   ` [OT] Your branch is ahead of the tracked remote branch 'origin/master' by 50 commits Jakub Narebski
2008-07-01  9:32 ` Junio C Hamano
2008-07-01 10:07   ` Ingo Molnar
2008-07-01 11:16     ` Miklos Vajna
2008-07-01 11:22       ` Ingo Molnar
2008-07-01 11:41         ` Miklos Vajna
2008-07-01 23:55           ` Junio C Hamano
2008-07-04  8:35         ` Pedro Melo
2008-07-01 12:46     ` Mikael Magnusson
2008-07-01 18:01     ` Björn Steinbrink

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=7vvdzoenbd.fsf@gitster.siamese.dyndns.org \
    --to=gitster@pobox.com \
    --cc=bruce.stephens@isode.com \
    --cc=git@vger.kernel.org \
    --cc=mingo@elte.hu \
    /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.