{"thread":{"id":"43351","subject":"Re: [PATCH] Add support to git-branch to show local and remote branches","startedAt":"2006-11-21T19:31:24Z","lastAt":"2006-11-22T08:53:22Z","messageCount":3,"participants":["Junio C Hamano","Andy Parkins"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"294896","messageId":"200611211931.24868.andyparkins@gmail.com","threadId":"43351","inReplyTo":null,"subject":"[PATCH] Add support to git-branch to show local and remote branches","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2006-11-21T19:31:24Z","receivedAt":"2006-11-21T19:31:24Z","isPatch":true,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"Instead of storing a list of refnames in append_ref, a list of structures is\ncreated.  Each of these stores the refname and a symbolic constant representing\nits type.\n\nThe creation of the list is filtered based on a command line switch; no switch\nmeans \"local branches only\", \"-r\" means \"remote branches only\" (as they always\ndid); but now \"-a\" means \"local branches or remote branches\".\n\nAs a side effect, the list is now not global, but allocated in print_ref_list()\nwhere it used.\n\nAlso a memory leak is plugged, the memory allocated during the list creation\nwas never freed.  This is now done in the new function, tidy_ref_list()\n\nSigned-off-by: Andy Parkins <andyparkins@gmail.com>\n---\n builtin-branch.c |   97 +++++++++++++++++++++++++++++++++++++++++++----------\n 1 files changed, 78 insertions(+), 19 deletions(-)\n\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 368b68e..9e0be22 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -11,7 +11,7 @@\n #include \"builtin.h\"\n \n static const char builtin_branch_usage[] =\n-\"git-branch (-d | -D) <branchname> | [-l] [-f] <branchname> [<start-point>] | [-r]\";\n+\"git-branch (-d | -D) <branchname> | [-l] [-f] <branchname> [<start-point>] | [-r] | [-a]\";\n \n \n static const char *head;\n@@ -79,46 +79,100 @@ static void delete_branches(int argc, co\n \t}\n }\n \n-static int ref_index, ref_alloc;\n-static char **ref_list;\n+#define REF_UNKNOWN_TYPE    0x00\n+#define REF_LOCAL_BRANCH    0x01\n+#define REF_REMOTE_BRANCH   0x02\n+#define REF_TAG             0x04\n+\n+struct ref_item {\n+\tchar *name;\n+\tunsigned int kind;\n+};\n+\n+struct ref_list {\n+\tint index, alloc;\n+\tstruct ref_item *list;\n+\tint kinds;\n+};\n \n static int append_ref(const char *refname, const unsigned char *sha1, int flags,\n \t\tvoid *cb_data)\n {\n-\tif (ref_index >= ref_alloc) {\n-\t\tref_alloc = alloc_nr(ref_alloc);\n-\t\tref_list = xrealloc(ref_list, ref_alloc * sizeof(char *));\n+\tstruct ref_list *ref_list = (struct ref_list*)(cb_data);\n+\tstruct ref_item *newitem;\n+\tint kind = REF_UNKNOWN_TYPE;\n+\n+\t/* Detect kind */\n+\tif (!strncmp(refname, \"refs/heads/\", 11)) {\n+\t\tkind = REF_LOCAL_BRANCH;\n+\t\trefname += 11;\n+\t} else if (!strncmp(refname, \"refs/remotes/\", 13)) {\n+\t\tkind = REF_REMOTE_BRANCH;\n+\t\trefname += 13;\n+\t} else if (!strncmp(refname, \"refs/tags/\", 10)) {\n+\t\tkind = REF_TAG;\n+\t\trefname += 10;\n+\t}\n+\n+\t/* Don't add types the caller doesn't want */\n+\tif ((kind & ref_list->kinds) == 0)\n+\t\treturn 0;\n+\n+\t/* Resize buffer */\n+\tif (ref_list->index >= ref_list->alloc) {\n+\t\tref_list->alloc = alloc_nr(ref_list->alloc);\n+\t\tref_list->list = xrealloc(ref_list->list,\n+\t\t\t\tref_list->alloc * sizeof(struct ref_item));\n \t}\n \n-\tref_list[ref_index++] = xstrdup(refname);\n+\t/* Record the new item */\n+\tnewitem = &(ref_list->list[ref_list->index++]);\n+\tnewitem->name = xstrdup(refname);\n+\tnewitem->kind = kind;\n \n \treturn 0;\n }\n \n+static void tidy_ref_list( struct ref_list *ref_list )\n+{\n+\tint i;\n+\tfor (i = 0; i < ref_list->index; i++) {\n+\t\tfree( ref_list->list[i].name );\n+\t}\n+\tfree( ref_list->list );\n+}\n+\n static int ref_cmp(const void *r1, const void *r2)\n {\n+\tstruct ref_item *c1 = (struct ref_item*)(r1),\n+\t\t\t\t\t*c2 = (struct ref_item*)(r2);\n+\tif( c1->kind != c2->kind )\n+\t\treturn c1->kind - c2->kind;\n \treturn strcmp(*(char **)r1, *(char **)r2);\n }\n \n-static void print_ref_list(int remote_only)\n+static void print_ref_list( int kinds )\n {\n \tint i;\n \tchar c;\n+\tstruct ref_list ref_list;\n \n-\tif (remote_only)\n-\t\tfor_each_remote_ref(append_ref, NULL);\n-\telse\n-\t\tfor_each_branch_ref(append_ref, NULL);\n+\tmemset( &ref_list, 0, sizeof( ref_list ) );\n+\tref_list.kinds = kinds;\n+\tfor_each_ref(append_ref, &ref_list);\n \n-\tqsort(ref_list, ref_index, sizeof(char *), ref_cmp);\n+\tqsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);\n \n-\tfor (i = 0; i < ref_index; i++) {\n+\tfor (i = 0; i < ref_list.index; i++) {\n \t\tc = ' ';\n-\t\tif (!strcmp(ref_list[i], head))\n+\t\tif (ref_list.list[i].kind == REF_LOCAL_BRANCH &&\n+\t\t\t\t!strcmp(ref_list.list[i].name, head))\n \t\t\tc = '*';\n \n-\t\tprintf(\"%c %s\\n\", c, ref_list[i]);\n+\t\tprintf(\"%c %s\\n\", c, ref_list.list[i].name );\n \t}\n+\n+\ttidy_ref_list( &ref_list );\n }\n \n static void create_branch(const char *name, const char *start,\n@@ -160,8 +214,9 @@ static void create_branch(const char *na\n \n int cmd_branch(int argc, const char **argv, const char *prefix)\n {\n-\tint delete = 0, force_delete = 0, force_create = 0, remote_only = 0;\n+\tint delete = 0, force_delete = 0, force_create = 0;\n \tint reflog = 0;\n+\tint kinds = REF_LOCAL_BRANCH;\n \tint i;\n \n \tgit_config(git_default_config);\n@@ -189,7 +244,11 @@ int cmd_branch(int argc, const char **ar\n \t\t\tcontinue;\n \t\t}\n \t\tif (!strcmp(arg, \"-r\")) {\n-\t\t\tremote_only = 1;\n+\t\t\tkinds = REF_REMOTE_BRANCH;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-a\")) {\n+\t\t\tkinds = REF_REMOTE_BRANCH | REF_LOCAL_BRANCH;\n \t\t\tcontinue;\n \t\t}\n \t\tif (!strcmp(arg, \"-l\")) {\n@@ -209,7 +268,7 @@ int cmd_branch(int argc, const char **ar\n \tif (delete)\n \t\tdelete_branches(argc - i, argv + i, force_delete);\n \telse if (i == argc)\n-\t\tprint_ref_list(remote_only);\n+\t\tprint_ref_list(kinds);\n \telse if (i == argc - 1)\n \t\tcreate_branch(argv[i], head, force_create, reflog);\n \telse if (i == argc - 2)\n-- \n1.4.3.5\n"},{"id":"294449","messageId":"7vwt5owlhm.fsf@assigned-by-dhcp.cox.net","threadId":"43351","inReplyTo":"200611211931.24868.andyparkins@gmail.com","subject":"Re: [PATCH] Add support to git-branch to show local and remote branches","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-21T21:14:29Z","receivedAt":"2006-11-21T21:14:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Andy Parkins <andyparkins@gmail.com> writes:\n\n> Instead of storing a list of refnames in append_ref, a list of\n> structures is created.  Each of these stores the refname and a\n> symbolic constant representing its type.\n\nThanks.  I'll drop the one in 'pu' and will replace with this\npatch but with style fixes and keeping the documentation updates\nfrom there.\n"},{"id":"297542","messageId":"200611220853.24378.andyparkins@gmail.com","threadId":"43351","inReplyTo":"7vwt5owlhm.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Add support to git-branch to show local and remote branches","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2006-11-22T08:53:22Z","receivedAt":"2006-11-22T08:53:22Z","isPatch":true,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"On Tuesday 2006 November 21 21:14, Junio C Hamano wrote:\n\n> Thanks.  I'll drop the one in 'pu' and will replace with this\n> patch but with style fixes and keeping the documentation updates\n> from there.\n\nSorry; I must remember to write documentation.  I'll be sure to look at the \nstyle changes and try to adhere to that style in future.\n\nAndy\n-- \nDr Andy Parkins, M Eng (hons), MIEE\n"}]}