Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Junio C Hamano committed Oct 5, 2015
2 parents be08dee + 4a71109 commit 9958dd8
Show file tree
Hide file tree
Showing 9 changed files with 420 additions and 51 deletions.
16 changes: 16 additions & 0 deletions Documentation/git-for-each-ref.txt
Expand Up @@ -10,6 +10,8 @@ SYNOPSIS
[verse]
'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]
[(--sort=<key>)...] [--format=<format>] [<pattern>...]
[--points-at <object>] [(--merged | --no-merged) [<object>]]
[--contains [<object>]]

DESCRIPTION
-----------
Expand Down Expand Up @@ -62,6 +64,20 @@ OPTIONS
the specified host language. This is meant to produce
a scriptlet that can directly be `eval`ed.

--points-at <object>::
Only list refs which points at the given object.

--merged [<object>]::
Only list refs whose tips are reachable from the
specified commit (HEAD if not specified).

--no-merged [<object>]::
Only list refs whose tips are not reachable from the
specified commit (HEAD if not specified).

--contains [<object>]::
Only list tags which contain the specified commit (HEAD if not
specified).

FIELD NAMES
-----------
Expand Down
22 changes: 10 additions & 12 deletions builtin/branch.c
Expand Up @@ -636,6 +636,10 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru
cb.pattern = pattern;
cb.ret = 0;
for_each_rawref(append_ref, &cb);
/*
* The following implementation is currently duplicated in ref-filter. It
* will eventually be removed when we port branch.c to use ref-filter APIs.
*/
if (merge_filter != NO_FILTER) {
struct commit *filter;
filter = lookup_commit_reference_gently(merge_filter_ref, 0);
Expand Down Expand Up @@ -746,6 +750,10 @@ static void rename_branch(const char *oldname, const char *newname, int force)
strbuf_release(&newsection);
}

