[PATCH] Support specific color for a specific remote branches

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Program 'show branch -a' supports different colors for 'local' and 'remote' branches.
When tracking more then one remote, all branches have the same color.
This change lets the user define a color for each remote, providing better visual distinction for different remotes.

Signed-off-by: Aviv Eyal <avivey@xxxxxxxxx>
---

Since my C days are now ancient history, I'm worried I might leak some char*s down there. Also, 
I might have missed some apis that would have made this patch smaller.

I'm using a sorted list as a dictionary (Remote name -> Color), which is not too elegant but
probably 'good enough', considering I expect it to be a very small (<3) list.

Aviv.

 Documentation/config.txt |    6 ++
 builtin/branch.c         |  119 +++++++++++++++++++++++++++++++++++++---------
 2 files changed, 102 insertions(+), 23 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 0658ffb..efdb61f 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -700,6 +700,7 @@ color.branch.<slot>::
 	`current` (the current branch), `local` (a local branch),
 	`remote` (a remote-tracking branch in refs/remotes/), `plain` (other
 	refs).
+	See also `remote.<name>.color`.
 +
 The value for these configuration variables is a list of colors (at most
 two) and attributes (at most one), separated by spaces.  The colors
@@ -1658,6 +1659,11 @@ remote.<name>.mirror::
 	If true, pushing to this remote will automatically behave
 	as if the `\--mirror` option was given on the command line.
 
+remote.<name>.color:
+	If set, the `branch` command will use the colors specified here
+	for the names of all branches tracking this remote. Colors
+	specified here take precedent over `color.branch.remote` config.
+
 remote.<name>.skipDefaultUpdate::
 	If true, this remote will be skipped by default when updating
 	using linkgit:git-fetch[1] or the `update` subcommand of
diff --git a/builtin/branch.c b/builtin/branch.c
index 3142daa..85e6920 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -15,6 +15,7 @@
 #include "branch.h"
 #include "diff.h"
 #include "revision.h"
+#include "string-list.h"
 
 static const char * const builtin_branch_usage[] = {
 	"git branch [options] [-r | -a] [--merged | --no-merged]",
@@ -46,6 +47,9 @@ enum color_branch {
 	BRANCH_COLOR_CURRENT = 4
 };
 
+// this string_list is used as a basic dictionary.
+struct string_list custom_colors = STRING_LIST_INIT_DUP;
+
 static enum merge_filter {
 	NO_FILTER = 0,
 	SHOW_NOT_MERGED,
@@ -68,6 +72,52 @@ static int parse_branch_color_slot(const char *var, int ofs)
 	return -1;
 }
 
+static char *strclone(const char *start, int len)
+{
+	char *result = malloc((len + 1) * sizeof(char));
+	if (!result)
+		return NULL;
+	strncpy(result, start, len);
+	result[len] = '\0';
+	return result;
+}
+
+static int git_branch_config_custom_color_remote(const char *var, const char *value)
+{
+	struct string_list_item *item;
+	char *name, *color;
+	name = strclone(var + 7, strlen(var) - 13); // "remote."=7, "remote..color"=13.
+	if (!name)
+		return 0;
+	color =  malloc(COLOR_MAXLEN * sizeof(char));
+	if (!color) {
+		free(name);
+		return 0;
+	}
+	item = string_list_insert(&custom_colors, name);
+	color_parse(value, var, color);
+	item->util = color;
+	return 0;
+}
+
+static char *git_branch_get_custom_color_remote(const char *name)
+{
+	int name_len;
+	char* repo_name;
+	struct string_list_item *custom;
+	name_len = strchr(name, '/') - name;
+	repo_name = strclone(name, name_len);
+	if (!repo_name)
+		return NULL;
+
+	custom = string_list_lookup(&custom_colors, repo_name);
+	free(repo_name);
+	if (custom)
+		return (char*) custom->util;
+	return NULL;
+}
+
+
 static int git_branch_config(const char *var, const char *value, void *cb)
 {
 	if (!strcmp(var, "color.branch")) {
@@ -83,14 +133,10 @@ static int git_branch_config(const char *var, const char *value, void *cb)
 		color_parse(value, var, branch_colors[slot]);
 		return 0;
 	}
-	return git_color_default_config(var, value, cb);
-}
+	if (!prefixcmp(var, "remote.") && !suffixcmp(var, ".color"))
+		return git_branch_config_custom_color_remote(var, value);
 
-static const char *branch_get_color(enum color_branch ix)
-{
-	if (branch_use_color > 0)
-		return branch_colors[ix];
-	return "";
+	return git_color_default_config(var, value, cb);
 }
 
 static int branch_merged(int kind, const char *name,
@@ -354,6 +400,43 @@ static int ref_cmp(const void *r1, const void *r2)
 	return strcmp(c1->name, c2->name);
 }
 
+static const char *branch_get_color(struct ref_item *item, int current)
+{
+	int index;
+	char *color;
+
+	if (branch_use_color <= 0)
+		return "";
+
+	if (!item)
+		index = BRANCH_COLOR_RESET;
+	else if (current)
+		index = BRANCH_COLOR_CURRENT;
+	else switch (item->kind) {
+		case REF_LOCAL_BRANCH:
+			index = BRANCH_COLOR_LOCAL;
+			break;
+		case REF_REMOTE_BRANCH:
+			index = BRANCH_COLOR_REMOTE;
+			color = git_branch_get_custom_color_remote(item->name);
+			if (color)
+				return color;
+			break;
+		default:
+			index = BRANCH_COLOR_PLAIN;
+			break;
+	}
+
+	return branch_colors[index];
+}
+
+static const char *branch_get_color_reset()
+{
+	if (branch_use_color <= 0)
+		return "";
+	return branch_colors[BRANCH_COLOR_RESET];
+}
+
 static void fill_tracking_info(struct strbuf *stat, const char *branch_name,
 		int show_upstream_ref)
 {
@@ -424,18 +507,6 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
 	if (!matches_merge_filter(commit))
 		return;
 
-	switch (item->kind) {
-	case REF_LOCAL_BRANCH:
-		color = BRANCH_COLOR_LOCAL;
-		break;
-	case REF_REMOTE_BRANCH:
-		color = BRANCH_COLOR_REMOTE;
-		break;
-	default:
-		color = BRANCH_COLOR_PLAIN;
-		break;
-	}
-
 	c = ' ';
 	if (current) {
 		c = '*';
@@ -444,12 +515,12 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
 
 	strbuf_addf(&name, "%s%s", prefix, item->name);
 	if (verbose)
-		strbuf_addf(&out, "%c %s%-*s%s", c, branch_get_color(color),
+		strbuf_addf(&out, "%c %s%-*s%s", c, branch_get_color(item, current),
 			    maxwidth, name.buf,
-			    branch_get_color(BRANCH_COLOR_RESET));
+			    branch_get_color_reset());
 	else
-		strbuf_addf(&out, "%c %s%s%s", c, branch_get_color(color),
-			    name.buf, branch_get_color(BRANCH_COLOR_RESET));
+		strbuf_addf(&out, "%c %s%s%s", c, branch_get_color(item, current),
+			    name.buf, branch_get_color_reset());
 
 	if (item->dest)
 		strbuf_addf(&out, " -> %s", item->dest);
@@ -712,5 +783,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	} else
 		usage_with_options(builtin_branch_usage, options);
 
+	string_list_clear(&custom_colors, 1);
+
 	return 0;
 }
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]