{"thread":{"id":"40010","subject":"[PATCH 0/10] Port branch.c to ref-filter.","startedAt":"2015-08-04T12:59:44Z","lastAt":"2015-08-14T18:45:56Z","messageCount":27,"participants":["Karthik Nayak","Junio C Hamano","Eric Sunshine","Matthieu Moy"],"isPatch":true,"patchVersion":1,"patchTotal":10},"messages":[{"id":"267408","messageId":"CAOLa=ZSnn19DR_Y5MqUXHed0g5MSk_dwFc48dk8GoPYvL5DQ=Q@mail.gmail.com","threadId":"40010","inReplyTo":null,"subject":"[PATCH 0/10] Port branch.c to ref-filter.","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-04T12:59:44Z","receivedAt":"2015-08-04T12:59:44Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"This is part of my GSoC project to unify git tag -l, git branch -l,\ngit for-each-ref.  This patch series is continued from: Git (next)\nhttps://github.com/git/git/commit/bf5418f49ff0cebc6e5ce04ad1417e1a47c81b61\n\nThis series consists of porting branch.c over to using the ref-filter\nAPIs. This does not involve the usage of show_ref_array_item() as it\nhas its own changes to be made, and on suggestion of my mentors I have\ndecided to split the porting of branch.c to this and eventually\nimplementation of the \"--format\" option.\n\nThe RFC version can be found here :\narticle.gmane.org/gmane.comp.version-control.git/274737\n\nThis is a follow up to the port of tag.c to use ref-filter APIs.\n(currently in the 9th iteration)\n\nChanges :\n* Change the order of ref_kind[] structure in filter_branch_kind.\n* Commit message changes.\n* Comments added if required.\n* Small code changes.\n\nNo interdiff as this was a split version and might as well be treated\nas the start of the patch series.\n\n-- \nRegards,\nKarthik Nayak\n"},{"id":"267409","messageId":"1438693282-15516-1-git-send-email-Karthik.188@gmail.com","threadId":"40010","inReplyTo":"CAOLa=ZSnn19DR_Y5MqUXHed0g5MSk_dwFc48dk8GoPYvL5DQ=Q@mail.gmail.com","subject":"[PATCH 01/10] ref-filter: add option to filter only branches","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-04T13:01:14Z","receivedAt":"2015-08-04T13:01:14Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"From: Karthik Nayak <karthik.188@gmail.com>\n\nAdd an option in 'filter_refs()' to use 'for_each_branch_ref()'\nand filter refs. This type checking is done by adding a\n'FILTER_REFS_BRANCHES' in 'ref-filter.h'.\n\nAdd an option in 'ref_filter_handler()' to filter different\ntypes of branches by calling 'filter_branch_kind()' which\nchecks for the type of branch needed.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n ref-filter.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++\n ref-filter.h | 10 ++++++++--\n 2 files changed, 55 insertions(+), 2 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex de84dd4..c573109 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -1044,6 +1044,46 @@ static const unsigned char *match_points_at(struct sha1_array *points_at,\n \treturn NULL;\n }\n \n+/*\n+ * Checks if a given refname is a branch and returns the kind of\n+ * branch it is. If not a branch, 0 is returned.\n+ */\n+static int filter_branch_kind(struct ref_filter *filter, const char *refname)\n+{\n+\tint kind, i;\n+\n+\tstatic struct {\n+\t\tconst char *prefix;\n+\t\tint kind;\n+\t} ref_kind[] = {\n+\t\t{ \"refs/heads/\" , REF_LOCAL_BRANCH },\n+\t\t{ \"refs/remotes/\" , REF_REMOTE_BRANCH },\n+\t};\n+\n+\t/*  If no kind is specified, no need to filter */\n+\tif (!filter->branch_kind)\n+\t\treturn REF_NO_BRANCH_FILTERING;\n+\n+\tfor (i = 0; i < ARRAY_SIZE(ref_kind); i++) {\n+\t\tif (starts_with(refname, ref_kind[i].prefix)) {\n+\t\t\tkind = ref_kind[i].kind;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tif (ARRAY_SIZE(ref_kind) <= i) {\n+\t\tif (!strcmp(refname, \"HEAD\"))\n+\t\t\tkind = REF_DETACHED_HEAD;\n+\t\telse\n+\t\t\treturn 0;\n+\t}\n+\n+\tif ((filter->branch_kind & kind) == 0)\n+\t\treturn 0;\n+\n+\treturn kind;\n+}\n+\n /* Allocate space for a new ref_array_item and copy the objectname and flag to it */\n static struct ref_array_item *new_ref_array_item(const char *refname,\n \t\t\t\t\t\t const unsigned char *objectname,\n@@ -1069,6 +1109,7 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,\n \tstruct ref_filter *filter = ref_cbdata->filter;\n \tstruct ref_array_item *ref;\n \tstruct commit *commit = NULL;\n+\tunsigned int kind;\n \n \tif (flag & REF_BAD_NAME) {\n \t\twarning(\"ignoring ref with broken name %s\", refname);\n@@ -1080,6 +1121,9 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,\n \t\treturn 0;\n \t}\n \n+\tif (!(kind = filter_branch_kind(filter, refname)))\n+\t\treturn 0;\n+\n \tif (!filter_pattern_match(filter, refname))\n \t\treturn 0;\n \n@@ -1108,6 +1152,7 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,\n \t */\n \tref = new_ref_array_item(refname, oid->hash, flag);\n \tref->commit = commit;\n+\tref->kind = kind;\n \n \tREALLOC_ARRAY(ref_cbdata->array->items, ref_cbdata->array->nr + 1);\n \tref_cbdata->array->items[ref_cbdata->array->nr++] = ref;\n@@ -1198,6 +1243,8 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int\n \t\tret = for_each_ref(ref_filter_handler, &ref_cbdata);\n \telse if (type & FILTER_REFS_TAGS)\n \t\tret = for_each_tag_ref_fullpath(ref_filter_handler, &ref_cbdata);\n+\telse if (type & FILTER_REFS_BRANCHES)\n+\t\tret = for_each_rawref(ref_filter_handler, &ref_cbdata);\n \telse if (type)\n \t\tdie(\"filter_refs: invalid type\");\n \ndiff --git a/ref-filter.h b/ref-filter.h\nindex 5be3e35..b5a13e8 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -16,6 +16,12 @@\n #define FILTER_REFS_INCLUDE_BROKEN 0x1\n #define FILTER_REFS_ALL 0x2\n #define FILTER_REFS_TAGS 0x4\n+#define FILTER_REFS_BRANCHES 0x8\n+\n+#define REF_DETACHED_HEAD   0x01\n+#define REF_LOCAL_BRANCH    0x02\n+#define REF_REMOTE_BRANCH   0x04\n+#define REF_NO_BRANCH_FILTERING 0x08\n \n #define ALIGN_LEFT 0x01\n #define ALIGN_RIGHT 0x02\n@@ -50,7 +56,7 @@ struct ref_sorting {\n \n struct ref_array_item {\n \tunsigned char objectname[20];\n-\tint flag;\n+\tint flag, kind;\n \tconst char *symref;\n \tstruct commit *commit;\n \tstruct atom_value *value;\n@@ -76,7 +82,7 @@ struct ref_filter {\n \n \tunsigned int with_commit_tag_algo : 1,\n \t\tmatch_as_path : 1;\n-\tunsigned int lines;\n+\tunsigned int lines, branch_kind;\n };\n \n struct ref_filter_cbdata {\n-- \n2.5.0\n"},{"id":"267410","messageId":"1438693282-15516-2-git-send-email-Karthik.188@gmail.com","threadId":"40010","inReplyTo":"CAOLa=ZSnn19DR_Y5MqUXHed0g5MSk_dwFc48dk8GoPYvL5DQ=Q@mail.gmail.com","subject":"[PATCH 02/10] branch: refactor width computation","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-04T13:01:15Z","receivedAt":"2015-08-04T13:01:15Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"From: Karthik Nayak <karthik.188@gmail.com>\n\nRemove unnecessary variables from ref_list and ref_item which were\nused for width computation. This is to make ref_item similar to\nref-filter's ref_array_item. This will ensure a smooth port of\nbranch.c to use ref-filter APIs in further patches.\n\nPreviously the maxwidth was computed when inserting the refs into the\nref_list. Now, we obtain the entire ref_list and then compute\nmaxwidth.\n\nBased-on-patch-by: Jeff King <peff@peff.net>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n builtin/branch.c | 61 +++++++++++++++++++++++++++++---------------------------\n 1 file changed, 32 insertions(+), 29 deletions(-)\n\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 4fc8beb..b058b74 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -282,14 +282,14 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,\n struct ref_item {\n \tchar *name;\n \tchar *dest;\n-\tunsigned int kind, width;\n+\tunsigned int kind;\n \tstruct commit *commit;\n \tint ignore;\n };\n \n struct ref_list {\n \tstruct rev_info revs;\n-\tint index, alloc, maxwidth, verbose, abbrev;\n+\tint index, alloc, verbose, abbrev;\n \tstruct ref_item *list;\n \tstruct commit_list *with_commit;\n \tint kinds;\n@@ -386,15 +386,8 @@ static int append_ref(const char *refname, const struct object_id *oid, int flag\n \tnewitem->name = xstrdup(refname);\n \tnewitem->kind = kind;\n \tnewitem->commit = commit;\n-\tnewitem->width = utf8_strwidth(refname);\n \tnewitem->dest = resolve_symref(orig_refname, prefix);\n \tnewitem->ignore = 0;\n-\t/* adjust for \"remotes/\" */\n-\tif (newitem->kind == REF_REMOTE_BRANCH &&\n-\t    ref_list->kinds != REF_REMOTE_BRANCH)\n-\t\tnewitem->width += 8;\n-\tif (newitem->width > ref_list->maxwidth)\n-\t\tref_list->maxwidth = newitem->width;\n \n \treturn 0;\n }\n@@ -505,11 +498,12 @@ static void add_verbose_info(struct strbuf *out, struct ref_item *item,\n }\n \n static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n-\t\t\t   int abbrev, int current, char *prefix)\n+\t\t\t   int abbrev, int current, const char *remote_prefix)\n {\n \tchar c;\n \tint color;\n \tstruct strbuf out = STRBUF_INIT, name = STRBUF_INIT;\n+\tconst char *prefix = \"\";\n \n \tif (item->ignore)\n \t\treturn;\n@@ -520,6 +514,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n \t\tbreak;\n \tcase REF_REMOTE_BRANCH:\n \t\tcolor = BRANCH_COLOR_REMOTE;\n+\t\tprefix = remote_prefix;\n \t\tbreak;\n \tdefault:\n \t\tcolor = BRANCH_COLOR_PLAIN;\n@@ -557,16 +552,21 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n \tstrbuf_release(&out);\n }\n \n-static int calc_maxwidth(struct ref_list *refs)\n+static int calc_maxwidth(struct ref_list *refs, int remote_bonus)\n {\n-\tint i, w = 0;\n+\tint i, max = 0;\n \tfor (i = 0; i < refs->index; i++) {\n+\t\tstruct ref_item *it = &refs->list[i];\n+\t\tint w = utf8_strwidth(it->name);\n+\n \t\tif (refs->list[i].ignore)\n \t\t\tcontinue;\n-\t\tif (refs->list[i].width > w)\n-\t\t\tw = refs->list[i].width;\n+\t\tif (it->kind == REF_REMOTE_BRANCH)\n+\t\t\tw += remote_bonus;\n+\t\tif (w > max)\n+\t\t\tmax = w;\n \t}\n-\treturn w;\n+\treturn max;\n }\n \n static char *get_head_description(void)\n@@ -600,21 +600,18 @@ static char *get_head_description(void)\n \treturn strbuf_detach(&desc, NULL);\n }\n \n-static void show_detached(struct ref_list *ref_list)\n+static void show_detached(struct ref_list *ref_list, int maxwidth)\n {\n \tstruct commit *head_commit = lookup_commit_reference_gently(head_sha1, 1);\n \n \tif (head_commit && is_descendant_of(head_commit, ref_list->with_commit)) {\n \t\tstruct ref_item item;\n \t\titem.name = get_head_description();\n-\t\titem.width = utf8_strwidth(item.name);\n \t\titem.kind = REF_LOCAL_BRANCH;\n \t\titem.dest = NULL;\n \t\titem.commit = head_commit;\n \t\titem.ignore = 0;\n-\t\tif (item.width > ref_list->maxwidth)\n-\t\t\tref_list->maxwidth = item.width;\n-\t\tprint_ref_item(&item, ref_list->maxwidth, ref_list->verbose, ref_list->abbrev, 1, \"\");\n+\t\tprint_ref_item(&item, maxwidth, ref_list->verbose, ref_list->abbrev, 1, \"\");\n \t\tfree(item.name);\n \t}\n }\n@@ -624,6 +621,16 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru\n \tint i;\n \tstruct append_ref_cb cb;\n \tstruct ref_list ref_list;\n+\tint maxwidth = 0;\n+\tconst char *remote_prefix = \"\";\n+\n+\t/*\n+\t * If we are listing more than just remote branches,\n+\t * then remote branches will have a \"remotes/\" prefix.\n+\t * We need to account for this in the width.\n+\t */\n+\tif (kinds != REF_REMOTE_BRANCH)\n+\t\tremote_prefix = \"remotes/\";\n \n \tmemset(&ref_list, 0, sizeof(ref_list));\n \tref_list.kinds = kinds;\n@@ -667,26 +674,22 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru\n \t\t\tclear_commit_marks(item->commit, ALL_REV_FLAGS);\n \t\t}\n \t\tclear_commit_marks(filter, ALL_REV_FLAGS);\n-\n-\t\tif (verbose)\n-\t\t\tref_list.maxwidth = calc_maxwidth(&ref_list);\n \t}\n+\tif (verbose)\n+\t\tmaxwidth = calc_maxwidth(&ref_list, strlen(remote_prefix));\n \n \tqsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);\n \n \tdetached = (detached && (kinds & REF_LOCAL_BRANCH));\n \tif (detached && match_patterns(pattern, \"HEAD\"))\n-\t\tshow_detached(&ref_list);\n+\t\tshow_detached(&ref_list, maxwidth);\n \n \tfor (i = 0; i < ref_list.index; i++) {\n \t\tint current = !detached &&\n \t\t\t(ref_list.list[i].kind == REF_LOCAL_BRANCH) &&\n \t\t\t!strcmp(ref_list.list[i].name, head);\n-\t\tchar *prefix = (kinds != REF_REMOTE_BRANCH &&\n-\t\t\t\tref_list.list[i].kind == REF_REMOTE_BRANCH)\n-\t\t\t\t? \"remotes/\" : \"\";\n-\t\tprint_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose,\n-\t\t\t       abbrev, current, prefix);\n+\t\tprint_ref_item(&ref_list.list[i], maxwidth, verbose,\n+\t\t\t       abbrev, current, remote_prefix);\n \t}\n \n \tfree_ref_list(&ref_list);\n-- \n2.5.0\n"},{"id":"267412","messageId":"1438693282-15516-3-git-send-email-Karthik.188@gmail.com","threadId":"40010","inReplyTo":"CAOLa=ZSnn19DR_Y5MqUXHed0g5MSk_dwFc48dk8GoPYvL5DQ=Q@mail.gmail.com","subject":"[PATCH 03/10] branch: bump get_head_description() to the top","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-04T13:01:16Z","receivedAt":"2015-08-04T13:01:16Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"This is a preperatory patch for 'roll show_detached HEAD into regular\nref_list'. This patch moves get_head_descrition() to the top so that\nit can be used in print_ref_item().\n\nBased-on-patch-by: Jeff King <peff@peff.net>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n builtin/branch.c | 62 ++++++++++++++++++++++++++++----------------------------\n 1 file changed, 31 insertions(+), 31 deletions(-)\n\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex b058b74..65f6d0d 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -497,6 +497,37 @@ static void add_verbose_info(struct strbuf *out, struct ref_item *item,\n \tstrbuf_release(&subject);\n }\n \n+static char *get_head_description(void)\n+{\n+\tstruct strbuf desc = STRBUF_INIT;\n+\tstruct wt_status_state state;\n+\tmemset(&state, 0, sizeof(state));\n+\twt_status_get_state(&state, 1);\n+\tif (state.rebase_in_progress ||\n+\t    state.rebase_interactive_in_progress)\n+\t\tstrbuf_addf(&desc, _(\"(no branch, rebasing %s)\"),\n+\t\t\t    state.branch);\n+\telse if (state.bisect_in_progress)\n+\t\tstrbuf_addf(&desc, _(\"(no branch, bisect started on %s)\"),\n+\t\t\t    state.branch);\n+\telse if (state.detached_from) {\n+\t\t/* TRANSLATORS: make sure these match _(\"HEAD detached at \")\n+\t\t   and _(\"HEAD detached from \") in wt-status.c */\n+\t\tif (state.detached_at)\n+\t\t\tstrbuf_addf(&desc, _(\"(HEAD detached at %s)\"),\n+\t\t\t\tstate.detached_from);\n+\t\telse\n+\t\t\tstrbuf_addf(&desc, _(\"(HEAD detached from %s)\"),\n+\t\t\t\tstate.detached_from);\n+\t}\n+\telse\n+\t\tstrbuf_addstr(&desc, _(\"(no branch)\"));\n+\tfree(state.branch);\n+\tfree(state.onto);\n+\tfree(state.detached_from);\n+\treturn strbuf_detach(&desc, NULL);\n+}\n+\n static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n \t\t\t   int abbrev, int current, const char *remote_prefix)\n {\n@@ -569,37 +600,6 @@ static int calc_maxwidth(struct ref_list *refs, int remote_bonus)\n \treturn max;\n }\n \n-static char *get_head_description(void)\n-{\n-\tstruct strbuf desc = STRBUF_INIT;\n-\tstruct wt_status_state state;\n-\tmemset(&state, 0, sizeof(state));\n-\twt_status_get_state(&state, 1);\n-\tif (state.rebase_in_progress ||\n-\t    state.rebase_interactive_in_progress)\n-\t\tstrbuf_addf(&desc, _(\"(no branch, rebasing %s)\"),\n-\t\t\t    state.branch);\n-\telse if (state.bisect_in_progress)\n-\t\tstrbuf_addf(&desc, _(\"(no branch, bisect started on %s)\"),\n-\t\t\t    state.branch);\n-\telse if (state.detached_from) {\n-\t\t/* TRANSLATORS: make sure these match _(\"HEAD detached at \")\n-\t\t   and _(\"HEAD detached from \") in wt-status.c */\n-\t\tif (state.detached_at)\n-\t\t\tstrbuf_addf(&desc, _(\"(HEAD detached at %s)\"),\n-\t\t\t\tstate.detached_from);\n-\t\telse\n-\t\t\tstrbuf_addf(&desc, _(\"(HEAD detached from %s)\"),\n-\t\t\t\tstate.detached_from);\n-\t}\n-\telse\n-\t\tstrbuf_addstr(&desc, _(\"(no branch)\"));\n-\tfree(state.branch);\n-\tfree(state.onto);\n-\tfree(state.detached_from);\n-\treturn strbuf_detach(&desc, NULL);\n-}\n-\n static void show_detached(struct ref_list *ref_list, int maxwidth)\n {\n \tstruct commit *head_commit = lookup_commit_reference_gently(head_sha1, 1);\n-- \n2.5.0\n"},{"id":"267411","messageId":"1438693282-15516-4-git-send-email-Karthik.188@gmail.com","threadId":"40010","inReplyTo":"CAOLa=ZSnn19DR_Y5MqUXHed0g5MSk_dwFc48dk8GoPYvL5DQ=Q@mail.gmail.com","subject":"[PATCH 04/10] branch: roll show_detached HEAD into regular ref_list","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-04T13:01:17Z","receivedAt":"2015-08-04T13:01:17Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Remove show_detached() and make detached HEAD to be rolled into\nregular ref_list by adding REF_DETACHED_HEAD as a kind of branch and\nsupporting the same in append_ref(). This eliminates the need for an\nextra function and helps in easier porting of branch.c to use\nref-filter APIs.\n\nBefore show_detached() used to check if the HEAD branch satisfies the\n'--contains' option, now that is taken care by append_ref().\n\nBased-on-patch-by: Jeff King <peff@peff.net>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n builtin/branch.c | 68 +++++++++++++++++++++++++++++++++-----------------------\n 1 file changed, 40 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 65f6d0d..81815c9 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -30,6 +30,7 @@ static const char * const builtin_branch_usage[] = {\n \n #define REF_LOCAL_BRANCH    0x01\n #define REF_REMOTE_BRANCH   0x02\n+#define REF_DETACHED_HEAD   0x04\n \n static const char *head;\n static unsigned char head_sha1[20];\n@@ -352,8 +353,12 @@ static int append_ref(const char *refname, const struct object_id *oid, int flag\n \t\t\tbreak;\n \t\t}\n \t}\n-\tif (ARRAY_SIZE(ref_kind) <= i)\n-\t\treturn 0;\n+\tif (ARRAY_SIZE(ref_kind) <= i) {\n+\t\tif (!strcmp(refname, \"HEAD\"))\n+\t\t\tkind = REF_DETACHED_HEAD;\n+\t\telse\n+\t\t\treturn 0;\n+\t}\n \n \t/* Don't add types the caller doesn't want */\n \tif ((kind & ref_list->kinds) == 0)\n@@ -535,6 +540,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n \tint color;\n \tstruct strbuf out = STRBUF_INIT, name = STRBUF_INIT;\n \tconst char *prefix = \"\";\n+\tconst char *desc = item->name;\n \n \tif (item->ignore)\n \t\treturn;\n@@ -547,6 +553,10 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n \t\tcolor = BRANCH_COLOR_REMOTE;\n \t\tprefix = remote_prefix;\n \t\tbreak;\n+\tcase REF_DETACHED_HEAD:\n+\t\tcolor = BRANCH_COLOR_CURRENT;\n+\t\tdesc = get_head_description();\n+\t\tbreak;\n \tdefault:\n \t\tcolor = BRANCH_COLOR_PLAIN;\n \t\tbreak;\n@@ -558,7 +568,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n \t\tcolor = BRANCH_COLOR_CURRENT;\n \t}\n \n-\tstrbuf_addf(&name, \"%s%s\", prefix, item->name);\n+\tstrbuf_addf(&name, \"%s%s\", prefix, desc);\n \tif (verbose) {\n \t\tint utf8_compensation = strlen(name.buf) - utf8_strwidth(name.buf);\n \t\tstrbuf_addf(&out, \"%c %s%-*s%s\", c, branch_get_color(color),\n@@ -581,6 +591,8 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n \t}\n \tstrbuf_release(&name);\n \tstrbuf_release(&out);\n+\tif (item->kind == REF_DETACHED_HEAD)\n+\t\tfree((void *)desc);\n }\n \n static int calc_maxwidth(struct ref_list *refs, int remote_bonus)\n@@ -600,25 +612,9 @@ static int calc_maxwidth(struct ref_list *refs, int remote_bonus)\n \treturn max;\n }\n \n-static void show_detached(struct ref_list *ref_list, int maxwidth)\n-{\n-\tstruct commit *head_commit = lookup_commit_reference_gently(head_sha1, 1);\n-\n-\tif (head_commit && is_descendant_of(head_commit, ref_list->with_commit)) {\n-\t\tstruct ref_item item;\n-\t\titem.name = get_head_description();\n-\t\titem.kind = REF_LOCAL_BRANCH;\n-\t\titem.dest = NULL;\n-\t\titem.commit = head_commit;\n-\t\titem.ignore = 0;\n-\t\tprint_ref_item(&item, maxwidth, ref_list->verbose, ref_list->abbrev, 1, \"\");\n-\t\tfree(item.name);\n-\t}\n-}\n-\n static int print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit, const char **pattern)\n {\n-\tint i;\n+\tint i, index;\n \tstruct append_ref_cb cb;\n \tstruct ref_list ref_list;\n \tint maxwidth = 0;\n@@ -642,7 +638,14 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru\n \tcb.ref_list = &ref_list;\n \tcb.pattern = pattern;\n \tcb.ret = 0;\n+\t/*\n+\t * First we obtain all regular branch refs and then if the\n+\t * HEAD is detached then we insert that ref to the end of the\n+\t * ref_fist so that it can be printed first.\n+\t */\n \tfor_each_rawref(append_ref, &cb);\n+\tif (detached)\n+\t\thead_ref(append_ref, &cb);\n \t/*\n \t * The following implementation is currently duplicated in ref-filter. It\n \t * will eventually be removed when we port branch.c to use ref-filter APIs.\n@@ -678,15 +681,20 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru\n \tif (verbose)\n \t\tmaxwidth = calc_maxwidth(&ref_list, strlen(remote_prefix));\n \n-\tqsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);\n+\tindex = ref_list.index;\n+\n+\t/* Print detached HEAD before sorting and printing the rest */\n+\tif (detached && (ref_list.list[index - 1].kind == REF_DETACHED_HEAD) &&\n+\t    !strcmp(ref_list.list[index - 1].name, head)) {\n+\t\tprint_ref_item(&ref_list.list[index - 1], maxwidth, verbose, abbrev,\n+\t\t\t       1, remote_prefix);\n+\t\tindex -= 1;\n+\t}\n \n-\tdetached = (detached && (kinds & REF_LOCAL_BRANCH));\n-\tif (detached && match_patterns(pattern, \"HEAD\"))\n-\t\tshow_detached(&ref_list, maxwidth);\n+\tqsort(ref_list.list, index, sizeof(struct ref_item), ref_cmp);\n \n-\tfor (i = 0; i < ref_list.index; i++) {\n-\t\tint current = !detached &&\n-\t\t\t(ref_list.list[i].kind == REF_LOCAL_BRANCH) &&\n+\tfor (i = 0; i < index; i++) {\n+\t\tint current = !detached && (ref_list.list[i].kind == REF_LOCAL_BRANCH) &&\n \t\t\t!strcmp(ref_list.list[i].name, head);\n \t\tprint_ref_item(&ref_list.list[i], maxwidth, verbose,\n \t\t\t       abbrev, current, remote_prefix);\n@@ -913,7 +921,11 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"branch name required\"));\n \t\treturn delete_branches(argc, argv, delete > 1, kinds, quiet);\n \t} else if (list) {\n-\t\tint ret = print_ref_list(kinds, detached, verbose, abbrev,\n+\t\tint ret;\n+\t\t/*  git branch --local also shows HEAD when it is detached */\n+\t\tif (kinds & REF_LOCAL_BRANCH)\n+\t\t\tkinds |= REF_DETACHED_HEAD;\n+\t\tret = print_ref_list(kinds, detached, verbose, abbrev,\n \t\t\t\t\t with_commit, argv);\n \t\tprint_columns(&output, colopts, NULL);\n \t\tstring_list_clear(&output, 0);\n-- \n2.5.0\n"},{"id":"267413","messageId":"1438693282-15516-5-git-send-email-Karthik.188@gmail.com","threadId":"40010","inReplyTo":"CAOLa=ZSnn19DR_Y5MqUXHed0g5MSk_dwFc48dk8GoPYvL5DQ=Q@mail.gmail.com","subject":"[PATCH 05/10] branch: move 'current' check down to the presentation layer","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-04T13:01:18Z","receivedAt":"2015-08-04T13:01:18Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"We check if given ref is the current branch in print_ref_list(). Move\nthis check to print_ref_item() where it is checked right before\nprinting.\n\nBased-on-patch-by: Jeff King <peff@peff.net>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n builtin/branch.c | 22 +++++++++++-----------\n 1 file changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 81815c9..c5f2944 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -534,9 +534,10 @@ static char *get_head_description(void)\n }\n \n static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n-\t\t\t   int abbrev, int current, const char *remote_prefix)\n+\t\t\t   int abbrev, int detached, const char *remote_prefix)\n {\n \tchar c;\n+\tint current = 0;\n \tint color;\n \tstruct strbuf out = STRBUF_INIT, name = STRBUF_INIT;\n \tconst char *prefix = \"\";\n@@ -547,15 +548,18 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n \n \tswitch (item->kind) {\n \tcase REF_LOCAL_BRANCH:\n-\t\tcolor = BRANCH_COLOR_LOCAL;\n+\t\tif (!detached && !strcmp(item->name, head))\n+\t\t\tcurrent = 1;\n+\t\telse\n+\t\t\tcolor = BRANCH_COLOR_LOCAL;\n \t\tbreak;\n \tcase REF_REMOTE_BRANCH:\n \t\tcolor = BRANCH_COLOR_REMOTE;\n \t\tprefix = remote_prefix;\n \t\tbreak;\n \tcase REF_DETACHED_HEAD:\n-\t\tcolor = BRANCH_COLOR_CURRENT;\n \t\tdesc = get_head_description();\n+\t\tcurrent = 1;\n \t\tbreak;\n \tdefault:\n \t\tcolor = BRANCH_COLOR_PLAIN;\n@@ -684,21 +688,17 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru\n \tindex = ref_list.index;\n \n \t/* Print detached HEAD before sorting and printing the rest */\n-\tif (detached && (ref_list.list[index - 1].kind == REF_DETACHED_HEAD) &&\n-\t    !strcmp(ref_list.list[index - 1].name, head)) {\n+\tif (detached) {\n \t\tprint_ref_item(&ref_list.list[index - 1], maxwidth, verbose, abbrev,\n-\t\t\t       1, remote_prefix);\n+\t\t\t       detached, remote_prefix);\n \t\tindex -= 1;\n \t}\n \n \tqsort(ref_list.list, index, sizeof(struct ref_item), ref_cmp);\n \n-\tfor (i = 0; i < index; i++) {\n-\t\tint current = !detached && (ref_list.list[i].kind == REF_LOCAL_BRANCH) &&\n-\t\t\t!strcmp(ref_list.list[i].name, head);\n+\tfor (i = 0; i < index; i++)\n \t\tprint_ref_item(&ref_list.list[i], maxwidth, verbose,\n-\t\t\t       abbrev, current, remote_prefix);\n-\t}\n+\t\t\t       abbrev, detached, remote_prefix);\n \n \tfree_ref_list(&ref_list);\n \n-- \n2.5.0\n"},{"id":"267415","messageId":"1438693282-15516-6-git-send-email-Karthik.188@gmail.com","threadId":"40010","inReplyTo":"CAOLa=ZSnn19DR_Y5MqUXHed0g5MSk_dwFc48dk8GoPYvL5DQ=Q@mail.gmail.com","subject":"[PATCH 06/10] branch: drop non-commit error reporting","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-04T13:01:19Z","receivedAt":"2015-08-04T13:01:19Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Remove the error reporting variable to make the code easier to port\nover to using ref-filter APIs.\n\nBased-on-patch-by: Jeff King <peff@peff.net>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n builtin/branch.c | 18 ++++--------------\n 1 file changed, 4 insertions(+), 14 deletions(-)\n\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex c5f2944..1ac7fbc 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -313,7 +313,6 @@ static char *resolve_symref(const char *src, const char *prefix)\n struct append_ref_cb {\n \tstruct ref_list *ref_list;\n \tconst char **pattern;\n-\tint ret;\n };\n \n static int match_patterns(const char **pattern, const char *refname)\n@@ -370,10 +369,8 @@ static int append_ref(const char *refname, const struct object_id *oid, int flag\n \tcommit = NULL;\n \tif (ref_list->verbose || ref_list->with_commit || merge_filter != NO_FILTER) {\n \t\tcommit = lookup_commit_reference_gently(oid->hash, 1);\n-\t\tif (!commit) {\n-\t\t\tcb->ret = error(_(\"branch '%s' does not point at a commit\"), refname);\n+\t\tif (!commit)\n \t\t\treturn 0;\n-\t\t}\n \n \t\t/* Filter with with_commit if specified */\n \t\tif (!is_descendant_of(commit, ref_list->with_commit))\n@@ -616,7 +613,7 @@ static int calc_maxwidth(struct ref_list *refs, int remote_bonus)\n \treturn max;\n }\n \n-static int print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit, const char **pattern)\n+static void print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit, const char **pattern)\n {\n \tint i, index;\n \tstruct append_ref_cb cb;\n@@ -641,7 +638,6 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru\n \t\tinit_revisions(&ref_list.revs, NULL);\n \tcb.ref_list = &ref_list;\n \tcb.pattern = pattern;\n-\tcb.ret = 0;\n \t/*\n \t * First we obtain all regular branch refs and then if the\n \t * HEAD is detached then we insert that ref to the end of the\n@@ -701,11 +697,6 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru\n \t\t\t       abbrev, detached, remote_prefix);\n \n \tfree_ref_list(&ref_list);\n-\n-\tif (cb.ret)\n-\t\terror(_(\"some refs could not be read\"));\n-\n-\treturn cb.ret;\n }\n \n static void rename_branch(const char *oldname, const char *newname, int force)\n@@ -921,15 +912,14 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"branch name required\"));\n \t\treturn delete_branches(argc, argv, delete > 1, kinds, quiet);\n \t} else if (list) {\n-\t\tint ret;\n \t\t/*  git branch --local also shows HEAD when it is detached */\n \t\tif (kinds & REF_LOCAL_BRANCH)\n \t\t\tkinds |= REF_DETACHED_HEAD;\n-\t\tret = print_ref_list(kinds, detached, verbose, abbrev,\n+\t\tprint_ref_list(kinds, detached, verbose, abbrev,\n \t\t\t\t\t with_commit, argv);\n \t\tprint_columns(&output, colopts, NULL);\n \t\tstring_list_clear(&output, 0);\n-\t\treturn ret;\n+\t\treturn 0;\n \t}\n \telse if (edit_description) {\n \t\tconst char *branch_name;\n-- \n2.5.0\n"},{"id":"267417","messageId":"1438693282-15516-7-git-send-email-Karthik.188@gmail.com","threadId":"40010","inReplyTo":"CAOLa=ZSnn19DR_Y5MqUXHed0g5MSk_dwFc48dk8GoPYvL5DQ=Q@mail.gmail.com","subject":"[PATCH 07/10] branch.c: use 'ref-filter' data structures","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-04T13:01:20Z","receivedAt":"2015-08-04T13:01:20Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Make 'branch.c' use 'ref-filter' data structures and make changes to\nsupport the new data structures. This is a part of the process of\nporting 'branch.c' to use 'ref-filter' APIs.\n\nThis is a temporary step before porting 'branch.c' to use 'ref-filter'\ncompletely. As this is a temporary step, most of the code introduced\nhere will be removed when 'branch.c' is ported over to use\n'ref-filter' APIs\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n builtin/branch.c | 295 ++++++++++++++++++++++---------------------------------\n ref-filter.h     |   7 +-\n 2 files changed, 122 insertions(+), 180 deletions(-)\n\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 1ac7fbc..edc3d7d 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -19,6 +19,7 @@\n #include \"column.h\"\n #include \"utf8.h\"\n #include \"wt-status.h\"\n+#include \"ref-filter.h\"\n \n static const char * const builtin_branch_usage[] = {\n \tN_(\"git branch [<options>] [-r | -a] [--merged | --no-merged]\"),\n@@ -28,10 +29,6 @@ static const char * const builtin_branch_usage[] = {\n \tNULL\n };\n \n-#define REF_LOCAL_BRANCH    0x01\n-#define REF_REMOTE_BRANCH   0x02\n-#define REF_DETACHED_HEAD   0x04\n-\n static const char *head;\n static unsigned char head_sha1[20];\n \n@@ -53,13 +50,6 @@ enum color_branch {\n \tBRANCH_COLOR_UPSTREAM = 5\n };\n \n-static enum merge_filter {\n-\tNO_FILTER = 0,\n-\tSHOW_NOT_MERGED,\n-\tSHOW_MERGED\n-} merge_filter;\n-static unsigned char merge_filter_ref[20];\n-\n static struct string_list output = STRING_LIST_INIT_DUP;\n static unsigned int colopts;\n \n@@ -280,22 +270,6 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,\n \treturn(ret);\n }\n \n-struct ref_item {\n-\tchar *name;\n-\tchar *dest;\n-\tunsigned int kind;\n-\tstruct commit *commit;\n-\tint ignore;\n-};\n-\n-struct ref_list {\n-\tstruct rev_info revs;\n-\tint index, alloc, verbose, abbrev;\n-\tstruct ref_item *list;\n-\tstruct commit_list *with_commit;\n-\tint kinds;\n-};\n-\n static char *resolve_symref(const char *src, const char *prefix)\n {\n \tunsigned char sha1[20];\n@@ -310,11 +284,6 @@ static char *resolve_symref(const char *src, const char *prefix)\n \treturn xstrdup(dst);\n }\n \n-struct append_ref_cb {\n-\tstruct ref_list *ref_list;\n-\tconst char **pattern;\n-};\n-\n static int match_patterns(const char **pattern, const char *refname)\n {\n \tif (!*pattern)\n@@ -327,11 +296,29 @@ static int match_patterns(const char **pattern, const char *refname)\n \treturn 0;\n }\n \n+/*\n+ * Allocate memory for a new ref_array_item and insert that into the\n+ * given ref_array. Doesn't take the objectname unlike\n+ * new_ref_array_item(). This is a temporary function which will be\n+ * removed when we port branch.c to use ref-filter APIs.\n+ */\n+static struct ref_array_item *ref_array_append(struct ref_array *array, const char *refname)\n+{\n+\tsize_t len = strlen(refname);\n+\tstruct ref_array_item *ref = xcalloc(1, sizeof(struct ref_array_item) + len + 1);\n+\tmemcpy(ref->refname, refname, len);\n+\tref->refname[len] = '\\0';\n+\tREALLOC_ARRAY(array->items, array->nr + 1);\n+\tarray->items[array->nr++] = ref;\n+\treturn ref;\n+}\n+\n static int append_ref(const char *refname, const struct object_id *oid, int flags, void *cb_data)\n {\n-\tstruct append_ref_cb *cb = (struct append_ref_cb *)(cb_data);\n-\tstruct ref_list *ref_list = cb->ref_list;\n-\tstruct ref_item *newitem;\n+\tstruct ref_filter_cbdata *cb = (struct ref_filter_cbdata *)(cb_data);\n+\tstruct ref_filter *filter = cb->filter;\n+\tstruct ref_array *array = cb->array;\n+\tstruct ref_array_item *item;\n \tstruct commit *commit;\n \tint kind, i;\n \tconst char *prefix, *orig_refname = refname;\n@@ -360,59 +347,46 @@ static int append_ref(const char *refname, const struct object_id *oid, int flag\n \t}\n \n \t/* Don't add types the caller doesn't want */\n-\tif ((kind & ref_list->kinds) == 0)\n+\tif ((kind & filter->branch_kind) == 0)\n \t\treturn 0;\n \n-\tif (!match_patterns(cb->pattern, refname))\n+\tif (!match_patterns(filter->name_patterns, refname))\n \t\treturn 0;\n \n \tcommit = NULL;\n-\tif (ref_list->verbose || ref_list->with_commit || merge_filter != NO_FILTER) {\n+\tif (filter->verbose || filter->with_commit || filter->merge != REF_FILTER_MERGED_NONE) {\n \t\tcommit = lookup_commit_reference_gently(oid->hash, 1);\n \t\tif (!commit)\n \t\t\treturn 0;\n \n \t\t/* Filter with with_commit if specified */\n-\t\tif (!is_descendant_of(commit, ref_list->with_commit))\n+\t\tif (!is_descendant_of(commit, filter->with_commit))\n \t\t\treturn 0;\n \n-\t\tif (merge_filter != NO_FILTER)\n-\t\t\tadd_pending_object(&ref_list->revs,\n+\t\tif (filter->merge != REF_FILTER_MERGED_NONE)\n+\t\t\tadd_pending_object(array->revs,\n \t\t\t\t\t   (struct object *)commit, refname);\n \t}\n \n-\tALLOC_GROW(ref_list->list, ref_list->index + 1, ref_list->alloc);\n+\titem = ref_array_append(array, refname);\n \n \t/* Record the new item */\n-\tnewitem = &(ref_list->list[ref_list->index++]);\n-\tnewitem->name = xstrdup(refname);\n-\tnewitem->kind = kind;\n-\tnewitem->commit = commit;\n-\tnewitem->dest = resolve_symref(orig_refname, prefix);\n-\tnewitem->ignore = 0;\n+\titem->kind = kind;\n+\titem->commit = commit;\n+\titem->symref = resolve_symref(orig_refname, prefix);\n+\titem->ignore = 0;\n \n \treturn 0;\n }\n \n-static void free_ref_list(struct ref_list *ref_list)\n-{\n-\tint i;\n-\n-\tfor (i = 0; i < ref_list->index; i++) {\n-\t\tfree(ref_list->list[i].name);\n-\t\tfree(ref_list->list[i].dest);\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-\tstruct ref_item *c2 = (struct ref_item *)(r2);\n+\tstruct ref_array_item *c1 = *((struct ref_array_item **)r1);\n+\tstruct ref_array_item *c2 = *((struct ref_array_item **)r2);\n \n \tif (c1->kind != c2->kind)\n \t\treturn c1->kind - c2->kind;\n-\treturn strcmp(c1->name, c2->name);\n+\treturn strcmp(c1->refname, c2->refname);\n }\n \n static void fill_tracking_info(struct strbuf *stat, const char *branch_name,\n@@ -477,8 +451,8 @@ static void fill_tracking_info(struct strbuf *stat, const char *branch_name,\n \tfree(ref);\n }\n \n-static void add_verbose_info(struct strbuf *out, struct ref_item *item,\n-\t\t\t     int verbose, int abbrev)\n+static void add_verbose_info(struct strbuf *out, struct ref_array_item *item,\n+\t\t\t     struct ref_filter *filter)\n {\n \tstruct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;\n \tconst char *sub = _(\" **** invalid ref ****\");\n@@ -490,10 +464,10 @@ static void add_verbose_info(struct strbuf *out, struct ref_item *item,\n \t}\n \n \tif (item->kind == REF_LOCAL_BRANCH)\n-\t\tfill_tracking_info(&stat, item->name, verbose > 1);\n+\t\tfill_tracking_info(&stat, item->refname, filter->verbose > 1);\n \n \tstrbuf_addf(out, \" %s %s%s\",\n-\t\tfind_unique_abbrev(item->commit->object.sha1, abbrev),\n+\t\tfind_unique_abbrev(item->commit->object.sha1, filter->abbrev),\n \t\tstat.buf, sub);\n \tstrbuf_release(&stat);\n \tstrbuf_release(&subject);\n@@ -530,22 +504,22 @@ static char *get_head_description(void)\n \treturn strbuf_detach(&desc, NULL);\n }\n \n-static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n-\t\t\t   int abbrev, int detached, const char *remote_prefix)\n+static void print_ref_item(struct ref_array_item *item, int maxwidth,\n+\t\t\t   struct ref_filter *filter, const char *remote_prefix)\n {\n \tchar c;\n \tint current = 0;\n \tint color;\n \tstruct strbuf out = STRBUF_INIT, name = STRBUF_INIT;\n \tconst char *prefix = \"\";\n-\tconst char *desc = item->name;\n+\tconst char *desc = item->refname;\n \n \tif (item->ignore)\n \t\treturn;\n \n \tswitch (item->kind) {\n \tcase REF_LOCAL_BRANCH:\n-\t\tif (!detached && !strcmp(item->name, head))\n+\t\tif (!filter->detached && !strcmp(item->refname, head))\n \t\t\tcurrent = 1;\n \t\telse\n \t\t\tcolor = BRANCH_COLOR_LOCAL;\n@@ -570,7 +544,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n \t}\n \n \tstrbuf_addf(&name, \"%s%s\", prefix, desc);\n-\tif (verbose) {\n+\tif (filter->verbose) {\n \t\tint utf8_compensation = strlen(name.buf) - utf8_strwidth(name.buf);\n \t\tstrbuf_addf(&out, \"%c %s%-*s%s\", c, branch_get_color(color),\n \t\t\t    maxwidth + utf8_compensation, name.buf,\n@@ -579,13 +553,13 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n \t\tstrbuf_addf(&out, \"%c %s%s%s\", c, branch_get_color(color),\n \t\t\t    name.buf, branch_get_color(BRANCH_COLOR_RESET));\n \n-\tif (item->dest)\n-\t\tstrbuf_addf(&out, \" -> %s\", item->dest);\n-\telse if (verbose)\n+\tif (item->symref)\n+\t\tstrbuf_addf(&out, \" -> %s\", item->symref);\n+\telse if (filter->verbose)\n \t\t/* \" f7c0c00 [ahead 58, behind 197] vcs-svn: drop obj_pool.h\" */\n-\t\tadd_verbose_info(&out, item, verbose, abbrev);\n+\t\tadd_verbose_info(&out, item, filter);\n \tif (column_active(colopts)) {\n-\t\tassert(!verbose && \"--column and --verbose are incompatible\");\n+\t\tassert(!filter->verbose && \"--column and --verbose are incompatible\");\n \t\tstring_list_append(&output, out.buf);\n \t} else {\n \t\tprintf(\"%s\\n\", out.buf);\n@@ -596,14 +570,14 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n \t\tfree((void *)desc);\n }\n \n-static int calc_maxwidth(struct ref_list *refs, int remote_bonus)\n+static int calc_maxwidth(struct ref_array *refs, int remote_bonus)\n {\n \tint i, max = 0;\n-\tfor (i = 0; i < refs->index; i++) {\n-\t\tstruct ref_item *it = &refs->list[i];\n-\t\tint w = utf8_strwidth(it->name);\n+\tfor (i = 0; i < refs->nr; i++) {\n+\t\tstruct ref_array_item *it = refs->items[i];\n+\t\tint w = utf8_strwidth(it->refname);\n \n-\t\tif (refs->list[i].ignore)\n+\t\tif (it->ignore)\n \t\t\tcontinue;\n \t\tif (it->kind == REF_REMOTE_BRANCH)\n \t\t\tw += remote_bonus;\n@@ -613,90 +587,81 @@ static int calc_maxwidth(struct ref_list *refs, int remote_bonus)\n \treturn max;\n }\n \n-static void print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit, const char **pattern)\n+static void print_ref_list(struct ref_filter *filter)\n {\n \tint i, index;\n-\tstruct append_ref_cb cb;\n-\tstruct ref_list ref_list;\n+\tstruct ref_array array;\n+\tstruct ref_filter_cbdata data;\n \tint maxwidth = 0;\n \tconst char *remote_prefix = \"\";\n+\tstruct rev_info revs;\n \n \t/*\n \t * If we are listing more than just remote branches,\n \t * then remote branches will have a \"remotes/\" prefix.\n \t * We need to account for this in the width.\n \t */\n-\tif (kinds != REF_REMOTE_BRANCH)\n+\tif (filter->branch_kind != REF_REMOTE_BRANCH)\n \t\tremote_prefix = \"remotes/\";\n \n-\tmemset(&ref_list, 0, sizeof(ref_list));\n-\tref_list.kinds = kinds;\n-\tref_list.verbose = verbose;\n-\tref_list.abbrev = abbrev;\n-\tref_list.with_commit = with_commit;\n-\tif (merge_filter != NO_FILTER)\n-\t\tinit_revisions(&ref_list.revs, NULL);\n-\tcb.ref_list = &ref_list;\n-\tcb.pattern = pattern;\n+\tmemset(&array, 0, sizeof(array));\n+\tif (filter->merge != REF_FILTER_MERGED_NONE)\n+\t\tinit_revisions(&revs, NULL);\n+\n+\tdata.array = &array;\n+\tdata.filter = filter;\n+\tarray.revs = &revs;\n+\n \t/*\n \t * First we obtain all regular branch refs and then if the\n \t * HEAD is detached then we insert that ref to the end of the\n \t * ref_fist so that it can be printed first.\n \t */\n-\tfor_each_rawref(append_ref, &cb);\n-\tif (detached)\n-\t\thead_ref(append_ref, &cb);\n+\tfor_each_rawref(append_ref, &data);\n+\tif (filter->detached)\n+\t\thead_ref(append_ref, &data);\n \t/*\n \t * The following implementation is currently duplicated in ref-filter. It\n \t * will eventually be removed when we port branch.c to use ref-filter APIs.\n \t */\n-\tif (merge_filter != NO_FILTER) {\n-\t\tstruct commit *filter;\n-\t\tfilter = lookup_commit_reference_gently(merge_filter_ref, 0);\n-\t\tif (!filter)\n-\t\t\tdie(_(\"object '%s' does not point to a commit\"),\n-\t\t\t    sha1_to_hex(merge_filter_ref));\n-\n-\t\tfilter->object.flags |= UNINTERESTING;\n-\t\tadd_pending_object(&ref_list.revs,\n-\t\t\t\t   (struct object *) filter, \"\");\n-\t\tref_list.revs.limited = 1;\n-\n-\t\tif (prepare_revision_walk(&ref_list.revs))\n+\tif (filter->merge != REF_FILTER_MERGED_NONE) {\n+\t\tfilter->merge_commit->object.flags |= UNINTERESTING;\n+\t\tadd_pending_object(&revs, &filter->merge_commit->object, \"\");\n+\t\trevs.limited = 1;\n+\n+\t\tif (prepare_revision_walk(&revs))\n \t\t\tdie(_(\"revision walk setup failed\"));\n \n-\t\tfor (i = 0; i < ref_list.index; i++) {\n-\t\t\tstruct ref_item *item = &ref_list.list[i];\n+\t\tfor (i = 0; i < array.nr; i++) {\n+\t\t\tstruct ref_array_item *item = array.items[i];\n \t\t\tstruct commit *commit = item->commit;\n \t\t\tint is_merged = !!(commit->object.flags & UNINTERESTING);\n-\t\t\titem->ignore = is_merged != (merge_filter == SHOW_MERGED);\n+\t\t\titem->ignore = is_merged != (filter->merge == REF_FILTER_MERGED_INCLUDE);\n \t\t}\n \n-\t\tfor (i = 0; i < ref_list.index; i++) {\n-\t\t\tstruct ref_item *item = &ref_list.list[i];\n+\t\tfor (i = 0; i < array.nr; i++) {\n+\t\t\tstruct ref_array_item *item = array.items[i];\n \t\t\tclear_commit_marks(item->commit, ALL_REV_FLAGS);\n \t\t}\n-\t\tclear_commit_marks(filter, ALL_REV_FLAGS);\n+\t\tclear_commit_marks(filter->merge_commit, ALL_REV_FLAGS);\n \t}\n-\tif (verbose)\n-\t\tmaxwidth = calc_maxwidth(&ref_list, strlen(remote_prefix));\n+\tif (filter->verbose)\n+\t\tmaxwidth = calc_maxwidth(&array, strlen(remote_prefix));\n \n-\tindex = ref_list.index;\n+\tindex = array.nr;\n \n \t/* Print detached HEAD before sorting and printing the rest */\n-\tif (detached) {\n-\t\tprint_ref_item(&ref_list.list[index - 1], maxwidth, verbose, abbrev,\n-\t\t\t       detached, remote_prefix);\n+\tif (filter->detached) {\n+\t\tprint_ref_item(array.items[index - 1], maxwidth, filter, remote_prefix);\n \t\tindex -= 1;\n \t}\n \n-\tqsort(ref_list.list, index, sizeof(struct ref_item), ref_cmp);\n+\tqsort(array.items, index, sizeof(struct ref_array_item *), ref_cmp);\n \n \tfor (i = 0; i < index; i++)\n-\t\tprint_ref_item(&ref_list.list[i], maxwidth, verbose,\n-\t\t\t       abbrev, detached, remote_prefix);\n+\t\tprint_ref_item(array.items[i], maxwidth, filter, remote_prefix);\n \n-\tfree_ref_list(&ref_list);\n+\tref_array_clear(&array);\n }\n \n static void rename_branch(const char *oldname, const char *newname, int force)\n@@ -752,24 +717,6 @@ static void rename_branch(const char *oldname, const char *newname, int force)\n \tstrbuf_release(&newsection);\n }\n \n-/*\n- * This function is duplicated in ref-filter. It will eventually be removed\n- * when we port branch.c to use ref-filter APIs.\n- */\n-static int opt_parse_merge_filter(const struct option *opt, const char *arg, int unset)\n-{\n-\tmerge_filter = ((opt->long_name[0] == 'n')\n-\t\t\t? SHOW_NOT_MERGED\n-\t\t\t: SHOW_MERGED);\n-\tif (unset)\n-\t\tmerge_filter = SHOW_NOT_MERGED; /* b/c for --no-merged */\n-\tif (!arg)\n-\t\targ = \"HEAD\";\n-\tif (get_sha1(arg, merge_filter_ref))\n-\t\tdie(_(\"malformed object name %s\"), arg);\n-\treturn 0;\n-}\n-\n static const char edit_description[] = \"BRANCH_DESCRIPTION\";\n \n static int edit_branch_description(const char *branch_name)\n@@ -809,17 +756,15 @@ static int edit_branch_description(const char *branch_name)\n int cmd_branch(int argc, const char **argv, const char *prefix)\n {\n \tint delete = 0, rename = 0, force = 0, list = 0;\n-\tint verbose = 0, abbrev = -1, detached = 0;\n \tint reflog = 0, edit_description = 0;\n \tint quiet = 0, unset_upstream = 0;\n \tconst char *new_upstream = NULL;\n \tenum branch_track track;\n-\tint kinds = REF_LOCAL_BRANCH;\n-\tstruct commit_list *with_commit = NULL;\n+\tstruct ref_filter filter;\n \n \tstruct option options[] = {\n \t\tOPT_GROUP(N_(\"Generic options\")),\n-\t\tOPT__VERBOSE(&verbose,\n+\t\tOPT__VERBOSE(&filter.verbose,\n \t\t\tN_(\"show hash and subject, give twice for upstream branch\")),\n \t\tOPT__QUIET(&quiet, N_(\"suppress informational messages\")),\n \t\tOPT_SET_INT('t', \"track\",  &track, N_(\"set up tracking mode (see git-pull(1))\"),\n@@ -829,14 +774,14 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\tOPT_STRING('u', \"set-upstream-to\", &new_upstream, \"upstream\", \"change the upstream info\"),\n \t\tOPT_BOOL(0, \"unset-upstream\", &unset_upstream, \"Unset the upstream info\"),\n \t\tOPT__COLOR(&branch_use_color, N_(\"use colored output\")),\n-\t\tOPT_SET_INT('r', \"remotes\",     &kinds, N_(\"act on remote-tracking branches\"),\n+\t\tOPT_SET_INT('r', \"remotes\",     &filter.branch_kind, N_(\"act on remote-tracking branches\"),\n \t\t\tREF_REMOTE_BRANCH),\n-\t\tOPT_CONTAINS(&with_commit, N_(\"print only branches that contain the commit\")),\n-\t\tOPT_WITH(&with_commit, N_(\"print only branches that contain the commit\")),\n-\t\tOPT__ABBREV(&abbrev),\n+\t\tOPT_CONTAINS(&filter.with_commit, N_(\"print only branches that contain the commit\")),\n+\t\tOPT_WITH(&filter.with_commit, N_(\"print only branches that contain the commit\")),\n+\t\tOPT__ABBREV(&filter.abbrev),\n \n \t\tOPT_GROUP(N_(\"Specific git-branch actions:\")),\n-\t\tOPT_SET_INT('a', \"all\", &kinds, N_(\"list both remote-tracking and local branches\"),\n+\t\tOPT_SET_INT('a', \"all\", &filter.branch_kind, N_(\"list both remote-tracking and local branches\"),\n \t\t\tREF_REMOTE_BRANCH | REF_LOCAL_BRANCH),\n \t\tOPT_BIT('d', \"delete\", &delete, N_(\"delete fully merged branch\"), 1),\n \t\tOPT_BIT('D', NULL, &delete, N_(\"delete branch (even if not merged)\"), 2),\n@@ -847,22 +792,16 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"edit-description\", &edit_description,\n \t\t\t N_(\"edit the description for the branch\")),\n \t\tOPT__FORCE(&force, N_(\"force creation, move/rename, deletion\")),\n-\t\t{\n-\t\t\tOPTION_CALLBACK, 0, \"no-merged\", &merge_filter_ref,\n-\t\t\tN_(\"commit\"), N_(\"print only not merged branches\"),\n-\t\t\tPARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,\n-\t\t\topt_parse_merge_filter, (intptr_t) \"HEAD\",\n-\t\t},\n-\t\t{\n-\t\t\tOPTION_CALLBACK, 0, \"merged\", &merge_filter_ref,\n-\t\t\tN_(\"commit\"), N_(\"print only merged branches\"),\n-\t\t\tPARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,\n-\t\t\topt_parse_merge_filter, (intptr_t) \"HEAD\",\n-\t\t},\n+\t\tOPT_MERGED(&filter, N_(\"print only branches that are merged\")),\n+\t\tOPT_NO_MERGED(&filter, N_(\"print only branches that are not merged\")),\n \t\tOPT_COLUMN(0, \"column\", &colopts, N_(\"list branches in columns\")),\n \t\tOPT_END(),\n \t};\n \n+\tmemset(&filter, 0, sizeof(filter));\n+\tfilter.branch_kind = REF_LOCAL_BRANCH;\n+\tfilter.abbrev = -1;\n+\n \tif (argc == 2 && !strcmp(argv[1], \"-h\"))\n \t\tusage_with_options(builtin_branch_usage, options);\n \n@@ -874,11 +813,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \tif (!head)\n \t\tdie(_(\"Failed to resolve HEAD as a valid ref.\"));\n \tif (!strcmp(head, \"HEAD\"))\n-\t\tdetached = 1;\n+\t\tfilter.detached = 1;\n \telse if (!skip_prefix(head, \"refs/heads/\", &head))\n \t\tdie(_(\"HEAD not found below refs/heads!\"));\n-\thashcpy(merge_filter_ref, head_sha1);\n-\n \n \targc = parse_options(argc, argv, prefix, options, builtin_branch_usage,\n \t\t\t     0);\n@@ -886,17 +823,17 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \tif (!delete && !rename && !edit_description && !new_upstream && !unset_upstream && argc == 0)\n \t\tlist = 1;\n \n-\tif (with_commit || merge_filter != NO_FILTER)\n+\tif (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE)\n \t\tlist = 1;\n \n \tif (!!delete + !!rename + !!new_upstream +\n \t    list + unset_upstream > 1)\n \t\tusage_with_options(builtin_branch_usage, options);\n \n-\tif (abbrev == -1)\n-\t\tabbrev = DEFAULT_ABBREV;\n+\tif (filter.abbrev == -1)\n+\t\tfilter.abbrev = DEFAULT_ABBREV;\n \tfinalize_colopts(&colopts, -1);\n-\tif (verbose) {\n+\tif (filter.verbose) {\n \t\tif (explicitly_enable_column(colopts))\n \t\t\tdie(_(\"--column and --verbose are incompatible\"));\n \t\tcolopts = 0;\n@@ -910,13 +847,13 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \tif (delete) {\n \t\tif (!argc)\n \t\t\tdie(_(\"branch name required\"));\n-\t\treturn delete_branches(argc, argv, delete > 1, kinds, quiet);\n+\t\treturn delete_branches(argc, argv, delete > 1, filter.branch_kind, quiet);\n \t} else if (list) {\n \t\t/*  git branch --local also shows HEAD when it is detached */\n-\t\tif (kinds & REF_LOCAL_BRANCH)\n-\t\t\tkinds |= REF_DETACHED_HEAD;\n-\t\tprint_ref_list(kinds, detached, verbose, abbrev,\n-\t\t\t\t\t with_commit, argv);\n+\t\tif (filter.branch_kind & REF_LOCAL_BRANCH)\n+\t\t\tfilter.branch_kind |= REF_DETACHED_HEAD;\n+\t\tfilter.name_patterns = argv;\n+\t\tprint_ref_list(&filter);\n \t\tprint_columns(&output, colopts, NULL);\n \t\tstring_list_clear(&output, 0);\n \t\treturn 0;\n@@ -926,7 +863,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\tstruct strbuf branch_ref = STRBUF_INIT;\n \n \t\tif (!argc) {\n-\t\t\tif (detached)\n+\t\t\tif (filter.detached)\n \t\t\t\tdie(_(\"Cannot give description to detached HEAD\"));\n \t\t\tbranch_name = head;\n \t\t} else if (argc == 1)\n@@ -1014,7 +951,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\tif (!branch)\n \t\t\tdie(_(\"no such branch '%s'\"), argv[0]);\n \n-\t\tif (kinds != REF_LOCAL_BRANCH)\n+\t\tif (filter.branch_kind != REF_LOCAL_BRANCH)\n \t\t\tdie(_(\"-a and -r options to 'git branch' do not make sense with a branch name\"));\n \n \t\tif (track == BRANCH_TRACK_OVERRIDE)\ndiff --git a/ref-filter.h b/ref-filter.h\nindex b5a13e8..1b1e6de 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -5,6 +5,7 @@\n #include \"refs.h\"\n #include \"commit.h\"\n #include \"parse-options.h\"\n+#include \"revision.h\"\n \n /* Quoting styles */\n #define QUOTE_NONE 0\n@@ -57,6 +58,7 @@ struct ref_sorting {\n struct ref_array_item {\n \tunsigned char objectname[20];\n \tint flag, kind;\n+\tint ignore : 1; /* To be removed in the next patch */\n \tconst char *symref;\n \tstruct commit *commit;\n \tstruct atom_value *value;\n@@ -66,6 +68,7 @@ struct ref_array_item {\n struct ref_array {\n \tint nr, alloc;\n \tstruct ref_array_item **items;\n+\tstruct rev_info *revs;\n };\n \n struct ref_filter {\n@@ -81,8 +84,10 @@ struct ref_filter {\n \tstruct commit *merge_commit;\n \n \tunsigned int with_commit_tag_algo : 1,\n-\t\tmatch_as_path : 1;\n+\t\tmatch_as_path : 1,\n+\t\tdetached : 1;\n \tunsigned int lines, branch_kind;\n+\tint abbrev, verbose;\n };\n \n struct ref_filter_cbdata {\n-- \n2.5.0\n"},{"id":"267416","messageId":"1438693282-15516-8-git-send-email-Karthik.188@gmail.com","threadId":"40010","inReplyTo":"CAOLa=ZSnn19DR_Y5MqUXHed0g5MSk_dwFc48dk8GoPYvL5DQ=Q@mail.gmail.com","subject":"[PATCH 08/10] branch.c: use 'ref-filter' APIs","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-04T13:01:21Z","receivedAt":"2015-08-04T13:01:21Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Make 'branch.c' use 'ref-filter' APIs for iterating through refs\nsorting. This removes most of the code used in 'branch.c' replacing it\nwith calls to the 'ref-filter' library.\n\nMake 'branch.c' use the 'filter_refs()' function provided by 'ref-filter'\nto filter out tags based on the options set.\n\nWe provide a sorting option provided for 'branch.c' by using the sorting\noptions provided by 'ref-filter'.\n\nAlso remove the 'ignore' variable from ref_array_item as it was\npreviously used for the '--merged' option and now that is handled by\nref-filter.\n\nThe test t1430 'git branch shows badly named ref' fails as this checks\nthe ability of branch.c to list broken refs, which is now displayed as\na warning while using ref-filter APIs.\n\nModify documentation and add tests for the same.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n Documentation/git-branch.txt |   9 +-\n builtin/branch.c             | 219 ++++++++-----------------------------------\n ref-filter.c                 |   8 +-\n ref-filter.h                 |   1 -\n t/t1430-bad-ref-name.sh      |  10 +-\n t/t3203-branch-output.sh     |  11 +++\n 6 files changed, 68 insertions(+), 190 deletions(-)\n\ndiff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt\nindex a67138a..897cd81 100644\n--- a/Documentation/git-branch.txt\n+++ b/Documentation/git-branch.txt\n@@ -11,7 +11,7 @@ SYNOPSIS\n 'git branch' [--color[=<when>] | --no-color] [-r | -a]\n \t[--list] [-v [--abbrev=<length> | --no-abbrev]]\n \t[--column[=<options>] | --no-column]\n-\t[(--merged | --no-merged | --contains) [<commit>]] [<pattern>...]\n+\t[(--merged | --no-merged | --contains) [<commit>]] [--sort=<key>] [<pattern>...]\n 'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]\n 'git branch' (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>]\n 'git branch' --unset-upstream [<branchname>]\n@@ -229,6 +229,13 @@ start-point is either a local or remote-tracking branch.\n \tThe new name for an existing branch. The same restrictions as for\n \t<branchname> apply.\n \n+--sort=<key>::\n+\tSort based on the key given. Prefix `-` to sort in descending\n+\torder of the value. You may use the --sort=<key> option\n+\tmultiple times, in which case the last key becomes the primary\n+\tkey. The keys supported are the same as those in `git\n+\tfor-each-ref`. Sort order defaults to sorting based on branch\n+\ttype.\n \n Examples\n --------\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex edc3d7d..34ccf0c 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -270,125 +270,6 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,\n \treturn(ret);\n }\n \n-static char *resolve_symref(const char *src, const char *prefix)\n-{\n-\tunsigned char sha1[20];\n-\tint flag;\n-\tconst char *dst;\n-\n-\tdst = resolve_ref_unsafe(src, 0, sha1, &flag);\n-\tif (!(dst && (flag & REF_ISSYMREF)))\n-\t\treturn NULL;\n-\tif (prefix)\n-\t\tskip_prefix(dst, prefix, &dst);\n-\treturn xstrdup(dst);\n-}\n-\n-static int match_patterns(const char **pattern, const char *refname)\n-{\n-\tif (!*pattern)\n-\t\treturn 1; /* no pattern always matches */\n-\twhile (*pattern) {\n-\t\tif (!wildmatch(*pattern, refname, 0, NULL))\n-\t\t\treturn 1;\n-\t\tpattern++;\n-\t}\n-\treturn 0;\n-}\n-\n-/*\n- * Allocate memory for a new ref_array_item and insert that into the\n- * given ref_array. Doesn't take the objectname unlike\n- * new_ref_array_item(). This is a temporary function which will be\n- * removed when we port branch.c to use ref-filter APIs.\n- */\n-static struct ref_array_item *ref_array_append(struct ref_array *array, const char *refname)\n-{\n-\tsize_t len = strlen(refname);\n-\tstruct ref_array_item *ref = xcalloc(1, sizeof(struct ref_array_item) + len + 1);\n-\tmemcpy(ref->refname, refname, len);\n-\tref->refname[len] = '\\0';\n-\tREALLOC_ARRAY(array->items, array->nr + 1);\n-\tarray->items[array->nr++] = ref;\n-\treturn ref;\n-}\n-\n-static int append_ref(const char *refname, const struct object_id *oid, int flags, void *cb_data)\n-{\n-\tstruct ref_filter_cbdata *cb = (struct ref_filter_cbdata *)(cb_data);\n-\tstruct ref_filter *filter = cb->filter;\n-\tstruct ref_array *array = cb->array;\n-\tstruct ref_array_item *item;\n-\tstruct commit *commit;\n-\tint kind, i;\n-\tconst char *prefix, *orig_refname = refname;\n-\n-\tstatic struct {\n-\t\tint kind;\n-\t\tconst char *prefix;\n-\t} ref_kind[] = {\n-\t\t{ REF_LOCAL_BRANCH, \"refs/heads/\" },\n-\t\t{ REF_REMOTE_BRANCH, \"refs/remotes/\" },\n-\t};\n-\n-\t/* Detect kind */\n-\tfor (i = 0; i < ARRAY_SIZE(ref_kind); i++) {\n-\t\tprefix = ref_kind[i].prefix;\n-\t\tif (skip_prefix(refname, prefix, &refname)) {\n-\t\t\tkind = ref_kind[i].kind;\n-\t\t\tbreak;\n-\t\t}\n-\t}\n-\tif (ARRAY_SIZE(ref_kind) <= i) {\n-\t\tif (!strcmp(refname, \"HEAD\"))\n-\t\t\tkind = REF_DETACHED_HEAD;\n-\t\telse\n-\t\t\treturn 0;\n-\t}\n-\n-\t/* Don't add types the caller doesn't want */\n-\tif ((kind & filter->branch_kind) == 0)\n-\t\treturn 0;\n-\n-\tif (!match_patterns(filter->name_patterns, refname))\n-\t\treturn 0;\n-\n-\tcommit = NULL;\n-\tif (filter->verbose || filter->with_commit || filter->merge != REF_FILTER_MERGED_NONE) {\n-\t\tcommit = lookup_commit_reference_gently(oid->hash, 1);\n-\t\tif (!commit)\n-\t\t\treturn 0;\n-\n-\t\t/* Filter with with_commit if specified */\n-\t\tif (!is_descendant_of(commit, filter->with_commit))\n-\t\t\treturn 0;\n-\n-\t\tif (filter->merge != REF_FILTER_MERGED_NONE)\n-\t\t\tadd_pending_object(array->revs,\n-\t\t\t\t\t   (struct object *)commit, refname);\n-\t}\n-\n-\titem = ref_array_append(array, refname);\n-\n-\t/* Record the new item */\n-\titem->kind = kind;\n-\titem->commit = commit;\n-\titem->symref = resolve_symref(orig_refname, prefix);\n-\titem->ignore = 0;\n-\n-\treturn 0;\n-}\n-\n-static int ref_cmp(const void *r1, const void *r2)\n-{\n-\tstruct ref_array_item *c1 = *((struct ref_array_item **)r1);\n-\tstruct ref_array_item *c2 = *((struct ref_array_item **)r2);\n-\n-\tif (c1->kind != c2->kind)\n-\t\treturn c1->kind - c2->kind;\n-\treturn strcmp(c1->refname, c2->refname);\n-}\n-\n static void fill_tracking_info(struct strbuf *stat, const char *branch_name,\n \t\tint show_upstream_ref)\n {\n@@ -452,7 +333,7 @@ static void fill_tracking_info(struct strbuf *stat, const char *branch_name,\n }\n \n static void add_verbose_info(struct strbuf *out, struct ref_array_item *item,\n-\t\t\t     struct ref_filter *filter)\n+\t\t\t     struct ref_filter *filter, const char *refname)\n {\n \tstruct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;\n \tconst char *sub = _(\" **** invalid ref ****\");\n@@ -464,7 +345,7 @@ static void add_verbose_info(struct strbuf *out, struct ref_array_item *item,\n \t}\n \n \tif (item->kind == REF_LOCAL_BRANCH)\n-\t\tfill_tracking_info(&stat, item->refname, filter->verbose > 1);\n+\t\tfill_tracking_info(&stat, refname, filter->verbose > 1);\n \n \tstrbuf_addf(out, \" %s %s%s\",\n \t\tfind_unique_abbrev(item->commit->object.sha1, filter->abbrev),\n@@ -504,8 +385,8 @@ static char *get_head_description(void)\n \treturn strbuf_detach(&desc, NULL);\n }\n \n-static void print_ref_item(struct ref_array_item *item, int maxwidth,\n-\t\t\t   struct ref_filter *filter, const char *remote_prefix)\n+static void format_and_print_ref_item(struct ref_array_item *item, int maxwidth,\n+\t\t\t\t      struct ref_filter *filter, const char *remote_prefix)\n {\n \tchar c;\n \tint current = 0;\n@@ -514,17 +395,16 @@ static void print_ref_item(struct ref_array_item *item, int maxwidth,\n \tconst char *prefix = \"\";\n \tconst char *desc = item->refname;\n \n-\tif (item->ignore)\n-\t\treturn;\n-\n \tswitch (item->kind) {\n \tcase REF_LOCAL_BRANCH:\n-\t\tif (!filter->detached && !strcmp(item->refname, head))\n+\t\tskip_prefix(desc, \"refs/heads/\", &desc);\n+\t\tif (!filter->detached && !strcmp(desc, head))\n \t\t\tcurrent = 1;\n \t\telse\n \t\t\tcolor = BRANCH_COLOR_LOCAL;\n \t\tbreak;\n \tcase REF_REMOTE_BRANCH:\n+\t\tskip_prefix(desc, \"refs/remotes/\", &desc);\n \t\tcolor = BRANCH_COLOR_REMOTE;\n \t\tprefix = remote_prefix;\n \t\tbreak;\n@@ -553,11 +433,13 @@ static void print_ref_item(struct ref_array_item *item, int maxwidth,\n \t\tstrbuf_addf(&out, \"%c %s%s%s\", c, branch_get_color(color),\n \t\t\t    name.buf, branch_get_color(BRANCH_COLOR_RESET));\n \n-\tif (item->symref)\n-\t\tstrbuf_addf(&out, \" -> %s\", item->symref);\n+\tif (item->symref) {\n+\t\tskip_prefix(item->symref, \"refs/remotes/\", &desc);\n+\t\tstrbuf_addf(&out, \" -> %s\", desc);\n+\t}\n \telse if (filter->verbose)\n \t\t/* \" f7c0c00 [ahead 58, behind 197] vcs-svn: drop obj_pool.h\" */\n-\t\tadd_verbose_info(&out, item, filter);\n+\t\tadd_verbose_info(&out, item, filter, desc);\n \tif (column_active(colopts)) {\n \t\tassert(!filter->verbose && \"--column and --verbose are incompatible\");\n \t\tstring_list_append(&output, out.buf);\n@@ -575,10 +457,13 @@ static int calc_maxwidth(struct ref_array *refs, int remote_bonus)\n \tint i, max = 0;\n \tfor (i = 0; i < refs->nr; i++) {\n \t\tstruct ref_array_item *it = refs->items[i];\n-\t\tint w = utf8_strwidth(it->refname);\n+\t\tconst char *desc = it->refname;\n+\t\tint w;\n+\n+\t\tskip_prefix(it->refname, \"refs/heads/\", &desc);\n+\t\tskip_prefix(it->refname, \"refs/remotes/\", &desc);\n+\t\tw = utf8_strwidth(desc);\n \n-\t\tif (it->ignore)\n-\t\t\tcontinue;\n \t\tif (it->kind == REF_REMOTE_BRANCH)\n \t\t\tw += remote_bonus;\n \t\tif (w > max)\n@@ -587,14 +472,14 @@ static int calc_maxwidth(struct ref_array *refs, int remote_bonus)\n \treturn max;\n }\n \n-static void print_ref_list(struct ref_filter *filter)\n+static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sorting)\n {\n \tint i, index;\n \tstruct ref_array array;\n-\tstruct ref_filter_cbdata data;\n \tint maxwidth = 0;\n \tconst char *remote_prefix = \"\";\n-\tstruct rev_info revs;\n+\tstruct ref_sorting def_sorting;\n+\tconst char *sort_type = \"type\";\n \n \t/*\n \t * If we are listing more than just remote branches,\n@@ -605,46 +490,10 @@ static void print_ref_list(struct ref_filter *filter)\n \t\tremote_prefix = \"remotes/\";\n \n \tmemset(&array, 0, sizeof(array));\n-\tif (filter->merge != REF_FILTER_MERGED_NONE)\n-\t\tinit_revisions(&revs, NULL);\n-\n-\tdata.array = &array;\n-\tdata.filter = filter;\n-\tarray.revs = &revs;\n \n-\t/*\n-\t * First we obtain all regular branch refs and then if the\n-\t * HEAD is detached then we insert that ref to the end of the\n-\t * ref_fist so that it can be printed first.\n-\t */\n-\tfor_each_rawref(append_ref, &data);\n-\tif (filter->detached)\n-\t\thead_ref(append_ref, &data);\n-\t/*\n-\t * The following implementation is currently duplicated in ref-filter. It\n-\t * will eventually be removed when we port branch.c to use ref-filter APIs.\n-\t */\n-\tif (filter->merge != REF_FILTER_MERGED_NONE) {\n-\t\tfilter->merge_commit->object.flags |= UNINTERESTING;\n-\t\tadd_pending_object(&revs, &filter->merge_commit->object, \"\");\n-\t\trevs.limited = 1;\n-\n-\t\tif (prepare_revision_walk(&revs))\n-\t\t\tdie(_(\"revision walk setup failed\"));\n-\n-\t\tfor (i = 0; i < array.nr; i++) {\n-\t\t\tstruct ref_array_item *item = array.items[i];\n-\t\t\tstruct commit *commit = item->commit;\n-\t\t\tint is_merged = !!(commit->object.flags & UNINTERESTING);\n-\t\t\titem->ignore = is_merged != (filter->merge == REF_FILTER_MERGED_INCLUDE);\n-\t\t}\n+\tverify_ref_format(\"%(refname)%(symref)\");\n+\tfilter_refs(&array, filter, FILTER_REFS_BRANCHES);\n \n-\t\tfor (i = 0; i < array.nr; i++) {\n-\t\t\tstruct ref_array_item *item = array.items[i];\n-\t\t\tclear_commit_marks(item->commit, ALL_REV_FLAGS);\n-\t\t}\n-\t\tclear_commit_marks(filter->merge_commit, ALL_REV_FLAGS);\n-\t}\n \tif (filter->verbose)\n \t\tmaxwidth = calc_maxwidth(&array, strlen(remote_prefix));\n \n@@ -652,15 +501,22 @@ static void print_ref_list(struct ref_filter *filter)\n \n \t/* Print detached HEAD before sorting and printing the rest */\n \tif (filter->detached) {\n-\t\tprint_ref_item(array.items[index - 1], maxwidth, filter, remote_prefix);\n-\t\tindex -= 1;\n+\t\tformat_and_print_ref_item(array.items[index - 1], maxwidth, filter, remote_prefix);\n+\t\tarray.nr--;\n \t}\n \n-\tqsort(array.items, index, sizeof(struct ref_array_item *), ref_cmp);\n+\tif (!sorting) {\n+\t\tdef_sorting.next = NULL;\n+\t\tdef_sorting.atom = parse_ref_filter_atom(sort_type,\n+\t\t\t\t\t\t\t sort_type + strlen(sort_type));\n+\t\tsorting = &def_sorting;\n+\t}\n+\tref_array_sort(sorting, &array);\n \n-\tfor (i = 0; i < index; i++)\n-\t\tprint_ref_item(array.items[i], maxwidth, filter, remote_prefix);\n+\tfor (i = 0; i < array.nr; i++)\n+\t\tformat_and_print_ref_item(array.items[i], maxwidth, filter, remote_prefix);\n \n+\tarray.nr = index;\n \tref_array_clear(&array);\n }\n \n@@ -761,6 +617,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \tconst char *new_upstream = NULL;\n \tenum branch_track track;\n \tstruct ref_filter filter;\n+\tstatic struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;\n \n \tstruct option options[] = {\n \t\tOPT_GROUP(N_(\"Generic options\")),\n@@ -795,6 +652,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\tOPT_MERGED(&filter, N_(\"print only branches that are merged\")),\n \t\tOPT_NO_MERGED(&filter, N_(\"print only branches that are not merged\")),\n \t\tOPT_COLUMN(0, \"column\", &colopts, N_(\"list branches in columns\")),\n+\t\tOPT_CALLBACK(0 , \"sort\", sorting_tail, N_(\"key\"),\n+\t\t\t     N_(\"field name to sort on\"), &parse_opt_ref_sorting),\n \t\tOPT_END(),\n \t};\n \n@@ -853,7 +712,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\tif (filter.branch_kind & REF_LOCAL_BRANCH)\n \t\t\tfilter.branch_kind |= REF_DETACHED_HEAD;\n \t\tfilter.name_patterns = argv;\n-\t\tprint_ref_list(&filter);\n+\t\tprint_ref_list(&filter, sorting);\n \t\tprint_columns(&output, colopts, NULL);\n \t\tstring_list_clear(&output, 0);\n \t\treturn 0;\ndiff --git a/ref-filter.c b/ref-filter.c\nindex c573109..d83d4d2 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -1135,7 +1135,7 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,\n \t * obtain the commit using the 'oid' available and discard all\n \t * non-commits early. The actual filtering is done later.\n \t */\n-\tif (filter->merge_commit || filter->with_commit) {\n+\tif (filter->merge_commit || filter->with_commit || filter->verbose) {\n \t\tcommit = lookup_commit_reference_gently(oid->hash, 1);\n \t\tif (!commit)\n \t\t\treturn 0;\n@@ -1243,9 +1243,11 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int\n \t\tret = for_each_ref(ref_filter_handler, &ref_cbdata);\n \telse if (type & FILTER_REFS_TAGS)\n \t\tret = for_each_tag_ref_fullpath(ref_filter_handler, &ref_cbdata);\n-\telse if (type & FILTER_REFS_BRANCHES)\n+\telse if (type & FILTER_REFS_BRANCHES) {\n \t\tret = for_each_rawref(ref_filter_handler, &ref_cbdata);\n-\telse if (type)\n+\t\tif (filter->detached)\n+\t\t\thead_ref(ref_filter_handler, &ref_cbdata);\n+\t} else if (type)\n \t\tdie(\"filter_refs: invalid type\");\n \n \t/*  Filters that need revision walking */\ndiff --git a/ref-filter.h b/ref-filter.h\nindex 1b1e6de..4379741 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -58,7 +58,6 @@ struct ref_sorting {\n struct ref_array_item {\n \tunsigned char objectname[20];\n \tint flag, kind;\n-\tint ignore : 1; /* To be removed in the next patch */\n \tconst char *symref;\n \tstruct commit *commit;\n \tstruct atom_value *value;\ndiff --git a/t/t1430-bad-ref-name.sh b/t/t1430-bad-ref-name.sh\nindex 16d0b8b..dcf2931 100755\n--- a/t/t1430-bad-ref-name.sh\n+++ b/t/t1430-bad-ref-name.sh\n@@ -38,11 +38,11 @@ test_expect_success 'fast-import: fail on invalid branch name \"bad[branch]name\"'\n \ttest_must_fail git fast-import <input\n '\n \n-test_expect_success 'git branch shows badly named ref' '\n-\tcp .git/refs/heads/master .git/refs/heads/broken...ref &&\n-\ttest_when_finished \"rm -f .git/refs/heads/broken...ref\" &&\n-\tgit branch >output &&\n-\tgrep -e \"broken\\.\\.\\.ref\" output\n+test_expect_failure 'git branch shows badly named ref' '\n+       cp .git/refs/heads/master .git/refs/heads/broken...ref &&\n+       test_when_finished \"rm -f .git/refs/heads/broken...ref\" &&\n+       git branch >output &&\n+       grep -e \"broken\\.\\.\\.ref\" output\n '\n \n test_expect_success 'branch -d can delete badly named ref' '\ndiff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh\nindex f51d0f3..38c68bd 100755\n--- a/t/t3203-branch-output.sh\n+++ b/t/t3203-branch-output.sh\n@@ -143,4 +143,15 @@ EOF\n \ttest_i18ncmp expect actual\n '\n \n+test_expect_success 'git branch `--sort` option' '\n+\tcat >expect <<EOF &&\n+* (HEAD detached from fromtag)\n+  branch-two\n+  branch-one\n+  master\n+EOF\n+\tgit branch --sort=objectsize >actual &&\n+\ttest_i18ncmp expect actual\n+'\n+\n test_done\n-- \n2.5.0\n"},{"id":"267414","messageId":"1438693282-15516-9-git-send-email-Karthik.188@gmail.com","threadId":"40010","inReplyTo":"CAOLa=ZSnn19DR_Y5MqUXHed0g5MSk_dwFc48dk8GoPYvL5DQ=Q@mail.gmail.com","subject":"[PATCH 09/10] branch: add '--points-at' option","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-04T13:01:22Z","receivedAt":"2015-08-04T13:01:22Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Add the '--points-at' option provided by 'ref-filter'. The option lets\nthe user to list only branches which points at the given object.\n\nAdd documentation and tests for the same.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n Documentation/git-branch.txt | 6 +++++-\n builtin/branch.c             | 7 ++++++-\n t/t3203-branch-output.sh     | 9 +++++++++\n 3 files changed, 20 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt\nindex 897cd81..211cfc3 100644\n--- a/Documentation/git-branch.txt\n+++ b/Documentation/git-branch.txt\n@@ -11,7 +11,8 @@ SYNOPSIS\n 'git branch' [--color[=<when>] | --no-color] [-r | -a]\n \t[--list] [-v [--abbrev=<length> | --no-abbrev]]\n \t[--column[=<options>] | --no-column]\n-\t[(--merged | --no-merged | --contains) [<commit>]] [--sort=<key>] [<pattern>...]\n+\t[(--merged | --no-merged | --contains) [<commit>]] [--sort=<key>]\n+\t[--points-at <object>] [<pattern>...]\n 'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]\n 'git branch' (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>]\n 'git branch' --unset-upstream [<branchname>]\n@@ -237,6 +238,9 @@ start-point is either a local or remote-tracking branch.\n \tfor-each-ref`. Sort order defaults to sorting based on branch\n \ttype.\n \n+--points-at <object>::\n+\tOnly list branches of the given object.\n+\n Examples\n --------\n \ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 34ccf0c..5dad1da 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -26,6 +26,7 @@ static const char * const builtin_branch_usage[] = {\n \tN_(\"git branch [<options>] [-l] [-f] <branch-name> [<start-point>]\"),\n \tN_(\"git branch [<options>] [-r] (-d | -D) <branch-name>...\"),\n \tN_(\"git branch [<options>] (-m | -M) [<old-branch>] <new-branch>\"),\n+\tN_(\"git branch [<options>] [-r | -a] [--points-at]\"),\n \tNULL\n };\n \n@@ -654,6 +655,10 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\tOPT_COLUMN(0, \"column\", &colopts, N_(\"list branches in columns\")),\n \t\tOPT_CALLBACK(0 , \"sort\", sorting_tail, N_(\"key\"),\n \t\t\t     N_(\"field name to sort on\"), &parse_opt_ref_sorting),\n+\t\t{\n+\t\t\tOPTION_CALLBACK, 0, \"points-at\", &filter.points_at, N_(\"object\"),\n+\t\t\tN_(\"print only branches of the object\"), 0, parse_opt_object_name\n+\t\t},\n \t\tOPT_END(),\n \t};\n \n@@ -682,7 +687,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \tif (!delete && !rename && !edit_description && !new_upstream && !unset_upstream && argc == 0)\n \t\tlist = 1;\n \n-\tif (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE)\n+\tif (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || filter.points_at.nr)\n \t\tlist = 1;\n \n \tif (!!delete + !!rename + !!new_upstream +\ndiff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh\nindex 38c68bd..1deb7cb 100755\n--- a/t/t3203-branch-output.sh\n+++ b/t/t3203-branch-output.sh\n@@ -154,4 +154,13 @@ EOF\n \ttest_i18ncmp expect actual\n '\n \n+test_expect_success 'git branch --points-at option' '\n+\tcat >expect <<EOF &&\n+  master\n+  branch-one\n+EOF\n+\tgit branch --points-at=branch-one >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n2.5.0\n"},{"id":"267418","messageId":"CAOLa=ZSR=7mvOG+RPSJ_xxr3k644WOiqirTrNMo-=jcXbtM3yw@mail.gmail.com","threadId":"40010","inReplyTo":"CAOLa=ZSnn19DR_Y5MqUXHed0g5MSk_dwFc48dk8GoPYvL5DQ=Q@mail.gmail.com","subject":"Re: [PATCH 0/10] Port branch.c to ref-filter.","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-04T13:01:53Z","receivedAt":"2015-08-04T13:01:53Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"There are nine patches in the series. Have put \"0/10\" by mistake.\n\n-- \nRegards,\nKarthik Nayak\n"},{"id":"267546","messageId":"xmqq614t2zbe.fsf@gitster.dls.corp.google.com","threadId":"40010","inReplyTo":"CAOLa=ZSR=7mvOG+RPSJ_xxr3k644WOiqirTrNMo-=jcXbtM3yw@mail.gmail.com","subject":"Re: [PATCH 0/10] Port branch.c to ref-filter.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-08-05T21:35:49Z","receivedAt":"2015-08-05T21:35:49Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> There are nine patches in the series. Have put \"0/10\" by mistake.\n\nFYI, format-patch has --cover-letter option.\n"},{"id":"267612","messageId":"CAOLa=ZTtLKNJ7zgXF7wqs9_18JAjnau=kmAutwKQMkqviH43kQ@mail.gmail.com","threadId":"40010","inReplyTo":"xmqq614t2zbe.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH 0/10] Port branch.c to ref-filter.","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-07T15:22:26Z","receivedAt":"2015-08-07T15:22:26Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On Thu, Aug 6, 2015 at 3:05 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> There are nine patches in the series. Have put \"0/10\" by mistake.\n>\n> FYI, format-patch has --cover-letter option.\n\nThanks! I need to check out a lot of options :)\n\n\n\n-- \nRegards,\nKarthik Nayak\n"},{"id":"267807","messageId":"CAPig+cRHvkAEM1ayVc5nj6RCih52x1+Bn9YTQPV93ej=3arK2Q@mail.gmail.com","threadId":"40010","inReplyTo":"1438693282-15516-2-git-send-email-Karthik.188@gmail.com","subject":"Re: [PATCH 02/10] branch: refactor width computation","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-08-11T01:58:10Z","receivedAt":"2015-08-11T01:58:10Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Aug 4, 2015 at 9:01 AM, Karthik Nayak <karthik.188@gmail.com> wrote:\n> Remove unnecessary variables from ref_list and ref_item which were\n> used for width computation. This is to make ref_item similar to\n> ref-filter's ref_array_item. This will ensure a smooth port of\n> branch.c to use ref-filter APIs in further patches.\n>\n> Previously the maxwidth was computed when inserting the refs into the\n> ref_list. Now, we obtain the entire ref_list and then compute\n> maxwidth.\n>\n> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n> ---\n> diff --git a/builtin/branch.c b/builtin/branch.c\n> index 4fc8beb..b058b74 100644\n> --- a/builtin/branch.c\n> +++ b/builtin/branch.c\n> @@ -557,16 +552,21 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n> -static int calc_maxwidth(struct ref_list *refs)\n> +static int calc_maxwidth(struct ref_list *refs, int remote_bonus)\n>  {\n> -       int i, w = 0;\n> +       int i, max = 0;\n>         for (i = 0; i < refs->index; i++) {\n> +               struct ref_item *it = &refs->list[i];\n> +               int w = utf8_strwidth(it->name);\n> +\n>                 if (refs->list[i].ignore)\n>                         continue;\n\nNit: Unnecessary work. You compute the width and then immediately\nthrow it away when 'ignore' is true.\n\nAlso, you use 'it' elsewhere rather than 'refs->list[i]' but not this\nline, which makes it seem out of place. I would have expected to see:\n\n    if (it->ignore)\n        continue;\n\n(Despite the noisier diff, the end result will be more consistent.)\n\n> -               if (refs->list[i].width > w)\n> -                       w = refs->list[i].width;\n> +               if (it->kind == REF_REMOTE_BRANCH)\n> +                       w += remote_bonus;\n> +               if (w > max)\n> +                       max = w;\n>         }\n> -       return w;\n> +       return max;\n>  }\n\n\nOn Tue, Aug 4, 2015 at 9:01 AM, Karthik Nayak <karthik.188@gmail.com> wrote:\n> From: Karthik Nayak <karthik.188@gmail.com>\n>\n> Remove unnecessary variables from ref_list and ref_item which were\n> used for width computation. This is to make ref_item similar to\n> ref-filter's ref_array_item. This will ensure a smooth port of\n> branch.c to use ref-filter APIs in further patches.\n>\n> Previously the maxwidth was computed when inserting the refs into the\n> ref_list. Now, we obtain the entire ref_list and then compute\n> maxwidth.\n>\n> Based-on-patch-by: Jeff King <peff@peff.net>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\n> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n> ---\n>  builtin/branch.c | 61 +++++++++++++++++++++++++++++---------------------------\n>  1 file changed, 32 insertions(+), 29 deletions(-)\n>\n> diff --git a/builtin/branch.c b/builtin/branch.c\n> index 4fc8beb..b058b74 100644\n> --- a/builtin/branch.c\n> +++ b/builtin/branch.c\n> @@ -282,14 +282,14 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,\n>  struct ref_item {\n>         char *name;\n>         char *dest;\n> -       unsigned int kind, width;\n> +       unsigned int kind;\n>         struct commit *commit;\n>         int ignore;\n>  };\n>\n>  struct ref_list {\n>         struct rev_info revs;\n> -       int index, alloc, maxwidth, verbose, abbrev;\n> +       int index, alloc, verbose, abbrev;\n>         struct ref_item *list;\n>         struct commit_list *with_commit;\n>         int kinds;\n> @@ -386,15 +386,8 @@ static int append_ref(const char *refname, const struct object_id *oid, int flag\n>         newitem->name = xstrdup(refname);\n>         newitem->kind = kind;\n>         newitem->commit = commit;\n> -       newitem->width = utf8_strwidth(refname);\n>         newitem->dest = resolve_symref(orig_refname, prefix);\n>         newitem->ignore = 0;\n> -       /* adjust for \"remotes/\" */\n> -       if (newitem->kind == REF_REMOTE_BRANCH &&\n> -           ref_list->kinds != REF_REMOTE_BRANCH)\n> -               newitem->width += 8;\n> -       if (newitem->width > ref_list->maxwidth)\n> -               ref_list->maxwidth = newitem->width;\n>\n>         return 0;\n>  }\n> @@ -505,11 +498,12 @@ static void add_verbose_info(struct strbuf *out, struct ref_item *item,\n>  }\n>\n>  static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n> -                          int abbrev, int current, char *prefix)\n> +                          int abbrev, int current, const char *remote_prefix)\n>  {\n>         char c;\n>         int color;\n>         struct strbuf out = STRBUF_INIT, name = STRBUF_INIT;\n> +       const char *prefix = \"\";\n>\n>         if (item->ignore)\n>                 return;\n> @@ -520,6 +514,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n>                 break;\n>         case REF_REMOTE_BRANCH:\n>                 color = BRANCH_COLOR_REMOTE;\n> +               prefix = remote_prefix;\n>                 break;\n>         default:\n>                 color = BRANCH_COLOR_PLAIN;\n> @@ -557,16 +552,21 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n>         strbuf_release(&out);\n>  }\n>\n> -static int calc_maxwidth(struct ref_list *refs)\n> +static int calc_maxwidth(struct ref_list *refs, int remote_bonus)\n>  {\n> -       int i, w = 0;\n> +       int i, max = 0;\n>         for (i = 0; i < refs->index; i++) {\n> +               struct ref_item *it = &refs->list[i];\n> +               int w = utf8_strwidth(it->name);\n> +\n>                 if (refs->list[i].ignore)\n>                         continue;\n> -               if (refs->list[i].width > w)\n> -                       w = refs->list[i].width;\n> +               if (it->kind == REF_REMOTE_BRANCH)\n> +                       w += remote_bonus;\n> +               if (w > max)\n> +                       max = w;\n>         }\n> -       return w;\n> +       return max;\n>  }\n>\n>  static char *get_head_description(void)\n> @@ -600,21 +600,18 @@ static char *get_head_description(void)\n>         return strbuf_detach(&desc, NULL);\n>  }\n>\n> -static void show_detached(struct ref_list *ref_list)\n> +static void show_detached(struct ref_list *ref_list, int maxwidth)\n>  {\n>         struct commit *head_commit = lookup_commit_reference_gently(head_sha1, 1);\n>\n>         if (head_commit && is_descendant_of(head_commit, ref_list->with_commit)) {\n>                 struct ref_item item;\n>                 item.name = get_head_description();\n> -               item.width = utf8_strwidth(item.name);\n>                 item.kind = REF_LOCAL_BRANCH;\n>                 item.dest = NULL;\n>                 item.commit = head_commit;\n>                 item.ignore = 0;\n> -               if (item.width > ref_list->maxwidth)\n> -                       ref_list->maxwidth = item.width;\n> -               print_ref_item(&item, ref_list->maxwidth, ref_list->verbose, ref_list->abbrev, 1, \"\");\n> +               print_ref_item(&item, maxwidth, ref_list->verbose, ref_list->abbrev, 1, \"\");\n>                 free(item.name);\n>         }\n>  }\n> @@ -624,6 +621,16 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru\n>         int i;\n>         struct append_ref_cb cb;\n>         struct ref_list ref_list;\n> +       int maxwidth = 0;\n> +       const char *remote_prefix = \"\";\n> +\n> +       /*\n> +        * If we are listing more than just remote branches,\n> +        * then remote branches will have a \"remotes/\" prefix.\n> +        * We need to account for this in the width.\n> +        */\n> +       if (kinds != REF_REMOTE_BRANCH)\n> +               remote_prefix = \"remotes/\";\n>\n>         memset(&ref_list, 0, sizeof(ref_list));\n>         ref_list.kinds = kinds;\n> @@ -667,26 +674,22 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru\n>                         clear_commit_marks(item->commit, ALL_REV_FLAGS);\n>                 }\n>                 clear_commit_marks(filter, ALL_REV_FLAGS);\n> -\n> -               if (verbose)\n> -                       ref_list.maxwidth = calc_maxwidth(&ref_list);\n>         }\n> +       if (verbose)\n> +               maxwidth = calc_maxwidth(&ref_list, strlen(remote_prefix));\n>\n>         qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);\n>\n>         detached = (detached && (kinds & REF_LOCAL_BRANCH));\n>         if (detached && match_patterns(pattern, \"HEAD\"))\n> -               show_detached(&ref_list);\n> +               show_detached(&ref_list, maxwidth);\n>\n>         for (i = 0; i < ref_list.index; i++) {\n>                 int current = !detached &&\n>                         (ref_list.list[i].kind == REF_LOCAL_BRANCH) &&\n>                         !strcmp(ref_list.list[i].name, head);\n> -               char *prefix = (kinds != REF_REMOTE_BRANCH &&\n> -                               ref_list.list[i].kind == REF_REMOTE_BRANCH)\n> -                               ? \"remotes/\" : \"\";\n> -               print_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose,\n> -                              abbrev, current, prefix);\n> +               print_ref_item(&ref_list.list[i], maxwidth, verbose,\n> +                              abbrev, current, remote_prefix);\n>         }\n>\n>         free_ref_list(&ref_list);\n> --\n> 2.5.0\n>\n> --\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n"},{"id":"267808","messageId":"CAPig+cR0F-CdsFRoazqPinFTOpWkCwLoNHva1X1bMo8LapMMVQ@mail.gmail.com","threadId":"40010","inReplyTo":"1438693282-15516-3-git-send-email-Karthik.188@gmail.com","subject":"Re: [PATCH 03/10] branch: bump get_head_description() to the top","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-08-11T01:59:36Z","receivedAt":"2015-08-11T01:59:36Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Aug 4, 2015 at 9:01 AM, Karthik Nayak <karthik.188@gmail.com> wrote:\n> This is a preperatory patch for 'roll show_detached HEAD into regular\n> ref_list'. This patch moves get_head_descrition() to the top so that\n\ns/descrition/description/\n\n> it can be used in print_ref_item().\n>\n> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n"},{"id":"267809","messageId":"CAPig+cRvdpv_NO8jCrWmFfpuQ+mcxaC5P_oHVrU+tQoH9DKnkg@mail.gmail.com","threadId":"40010","inReplyTo":"1438693282-15516-4-git-send-email-Karthik.188@gmail.com","subject":"Re: [PATCH 04/10] branch: roll show_detached HEAD into regular ref_list","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-08-11T02:41:57Z","receivedAt":"2015-08-11T02:41:57Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Aug 4, 2015 at 9:01 AM, Karthik Nayak <karthik.188@gmail.com> wrote:\n> Remove show_detached() and make detached HEAD to be rolled into\n> regular ref_list by adding REF_DETACHED_HEAD as a kind of branch and\n> supporting the same in append_ref(). This eliminates the need for an\n> extra function and helps in easier porting of branch.c to use\n> ref-filter APIs.\n>\n> Before show_detached() used to check if the HEAD branch satisfies the\n> '--contains' option, now that is taken care by append_ref().\n>\n> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n> ---\n> diff --git a/builtin/branch.c b/builtin/branch.c\n> index 65f6d0d..81815c9 100644\n> --- a/builtin/branch.c\n> +++ b/builtin/branch.c\n> @@ -535,6 +540,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n>         int color;\n>         struct strbuf out = STRBUF_INIT, name = STRBUF_INIT;\n>         const char *prefix = \"\";\n> +       const char *desc = item->name;\n>\n>         if (item->ignore)\n>                 return;\n> @@ -547,6 +553,10 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n>                 color = BRANCH_COLOR_REMOTE;\n>                 prefix = remote_prefix;\n>                 break;\n> +       case REF_DETACHED_HEAD:\n> +               color = BRANCH_COLOR_CURRENT;\n> +               desc = get_head_description();\n> +               break;\n>         default:\n>                 color = BRANCH_COLOR_PLAIN;\n>                 break;\n> @@ -558,7 +568,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n>                 color = BRANCH_COLOR_CURRENT;\n>         }\n>\n> -       strbuf_addf(&name, \"%s%s\", prefix, item->name);\n> +       strbuf_addf(&name, \"%s%s\", prefix, desc);\n>         if (verbose) {\n>                 int utf8_compensation = strlen(name.buf) - utf8_strwidth(name.buf);\n>                 strbuf_addf(&out, \"%c %s%-*s%s\", c, branch_get_color(color),\n> @@ -581,6 +591,8 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n>         }\n>         strbuf_release(&name);\n>         strbuf_release(&out);\n> +       if (item->kind == REF_DETACHED_HEAD)\n> +               free((void *)desc);\n\nThis would be cleaner, and more easily extended to other cases if you\nused a 'to_free' variable. For instance, something like this:\n\n    const char *desc = item->name;\n    char *to_free = NULL;\n    ...\n    case REF_DETACHED_HEAD:\n        ...\n        desc = to_free = get_head_description();\n        break;\n    ...\n    strbuf_addf(&name, \"%s%s\", prefix, desc);\n    ...\n    free(to_free);\n\nNote that it's safe to free 'to_free' when it's NULL, so you don't\nneed to protect the free() with that ugly specialized 'if' which\nchecks for REF_DETACHED_HEAD. You can also do away with the \"cast to\nnon-const\" when freeing.\n\n>  }\n> @@ -642,7 +638,14 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru\n>         cb.ref_list = &ref_list;\n>         cb.pattern = pattern;\n>         cb.ret = 0;\n> +       /*\n> +        * First we obtain all regular branch refs and then if the\n\ns/then//\n\n> +        * HEAD is detached then we insert that ref to the end of the\n> +        * ref_fist so that it can be printed first.\n> +        */\n>         for_each_rawref(append_ref, &cb);\n> +       if (detached)\n> +               head_ref(append_ref, &cb);\n"},{"id":"267826","messageId":"CAOLa=ZQSm+YRHVUGxrKDLHaUu4jT82XSLaH-BBf-cL0KNNZ82A@mail.gmail.com","threadId":"40010","inReplyTo":"CAPig+cRHvkAEM1ayVc5nj6RCih52x1+Bn9YTQPV93ej=3arK2Q@mail.gmail.com","subject":"Re: [PATCH 02/10] branch: refactor width computation","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-11T13:10:17Z","receivedAt":"2015-08-11T13:10:17Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On Tue, Aug 11, 2015 at 7:28 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Tue, Aug 4, 2015 at 9:01 AM, Karthik Nayak <karthik.188@gmail.com> wrote:\n>> Remove unnecessary variables from ref_list and ref_item which were\n>> used for width computation. This is to make ref_item similar to\n>> ref-filter's ref_array_item. This will ensure a smooth port of\n>> branch.c to use ref-filter APIs in further patches.\n>>\n>> Previously the maxwidth was computed when inserting the refs into the\n>> ref_list. Now, we obtain the entire ref_list and then compute\n>> maxwidth.\n>>\n>> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n>> ---\n>> diff --git a/builtin/branch.c b/builtin/branch.c\n>> index 4fc8beb..b058b74 100644\n>> --- a/builtin/branch.c\n>> +++ b/builtin/branch.c\n>> @@ -557,16 +552,21 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n>> -static int calc_maxwidth(struct ref_list *refs)\n>> +static int calc_maxwidth(struct ref_list *refs, int remote_bonus)\n>>  {\n>> -       int i, w = 0;\n>> +       int i, max = 0;\n>>         for (i = 0; i < refs->index; i++) {\n>> +               struct ref_item *it = &refs->list[i];\n>> +               int w = utf8_strwidth(it->name);\n>> +\n>>                 if (refs->list[i].ignore)\n>>                         continue;\n>\n> Nit: Unnecessary work. You compute the width and then immediately\n> throw it away when 'ignore' is true.\n>\n> Also, you use 'it' elsewhere rather than 'refs->list[i]' but not this\n> line, which makes it seem out of place. I would have expected to see:\n>\n>     if (it->ignore)\n>         continue;\n>\n> (Despite the noisier diff, the end result will be more consistent.)\n>\n\nAh right, will put that after the check :D\n\nYea, that seems out of place. Thanks\n\n-- \nRegards,\nKarthik Nayak\n"},{"id":"267827","messageId":"CAOLa=ZThF+5-mzyR+wXOPzzTWoGyyPvHnw_x9TbyjW=xkQKEsA@mail.gmail.com","threadId":"40010","inReplyTo":"CAPig+cR0F-CdsFRoazqPinFTOpWkCwLoNHva1X1bMo8LapMMVQ@mail.gmail.com","subject":"Re: [PATCH 03/10] branch: bump get_head_description() to the top","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-11T13:12:58Z","receivedAt":"2015-08-11T13:12:58Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On Tue, Aug 11, 2015 at 7:29 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Tue, Aug 4, 2015 at 9:01 AM, Karthik Nayak <karthik.188@gmail.com> wrote:\n>> This is a preperatory patch for 'roll show_detached HEAD into regular\n>> ref_list'. This patch moves get_head_descrition() to the top so that\n>\n> s/descrition/description/\n>\n>> it can be used in print_ref_item().\n>>\n>> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n\nThanks, will change.\n\n-- \nRegards,\nKarthik Nayak\n"},{"id":"267828","messageId":"CAOLa=ZRVr9a8kj+MLbi7ybYCHJVdHrX42vzMRU8PS6nvHmB_og@mail.gmail.com","threadId":"40010","inReplyTo":"CAPig+cRvdpv_NO8jCrWmFfpuQ+mcxaC5P_oHVrU+tQoH9DKnkg@mail.gmail.com","subject":"Re: [PATCH 04/10] branch: roll show_detached HEAD into regular ref_list","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-11T13:17:31Z","receivedAt":"2015-08-11T13:17:31Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On Tue, Aug 11, 2015 at 8:11 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Tue, Aug 4, 2015 at 9:01 AM, Karthik Nayak <karthik.188@gmail.com> wrote:\n>> Remove show_detached() and make detached HEAD to be rolled into\n>> regular ref_list by adding REF_DETACHED_HEAD as a kind of branch and\n>> supporting the same in append_ref(). This eliminates the need for an\n>> extra function and helps in easier porting of branch.c to use\n>> ref-filter APIs.\n>>\n>> Before show_detached() used to check if the HEAD branch satisfies the\n>> '--contains' option, now that is taken care by append_ref().\n>>\n>> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n>> ---\n>> diff --git a/builtin/branch.c b/builtin/branch.c\n>> index 65f6d0d..81815c9 100644\n>> --- a/builtin/branch.c\n>> +++ b/builtin/branch.c\n>> @@ -535,6 +540,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n>>         int color;\n>>         struct strbuf out = STRBUF_INIT, name = STRBUF_INIT;\n>>         const char *prefix = \"\";\n>> +       const char *desc = item->name;\n>>\n>>         if (item->ignore)\n>>                 return;\n>> @@ -547,6 +553,10 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n>>                 color = BRANCH_COLOR_REMOTE;\n>>                 prefix = remote_prefix;\n>>                 break;\n>> +       case REF_DETACHED_HEAD:\n>> +               color = BRANCH_COLOR_CURRENT;\n>> +               desc = get_head_description();\n>> +               break;\n>>         default:\n>>                 color = BRANCH_COLOR_PLAIN;\n>>                 break;\n>> @@ -558,7 +568,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n>>                 color = BRANCH_COLOR_CURRENT;\n>>         }\n>>\n>> -       strbuf_addf(&name, \"%s%s\", prefix, item->name);\n>> +       strbuf_addf(&name, \"%s%s\", prefix, desc);\n>>         if (verbose) {\n>>                 int utf8_compensation = strlen(name.buf) - utf8_strwidth(name.buf);\n>>                 strbuf_addf(&out, \"%c %s%-*s%s\", c, branch_get_color(color),\n>> @@ -581,6 +591,8 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n>>         }\n>>         strbuf_release(&name);\n>>         strbuf_release(&out);\n>> +       if (item->kind == REF_DETACHED_HEAD)\n>> +               free((void *)desc);\n>\n> This would be cleaner, and more easily extended to other cases if you\n> used a 'to_free' variable. For instance, something like this:\n>\n>     const char *desc = item->name;\n>     char *to_free = NULL;\n>     ...\n>     case REF_DETACHED_HEAD:\n>         ...\n>         desc = to_free = get_head_description();\n>         break;\n>     ...\n>     strbuf_addf(&name, \"%s%s\", prefix, desc);\n>     ...\n>     free(to_free);\n>\n\nThis looks neater!\n\n> Note that it's safe to free 'to_free' when it's NULL, so you don't\n> need to protect the free() with that ugly specialized 'if' which\n> checks for REF_DETACHED_HEAD. You can also do away with the \"cast to\n> non-const\" when freeing.\n>\n\nYea makes sense will change to what you suggested.\n\n>>  }\n>> @@ -642,7 +638,14 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru\n>>         cb.ref_list = &ref_list;\n>>         cb.pattern = pattern;\n>>         cb.ret = 0;\n>> +       /*\n>> +        * First we obtain all regular branch refs and then if the\n>\n> s/then//\n>\n\nThanks\n\n-- \nRegards,\nKarthik Nayak\n"},{"id":"267838","messageId":"xmqqpp2tspb6.fsf@gitster.dls.corp.google.com","threadId":"40010","inReplyTo":"1438693282-15516-1-git-send-email-Karthik.188@gmail.com","subject":"Re: [PATCH 01/10] ref-filter: add option to filter only branches","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-08-11T17:33:17Z","receivedAt":"2015-08-11T17:33:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> From: Karthik Nayak <karthik.188@gmail.com>\n>\n> Add an option in 'filter_refs()' to use 'for_each_branch_ref()'\n> and filter refs. This type checking is done by adding a\n> 'FILTER_REFS_BRANCHES' in 'ref-filter.h'.\n>\n> Add an option in 'ref_filter_handler()' to filter different\n> types of branches by calling 'filter_branch_kind()' which\n> checks for the type of branch needed.\n>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\n> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n> ---\n>  ref-filter.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++\n>  ref-filter.h | 10 ++++++++--\n>  2 files changed, 55 insertions(+), 2 deletions(-)\n>\n> diff --git a/ref-filter.c b/ref-filter.c\n> index de84dd4..c573109 100644\n> --- a/ref-filter.c\n> +++ b/ref-filter.c\n> @@ -1044,6 +1044,46 @@ static const unsigned char *match_points_at(struct sha1_array *points_at,\n>  \treturn NULL;\n>  }\n>  \n> +/*\n> + * Checks if a given refname is a branch and returns the kind of\n> + * branch it is. If not a branch, 0 is returned.\n> + */\n> +static int filter_branch_kind(struct ref_filter *filter, const char *refname)\n> +{\n> +\tint kind, i;\n> +\n> +\tstatic struct {\n> +\t\tconst char *prefix;\n> +\t\tint kind;\n\nMake a mental note that this is signed int.\n\n> +\t} ref_kind[] = {\n> +\t\t{ \"refs/heads/\" , REF_LOCAL_BRANCH },\n> +\t\t{ \"refs/remotes/\" , REF_REMOTE_BRANCH },\n> +\t};\n> +\n> +\t/*  If no kind is specified, no need to filter */\n> +\tif (!filter->branch_kind)\n> +\t\treturn REF_NO_BRANCH_FILTERING;\n> +\n> +\tfor (i = 0; i < ARRAY_SIZE(ref_kind); i++) {\n> +\t\tif (starts_with(refname, ref_kind[i].prefix)) {\n> +\t\t\tkind = ref_kind[i].kind;\n> +\t\t\tbreak;\n> +\t\t}\n> +\t}\n> +\n> +\tif (ARRAY_SIZE(ref_kind) <= i) {\n> +\t\tif (!strcmp(refname, \"HEAD\"))\n> +\t\t\tkind = REF_DETACHED_HEAD;\n> +\t\telse\n> +\t\t\treturn 0;\n> +\t}\n> +\n> +\tif ((filter->branch_kind & kind) == 0)\n> +\t\treturn 0;\n> +\n> +\treturn kind;\n> +}\n\nWhile this looks fine, I am not sure if this is a good interface for\nfiltering, though.\n\nIf you start from already having everything and want to limit things\ndown to \"refs/heads/\", this might make sense but it would be far\nmore efficient, if you know that you want to limit to \"refs/heads/\"\nupfront, not to collect everything but just limit the collection to\nthose under \"refs/heads/\" without wasting cycles in the first place.\n\n> diff --git a/ref-filter.h b/ref-filter.h\n> index 5be3e35..b5a13e8 100644\n> --- a/ref-filter.h\n> +++ b/ref-filter.h\n> @@ -16,6 +16,12 @@\n>  #define FILTER_REFS_INCLUDE_BROKEN 0x1\n>  #define FILTER_REFS_ALL 0x2\n>  #define FILTER_REFS_TAGS 0x4\n> +#define FILTER_REFS_BRANCHES 0x8\n\nIs this a sensible set of bits?  Does it make sense to have ALL and\nTAGS at the same time (and what does that mean?)?\n\n> +#define REF_DETACHED_HEAD   0x01\n> +#define REF_LOCAL_BRANCH    0x02\n> +#define REF_REMOTE_BRANCH   0x04\n> +#define REF_NO_BRANCH_FILTERING 0x08\n\nWhere do these values go?  It is a returned by filter-branch-kind\nfor each ref, i.e. given \"refs/heads/bar\", it answers \"Yeah, that is\na local branch\".  Why are these values pretending to be a set of\nbits that can be combined together, as if a branch can be both LOCAL\nand REMOTE?  This does not make _any_ sense.\n\n\n>  #define ALIGN_LEFT 0x01\n>  #define ALIGN_RIGHT 0x02\n> @@ -50,7 +56,7 @@ struct ref_sorting {\n>  \n>  struct ref_array_item {\n>  \tunsigned char objectname[20];\n> -\tint flag;\n> +\tint flag, kind;\n\nFor readability, do not define multiple structure fields on a single\nline.\n\nIf you are storing a set of bits in an integer, use unsigned.  If it\nis an enumeration, int is fine.\n\n>  \tconst char *symref;\n>  \tstruct commit *commit;\n>  \tstruct atom_value *value;\n> @@ -76,7 +82,7 @@ struct ref_filter {\n>  \n>  \tunsigned int with_commit_tag_algo : 1,\n>  \t\tmatch_as_path : 1;\n> -\tunsigned int lines;\n> +\tunsigned int lines, branch_kind;\n\nFor readability, do not define multiple structure fields on a single\nline.\n\n>  };\n>  \n>  struct ref_filter_cbdata {\n"},{"id":"267976","messageId":"CAOLa=ZRRU4htKgB46g0FAGVEGGFN+1N1250AOYJh7H5apv=RJQ@mail.gmail.com","threadId":"40010","inReplyTo":"xmqqpp2tspb6.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH 01/10] ref-filter: add option to filter only branches","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-13T10:51:29Z","receivedAt":"2015-08-13T10:51:29Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On Tue, Aug 11, 2015 at 11:03 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> From: Karthik Nayak <karthik.188@gmail.com>\n>>\n>> Add an option in 'filter_refs()' to use 'for_each_branch_ref()'\n>> and filter refs. This type checking is done by adding a\n>> 'FILTER_REFS_BRANCHES' in 'ref-filter.h'.\n>>\n>> Add an option in 'ref_filter_handler()' to filter different\n>> types of branches by calling 'filter_branch_kind()' which\n>> checks for the type of branch needed.\n>>\n>> Mentored-by: Christian Couder <christian.couder@gmail.com>\n>> Mentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\n>> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n>> ---\n>>  ref-filter.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++\n>>  ref-filter.h | 10 ++++++++--\n>>  2 files changed, 55 insertions(+), 2 deletions(-)\n>>\n>> diff --git a/ref-filter.c b/ref-filter.c\n>> index de84dd4..c573109 100644\n>> --- a/ref-filter.c\n>> +++ b/ref-filter.c\n>> @@ -1044,6 +1044,46 @@ static const unsigned char *match_points_at(struct sha1_array *points_at,\n>>       return NULL;\n>>  }\n>>\n>> +/*\n>> + * Checks if a given refname is a branch and returns the kind of\n>> + * branch it is. If not a branch, 0 is returned.\n>> + */\n>> +static int filter_branch_kind(struct ref_filter *filter, const char *refname)\n>> +{\n>> +     int kind, i;\n>> +\n>> +     static struct {\n>> +             const char *prefix;\n>> +             int kind;\n>\n> Make a mental note that this is signed int.\n>\n>> +     } ref_kind[] = {\n>> +             { \"refs/heads/\" , REF_LOCAL_BRANCH },\n>> +             { \"refs/remotes/\" , REF_REMOTE_BRANCH },\n>> +     };\n>> +\n>> +     /*  If no kind is specified, no need to filter */\n>> +     if (!filter->branch_kind)\n>> +             return REF_NO_BRANCH_FILTERING;\n>> +\n>> +     for (i = 0; i < ARRAY_SIZE(ref_kind); i++) {\n>> +             if (starts_with(refname, ref_kind[i].prefix)) {\n>> +                     kind = ref_kind[i].kind;\n>> +                     break;\n>> +             }\n>> +     }\n>> +\n>> +     if (ARRAY_SIZE(ref_kind) <= i) {\n>> +             if (!strcmp(refname, \"HEAD\"))\n>> +                     kind = REF_DETACHED_HEAD;\n>> +             else\n>> +                     return 0;\n>> +     }\n>> +\n>> +     if ((filter->branch_kind & kind) == 0)\n>> +             return 0;\n>> +\n>> +     return kind;\n>> +}\n>\n> While this looks fine, I am not sure if this is a good interface for\n> filtering, though.\n>\n> If you start from already having everything and want to limit things\n> down to \"refs/heads/\", this might make sense but it would be far\n> more efficient, if you know that you want to limit to \"refs/heads/\"\n> upfront, not to collect everything but just limit the collection to\n> those under \"refs/heads/\" without wasting cycles in the first place.\n>\n\nYes, considering this and what you've said below about how the\nbits don't make sense, I re-wrote filter_refs() to filter based on what we want\nSo this part will be removed entirely. Thanks for pointing me in the\nright direction.\n\n>> diff --git a/ref-filter.h b/ref-filter.h\n>> index 5be3e35..b5a13e8 100644\n>> --- a/ref-filter.h\n>> +++ b/ref-filter.h\n>> @@ -16,6 +16,12 @@\n>>  #define FILTER_REFS_INCLUDE_BROKEN 0x1\n>>  #define FILTER_REFS_ALL 0x2\n>>  #define FILTER_REFS_TAGS 0x4\n>> +#define FILTER_REFS_BRANCHES 0x8\n>\n> Is this a sensible set of bits?  Does it make sense to have ALL and\n> TAGS at the same time (and what does that mean?)?\n>\n>> +#define REF_DETACHED_HEAD   0x01\n>> +#define REF_LOCAL_BRANCH    0x02\n>> +#define REF_REMOTE_BRANCH   0x04\n>> +#define REF_NO_BRANCH_FILTERING 0x08\n>\n> Where do these values go?  It is a returned by filter-branch-kind\n> for each ref, i.e. given \"refs/heads/bar\", it answers \"Yeah, that is\n> a local branch\".  Why are these values pretending to be a set of\n> bits that can be combined together, as if a branch can be both LOCAL\n> and REMOTE?  This does not make _any_ sense.\n>\n\nThis was taken from branch.c, I thought of using an enum instead but that\nwould again require most of branch.c, hence it's been carried over\nwithout changing\nI'm thinking of changing it, any suggestions?\n\n>\n>>  #define ALIGN_LEFT 0x01\n>>  #define ALIGN_RIGHT 0x02\n>> @@ -50,7 +56,7 @@ struct ref_sorting {\n>>\n>>  struct ref_array_item {\n>>       unsigned char objectname[20];\n>> -     int flag;\n>> +     int flag, kind;\n>\n> For readability, do not define multiple structure fields on a single\n> line.\n>\n> If you are storing a set of bits in an integer, use unsigned.  If it\n> is an enumeration, int is fine.\n>\n\nThanks will change.\n\n>>       const char *symref;\n>>       struct commit *commit;\n>>       struct atom_value *value;\n>> @@ -76,7 +82,7 @@ struct ref_filter {\n>>\n>>       unsigned int with_commit_tag_algo : 1,\n>>               match_as_path : 1;\n>> -     unsigned int lines;\n>> +     unsigned int lines, branch_kind;\n>\n> For readability, do not define multiple structure fields on a single\n> line.\n>\n>>  };\n>>\n>>  struct ref_filter_cbdata {\n\nWill do.\n\n-- \nRegards,\nKarthik Nayak\n"},{"id":"267977","messageId":"CAOLa=ZQic2=z6bJ0Ykhn2x8mE86w4HwBrJP7pb_RaemGKCZzmQ@mail.gmail.com","threadId":"40010","inReplyTo":"CAOLa=ZRRU4htKgB46g0FAGVEGGFN+1N1250AOYJh7H5apv=RJQ@mail.gmail.com","subject":"Re: [PATCH 01/10] ref-filter: add option to filter only branches","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-13T11:35:21Z","receivedAt":"2015-08-13T11:35:21Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On Thu, Aug 13, 2015 at 4:21 PM, Karthik Nayak <karthik.188@gmail.com> wrote:\n>\n> This was taken from branch.c, I thought of using an enum instead but that\n> would again require most of branch.c, hence it's been carried over\n> without changing\n> I'm thinking of changing it, any suggestions?\n>\n\nWhat I was thinking was of having:\n\n#define FILTER_REFS_INCLUDE_BROKEN 0x1\n#define FILTER_REFS_TAGS 0x2\n#define FILTER_REFS_BRANCHES 0x4\n#define FILTER_REFS_REMOTES 0x8\n#define FILTER_REFS_DETACHED_HEAD 0x16\n\nand using these for showing ref kind also instead of separately\nhaving 'REF_DETACHED_HEAD' and so on.\n\n-- \nRegards,\nKarthik Nayak\n"},{"id":"267983","messageId":"CAOLa=ZQSVCgcuUQFsF2Mq-m+wS8im3t4Z3PSEgoAHcV0gGuvPA@mail.gmail.com","threadId":"40010","inReplyTo":"CAOLa=ZQic2=z6bJ0Ykhn2x8mE86w4HwBrJP7pb_RaemGKCZzmQ@mail.gmail.com","subject":"Re: [PATCH 01/10] ref-filter: add option to filter only branches","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-13T15:13:02Z","receivedAt":"2015-08-13T15:13:02Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On Thu, Aug 13, 2015 at 5:05 PM, Karthik Nayak <karthik.188@gmail.com> wrote:\n> On Thu, Aug 13, 2015 at 4:21 PM, Karthik Nayak <karthik.188@gmail.com> wrote:\n>>\n>> This was taken from branch.c, I thought of using an enum instead but that\n>> would again require most of branch.c, hence it's been carried over\n>> without changing\n>> I'm thinking of changing it, any suggestions?\n>>\n>\n> What I was thinking was of having:\n>\n> #define FILTER_REFS_INCLUDE_BROKEN 0x1\n> #define FILTER_REFS_TAGS 0x2\n> #define FILTER_REFS_BRANCHES 0x4\n> #define FILTER_REFS_REMOTES 0x8\n> #define FILTER_REFS_DETACHED_HEAD 0x16\n>\n> and using these for showing ref kind also instead of separately\n> having 'REF_DETACHED_HEAD' and so on.\n>\n\nSomething like this:\nhttps://github.com/KarthikNayak/git/commit/0ec5381420dcdfe7c62000b56168e2842d5d0063\n\n-- \nRegards,\nKarthik Nayak\n"},{"id":"267998","messageId":"FC0BD660-1476-430A-9F71-E9D0E6681780@imag.fr","threadId":"40010","inReplyTo":"CAOLa=ZQic2=z6bJ0Ykhn2x8mE86w4HwBrJP7pb_RaemGKCZzmQ@mail.gmail.com","subject":"Re: [PATCH 01/10] ref-filter: add option to filter only branches","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2015-08-13T16:52:11Z","receivedAt":"2015-08-13T16:52:11Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"\n\nLe 13 août 2015 13:35:21 GMT+02:00, Karthik Nayak <karthik.188@gmail.com> a écrit :\n>On Thu, Aug 13, 2015 at 4:21 PM, Karthik Nayak <karthik.188@gmail.com>\n>wrote:\n>>\n>> This was taken from branch.c, I thought of using an enum instead but\n>that\n>> would again require most of branch.c, hence it's been carried over\n>> without changing\n>> I'm thinking of changing it, any suggestions?\n>>\n>\n>What I was thinking was of having:\n>\n>#define FILTER_REFS_INCLUDE_BROKEN 0x1\n>#define FILTER_REFS_TAGS 0x2\n>#define FILTER_REFS_BRANCHES 0x4\n>#define FILTER_REFS_REMOTES 0x8\n>#define FILTER_REFS_DETACHED_HEAD 0x16\n\nYou meant 0x10, not 0x16 I guess.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"268025","messageId":"CAOLa=ZRyL4PLKQiw1ie5e4NN21BTy3KPVxCvf_eUeW-C5wSU2w@mail.gmail.com","threadId":"40010","inReplyTo":"FC0BD660-1476-430A-9F71-E9D0E6681780@imag.fr","subject":"Re: [PATCH 01/10] ref-filter: add option to filter only branches","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-13T20:13:47Z","receivedAt":"2015-08-13T20:13:47Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On Thu, Aug 13, 2015 at 10:22 PM, Matthieu Moy <matthieu.moy@imag.fr> wrote:\n>\n>\n> Le 13 août 2015 13:35:21 GMT+02:00, Karthik Nayak <karthik.188@gmail.com> a écrit :\n>>On Thu, Aug 13, 2015 at 4:21 PM, Karthik Nayak <karthik.188@gmail.com>\n>>wrote:\n>>>\n>>> This was taken from branch.c, I thought of using an enum instead but\n>>that\n>>> would again require most of branch.c, hence it's been carried over\n>>> without changing\n>>> I'm thinking of changing it, any suggestions?\n>>>\n>>\n>>What I was thinking was of having:\n>>\n>>#define FILTER_REFS_INCLUDE_BROKEN 0x1\n>>#define FILTER_REFS_TAGS 0x2\n>>#define FILTER_REFS_BRANCHES 0x4\n>>#define FILTER_REFS_REMOTES 0x8\n>>#define FILTER_REFS_DETACHED_HEAD 0x16\n>\n> You meant 0x10, not 0x16 I guess.\n>\n\nYea! Of course, was randomly typing out an example :)\n\n\n-- \nRegards,\nKarthik Nayak\n"},{"id":"268042","messageId":"xmqq614hkgnd.fsf@gitster.dls.corp.google.com","threadId":"40010","inReplyTo":"CAOLa=ZQSVCgcuUQFsF2Mq-m+wS8im3t4Z3PSEgoAHcV0gGuvPA@mail.gmail.com","subject":"Re: [PATCH 01/10] ref-filter: add option to filter only branches","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-08-14T15:56:38Z","receivedAt":"2015-08-14T15:56:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> On Thu, Aug 13, 2015 at 5:05 PM, Karthik Nayak <karthik.188@gmail.com> wrote:\n>> On Thu, Aug 13, 2015 at 4:21 PM, Karthik Nayak <karthik.188@gmail.com> wrote:\n>>>\n>>> This was taken from branch.c, I thought of using an enum instead but that\n>>> would again require most of branch.c, hence it's been carried over\n>>> without changing\n>>> I'm thinking of changing it, any suggestions?\n>>>\n>>\n>> What I was thinking was of having:\n>>\n>> #define FILTER_REFS_INCLUDE_BROKEN 0x1\n>> #define FILTER_REFS_TAGS 0x2\n>> #define FILTER_REFS_BRANCHES 0x4\n>> #define FILTER_REFS_REMOTES 0x8\n>> #define FILTER_REFS_DETACHED_HEAD 0x16\n>>\n>> and using these for showing ref kind also instead of separately\n>> having 'REF_DETACHED_HEAD' and so on.\n>>\n>\n> Something like this:\n> https://github.com/KarthikNayak/git/commit/0ec5381420dcdfe7c62000b56168e2842d5d0063\n\nI notice a few things in ref-filter.c in that commit (a web\ninterface including GitHub one is horrible in showing the things in\nwider context across files, so I'll base my discussion by guessing\nwhat the caller of this function and helpers this function calls\ndo):\n\n - Your \"ALL\" silently overrides others.  Is that sensible?  Perhaps\n   you would instead want to define FILTER_REFS_OTHER (not needed to\n   be exposed to UI) and then define FILTER_REFS_ALL as the ORed\n   value of FILTER_REFS_{BRANCHES,...,OTHER}?\n\n - When the caller asks for \"--branches --tags\", you run\n   ref-filter-handler twice on ref_cbdata.  Does that make sense?\n   Shouldn't you iterate over all the available refs just once,\n   rejecting ones that aren't in either refs/{heads,tags}/ instead?\n"},{"id":"268058","messageId":"CAOLa=ZTiVftC51e+dpq1=Ui38L5bUseq0M0+vMJ3O-Db9311XQ@mail.gmail.com","threadId":"40010","inReplyTo":"xmqq614hkgnd.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH 01/10] ref-filter: add option to filter only branches","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-08-14T18:45:56Z","receivedAt":"2015-08-14T18:45:56Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On Fri, Aug 14, 2015 at 9:26 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> On Thu, Aug 13, 2015 at 5:05 PM, Karthik Nayak <karthik.188@gmail.com> wrote:\n>>> On Thu, Aug 13, 2015 at 4:21 PM, Karthik Nayak <karthik.188@gmail.com> wrote:\n>>>>\n>>>> This was taken from branch.c, I thought of using an enum instead but that\n>>>> would again require most of branch.c, hence it's been carried over\n>>>> without changing\n>>>> I'm thinking of changing it, any suggestions?\n>>>>\n>>>\n>>> What I was thinking was of having:\n>>>\n>>> #define FILTER_REFS_INCLUDE_BROKEN 0x1\n>>> #define FILTER_REFS_TAGS 0x2\n>>> #define FILTER_REFS_BRANCHES 0x4\n>>> #define FILTER_REFS_REMOTES 0x8\n>>> #define FILTER_REFS_DETACHED_HEAD 0x16\n>>>\n>>> and using these for showing ref kind also instead of separately\n>>> having 'REF_DETACHED_HEAD' and so on.\n>>>\n>>\n>> Something like this:\n>> https://github.com/KarthikNayak/git/commit/0ec5381420dcdfe7c62000b56168e2842d5d0063\n>\n> I notice a few things in ref-filter.c in that commit (a web\n> interface including GitHub one is horrible in showing the things in\n> wider context across files, so I'll base my discussion by guessing\n> what the caller of this function and helpers this function calls\n> do):\n>\n>  - Your \"ALL\" silently overrides others.  Is that sensible?  Perhaps\n>    you would instead want to define FILTER_REFS_OTHER (not needed to\n>    be exposed to UI) and then define FILTER_REFS_ALL as the ORed\n>    value of FILTER_REFS_{BRANCHES,...,OTHER}?\n>\n\nWell okay I could something on those lines.\n\n>  - When the caller asks for \"--branches --tags\", you run\n>    ref-filter-handler twice on ref_cbdata.  Does that make sense?\n>    Shouldn't you iterate over all the available refs just once,\n>    rejecting ones that aren't in either refs/{heads,tags}/ instead?\n\nI was under the idea that since we're dealing with do_for_each_entry()\neventually and in that we set the loose_dir value based on the given 'base'\nhence when the caller asks for something like \"--branches --tags\", it would\nbe better to just iterate through the refs in the directory of\n\"--branches --tags\"\nrather than go through the whole list of refs and drop ones which don't belong\nto \"--branches --tags\". but this was an over the top look at how\ndo_for_each_entry()\nworks, I could be totally off the mark.\n\n-- \nRegards,\nKarthik Nayak\n"}]}