branch.c: use 'ref-filter' data structures

Make 'branch.c' use 'ref-filter' data structures and make changes to support the new data structures. This is a part of the process of porting 'branch.c' to use 'ref-filter' APIs. This is a temporary step before porting 'branch.c' to use 'ref-filter' completely. As this is a temporary step, most of the code introduced here will be removed when 'branch.c' is ported over to use 'ref-filter' APIs. Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr> Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Karthik Nayak committed Sep 23, 2015 at 23:41 UTC 1511b22d40d102f397104858a617aa1662bb1c98
2 files changed +134 -190
builtin/branch.c
+128 -189
@@ -19,6 +19,7 @@
19 #include "column.h"
20 #include "utf8.h"
21 #include "wt-status.h"
22 +#include "ref-filter.h"
23
24 static const char * const builtin_branch_usage[] = {
25 N_("git branch [<options>] [-r | -a] [--merged | --no-merged]"),
@@ -28,10 +29,6 @@ static const char * const builtin_branch_usage[] = {
29 NULL
30 };
31
31 -#define REF_DETACHED_HEAD 0x01
32 -#define REF_LOCAL_BRANCH 0x02
33 -#define REF_REMOTE_BRANCH 0x04
34 -
32 static const char *head;
33 static unsigned char head_sha1[20];
34
@@ -53,13 +50,6 @@ enum color_branch {
50 BRANCH_COLOR_UPSTREAM = 5
51 };
52
56 -static enum merge_filter {
57 - NO_FILTER = 0,
58 - SHOW_NOT_MERGED,
59 - SHOW_MERGED
60 -} merge_filter;
61 -static unsigned char merge_filter_ref[20];
62 -
53 static struct string_list output = STRING_LIST_INIT_DUP;
54 static unsigned int colopts;
55
@@ -122,7 +112,7 @@ static int branch_merged(int kind, const char *name,
112 void *reference_name_to_free = NULL;
113 int merged;
114
125 - if (kind == REF_LOCAL_BRANCH) {
115 + if (kind == FILTER_REFS_BRANCHES) {
116 struct branch *branch = branch_get(name);
117 const char *upstream = branch_get_upstream(branch, NULL);
118 unsigned char sha1[20];
@@ -200,14 +190,14 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
190 struct strbuf bname = STRBUF_INIT;
191
192 switch (kinds) {
203 - case REF_REMOTE_BRANCH:
193 + case FILTER_REFS_REMOTES:
194 fmt = "refs/remotes/%s";
195 /* For subsequent UI messages */
196 remote_branch = 1;
197
198 force = 1;
199 break;
210 - case REF_LOCAL_BRANCH:
200 + case FILTER_REFS_BRANCHES:
201 fmt = "refs/heads/%s";
202 break;
203 default:
@@ -224,7 +214,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
214 int flags = 0;
215
216 strbuf_branchname(&bname, argv[i]);
227 - if (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) {
217 + if (kinds == FILTER_REFS_BRANCHES && !strcmp(head, bname.buf)) {
218 error(_("Cannot delete the branch '%s' "
219 "which you are currently on."), bname.buf);
220 ret = 1;
@@ -280,22 +270,6 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
270 return(ret);
271 }
272
283 -struct ref_item {
284 - char *name;
285 - char *dest;
286 - unsigned int kind;
287 - struct commit *commit;
288 - int ignore;
289 -};
290 -
291 -struct ref_list {
292 - struct rev_info revs;
293 - int index, alloc, verbose, abbrev;
294 - struct ref_item *list;
295 - struct commit_list *with_commit;
296 - int kinds;
297 -};
298 -
273 static char *resolve_symref(const char *src, const char *prefix)
274 {
275 unsigned char sha1[20];
@@ -310,11 +284,6 @@ static char *resolve_symref(const char *src, const char *prefix)
284 return xstrdup(dst);
285 }
286
313 -struct append_ref_cb {
314 - struct ref_list *ref_list;
315 - const char **pattern;
316 -};
317 -
287 static int match_patterns(const char **pattern, const char *refname)
288 {
289 if (!*pattern)
@@ -327,11 +296,29 @@ static int match_patterns(const char **pattern, const char *refname)
296 return 0;
297 }
298
299 +/*
300 + * Allocate memory for a new ref_array_item and insert that into the
301 + * given ref_array. Doesn't take the objectname unlike
302 + * new_ref_array_item(). This is a temporary function which will be
303 + * removed when we port branch.c to use ref-filter APIs.
304 + */
305 +static struct ref_array_item *ref_array_append(struct ref_array *array, const char *refname)
306 +{
307 + size_t len = strlen(refname);
308 + struct ref_array_item *ref = xcalloc(1, sizeof(struct ref_array_item) + len + 1);
309 + memcpy(ref->refname, refname, len);
310 + ref->refname[len] = '\0';
311 + REALLOC_ARRAY(array->items, array->nr + 1);
312 + array->items[array->nr++] = ref;
313 + return ref;
314 +}
315 +
316 static int append_ref(const char *refname, const struct object_id *oid, int flags, void *cb_data)
317 {
332 - struct append_ref_cb *cb = (struct append_ref_cb *)(cb_data);
333 - struct ref_list *ref_list = cb->ref_list;
334 - struct ref_item *newitem;
318 + struct ref_filter_cbdata *cb = (struct ref_filter_cbdata *)(cb_data);
319 + struct ref_filter *filter = cb->filter;
320 + struct ref_array *array = cb->array;
321 + struct ref_array_item *item;
322 struct commit *commit;
323 int kind, i;
324 const char *prefix, *orig_refname = refname;
@@ -340,8 +327,8 @@ static int append_ref(const char *refname, const struct object_id *oid, int flag
327 int kind;
328 const char *prefix;
329 } ref_kind[] = {
343 - { REF_LOCAL_BRANCH, "refs/heads/" },
344 - { REF_REMOTE_BRANCH, "refs/remotes/" },
330 + { FILTER_REFS_BRANCHES, "refs/heads/" },
331 + { FILTER_REFS_REMOTES, "refs/remotes/" },
332 };
333
334 /* Detect kind */
@@ -354,65 +341,52 @@ static int append_ref(const char *refname, const struct object_id *oid, int flag
341 }
342 if (ARRAY_SIZE(ref_kind) <= i) {
343 if (!strcmp(refname, "HEAD"))
357 - kind = REF_DETACHED_HEAD;
344 + kind = FILTER_REFS_DETACHED_HEAD;
345 else
346 return 0;
347 }
348
349 /* Don't add types the caller doesn't want */
363 - if ((kind & ref_list->kinds) == 0)
350 + if ((kind & filter->kind) == 0)
351 return 0;
352
366 - if (!match_patterns(cb->pattern, refname))
353 + if (!match_patterns(filter->name_patterns, refname))
354 return 0;
355
356 commit = NULL;
370 - if (ref_list->verbose || ref_list->with_commit || merge_filter != NO_FILTER) {
357 + if (filter->verbose || filter->with_commit || filter->merge != REF_FILTER_MERGED_NONE) {
358 commit = lookup_commit_reference_gently(oid->hash, 1);
359 if (!commit)
360 return 0;
361
362 /* Filter with with_commit if specified */
376 - if (!is_descendant_of(commit, ref_list->with_commit))
363 + if (!is_descendant_of(commit, filter->with_commit))
364 return 0;
365
379 - if (merge_filter != NO_FILTER)
380 - add_pending_object(&ref_list->revs,
366 + if (filter->merge != REF_FILTER_MERGED_NONE)
367 + add_pending_object(array->revs,
368 (struct object *)commit, refname);
369 }
370
384 - ALLOC_GROW(ref_list->list, ref_list->index + 1, ref_list->alloc);
371 + item = ref_array_append(array, refname);
372
373 /* Record the new item */
387 - newitem = &(ref_list->list[ref_list->index++]);
388 - newitem->name = xstrdup(refname);
389 - newitem->kind = kind;
390 - newitem->commit = commit;
391 - newitem->dest = resolve_symref(orig_refname, prefix);
392 - newitem->ignore = 0;
374 + item->kind = kind;
375 + item->commit = commit;
376 + item->symref = resolve_symref(orig_refname, prefix);
377 + item->ignore = 0;
378
379 return 0;
380 }
381
397 -static void free_ref_list(struct ref_list *ref_list)
398 -{
399 - int i;
400 -
401 - for (i = 0; i < ref_list->index; i++) {
402 - free(ref_list->list[i].name);
403 - free(ref_list->list[i].dest);
404 - }
405 - free(ref_list->list);
406 -}
407 -
382 static int ref_cmp(const void *r1, const void *r2)
383 {
410 - struct ref_item *c1 = (struct ref_item *)(r1);
411 - struct ref_item *c2 = (struct ref_item *)(r2);
384 + struct ref_array_item *c1 = *((struct ref_array_item **)r1);
385 + struct ref_array_item *c2 = *((struct ref_array_item **)r2);
386
387 if (c1->kind != c2->kind)
388 return c1->kind - c2->kind;
415 - return strcmp(c1->name, c2->name);
389 + return strcmp(c1->refname, c2->refname);
390 }
391
392 static void fill_tracking_info(struct strbuf *stat, const char *branch_name,
@@ -477,8 +451,8 @@ static void fill_tracking_info(struct strbuf *stat, const char *branch_name,
451 free(ref);
452 }
453
480 -static void add_verbose_info(struct strbuf *out, struct ref_item *item,
481 - int verbose, int abbrev)
454 +static void add_verbose_info(struct strbuf *out, struct ref_array_item *item,
455 + struct ref_filter *filter)
456 {
457 struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;
458 const char *sub = _(" **** invalid ref ****");
@@ -489,11 +463,11 @@ static void add_verbose_info(struct strbuf *out, struct ref_item *item,
463 sub = subject.buf;
464 }
465
492 - if (item->kind == REF_LOCAL_BRANCH)
493 - fill_tracking_info(&stat, item->name, verbose > 1);
466 + if (item->kind == FILTER_REFS_BRANCHES)
467 + fill_tracking_info(&stat, item->refname, filter->verbose > 1);
468
469 strbuf_addf(out, " %s %s%s",
496 - find_unique_abbrev(item->commit->object.sha1, abbrev),
470 + find_unique_abbrev(item->commit->object.sha1, filter->abbrev),
471 stat.buf, sub);
472 strbuf_release(&stat);
473 strbuf_release(&subject);
@@ -530,32 +504,32 @@ static char *get_head_description(void)
504 return strbuf_detach(&desc, NULL);
505 }
506
533 -static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
534 - int abbrev, int detached, const char *remote_prefix)
507 +static void print_ref_item(struct ref_array_item *item, int maxwidth,
508 + struct ref_filter *filter, const char *remote_prefix)
509 {
510 char c;
511 int current = 0;
512 int color;
513 struct strbuf out = STRBUF_INIT, name = STRBUF_INIT;
514 const char *prefix = "";
541 - const char *desc = item->name;
515 + const char *desc = item->refname;
516 char *to_free = NULL;
517
518 if (item->ignore)
519 return;
520
521 switch (item->kind) {
548 - case REF_LOCAL_BRANCH:
549 - if (!detached && !strcmp(item->name, head))
522 + case FILTER_REFS_BRANCHES:
523 + if (!filter->detached && !strcmp(item->refname, head))
524 current = 1;
525 else
526 color = BRANCH_COLOR_LOCAL;
527 break;
554 - case REF_REMOTE_BRANCH:
528 + case FILTER_REFS_REMOTES:
529 color = BRANCH_COLOR_REMOTE;
530 prefix = remote_prefix;
531 break;
558 - case REF_DETACHED_HEAD:
532 + case FILTER_REFS_DETACHED_HEAD:
533 desc = to_free = get_head_description();
534 current = 1;
535 break;
@@ -571,7 +545,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
545 }
546
547 strbuf_addf(&name, "%s%s", prefix, desc);
574 - if (verbose) {
548 + if (filter->verbose) {
549 int utf8_compensation = strlen(name.buf) - utf8_strwidth(name.buf);
550 strbuf_addf(&out, "%c %s%-*s%s", c, branch_get_color(color),
551 maxwidth + utf8_compensation, name.buf,
@@ -580,13 +554,13 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
554 strbuf_addf(&out, "%c %s%s%s", c, branch_get_color(color),
555 name.buf, branch_get_color(BRANCH_COLOR_RESET));
556
583 - if (item->dest)
584 - strbuf_addf(&out, " -> %s", item->dest);
585 - else if (verbose)
557 + if (item->symref)
558 + strbuf_addf(&out, " -> %s", item->symref);
559 + else if (filter->verbose)
560 /* " f7c0c00 [ahead 58, behind 197] vcs-svn: drop obj_pool.h" */
587 - add_verbose_info(&out, item, verbose, abbrev);
561 + add_verbose_info(&out, item, filter);
562 if (column_active(colopts)) {
589 - assert(!verbose && "--column and --verbose are incompatible");
563 + assert(!filter->verbose && "--column and --verbose are incompatible");
564 string_list_append(&output, out.buf);
565 } else {
566 printf("%s\n", out.buf);
@@ -596,17 +570,17 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
570 free(to_free);
571 }
572
599 -static int calc_maxwidth(struct ref_list *refs, int remote_bonus)
573 +static int calc_maxwidth(struct ref_array *refs, int remote_bonus)
574 {
575 int i, max = 0;
602 - for (i = 0; i < refs->index; i++) {
603 - struct ref_item *it = &refs->list[i];
576 + for (i = 0; i < refs->nr; i++) {
577 + struct ref_array_item *it = refs->items[i];
578 int w;
579
580 if (it->ignore)
581 continue;
608 - w = utf8_strwidth(it->name);
609 - if (it->kind == REF_REMOTE_BRANCH)
582 + w = utf8_strwidth(it->refname);
583 + if (it->kind == FILTER_REFS_REMOTES)
584 w += remote_bonus;
585 if (w > max)
586 max = w;
@@ -614,81 +588,74 @@ static int calc_maxwidth(struct ref_list *refs, int remote_bonus)
588 return max;
589 }
590
617 -static void print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit, const char **pattern)
591 +static void print_ref_list(struct ref_filter *filter)
592 {
593 int i;
620 - struct append_ref_cb cb;
621 - struct ref_list ref_list;
594 + struct ref_array array;
595 + struct ref_filter_cbdata data;
596 int maxwidth = 0;
597 const char *remote_prefix = "";
598 + struct rev_info revs;
599
600 /*
601 * If we are listing more than just remote branches,
602 * then remote branches will have a "remotes/" prefix.
603 * We need to account for this in the width.
604 */
630 - if (kinds != REF_REMOTE_BRANCH)
605 + if (filter->kind != FILTER_REFS_REMOTES)
606 remote_prefix = "remotes/";
607
633 - memset(&ref_list, 0, sizeof(ref_list));
634 - ref_list.kinds = kinds;
635 - ref_list.verbose = verbose;
636 - ref_list.abbrev = abbrev;
637 - ref_list.with_commit = with_commit;
638 - if (merge_filter != NO_FILTER)
639 - init_revisions(&ref_list.revs, NULL);
640 - cb.ref_list = &ref_list;
641 - cb.pattern = pattern;
608 + memset(&array, 0, sizeof(array));
609 + if (filter->merge != REF_FILTER_MERGED_NONE)
610 + init_revisions(&revs, NULL);
611 +
612 + data.array = &array;
613 + data.filter = filter;
614 + array.revs = &revs;
615 +
616 /*
617 * First we obtain all regular branch refs and if the HEAD is
618 * detached then we insert that ref to the end of the ref_fist
619 * so that it can be printed and removed first.
620 */
647 - for_each_rawref(append_ref, &cb);
648 - if (detached)
649 - head_ref(append_ref, &cb);
621 + for_each_rawref(append_ref, &data);
622 + if (filter->detached)
623 + head_ref(append_ref, &data);
624 /*
625 * The following implementation is currently duplicated in ref-filter. It
626 * will eventually be removed when we port branch.c to use ref-filter APIs.
627 */
654 - if (merge_filter != NO_FILTER) {
655 - struct commit *filter;
656 - filter = lookup_commit_reference_gently(merge_filter_ref, 0);
657 - if (!filter)
658 - die(_("object '%s' does not point to a commit"),
659 - sha1_to_hex(merge_filter_ref));
660 -
661 - filter->object.flags |= UNINTERESTING;
662 - add_pending_object(&ref_list.revs,
663 - (struct object *) filter, "");
664 - ref_list.revs.limited = 1;
665 -
666 - if (prepare_revision_walk(&ref_list.revs))
628 + if (filter->merge != REF_FILTER_MERGED_NONE) {
629 + filter->merge_commit->object.flags |= UNINTERESTING;
630 + add_pending_object(&revs, &filter->merge_commit->object, "");
631 + revs.limited = 1;
632 +
633 + if (prepare_revision_walk(&revs))
634 die(_("revision walk setup failed"));
635
669 - for (i = 0; i < ref_list.index; i++) {
670 - struct ref_item *item = &ref_list.list[i];
636 + for (i = 0; i < array.nr; i++) {
637 + struct ref_array_item *item = array.items[i];
638 struct commit *commit = item->commit;
639 int is_merged = !!(commit->object.flags & UNINTERESTING);
673 - item->ignore = is_merged != (merge_filter == SHOW_MERGED);
640 + item->ignore = is_merged != (filter->merge == REF_FILTER_MERGED_INCLUDE);
641 }
642
676 - for (i = 0; i < ref_list.index; i++) {
677 - struct ref_item *item = &ref_list.list[i];
643 + for (i = 0; i < array.nr; i++) {
644 + struct ref_array_item *item = array.items[i];
645 clear_commit_marks(item->commit, ALL_REV_FLAGS);
646 }
680 - clear_commit_marks(filter, ALL_REV_FLAGS);
647 + clear_commit_marks(filter->merge_commit, ALL_REV_FLAGS);
648 }
682 - if (verbose)
683 - maxwidth = calc_maxwidth(&ref_list, strlen(remote_prefix));
649
685 - qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);
650 + if (filter->verbose)
651 + maxwidth = calc_maxwidth(&array, strlen(remote_prefix));
652 +
653 + qsort(array.items, array.nr, sizeof(struct ref_array_item *), ref_cmp);
654
687 - for (i = 0; i < ref_list.index; i++)
688 - print_ref_item(&ref_list.list[i], maxwidth, verbose,
689 - abbrev, detached, remote_prefix);
655 + for (i = 0; i < array.nr; i++)
656 + print_ref_item(array.items[i], maxwidth, filter, remote_prefix);
657
691 - free_ref_list(&ref_list);
658 + ref_array_clear(&array);
659 }
660
661 static void rename_branch(const char *oldname, const char *newname, int force)
@@ -744,24 +711,6 @@ static void rename_branch(const char *oldname, const char *newname, int force)
711 strbuf_release(&newsection);
712 }
713
747 -/*
748 - * This function is duplicated in ref-filter. It will eventually be removed
749 - * when we port branch.c to use ref-filter APIs.
750 - */
751 -static int opt_parse_merge_filter(const struct option *opt, const char *arg, int unset)
752 -{
753 - merge_filter = ((opt->long_name[0] == 'n')
754 - ? SHOW_NOT_MERGED
755 - : SHOW_MERGED);
756 - if (unset)
757 - merge_filter = SHOW_NOT_MERGED; /* b/c for --no-merged */
758 - if (!arg)
759 - arg = "HEAD";
760 - if (get_sha1(arg, merge_filter_ref))
761 - die(_("malformed object name %s"), arg);
762 - return 0;
763 -}
764 -
714 static const char edit_description[] = "BRANCH_DESCRIPTION";
715
716 static int edit_branch_description(const char *branch_name)
@@ -801,17 +750,15 @@ static int edit_branch_description(const char *branch_name)
750 int cmd_branch(int argc, const char **argv, const char *prefix)
751 {
752 int delete = 0, rename = 0, force = 0, list = 0;
804 - int verbose = 0, abbrev = -1, detached = 0;
753 int reflog = 0, edit_description = 0;
754 int quiet = 0, unset_upstream = 0;
755 const char *new_upstream = NULL;
756 enum branch_track track;
809 - int kinds = REF_LOCAL_BRANCH;
810 - struct commit_list *with_commit = NULL;
757 + struct ref_filter filter;
758
759 struct option options[] = {
760 OPT_GROUP(N_("Generic options")),
814 - OPT__VERBOSE(&verbose,
761 + OPT__VERBOSE(&filter.verbose,
762 N_("show hash and subject, give twice for upstream branch")),
763 OPT__QUIET(&quiet, N_("suppress informational messages")),
764 OPT_SET_INT('t', "track", &track, N_("set up tracking mode (see git-pull(1))"),
@@ -821,15 +768,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
768 OPT_STRING('u', "set-upstream-to", &new_upstream, "upstream", "change the upstream info"),
769 OPT_BOOL(0, "unset-upstream", &unset_upstream, "Unset the upstream info"),
770 OPT__COLOR(&branch_use_color, N_("use colored output")),
824 - OPT_SET_INT('r', "remotes", &kinds, N_("act on remote-tracking branches"),
825 - REF_REMOTE_BRANCH),
826 - OPT_CONTAINS(&with_commit, N_("print only branches that contain the commit")),
827 - OPT_WITH(&with_commit, N_("print only branches that contain the commit")),
828 - OPT__ABBREV(&abbrev),
771 + OPT_SET_INT('r', "remotes", &filter.kind, N_("act on remote-tracking branches"),
772 + FILTER_REFS_REMOTES),
773 + OPT_CONTAINS(&filter.with_commit, N_("print only branches that contain the commit")),
774 + OPT_WITH(&filter.with_commit, N_("print only branches that contain the commit")),
775 + OPT__ABBREV(&filter.abbrev),
776
777 OPT_GROUP(N_("Specific git-branch actions:")),
831 - OPT_SET_INT('a', "all", &kinds, N_("list both remote-tracking and local branches"),
832 - REF_REMOTE_BRANCH | REF_LOCAL_BRANCH),
778 + OPT_SET_INT('a', "all", &filter.kind, N_("list both remote-tracking and local branches"),
779 + FILTER_REFS_REMOTES | FILTER_REFS_BRANCHES),
780 OPT_BIT('d', "delete", &delete, N_("delete fully merged branch"), 1),
781 OPT_BIT('D', NULL, &delete, N_("delete branch (even if not merged)"), 2),
782 OPT_BIT('m', "move", &rename, N_("move/rename a branch and its reflog"), 1),
@@ -839,22 +786,16 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
786 OPT_BOOL(0, "edit-description", &edit_description,
787 N_("edit the description for the branch")),
788 OPT__FORCE(&force, N_("force creation, move/rename, deletion")),
842 - {
843 - OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref,
844 - N_("commit"), N_("print only not merged branches"),
845 - PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,
846 - opt_parse_merge_filter, (intptr_t) "HEAD",
847 - },
848 - {
849 - OPTION_CALLBACK, 0, "merged", &merge_filter_ref,
850 - N_("commit"), N_("print only merged branches"),
851 - PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,
852 - opt_parse_merge_filter, (intptr_t) "HEAD",
853 - },
789 + OPT_MERGED(&filter, N_("print only branches that are merged")),
790 + OPT_NO_MERGED(&filter, N_("print only branches that are not merged")),
791 OPT_COLUMN(0, "column", &colopts, N_("list branches in columns")),
792 OPT_END(),
793 };
794
795 + memset(&filter, 0, sizeof(filter));
796 + filter.kind = FILTER_REFS_BRANCHES;
797 + filter.abbrev = -1;
798 +
799 if (argc == 2 && !strcmp(argv[1], "-h"))
800 usage_with_options(builtin_branch_usage, options);
801
@@ -866,11 +807,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
807 if (!head)
808 die(_("Failed to resolve HEAD as a valid ref."));
809 if (!strcmp(head, "HEAD"))
869 - detached = 1;
810 + filter.detached = 1;
811 else if (!skip_prefix(head, "refs/heads/", &head))
812 die(_("HEAD not found below refs/heads!"));
872 - hashcpy(merge_filter_ref, head_sha1);
873 -
813
814 argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
815 0);
@@ -878,17 +817,17 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
817 if (!delete && !rename && !edit_description && !new_upstream && !unset_upstream && argc == 0)
818 list = 1;
819
881 - if (with_commit || merge_filter != NO_FILTER)
820 + if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE)
821 list = 1;
822
823 if (!!delete + !!rename + !!new_upstream +
824 list + unset_upstream > 1)
825 usage_with_options(builtin_branch_usage, options);
826
888 - if (abbrev == -1)
889 - abbrev = DEFAULT_ABBREV;
827 + if (filter.abbrev == -1)
828 + filter.abbrev = DEFAULT_ABBREV;
829 finalize_colopts(&colopts, -1);
891 - if (verbose) {
830 + if (filter.verbose) {
831 if (explicitly_enable_column(colopts))
832 die(_("--column and --verbose are incompatible"));
833 colopts = 0;
@@ -902,13 +841,13 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
841 if (delete) {
842 if (!argc)
843 die(_("branch name required"));
905 - return delete_branches(argc, argv, delete > 1, kinds, quiet);
844 + return delete_branches(argc, argv, delete > 1, filter.kind, quiet);
845 } else if (list) {
846 /* git branch --local also shows HEAD when it is detached */
908 - if (kinds & REF_LOCAL_BRANCH)
909 - kinds |= REF_DETACHED_HEAD;
910 - print_ref_list(kinds, detached, verbose, abbrev,
911 - with_commit, argv);
847 + if ((filter.kind & FILTER_REFS_BRANCHES) && filter.detached)
848 + filter.kind |= FILTER_REFS_DETACHED_HEAD;
849 + filter.name_patterns = argv;
850 + print_ref_list(&filter);
851 print_columns(&output, colopts, NULL);
852 string_list_clear(&output, 0);
853 return 0;
@@ -918,7 +857,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
857 struct strbuf branch_ref = STRBUF_INIT;
858
859 if (!argc) {
921 - if (detached)
860 + if (filter.detached)
861 die(_("Cannot give description to detached HEAD"));
862 branch_name = head;
863 } else if (argc == 1)
@@ -1006,7 +945,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
945 if (!branch)
946 die(_("no such branch '%s'"), argv[0]);
947
1009 - if (kinds != REF_LOCAL_BRANCH)
948 + if (filter.kind != FILTER_REFS_BRANCHES)
949 die(_("-a and -r options to 'git branch' do not make sense with a branch name"));
950
951 if (track == BRANCH_TRACK_OVERRIDE)
ref-filter.h
+6 -1
@@ -36,6 +36,7 @@ struct ref_array_item {
36 unsigned char objectname[20];
37 int flag;
38 unsigned int kind;
39 + int ignore : 1; /* To be removed in the next patch */
40 const char *symref;
41 struct commit *commit;
42 struct atom_value *value;
@@ -45,6 +46,7 @@ struct ref_array_item {
46 struct ref_array {
47 int nr, alloc;
48 struct ref_array_item **items;
49 + struct rev_info *revs;
50 };
51
52 struct ref_filter {
@@ -60,9 +62,12 @@ struct ref_filter {
62 struct commit *merge_commit;
63
64 unsigned int with_commit_tag_algo : 1,
63 - match_as_path : 1;
65 + match_as_path : 1,
66 + detached : 1;
67 unsigned int kind,
68 lines;
69 + int abbrev,
70 + verbose;
71 };
72
73 struct ref_filter_cbdata {