/*
* This function is duplicated in ref-filter. It will eventually be removed
* when we port branch.c to use ref-filter APIs.
*/
static int opt_parse_merge_filter(const struct option *opt, const char *arg, int unset)
{
merge_filter = ((opt->long_name[0] == 'n')
Expand Down Expand Up @@ -821,18 +829,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
OPT__COLOR(&branch_use_color, N_("use colored output")),
OPT_SET_INT('r', "remotes", &kinds, N_("act on remote-tracking branches"),
REF_REMOTE_BRANCH),
{
OPTION_CALLBACK, 0, "contains", &with_commit, N_("commit"),
N_("print only branches that contain the commit"),
PARSE_OPT_LASTARG_DEFAULT,
parse_opt_with_commit, (intptr_t)"HEAD",
},
{
OPTION_CALLBACK, 0, "with", &with_commit, N_("commit"),
N_("print only branches that contain the commit"),
PARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT,
parse_opt_with_commit, (intptr_t) "HEAD",
},
OPT_CONTAINS(&with_commit, N_("print only branches that contain the commit")),
OPT_WITH(&with_commit, N_("print only branches that contain the commit")),
OPT__ABBREV(&abbrev),

OPT_GROUP(N_("Specific git-branch actions:")),
Expand Down
14 changes: 12 additions & 2 deletions builtin/for-each-ref.c
Expand Up @@ -7,6 +7,9 @@

static char const * const for_each_ref_usage[] = {
N_("git for-each-ref [<options>] [<pattern>]"),
N_("git for-each-ref [--points-at <object>]"),
N_("git for-each-ref [(--merged | --no-merged) [<object>]]"),
N_("git for-each-ref [--contains [<object>]]"),
NULL
};

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

memset(&array, 0, sizeof(array));
memset(&filter, 0, sizeof(filter));

parse_options(argc, argv, prefix, opts, for_each_ref_usage, 0);
if (maxcount < 0) {
error("invalid --count argument: `%d'", maxcount);
Expand All @@ -55,8 +67,6 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
/* for warn_ambiguous_refs */
git_config(git_default_config, NULL);

memset(&array, 0, sizeof(array));
memset(&filter, 0, sizeof(filter));
filter.name_patterns = argv;
filter_refs(&array, &filter, FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN);
ref_array_sort(sorting, &array);
Expand Down
44 changes: 13 additions & 31 deletions builtin/tag.c
Expand Up @@ -56,6 +56,10 @@ static int match_pattern(const char **patterns, const char *ref)
return 0;
}

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

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

static int parse_opt_points_at(const struct option *opt __attribute__((unused)),
const char *arg, int unset)
{
unsigned char sha1[20];

if (unset) {
sha1_array_clear(&points_at);
return 0;
}
if (!arg)
return error(_("switch 'points-at' requires an object"));
if (get_sha1(arg, sha1))
return error(_("malformed object name '%s'"), arg);
sha1_array_append(&points_at, sha1);
return 0;
}

static int parse_opt_sort(const struct option *opt, const char *arg, int unset)
{
int *sort = opt->value;
Expand Down Expand Up @@ -610,25 +602,15 @@ int cmd_tag(int argc, const char **argv, const char *prefix)

OPT_GROUP(N_("Tag listing options")),
OPT_COLUMN(0, "column", &colopts, N_("show tag list in columns")),
OPT_CONTAINS(&with_commit, N_("print only tags that contain the commit")),
OPT_WITH(&with_commit, N_("print only tags that contain the commit")),
{
OPTION_CALLBACK, 0, "sort", &tag_sort, N_("type"), N_("sort tags"),
PARSE_OPT_NONEG, parse_opt_sort
},
{
OPTION_CALLBACK, 0, "contains", &with_commit, N_("commit"),
N_("print only tags that contain the commit"),
PARSE_OPT_LASTARG_DEFAULT,
parse_opt_with_commit, (intptr_t)"HEAD",
},
{
OPTION_CALLBACK, 0, "with", &with_commit, N_("commit"),
N_("print only tags that contain the commit"),
PARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT,
parse_opt_with_commit, (intptr_t)"HEAD",
},
{
OPTION_CALLBACK, 0, "points-at", NULL, N_("object"),
N_("print only tags of the object"), 0, parse_opt_points_at
OPTION_CALLBACK, 0, "points-at", &points_at, N_("object"),
N_("print only tags of the object"), 0, parse_opt_object_name
},
OPT_END()
};
Expand Down
19 changes: 18 additions & 1 deletion parse-options-cb.c
Expand Up @@ -5,6 +5,7 @@
#include "color.h"
#include "string-list.h"
#include "argv-array.h"
#include "sha1-array.h"

/*----- some often used options -----*/

Expand Down Expand Up @@ -77,7 +78,7 @@ int parse_opt_verbosity_cb(const struct option *opt, const char *arg,
return 0;
}

int parse_opt_with_commit(const struct option *opt, const char *arg, int unset)
int parse_opt_commits(const struct option *opt, const char *arg, int unset)
{
unsigned char sha1[20];
struct commit *commit;
Expand All @@ -93,6 +94,22 @@ int parse_opt_with_commit(const struct option *opt, const char *arg, int unset)
return 0;
}

int parse_opt_object_name(const struct option *opt, const char *arg, int unset)
{
unsigned char sha1[20];

if (unset) {
sha1_array_clear(opt->value);
return 0;
}
if (!arg)
return -1;
if (get_sha1(arg, sha1))
return error(_("malformed object name '%s'"), arg);
sha1_array_append(opt->value, sha1);
return 0;
}

int parse_opt_tertiary(const struct option *opt, const char *arg, int unset)
{
int *target = opt->value;
Expand Down
10 changes: 9 additions & 1 deletion parse-options.h
Expand Up @@ -223,7 +223,8 @@ extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
extern int parse_opt_expiry_date_cb(const struct option *, const char *, int);
extern int parse_opt_color_flag_cb(const struct option *, const char *, int);
extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
extern int parse_opt_with_commit(const struct option *, const char *, int);
extern int parse_opt_object_name(const struct option *, const char *, int);
extern int parse_opt_commits(const struct option *, const char *, int);
extern int parse_opt_tertiary(const struct option *, const char *, int);
extern int parse_opt_string_list(const struct option *, const char *, int);
extern int parse_opt_noop_cb(const struct option *, const char *, int);
Expand Down Expand Up @@ -251,5 +252,12 @@ extern int parse_opt_passthru_argv(const struct option *, const char *, int);
{ OPTION_CALLBACK, (s), (l), (v), (a), (h), (f), parse_opt_passthru }
#define OPT_PASSTHRU_ARGV(s, l, v, a, h, f) \
{ OPTION_CALLBACK, (s), (l), (v), (a), (h), (f), parse_opt_passthru_argv }
#define _OPT_CONTAINS_OR_WITH(name, variable, help, flag) \
{ OPTION_CALLBACK, 0, name, (variable), N_("commit"), (help), \
PARSE_OPT_LASTARG_DEFAULT | flag, \
parse_opt_commits, (intptr_t) "HEAD" \
}
#define OPT_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h, 0)
#define OPT_WITH(v, h) _OPT_CONTAINS_OR_WITH("with", v, h, PARSE_OPT_HIDDEN)

#endif

0 comments on commit 9958dd8

Please sign in to comment.