Skip to content

Commit 9958dd8

Browse files
committed
Merge branch 'kn/for-each-tag-branch'
Some features from "git tag -l" and "git branch -l" have been made available to "git for-each-ref" so that eventually the unified implementation can be shared across all three, in a follow-up series or two. * kn/for-each-tag-branch: for-each-ref: add '--contains' option ref-filter: implement '--contains' option parse-options.h: add macros for '--contains' option parse-option: rename parse_opt_with_commit() for-each-ref: add '--merged' and '--no-merged' options ref-filter: implement '--merged' and '--no-merged' options ref-filter: add parse_opt_merge_filter() for-each-ref: add '--points-at' option ref-filter: implement '--points-at' option tag: libify parse_opt_points_at() t6302: for-each-ref tests for ref-filter APIs
2 parents be08dee + 4a71109 commit 9958dd8

9 files changed

+420
-51
lines changed

Documentation/git-for-each-ref.txt

+16
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ SYNOPSIS
1010
[verse]
1111
'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]
1212
[(--sort=<key>)...] [--format=<format>] [<pattern>...]
13+
[--points-at <object>] [(--merged | --no-merged) [<object>]]
14+
[--contains [<object>]]
1315

1416
DESCRIPTION
1517
-----------
@@ -62,6 +64,20 @@ OPTIONS
6264
the specified host language. This is meant to produce
6365
a scriptlet that can directly be `eval`ed.
6466

67+
--points-at <object>::
68+
Only list refs which points at the given object.
69+
70+
--merged [<object>]::
71+
Only list refs whose tips are reachable from the
72+
specified commit (HEAD if not specified).
73+
74+
--no-merged [<object>]::
75+
Only list refs whose tips are not reachable from the
76+
specified commit (HEAD if not specified).
77+
78+
--contains [<object>]::
79+
Only list tags which contain the specified commit (HEAD if not
80+
specified).
6581

6682
FIELD NAMES
6783
-----------

builtin/branch.c

+10-12
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,10 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru
636636
cb.pattern = pattern;
637637
cb.ret = 0;
638638
for_each_rawref(append_ref, &cb);
639+
/*
640+
* The following implementation is currently duplicated in ref-filter. It
641+
* will eventually be removed when we port branch.c to use ref-filter APIs.
642+
*/
639643
if (merge_filter != NO_FILTER) {
640644
struct commit *filter;
641645
filter = lookup_commit_reference_gently(merge_filter_ref, 0);
@@ -746,6 +750,10 @@ static void rename_branch(const char *oldname, const char *newname, int force)
746750
strbuf_release(&newsection);
747751
}
748752

753+
/*
754+
* This function is duplicated in ref-filter. It will eventually be removed
755+
* when we port branch.c to use ref-filter APIs.
756+
*/
749757
static int opt_parse_merge_filter(const struct option *opt, const char *arg, int unset)
750758
{
751759
merge_filter = ((opt->long_name[0] == 'n')
@@ -821,18 +829,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
821829
OPT__COLOR(&branch_use_color, N_("use colored output")),
822830
OPT_SET_INT('r', "remotes", &kinds, N_("act on remote-tracking branches"),
823831
REF_REMOTE_BRANCH),
824-
{
825-
OPTION_CALLBACK, 0, "contains", &with_commit, N_("commit"),
826-
N_("print only branches that contain the commit"),
827-
PARSE_OPT_LASTARG_DEFAULT,
828-
parse_opt_with_commit, (intptr_t)"HEAD",
829-
},
830-
{
831-
OPTION_CALLBACK, 0, "with", &with_commit, N_("commit"),
832-
N_("print only branches that contain the commit"),
833-
PARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT,
834-
parse_opt_with_commit, (intptr_t) "HEAD",
835-
},
832+
OPT_CONTAINS(&with_commit, N_("print only branches that contain the commit")),
833+
OPT_WITH(&with_commit, N_("print only branches that contain the commit")),
836834
OPT__ABBREV(&abbrev),
837835

838836
OPT_GROUP(N_("Specific git-branch actions:")),

builtin/for-each-ref.c

+12-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77

88
static char const * const for_each_ref_usage[] = {
99
N_("git for-each-ref [<options>] [<pattern>]"),
10+
N_("git for-each-ref [--points-at <object>]"),
11+
N_("git for-each-ref [(--merged | --no-merged) [<object>]]"),
12+
N_("git for-each-ref [--contains [<object>]]"),
1013
NULL
1114
};
1215

@@ -34,9 +37,18 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
3437
OPT_STRING( 0 , "format", &format, N_("format"), N_("format to use for the output")),
3538
OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"),
3639
N_("field name to sort on"), &parse_opt_ref_sorting),
40+
OPT_CALLBACK(0, "points-at", &filter.points_at,
41+
N_("object"), N_("print only refs which points at the given object"),
42+
parse_opt_object_name),
43+
OPT_MERGED(&filter, N_("print only refs that are merged")),
44+
OPT_NO_MERGED(&filter, N_("print only refs that are not merged")),
45+
OPT_CONTAINS(&filter.with_commit, N_("print only refs which contain the commit")),
3746
OPT_END(),
3847
};
3948

