git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 3/3] for-each-ref: introduce %(upstream:track[short])

From
Ramkumar Ramachandra <artagnon@gmail.com>
Date
May 24, 2013, 14:19 UTC
Message-ID
<1369405177-7855-4-git-send-email-artagnon@gmail.com>
In-Reply-To
<1369405177-7855-1-git-send-email-artagnon@gmail.com>

Introduce %(upstream:track) to display "[ahead M, behind N]" and %(upstream:trackshort) to display "=", ">", "<", or "<>" appropriately (inspired by the contrib/completion/git-prompt.sh).

Now you can use the following format in for-each-ref:
  %C(red)%(HEAD)%C(reset) %C(green)%(refname:short)%C(reset)%(upstream:trackshort)
to display refs with terse tracking information.

Note that :track and :trackshort only works with upstream, and errors out when used with anything else.

Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
---
 builtin/for-each-ref.c | 42 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 40 insertions(+), 2 deletions(-)
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 63d3a85..838b125 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -632,6 +632,7 @@ static void populate_value(struct refinfo *ref)
 	int eaten, i;
 	unsigned long size;
 	const unsigned char *tagged;
+	int upstream_present = 0;
 
 	ref->value = xcalloc(sizeof(struct atom_value), used_atom_cnt);
 
@@ -649,6 +650,7 @@ static void populate_value(struct refinfo *ref)
 		int deref = 0;
 		const char *refname;
 		const char *formatp;
+		struct branch *branch;
 
 		if (*name == '*') {
 			deref = 1;
@@ -660,7 +662,6 @@ static void populate_value(struct refinfo *ref)
 		else if (!prefixcmp(name, "symref"))
 			refname = ref->symref ? ref->symref : "";
 		else if (!prefixcmp(name, "upstream")) {
-			struct branch *branch;
 			/* only local branches may have an upstream */
 			if (prefixcmp(ref->refname, "refs/heads/"))
 				continue;
@@ -670,6 +671,7 @@ static void populate_value(struct refinfo *ref)
 			    !branch->merge[0]->dst)
 				continue;
 			refname = branch->merge[0]->dst;
+			upstream_present = 1;
 		}
 		else if (!strcmp(name, "flag")) {
 			char buf[256], *cp = buf;
@@ -687,6 +689,7 @@ static void populate_value(struct refinfo *ref)
 		} else if (!strcmp(name, "HEAD")) {
 			const char *head;
 			unsigned char sha1[20];
+
 			head = resolve_ref_unsafe("HEAD", sha1, 1, NULL);
 			if (!strcmp(ref->refname, head))
 				v->s = "*";
@@ -699,11 +702,46 @@ static void populate_value(struct refinfo *ref)
 		formatp = strchr(name, ':');
 		/* look for "short" refname format */
 		if (formatp) {
+			int num_ours, num_theirs;
+
 			formatp++;
 			if (!strcmp(formatp, "short"))
 				refname = shorten_unambiguous_ref(refname,
 						      warn_ambiguous_refs);
-			else
+			else if (!strcmp(formatp, "track") &&
+				!prefixcmp(name, "upstream")) {
+				char buf[40];
+
+				if (!upstream_present)
+					continue;
+				if (!stat_tracking_info(branch, &num_ours, &num_theirs))
+					v->s = "";
+				else if (!num_ours) {
+					sprintf(buf, "[behind %d]", num_theirs);
+					v->s = xstrdup(buf);
+				} else if (!num_theirs) {
+					sprintf(buf, "[ahead %d]", num_ours);
+					v->s = xstrdup(buf);
+				} else {
+					sprintf(buf, "[ahead %d, behind %d]",
+						num_ours, num_theirs);
+					v->s = xstrdup(buf);
+				}
+				continue;
+			} else if (!strcmp(formatp, "trackshort") &&
+				!prefixcmp(name, "upstream")) {
+				if (!upstream_present)
+					continue;
+				if (!stat_tracking_info(branch, &num_ours, &num_theirs))
+					v->s = "=";
+				else if (!num_ours)
+					v->s = "<";
+				else if (!num_theirs)
+					v->s = ">";
+				else
+					v->s = "<>";
+				continue;
+			} else
 				die("unknown %.*s format %s",
 				    (int)(formatp - name), name, formatp);
 		}
-- 
1.8.3.rc3.2.g99b8f3f.dirty
Previous: Philip OakleyNext: Duy Nguyen
Message 13 of 31 in “Towards a useable git-branch”
  1. 0/3 Towards a useable git-branchRamkumar Ramachandra, May 24, 2013
  2. 1/3 for-each-ref: introduce %C(...) for colorRamkumar Ramachandra, May 24, 2013
  3. Antoine PelisseMay 24, 2013
  4. Ramkumar RamachandraMay 25, 2013
  5. John KeepingMay 25, 2013
  6. Ramkumar RamachandraMay 25, 2013
  7. Antoine PelisseMay 25, 2013
  8. David AguilarMay 24, 2013
  9. Ramkumar RamachandraMay 25, 2013
  10. Eric SunshineMay 25, 2013
  11. 2/3 for-each-ref: introduce %(HEAD) markerRamkumar Ramachandra, May 24, 2013
  12. Philip OakleyMay 24, 2013
  13. 3/3 for-each-ref: introduce %(upstream:track[short])Ramkumar Ramachandra, May 24, 2013
  14. Duy NguyenMay 24, 2013
  15. Ramkumar RamachandraMay 24, 2013
  16. Junio C HamanoMay 24, 2013
  17. Ramkumar RamachandraMay 24, 2013
  18. Ramkumar RamachandraMay 24, 2013
  19. Duy NguyenMay 24, 2013
  20. Duy NguyenMay 25, 2013
  21. Duy NguyenMay 25, 2013
  22. Ramkumar RamachandraMay 25, 2013
  23. Ramkumar RamachandraMay 28, 2013
  24. Ramkumar RamachandraMay 28, 2013
  25. Duy NguyenMay 30, 2013
  26. Ramkumar RamachandraJun 4, 2013
  27. Duy NguyenJun 4, 2013
  28. Ramkumar RamachandraMay 28, 2013
  29. Duy NguyenMay 29, 2013
  30. Ramkumar RamachandraMay 29, 2013
  31. Duy NguyenMay 29, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.