49+
memset(&array, 0, sizeof(array));
50+
memset(&filter, 0, sizeof(filter));
51+
4052
parse_options(argc, argv, prefix, opts, for_each_ref_usage, 0);
4153
if (maxcount < 0) {
4254
error("invalid --count argument: `%d'", maxcount);
@@ -55,8 +67,6 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
5567
/* for warn_ambiguous_refs */
5668
git_config(git_default_config, NULL);
5769

58-
memset(&array, 0, sizeof(array));
59-
memset(&filter, 0, sizeof(filter));
6070
filter.name_patterns = argv;
6171
filter_refs(&array, &filter, FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN);
6272
ref_array_sort(sorting, &array);

builtin/tag.c

+13-31
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ static int match_pattern(const char **patterns, const char *ref)
5656
return 0;
5757
}
5858

59+
/*
60+
* This is currently duplicated in ref-filter.c, and will eventually be
61+
* removed as we port tag.c to use the ref-filter APIs.
62+
*/
5963
static const unsigned char *match_points_at(const char *refname,
6064
const unsigned char *sha1)
6165
{
@@ -82,6 +86,11 @@ static int in_commit_list(const struct commit_list *want, struct commit *c)
8286
return 0;
8387
}
8488

89+
/*
90+
* The entire code segment for supporting the --contains option has been
91+
* copied over to ref-filter.{c,h}. This will be deleted evetually when
92+
* we port tag.c to use ref-filter APIs.
93+
*/
8594
enum contains_result {
8695
CONTAINS_UNKNOWN = -1,
8796
CONTAINS_NO = 0,
@@ -546,23 +555,6 @@ static int strbuf_check_tag_ref(struct strbuf *sb, const char *name)
546555
return check_refname_format(sb->buf, 0);
547556
}
548557

549-
static int parse_opt_points_at(const struct option *opt __attribute__((unused)),
550-
const char *arg, int unset)
551-
{
552-
unsigned char sha1[20];
553-
554-
if (unset) {
555-
sha1_array_clear(&points_at);
556-
return 0;
557-
}
558-
if (!arg)
559-
return error(_("switch 'points-at' requires an object"));
560-
if (get_sha1(arg, sha1))
561-
return error(_("malformed object name '%s'"), arg);
562-
sha1_array_append(&points_at, sha1);
563-
return 0;
564-
}
565-
566558
static int parse_opt_sort(const struct option *opt, const char *arg, int unset)
567559
{
568560
int *sort = opt->value;
@@ -610,25 +602,15 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
610602

611603
OPT_GROUP(N_("Tag listing options")),
612604
OPT_COLUMN(0, "column", &colopts, N_("show tag list in columns")),
605+
OPT_CONTAINS(&with_commit, N_("print only tags that contain the commit")),
606+
OPT_WITH(&with_commit, N_("print only tags that contain the commit")),
613607
{
614608
OPTION_CALLBACK, 0, "sort", &tag_sort, N_("type"), N_("sort tags"),
615609
PARSE_OPT_NONEG, parse_opt_sort
616610
},
617611
{
618-
OPTION_CALLBACK, 0, "contains", &with_commit, N_("commit"),
619-
N_("print only tags that contain the commit"),
620-
PARSE_OPT_LASTARG_DEFAULT,
621-
parse_opt_with_commit, (intptr_t)"HEAD",
622-
},
623-
{
624-
OPTION_CALLBACK, 0, "with", &with_commit, N_("commit"),
625-
N_("print only tags that contain the commit"),
626-
PARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT,
627-
parse_opt_with_commit, (intptr_t)"HEAD",
628-
},
629-
{
630-
OPTION_CALLBACK, 0, "points-at", NULL, N_("object"),
631-
N_("print only tags of the object"), 0, parse_opt_points_at
612+
OPTION_CALLBACK, 0, "points-at", &points_at, N_("object"),
613+
N_("print only tags of the object"), 0, parse_opt_object_name
632614
},
633615
OPT_END()
634616
};

parse-options-cb.c

+18-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "color.h"
66
#include "string-list.h"
77
#include "argv-array.h"
8+
#include "sha1-array.h"
89

910
/*----- some often used options -----*/
1011

@@ -77,7 +78,7 @@ int parse_opt_verbosity_cb(const struct option *opt, const char *arg,
7778
return 0;
7879
}
7980

80-
int parse_opt_with_commit(const struct option *opt, const char *arg, int unset)
81+
int parse_opt_commits(const struct option *opt, const char *arg, int unset)
8182
{
8283
unsigned char sha1[20];
8384
struct commit *commit;
@@ -93,6 +94,22 @@ int parse_opt_with_commit(const struct option *opt, const char *arg, int unset)
9394
return 0;
9495
}
9596

97+
int parse_opt_object_name(const struct option *opt, const char *arg, int unset)
98+
{
99+
unsigned char sha1[20];
100+
101+
if (unset) {
102+
sha1_array_clear(opt->value);
103+
return 0;
104+
}
105+
if (!arg)
106+
return -1;
107+
if (get_sha1(arg, sha1))
108+
return error(_("malformed object name '%s'"), arg);
109+
sha1_array_append(opt->value, sha1);
110+
return 0;
111+
}
112+
96113
int parse_opt_tertiary(const struct option *opt, const char *arg, int unset)
97114
{
98115
int *target = opt->value;

parse-options.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
223223
extern int parse_opt_expiry_date_cb(const struct option *, const char *, int);
224224
extern int parse_opt_color_flag_cb(const struct option *, const char *, int);
225225
extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
226-
extern int parse_opt_with_commit(const struct option *, const char *, int);
226+
extern int parse_opt_object_name(const struct option *, const char *, int);
227+
extern int parse_opt_commits(const struct option *, const char *, int);
227228
extern int parse_opt_tertiary(const struct option *, const char *, int);
228229
extern int parse_opt_string_list(const struct option *, const char *, int);
229230
extern int parse_opt_noop_cb(const struct option *, const char *, int);
@@ -251,5 +252,12 @@ extern int parse_opt_passthru_argv(const struct option *, const char *, int);
251252
{ OPTION_CALLBACK, (s), (l), (v), (a), (h), (f), parse_opt_passthru }
252253
#define OPT_PASSTHRU_ARGV(s, l, v, a, h, f) \
253254
{ OPTION_CALLBACK, (s), (l), (v), (a), (h), (f), parse_opt_passthru_argv }
255+
#define _OPT_CONTAINS_OR_WITH(name, variable, help, flag) \
256+
{ OPTION_CALLBACK, 0, name, (variable), N_("commit"), (help), \
257+
PARSE_OPT_LASTARG_DEFAULT | flag, \
258+
parse_opt_commits, (intptr_t) "HEAD" \
259+
}
260+
#define OPT_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h, 0)
261+
#define OPT_WITH(v, h) _OPT_CONTAINS_OR_WITH("with", v, h, PARSE_OPT_HIDDEN)
254262

255263
#endif

0 commit comments

Comments
 (0)