* [PATCH v2 00/11] add options to for-each-ref
@ 2015-06-13 20:17 karthik nayak
2015-06-13 20:18 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Karthik Nayak
0 siblings, 1 reply; 20+ messages in thread
From: karthik nayak @ 2015-06-13 20:17 UTC (permalink / raw)
To: Git; +Cc: Christian Couder, Matthieu Moy
This is continuation of the patch series 'Create ref-filter from for-each-ref'
found at : http://article.gmane.org/gmane.comp.version-control.git/271563
The previous version of this series can be found at :
http://www.mail-archive.com/git%40vger.kernel.org/msg70929.html
Changes made:
* Added tests
* Added comments to filter_refs()
* Small structural changes
* Various coding style fixes
Thanks to Junio C Hamano, Matthieu Moy, and Christian Couder for all
the suggestions.
--
Regards,
Karthik Nayak
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs
2015-06-13 20:17 [PATCH v2 00/11] add options to for-each-ref karthik nayak
@ 2015-06-13 20:18 ` Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 02/11] tag: libify parse_opt_points_at() Karthik Nayak
` (10 more replies)
0 siblings, 11 replies; 20+ messages in thread
From: Karthik Nayak @ 2015-06-13 20:18 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, Karthik Nayak
Add tests for for-each-ref which utilizes the ref-filter APIs.
Based-on-patch-by: Jeff King <peff@peff.net>
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>
---
t/t6301-for-each-ref-filter.sh | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
create mode 100644 t/t6301-for-each-ref-filter.sh
diff --git a/t/t6301-for-each-ref-filter.sh b/t/t6301-for-each-ref-filter.sh
new file mode 100644
index 0000000..5bd49b3
--- /dev/null
+++ b/t/t6301-for-each-ref-filter.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+test_description='test for-each-refs usage of ref-filter APIs'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-gpg.sh
+
+test_expect_success 'setup some history and refs' '
+ test_commit one &&
+ test_commit two &&
+ test_commit three &&
+ git checkout -b side &&
+ test_commit four &&
+ git checkout master &&
+ git update-ref refs/odd/spot master
+'
+test_expect_success 'filtering by leading name' '
+ cat >expect <<-\EOF &&
+ refs/heads/master
+ refs/heads/side
+ EOF
+ git for-each-ref --format="%(refname)" refs/heads >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'filtering with fnmatch' '
+ cat >expect <<-\EOF &&
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" refs/tags/t* >actual &&
+ test_cmp expect actual
+'
+
+test_done
--
2.4.3.435.g2403634.dirty
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 02/11] tag: libify parse_opt_points_at()
2015-06-13 20:18 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Karthik Nayak
@ 2015-06-13 20:18 ` Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 03/11] ref-filter: implement '--points-at' option Karthik Nayak
` (9 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Karthik Nayak @ 2015-06-13 20:18 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, Karthik Nayak
Rename 'parse_opt_points_at()' to 'parse_opt_object_name()' and
move it from 'tag.c' to 'parse-options'. This now acts as a common
parse_opt function which accepts an objectname and stores it into
a sha1_array.
Based-on-patch-by: Jeff King <peff@peff.net>
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>
---
builtin/tag.c | 21 ++-------------------
parse-options-cb.c | 17 +++++++++++++++++
parse-options.h | 1 +
3 files changed, 20 insertions(+), 19 deletions(-)
diff --git a/builtin/tag.c b/builtin/tag.c
index 5f6cdc5..e36c43e 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -546,23 +546,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;
@@ -625,8 +608,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
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()
};
diff --git a/parse-options-cb.c b/parse-options-cb.c
index be8c413..de75411 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -4,6 +4,7 @@
#include "commit.h"
#include "color.h"
#include "string-list.h"
+#include "sha1-array.h"
/*----- some often used options -----*/
@@ -92,6 +93,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;
diff --git a/parse-options.h b/parse-options.h
index c71e9da..36c71fe 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -220,6 +220,7 @@ 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_object_name(const struct option *, const char *, int);
extern int parse_opt_with_commit(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);
--
2.4.3.435.g2403634.dirty
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 03/11] ref-filter: implement '--points-at' option
2015-06-13 20:18 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 02/11] tag: libify parse_opt_points_at() Karthik Nayak
@ 2015-06-13 20:18 ` Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 04/11] for-each-ref: add " Karthik Nayak
` (8 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Karthik Nayak @ 2015-06-13 20:18 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, Karthik Nayak
In 'tag -l' we have '--points-at' option which lets users
list only tags which point to a particular commit. Implement
this option in 'ref-filter.{c,h}' so that other commands can
benefit from this.
This is duplicated from tag.c, we will eventually remove that
when we port tag.c to use ref-filter APIs.
Based-on-patch-by: Jeff King <peff@peff.net>
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>
---
builtin/tag.c | 4 ++++
ref-filter.c | 26 ++++++++++++++++++++++++++
ref-filter.h | 1 +
3 files changed, 31 insertions(+)
diff --git a/builtin/tag.c b/builtin/tag.c
index e36c43e..280981f 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -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)
{
diff --git a/ref-filter.c b/ref-filter.c
index 43502a4..591e281 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -842,6 +842,29 @@ static int match_name_as_path(const char **pattern, const char *refname)
return 0;
}
+/*
+ * Given a ref (sha1, refname) see if it points to a one of the sha1s
+ * in a sha1_array.
+ */
+static int match_points_at(struct sha1_array *points_at, const unsigned char *sha1,
+ const char *refname)
+{
+ struct object *obj;
+
+ if (!points_at || !points_at->nr)
+ return 1;
+
+ if (sha1_array_lookup(points_at, sha1) >= 0)
+ return 1;
+
+ obj = parse_object_or_die(sha1, refname);
+ if (obj->type == OBJ_TAG &&
+ sha1_array_lookup(points_at, ((struct tag *)obj)->tagged->sha1) >= 0)
+ return 1;
+
+ return 0;
+}
+
/* Allocate space for a new ref_array_item and copy the objectname and flag to it */
static struct ref_array_item *new_ref_array_item(const char *refname,
const unsigned char *objectname,
@@ -875,6 +898,9 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,
if (*filter->name_patterns && !match_name_as_path(filter->name_patterns, refname))
return 0;
+ if (!match_points_at(&filter->points_at, oid->hash, refname))
+ return 0;
+
/*
* We do not open the object yet; sort may only need refname
* to do its job and the resulting list may yet to be pruned
diff --git a/ref-filter.h b/ref-filter.h
index 6997984..c2856b8 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -42,6 +42,7 @@ struct ref_array {
struct ref_filter {
const char **name_patterns;
+ struct sha1_array points_at;
};
struct ref_filter_cbdata {
--
2.4.3.435.g2403634.dirty
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 04/11] for-each-ref: add '--points-at' option
2015-06-13 20:18 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 02/11] tag: libify parse_opt_points_at() Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 03/11] ref-filter: implement '--points-at' option Karthik Nayak
@ 2015-06-13 20:18 ` Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 05/11] ref-filter: add parse_opt_merge_filter() Karthik Nayak
` (7 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Karthik Nayak @ 2015-06-13 20:18 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, Karthik Nayak
Add the '--points-at' option provided by 'ref-filter'. The
option lets the user to pick only refs which point to a particular
commit.
Add documentation and tests for the same.
Based-on-patch-by: Jeff King <peff@peff.net>
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>
---
Documentation/git-for-each-ref.txt | 3 +++
builtin/for-each-ref.c | 9 +++++++--
t/t6301-for-each-ref-filter.sh | 10 ++++++++++
3 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index 7f8d9a5..0524ac4 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -10,6 +10,7 @@ SYNOPSIS
[verse]
'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]
[(--sort=<key>)...] [--format=<format>] [<pattern>...]
+ [--points-at <object>]
DESCRIPTION
-----------
@@ -62,6 +63,8 @@ OPTIONS
the specified host language. This is meant to produce
a scriptlet that can directly be `eval`ed.
+--points-at <object>::
+ Only list refs of the given object.
FIELD NAMES
-----------
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 7919206..2dee149 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -7,6 +7,7 @@
static char const * const for_each_ref_usage[] = {
N_("git for-each-ref [<options>] [<pattern>]"),
+ N_("git for-each-ref [--points-at <object>]"),
NULL
};
@@ -34,9 +35,15 @@ 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 of the object"),
+ parse_opt_object_name),
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);
@@ -55,8 +62,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);
diff --git a/t/t6301-for-each-ref-filter.sh b/t/t6301-for-each-ref-filter.sh
index 5bd49b3..3a1c3f6 100644
--- a/t/t6301-for-each-ref-filter.sh
+++ b/t/t6301-for-each-ref-filter.sh
@@ -32,4 +32,14 @@ test_expect_success 'filtering with fnmatch' '
test_cmp expect actual
'
+test_expect_success 'filtering with --points-at' '
+ cat >expect <<-\EOF &&
+ refs/heads/master
+ refs/odd/spot
+ refs/tags/three
+ EOF
+ git for-each-ref --format="%(refname)" --points-at=master >actual &&
+ test_cmp expect actual
+'
+
test_done
--
2.4.3.435.g2403634.dirty
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 05/11] ref-filter: add parse_opt_merge_filter()
2015-06-13 20:18 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Karthik Nayak
` (2 preceding siblings ...)
2015-06-13 20:18 ` [PATCH v2 04/11] for-each-ref: add " Karthik Nayak
@ 2015-06-13 20:18 ` Karthik Nayak
2015-06-14 5:49 ` Christian Couder
2015-06-13 20:18 ` [PATCH v2 06/11] ref-filter: implement '--merged' and '--no-merged' options Karthik Nayak
` (6 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Karthik Nayak @ 2015-06-13 20:18 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, Karthik Nayak
Add 'parse_opt_merge_filter()' to parse '--merged' and '--no-merged'
options and write MACROS for the same.
This is copied from 'builtin/branch.c' which will eventually be removed
when we port 'branch.c' to use ref-filter APIs.
Based-on-patch-by: Jeff King <peff@peff.net>
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>
---
builtin/branch.c | 4 ++++
ref-filter.c | 21 +++++++++++++++++++++
ref-filter.h | 14 ++++++++++++++
3 files changed, 39 insertions(+)
diff --git a/builtin/branch.c b/builtin/branch.c
index b42e5b6..ddd90e6 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -745,6 +745,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')
diff --git a/ref-filter.c b/ref-filter.c
index 591e281..6502179 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1125,3 +1125,24 @@ int parse_opt_ref_sorting(const struct option *opt, const char *arg, int unset)
s->atom = parse_ref_filter_atom(arg, arg+len);
return 0;
}
+
+int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)
+{
+ struct ref_filter *rf = opt->value;
+ unsigned char sha1[20];
+
+ rf->merge = starts_with(opt->long_name, "no")
+ ? REF_FILTER_MERGED_OMIT
+ : REF_FILTER_MERGED_INCLUDE;
+
+ if (!arg)
+ arg = "HEAD";
+ if (get_sha1(arg, sha1))
+ die(_("malformed object name %s"), arg);
+
+ rf->merge_commit = lookup_commit_reference_gently(sha1, 0);
+ if (!rf->merge_commit)
+ return opterror(opt, "must point to a commit", 0);
+
+ return 0;
+}
diff --git a/ref-filter.h b/ref-filter.h
index c2856b8..799e118 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -50,6 +50,18 @@ struct ref_filter_cbdata {
struct ref_filter *filter;
};
+/* Macros for checking --merged and --no-merged options */
+#define OPT_NO_MERGED(filter, h) \
+ { OPTION_CALLBACK, 0, "no-merged", (filter), N_("commit"), (h), \
+ PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \
+ parse_opt_merge_filter, (intptr_t) "HEAD" \
+ }
+#define OPT_MERGED(filter, h) \
+ { OPTION_CALLBACK, 0, "merged", (filter), N_("commit"), (h), \
+ PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \
+ parse_opt_merge_filter, (intptr_t) "HEAD" \
+ }
+
/*
* API for filtering a set of refs. Based on the type of refs the user
* has requested, we iterate through those refs and apply filters
@@ -71,5 +83,7 @@ void show_ref_array_item(struct ref_array_item *info, const char *format, int qu
int parse_opt_ref_sorting(const struct option *opt, const char *arg, int unset);
/* Default sort option based on refname */
struct ref_sorting *ref_default_sorting(void);
+/* Function to parse --merged and --no-merged options */
+int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset);
#endif /* REF_FILTER_H */
--
2.4.3.435.g2403634.dirty
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 06/11] ref-filter: implement '--merged' and '--no-merged' options
2015-06-13 20:18 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Karthik Nayak
` (3 preceding siblings ...)
2015-06-13 20:18 ` [PATCH v2 05/11] ref-filter: add parse_opt_merge_filter() Karthik Nayak
@ 2015-06-13 20:18 ` Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 07/11] for-each-ref: add " Karthik Nayak
` (5 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Karthik Nayak @ 2015-06-13 20:18 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, Karthik Nayak
In 'branch -l' we have '--merged' option which only lists refs (branches)
merged into the named commit and '--no-merged' option which only lists
refs (branches) not merged into the named commit. Implement these two
options in ref-filter.{c,h} so that other commands can benefit from this.
Based-on-patch-by: Jeff King <peff@peff.net>
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>
---
ref-filter.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
ref-filter.h | 8 +++++++
2 files changed, 72 insertions(+), 4 deletions(-)
diff --git a/ref-filter.c b/ref-filter.c
index 6502179..06328eb 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -9,6 +9,7 @@
#include "tag.h"
#include "quote.h"
#include "ref-filter.h"
+#include "revision.h"
typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;
@@ -889,6 +890,7 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,
struct ref_filter_cbdata *ref_cbdata = cb_data;
struct ref_filter *filter = ref_cbdata->filter;
struct ref_array_item *ref;
+ struct commit *commit = NULL;
if (flag & REF_BAD_NAME) {
warning("ignoring ref with broken name %s", refname);
@@ -901,12 +903,19 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,
if (!match_points_at(&filter->points_at, oid->hash, refname))
return 0;
+ if (filter->merge_commit) {
+ commit = lookup_commit_reference_gently(oid->hash, 1);
+ if (!commit)
+ return 0;
+ }
+
/*
* We do not open the object yet; sort may only need refname
* to do its job and the resulting list may yet to be pruned
* by maxcount logic.
*/
ref = new_ref_array_item(refname, oid->hash, flag);
+ ref->commit = commit;
REALLOC_ARRAY(ref_cbdata->array->items, ref_cbdata->array->nr + 1);
ref_cbdata->array->items[ref_cbdata->array->nr++] = ref;
@@ -932,6 +941,50 @@ void ref_array_clear(struct ref_array *array)
array->nr = array->alloc = 0;
}
+static void do_merge_filter(struct ref_filter_cbdata *ref_cbdata)
+{
+ struct rev_info revs;
+ int i, old_nr;
+ struct ref_filter *filter = ref_cbdata->filter;
+ struct ref_array *array = ref_cbdata->array;
+ struct commit_list *p, *to_clear = NULL;
+
+ init_revisions(&revs, NULL);
+
+ for (i = 0; i < array->nr; i++) {
+ struct ref_array_item *item = array->items[i];
+ add_pending_object(&revs, &item->commit->object, item->refname);
+ commit_list_insert(item->commit, &to_clear);
+ }
+
+ filter->merge_commit->object.flags |= UNINTERESTING;
+ add_pending_object(&revs, &filter->merge_commit->object, "");
+
+ revs.limited = 1;
+ if (prepare_revision_walk(&revs))
+ die(_("revision walk setup failed"));
+
+ old_nr = array->nr;
+ array->nr = 0;
+
+ for (i = 0; i < old_nr; i++) {
+ struct ref_array_item *item = array->items[i];
+ struct commit *commit = item->commit;
+
+ int is_merged = !!(commit->object.flags & UNINTERESTING);
+
+ if (is_merged == (filter->merge == REF_FILTER_MERGED_INCLUDE))
+ array->items[array->nr++] = array->items[i];
+ else
+ free_array_item(item);
+ }
+
+ for (p = to_clear; p; p = p->next)
+ clear_commit_marks(p->item, ALL_REV_FLAGS);
+ clear_commit_marks(filter->merge_commit, ALL_REV_FLAGS);
+ free_commit_list(to_clear);
+}
+
/*
* API for filtering a set of refs. Based on the type of refs the user
* has requested, we iterate through those refs and apply filters
@@ -941,17 +994,24 @@ void ref_array_clear(struct ref_array *array)
int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int type)
{
struct ref_filter_cbdata ref_cbdata;
+ int ret = 0;
ref_cbdata.array = array;
ref_cbdata.filter = filter;
+ /* Simple per-ref filtering */
if (type & (FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN))
- return for_each_rawref(ref_filter_handler, &ref_cbdata);
+ ret = for_each_rawref(ref_filter_handler, &ref_cbdata);
else if (type & FILTER_REFS_ALL)
- return for_each_ref(ref_filter_handler, &ref_cbdata);
- else
+ ret = for_each_ref(ref_filter_handler, &ref_cbdata);
+ else if (type)
die("filter_refs: invalid type");
- return 0;
+
+ /* Filters that need revision walking */
+ if (filter->merge_commit)
+ do_merge_filter(&ref_cbdata);
+
+ return ret;
}
static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, struct ref_array_item *b)
diff --git a/ref-filter.h b/ref-filter.h
index 799e118..39d66b0 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -31,6 +31,7 @@ struct ref_array_item {
unsigned char objectname[20];
int flag;
const char *symref;
+ struct commit *commit;
struct atom_value *value;
char refname[FLEX_ARRAY];
};
@@ -43,6 +44,13 @@ struct ref_array {
struct ref_filter {
const char **name_patterns;
struct sha1_array points_at;
+
+ enum {
+ REF_FILTER_MERGED_NONE = 0,
+ REF_FILTER_MERGED_INCLUDE,
+ REF_FILTER_MERGED_OMIT
+ } merge;
+ struct commit *merge_commit;
};
struct ref_filter_cbdata {
--
2.4.3.435.g2403634.dirty
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 07/11] for-each-ref: add '--merged' and '--no-merged' options
2015-06-13 20:18 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Karthik Nayak
` (4 preceding siblings ...)
2015-06-13 20:18 ` [PATCH v2 06/11] ref-filter: implement '--merged' and '--no-merged' options Karthik Nayak
@ 2015-06-13 20:18 ` Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 08/11] parse-option: rename parse_opt_with_commit() Karthik Nayak
` (4 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Karthik Nayak @ 2015-06-13 20:18 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, Karthik Nayak
Add the '--merged' and '--no-merged' options provided by 'ref-filter'.
The '--merged' option lets the user to only list refs merged into the
named commit. The '--no-merged' option lets the user to only list refs
not merged into the named commit.
Add documentation and tests for the same.
Based-on-patch-by: Jeff King <peff@peff.net>
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>
---
Documentation/git-for-each-ref.txt | 10 +++++++++-
builtin/for-each-ref.c | 3 +++
t/t6301-for-each-ref-filter.sh | 21 +++++++++++++++++++++
3 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index 0524ac4..d61a756 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -10,7 +10,7 @@ SYNOPSIS
[verse]
'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]
[(--sort=<key>)...] [--format=<format>] [<pattern>...]
- [--points-at <object>]
+ [--points-at <object>] [(--merged | --no-merged) <object>]
DESCRIPTION
-----------
@@ -66,6 +66,14 @@ OPTIONS
--points-at <object>::
Only list refs of the given object.
+--merged [<commit>]::
+ Only list refs whose tips are reachable from the
+ specified commit (HEAD if not specified).
+
+--no-merged [<commit>]::
+ Only list refs whose tips are not reachable from the
+ specified commit (HEAD if not specified).
+
FIELD NAMES
-----------
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 2dee149..00913f4 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -8,6 +8,7 @@
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>]"),
NULL
};
@@ -38,6 +39,8 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
OPT_CALLBACK(0, "points-at", &filter.points_at,
N_("object"), N_("print only refs of the 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_END(),
};
diff --git a/t/t6301-for-each-ref-filter.sh b/t/t6301-for-each-ref-filter.sh
index 3a1c3f6..3ed97bd 100644
--- a/t/t6301-for-each-ref-filter.sh
+++ b/t/t6301-for-each-ref-filter.sh
@@ -42,4 +42,25 @@ test_expect_success 'filtering with --points-at' '
test_cmp expect actual
'
+test_expect_success 'filtering with --merged' '
+ cat >expect <<-\EOF &&
+ refs/heads/master
+ refs/odd/spot
+ refs/tags/one
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" --merged=master >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'filtering with --no-merged' '
+ cat >expect <<-\EOF &&
+ refs/heads/side
+ refs/tags/four
+ EOF
+ git for-each-ref --format="%(refname)" --no-merged=master >actual &&
+ test_cmp expect actual
+'
+
test_done
--
2.4.3.435.g2403634.dirty
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 08/11] parse-option: rename parse_opt_with_commit()
2015-06-13 20:18 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Karthik Nayak
` (5 preceding siblings ...)
2015-06-13 20:18 ` [PATCH v2 07/11] for-each-ref: add " Karthik Nayak
@ 2015-06-13 20:18 ` Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 09/11] parse-options.h: add macros for '--contains' option Karthik Nayak
` (3 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Karthik Nayak @ 2015-06-13 20:18 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, Karthik Nayak
Rename parse_opt_with_commit() to parse_opt_commit_object_name()
to show that it can be used to obtain a list of commits and is
not constricted to usage of '--contains' option.
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>
---
builtin/branch.c | 4 ++--
builtin/tag.c | 4 ++--
parse-options-cb.c | 2 +-
parse-options.h | 2 +-
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/builtin/branch.c b/builtin/branch.c
index ddd90e6..ddd728e 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -828,13 +828,13 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
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",
+ parse_opt_commit_object_name, (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",
+ parse_opt_commit_object_name, (intptr_t) "HEAD",
},
OPT__ABBREV(&abbrev),
diff --git a/builtin/tag.c b/builtin/tag.c
index 280981f..2d6610a 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -603,13 +603,13 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
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",
+ parse_opt_commit_object_name, (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",
+ parse_opt_commit_object_name, (intptr_t)"HEAD",
},
{
OPTION_CALLBACK, 0, "points-at", &points_at, N_("object"),
diff --git a/parse-options-cb.c b/parse-options-cb.c
index de75411..8bec5e4 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -77,7 +77,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_commit_object_name(const struct option *opt, const char *arg, int unset)
{
unsigned char sha1[20];
struct commit *commit;
diff --git a/parse-options.h b/parse-options.h
index 36c71fe..8542d9c 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -221,7 +221,7 @@ 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_object_name(const struct option *, const char *, int);
-extern int parse_opt_with_commit(const struct option *, const char *, int);
+extern int parse_opt_commit_object_name(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);
--
2.4.3.435.g2403634.dirty
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 09/11] parse-options.h: add macros for '--contains' option
2015-06-13 20:18 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Karthik Nayak
` (6 preceding siblings ...)
2015-06-13 20:18 ` [PATCH v2 08/11] parse-option: rename parse_opt_with_commit() Karthik Nayak
@ 2015-06-13 20:18 ` Karthik Nayak
2015-06-14 6:13 ` Christian Couder
2015-06-13 20:18 ` [PATCH v2 10/11] ref-filter: implement " Karthik Nayak
` (2 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Karthik Nayak @ 2015-06-13 20:18 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, Karthik Nayak
Add a macro for using the '--contains' option in parse-options.h
also include an optional '--with' option macro which performs the
same action as '--contains'.
Make tag.c use this new macro
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>
---
builtin/tag.c | 14 ++------------
parse-options.h | 7 +++++++
2 files changed, 9 insertions(+), 12 deletions(-)
diff --git a/builtin/tag.c b/builtin/tag.c
index 2d6610a..767162e 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -595,23 +595,13 @@ 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_commit_object_name, (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_commit_object_name, (intptr_t)"HEAD",
- },
- {
OPTION_CALLBACK, 0, "points-at", &points_at, N_("object"),
N_("print only tags of the object"), 0, parse_opt_object_name
},
diff --git a/parse-options.h b/parse-options.h
index 8542d9c..d76e907 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -243,5 +243,12 @@ extern int parse_opt_noop_cb(const struct option *, const char *, int);
OPT_COLOR_FLAG(0, "color", (var), (h))
#define OPT_COLUMN(s, l, v, h) \
{ OPTION_CALLBACK, (s), (l), (v), N_("style"), (h), PARSE_OPT_OPTARG, parseopt_column_callback }
+#define _OPT_CONTAINS_OR_WITH(name, variable, help) \
+ { OPTION_CALLBACK, 0, name, (variable), N_("commit"), (help), \
+ PARSE_OPT_LASTARG_DEFAULT, \
+ parse_opt_commit_object_name, (intptr_t) "HEAD" \
+ }
+#define OPT_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h)
+#define OPT_WITH(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h)
#endif
--
2.4.3.435.g2403634.dirty
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 10/11] ref-filter: implement '--contains' option
2015-06-13 20:18 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Karthik Nayak
` (7 preceding siblings ...)
2015-06-13 20:18 ` [PATCH v2 09/11] parse-options.h: add macros for '--contains' option Karthik Nayak
@ 2015-06-13 20:18 ` Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 11/11] for-each-ref: add " Karthik Nayak
2015-06-14 8:12 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Matthieu Moy
10 siblings, 0 replies; 20+ messages in thread
From: Karthik Nayak @ 2015-06-13 20:18 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, Karthik Nayak
'tag -l' and 'branch -l' have two different ways of finding
out if a certain ref contains a commit. Implement both these
methods in ref-filter and give the caller of ref-filter API
the option to pick which implementation to be used.
'branch -l' uses 'is_descendant_of()' from commit.c which is
left as the default implementation to be used.
'tag -l' uses a more specific algorithm since ffc4b80. This
implementation is used whenever the 'with_commit_tag_algo' bit
is set in 'struct ref_filter'.
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>
---
ref-filter.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
ref-filter.h | 3 ++
2 files changed, 114 insertions(+), 1 deletion(-)
diff --git a/ref-filter.c b/ref-filter.c
index 06328eb..40eb90e 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -818,6 +818,113 @@ static void get_ref_atom_value(struct ref_array_item *ref, int atom, struct atom
*v = &ref->value[atom];
}
+enum contains_result {
+ CONTAINS_UNKNOWN = -1,
+ CONTAINS_NO = 0,
+ CONTAINS_YES = 1
+};
+
+/*
+ * Mimicking the real stack, this stack lives on the heap, avoiding stack
+ * overflows.
+ *
+ * At each recursion step, the stack items points to the commits whose
+ * ancestors are to be inspected.
+ */
+struct contains_stack {
+ int nr, alloc;
+ struct contains_stack_entry {
+ struct commit *commit;
+ struct commit_list *parents;
+ } *contains_stack;
+};
+
+static int in_commit_list(const struct commit_list *want, struct commit *c)
+{
+ for (; want; want = want->next)
+ if (!hashcmp(want->item->object.sha1, c->object.sha1))
+ return 1;
+ return 0;
+}
+
+/*
+ * Test whether the candidate or one of its parents is contained in the list.
+ * Do not recurse to find out, though, but return -1 if inconclusive.
+ */
+static enum contains_result contains_test(struct commit *candidate,
+ const struct commit_list *want)
+{
+ /* was it previously marked as containing a want commit? */
+ if (candidate->object.flags & TMP_MARK)
+ return 1;
+ /* or marked as not possibly containing a want commit? */
+ if (candidate->object.flags & UNINTERESTING)
+ return 0;
+ /* or are we it? */
+ if (in_commit_list(want, candidate)) {
+ candidate->object.flags |= TMP_MARK;
+ return 1;
+ }
+
+ if (parse_commit(candidate) < 0)
+ return 0;
+
+ return -1;
+}
+
+static void push_to_contains_stack(struct commit *candidate, struct contains_stack *contains_stack)
+{
+ ALLOC_GROW(contains_stack->contains_stack, contains_stack->nr + 1, contains_stack->alloc);
+ contains_stack->contains_stack[contains_stack->nr].commit = candidate;
+ contains_stack->contains_stack[contains_stack->nr++].parents = candidate->parents;
+}
+
+static enum contains_result contains_tag_algo(struct commit *candidate,
+ const struct commit_list *want)
+{
+ struct contains_stack contains_stack = { 0, 0, NULL };
+ int result = contains_test(candidate, want);
+
+ if (result != CONTAINS_UNKNOWN)
+ return result;
+
+ push_to_contains_stack(candidate, &contains_stack);
+ while (contains_stack.nr) {
+ struct contains_stack_entry *entry = &contains_stack.contains_stack[contains_stack.nr - 1];
+ struct commit *commit = entry->commit;
+ struct commit_list *parents = entry->parents;
+
+ if (!parents) {
+ commit->object.flags |= UNINTERESTING;
+ contains_stack.nr--;
+ }
+ /*
+ * If we just popped the stack, parents->item has been marked,
+ * therefore contains_test will return a meaningful 0 or 1.
+ */
+ else switch (contains_test(parents->item, want)) {
+ case CONTAINS_YES:
+ commit->object.flags |= TMP_MARK;
+ contains_stack.nr--;
+ break;
+ case CONTAINS_NO:
+ entry->parents = parents->next;
+ break;
+ case CONTAINS_UNKNOWN:
+ push_to_contains_stack(parents->item, &contains_stack);
+ break;
+ }
+ }
+ free(contains_stack.contains_stack);
+ return contains_test(candidate, want);
+}
+
+static int commit_contains(struct ref_filter *filter, struct commit *commit)
+{
+ if (filter->with_commit_tag_algo)
+ return contains_tag_algo(commit, filter->with_commit);
+ return is_descendant_of(commit, filter->with_commit);
+}
/*
* Return 1 if the refname matches one of the patterns, otherwise 0.
* A pattern can be path prefix (e.g. a refname "refs/heads/master"
@@ -903,10 +1010,13 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,
if (!match_points_at(&filter->points_at, oid->hash, refname))
return 0;
- if (filter->merge_commit) {
+ if (filter->merge_commit || filter->with_commit) {
commit = lookup_commit_reference_gently(oid->hash, 1);
if (!commit)
return 0;
+ if (filter->with_commit &&
+ !commit_contains(filter, commit))
+ return 0;
}
/*
diff --git a/ref-filter.h b/ref-filter.h
index 39d66b0..e614713 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -44,6 +44,7 @@ struct ref_array {
struct ref_filter {
const char **name_patterns;
struct sha1_array points_at;
+ struct commit_list *with_commit;
enum {
REF_FILTER_MERGED_NONE = 0,
@@ -51,6 +52,8 @@ struct ref_filter {
REF_FILTER_MERGED_OMIT
} merge;
struct commit *merge_commit;
+
+ unsigned int with_commit_tag_algo: 1;
};
struct ref_filter_cbdata {
--
2.4.3.435.g2403634.dirty
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 11/11] for-each-ref: add '--contains' option
2015-06-13 20:18 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Karthik Nayak
` (8 preceding siblings ...)
2015-06-13 20:18 ` [PATCH v2 10/11] ref-filter: implement " Karthik Nayak
@ 2015-06-13 20:18 ` Karthik Nayak
2015-06-14 8:12 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Matthieu Moy
10 siblings, 0 replies; 20+ messages in thread
From: Karthik Nayak @ 2015-06-13 20:18 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, Karthik Nayak
Add the '--contains' option provided by 'ref-filter'. The '--contains'
option lists only refs which are contain the mentioned commit (HEAD if
no commit is explicitly given).
Add documentation and tests for the same.
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>
---
Documentation/git-for-each-ref.txt | 5 +++++
builtin/for-each-ref.c | 2 ++
t/t6301-for-each-ref-filter.sh | 13 +++++++++++++
3 files changed, 20 insertions(+)
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index d61a756..7a949f3 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -11,6 +11,7 @@ SYNOPSIS
'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
-----------
@@ -74,6 +75,10 @@ OPTIONS
Only list refs whose tips are not reachable from the
specified commit (HEAD if not specified).
+--contains [<commit>]::
+ Only list tags which contain the specified commit (HEAD if not
+ specified).
+
FIELD NAMES
-----------
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 00913f4..8ccbb1c 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -9,6 +9,7 @@ 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
};
@@ -41,6 +42,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
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(),
};
diff --git a/t/t6301-for-each-ref-filter.sh b/t/t6301-for-each-ref-filter.sh
index 3ed97bd..17cf7b0 100644
--- a/t/t6301-for-each-ref-filter.sh
+++ b/t/t6301-for-each-ref-filter.sh
@@ -63,4 +63,17 @@ test_expect_success 'filtering with --no-merged' '
test_cmp expect actual
'
+test_expect_success 'filtering with --contains' '
+ cat >expect <<-\EOF &&
+ refs/heads/master
+ refs/heads/side
+ refs/odd/spot
+ refs/tags/four
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" --contains=two >actual &&
+ test_cmp expect actual
+'
+
test_done
--
2.4.3.435.g2403634.dirty
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v2 05/11] ref-filter: add parse_opt_merge_filter()
2015-06-13 20:18 ` [PATCH v2 05/11] ref-filter: add parse_opt_merge_filter() Karthik Nayak
@ 2015-06-14 5:49 ` Christian Couder
2015-06-14 6:49 ` karthik nayak
0 siblings, 1 reply; 20+ messages in thread
From: Christian Couder @ 2015-06-14 5:49 UTC (permalink / raw)
To: Karthik Nayak; +Cc: git, Matthieu Moy
On Sat, Jun 13, 2015 at 10:18 PM, Karthik Nayak <karthik.188@gmail.com> wrote:
>
> diff --git a/ref-filter.h b/ref-filter.h
> index c2856b8..799e118 100644
> --- a/ref-filter.h
> +++ b/ref-filter.h
> @@ -50,6 +50,18 @@ struct ref_filter_cbdata {
> struct ref_filter *filter;
> };
>
> +/* Macros for checking --merged and --no-merged options */
> +#define OPT_NO_MERGED(filter, h) \
> + { OPTION_CALLBACK, 0, "no-merged", (filter), N_("commit"), (h), \
> + PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \
> + parse_opt_merge_filter, (intptr_t) "HEAD" \
> + }
> +#define OPT_MERGED(filter, h) \
> + { OPTION_CALLBACK, 0, "merged", (filter), N_("commit"), (h), \
> + PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \
> + parse_opt_merge_filter, (intptr_t) "HEAD" \
> + }
Could you reduce the redundancy in these 2 macros?
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 09/11] parse-options.h: add macros for '--contains' option
2015-06-13 20:18 ` [PATCH v2 09/11] parse-options.h: add macros for '--contains' option Karthik Nayak
@ 2015-06-14 6:13 ` Christian Couder
2015-06-14 6:58 ` karthik nayak
2015-06-15 19:27 ` Junio C Hamano
0 siblings, 2 replies; 20+ messages in thread
From: Christian Couder @ 2015-06-14 6:13 UTC (permalink / raw)
To: Karthik Nayak; +Cc: git, Matthieu Moy
On Sat, Jun 13, 2015 at 10:18 PM, Karthik Nayak <karthik.188@gmail.com> wrote:
> Add a macro for using the '--contains' option in parse-options.h
> also include an optional '--with' option macro which performs the
> same action as '--contains'.
>
> Make tag.c use this new macro
>
> 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>
> ---
> builtin/tag.c | 14 ++------------
> parse-options.h | 7 +++++++
> 2 files changed, 9 insertions(+), 12 deletions(-)
>
> diff --git a/builtin/tag.c b/builtin/tag.c
> index 2d6610a..767162e 100644
> --- a/builtin/tag.c
> +++ b/builtin/tag.c
> @@ -595,23 +595,13 @@ 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_commit_object_name, (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,
The PARSE_OPT_HIDDEN flag is removed below. This means that "--with"
will appear in the "git tag -h" output, which means that "--with"
should appear in the documentation...
The commit message may also want to tell that with is not hidden any more.
> - parse_opt_commit_object_name, (intptr_t)"HEAD",
> - },
> - {
> OPTION_CALLBACK, 0, "points-at", &points_at, N_("object"),
> N_("print only tags of the object"), 0, parse_opt_object_name
> },
> diff --git a/parse-options.h b/parse-options.h
> index 8542d9c..d76e907 100644
> --- a/parse-options.h
> +++ b/parse-options.h
> @@ -243,5 +243,12 @@ extern int parse_opt_noop_cb(const struct option *, const char *, int);
> OPT_COLOR_FLAG(0, "color", (var), (h))
> #define OPT_COLUMN(s, l, v, h) \
> { OPTION_CALLBACK, (s), (l), (v), N_("style"), (h), PARSE_OPT_OPTARG, parseopt_column_callback }
> +#define _OPT_CONTAINS_OR_WITH(name, variable, help) \
> + { OPTION_CALLBACK, 0, name, (variable), N_("commit"), (help), \
> + PARSE_OPT_LASTARG_DEFAULT, \
> + parse_opt_commit_object_name, (intptr_t) "HEAD" \
> + }
> +#define OPT_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h)
> +#define OPT_WITH(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h)
Shouldn't it be "with" instead of "contains"?
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 05/11] ref-filter: add parse_opt_merge_filter()
2015-06-14 5:49 ` Christian Couder
@ 2015-06-14 6:49 ` karthik nayak
0 siblings, 0 replies; 20+ messages in thread
From: karthik nayak @ 2015-06-14 6:49 UTC (permalink / raw)
To: Christian Couder; +Cc: git, Matthieu Moy
On Sun, Jun 14, 2015 at 11:19 AM, Christian Couder
<christian.couder@gmail.com> wrote:
> On Sat, Jun 13, 2015 at 10:18 PM, Karthik Nayak <karthik.188@gmail.com> wrote:
>>
>> diff --git a/ref-filter.h b/ref-filter.h
>> index c2856b8..799e118 100644
>> --- a/ref-filter.h
>> +++ b/ref-filter.h
>> @@ -50,6 +50,18 @@ struct ref_filter_cbdata {
>> struct ref_filter *filter;
>> };
>>
>> +/* Macros for checking --merged and --no-merged options */
>> +#define OPT_NO_MERGED(filter, h) \
>> + { OPTION_CALLBACK, 0, "no-merged", (filter), N_("commit"), (h), \
>> + PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \
>> + parse_opt_merge_filter, (intptr_t) "HEAD" \
>> + }
>> +#define OPT_MERGED(filter, h) \
>> + { OPTION_CALLBACK, 0, "merged", (filter), N_("commit"), (h), \
>> + PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \
>> + parse_opt_merge_filter, (intptr_t) "HEAD" \
>> + }
>
> Could you reduce the redundancy in these 2 macros?
Yes, will do!
--
Regards,
Karthik Nayak
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 09/11] parse-options.h: add macros for '--contains' option
2015-06-14 6:13 ` Christian Couder
@ 2015-06-14 6:58 ` karthik nayak
2015-06-15 19:27 ` Junio C Hamano
1 sibling, 0 replies; 20+ messages in thread
From: karthik nayak @ 2015-06-14 6:58 UTC (permalink / raw)
To: Christian Couder; +Cc: git, Matthieu Moy
On Sun, Jun 14, 2015 at 11:43 AM, Christian Couder
<christian.couder@gmail.com> wrote:
> On Sat, Jun 13, 2015 at 10:18 PM, Karthik Nayak <karthik.188@gmail.com> wrote:
>> Add a macro for using the '--contains' option in parse-options.h
>> also include an optional '--with' option macro which performs the
>> same action as '--contains'.
>>
>> Make tag.c use this new macro
>>
>> 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>
>> ---
>> builtin/tag.c | 14 ++------------
>> parse-options.h | 7 +++++++
>> 2 files changed, 9 insertions(+), 12 deletions(-)
>>
>> diff --git a/builtin/tag.c b/builtin/tag.c
>> index 2d6610a..767162e 100644
>> --- a/builtin/tag.c
>> +++ b/builtin/tag.c
>> @@ -595,23 +595,13 @@ 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_commit_object_name, (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,
>
> The PARSE_OPT_HIDDEN flag is removed below. This means that "--with"
> will appear in the "git tag -h" output, which means that "--with"
> should appear in the documentation...
> The commit message may also want to tell that with is not hidden any more.
>
Yes! I will add that.
>> - parse_opt_commit_object_name, (intptr_t)"HEAD",
>> - },
>> - {
>> OPTION_CALLBACK, 0, "points-at", &points_at, N_("object"),
>> N_("print only tags of the object"), 0, parse_opt_object_name
>> },
>> diff --git a/parse-options.h b/parse-options.h
>> index 8542d9c..d76e907 100644
>> --- a/parse-options.h
>> +++ b/parse-options.h
>> @@ -243,5 +243,12 @@ extern int parse_opt_noop_cb(const struct option *, const char *, int);
>> OPT_COLOR_FLAG(0, "color", (var), (h))
>> #define OPT_COLUMN(s, l, v, h) \
>> { OPTION_CALLBACK, (s), (l), (v), N_("style"), (h), PARSE_OPT_OPTARG, parseopt_column_callback }
>> +#define _OPT_CONTAINS_OR_WITH(name, variable, help) \
>> + { OPTION_CALLBACK, 0, name, (variable), N_("commit"), (help), \
>> + PARSE_OPT_LASTARG_DEFAULT, \
>> + parse_opt_commit_object_name, (intptr_t) "HEAD" \
>> + }
>> +#define OPT_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h)
>> +#define OPT_WITH(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h)
>
> Shouldn't it be "with" instead of "contains"?
Actually it wouldn't matter, but since I've removed the PARSE_OPT_HIDDEN flag
it would show 'contains' twice. Will change it to 'with'.
Thanks for the review.
--
Regards,
Karthik Nayak
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs
2015-06-13 20:18 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Karthik Nayak
` (9 preceding siblings ...)
2015-06-13 20:18 ` [PATCH v2 11/11] for-each-ref: add " Karthik Nayak
@ 2015-06-14 8:12 ` Matthieu Moy
2015-06-14 8:32 ` karthik nayak
10 siblings, 1 reply; 20+ messages in thread
From: Matthieu Moy @ 2015-06-14 8:12 UTC (permalink / raw)
To: Karthik Nayak; +Cc: git, christian.couder
Karthik Nayak <karthik.188@gmail.com> writes:
> +test_expect_success 'setup some history and refs' '
> + test_commit one &&
> + test_commit two &&
> + test_commit three &&
> + git checkout -b side &&
> + test_commit four &&
> + git checkout master &&
> + git update-ref refs/odd/spot master
I think you want more corner-cases here. For example,
refs/headsfoo/master should not match refs/heads, and it's easy to write
an incorrect implementation for this => test.
> +'
> +test_expect_success 'filtering by leading name' '
Blank line between tests please.
> + cat >expect <<-\EOF &&
> + refs/heads/master
> + refs/heads/side
> + EOF
> + git for-each-ref --format="%(refname)" refs/heads >actual &&
> + test_cmp expect actual
> +'
Isn't this test redundant with the content of t6300-for-each-ref.sh?
At this point, you've done only internal refactoring, so you shouldn't
need new tests (except to fix coverage holes in existing tests).
I guess you're adding this to build more tests on top, but the commit
message should clarify this.
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs
2015-06-14 8:12 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Matthieu Moy
@ 2015-06-14 8:32 ` karthik nayak
0 siblings, 0 replies; 20+ messages in thread
From: karthik nayak @ 2015-06-14 8:32 UTC (permalink / raw)
To: Matthieu Moy; +Cc: Git, Christian Couder
On Sun, Jun 14, 2015 at 1:42 PM, Matthieu Moy
<Matthieu.Moy@grenoble-inp.fr> wrote:
> Karthik Nayak <karthik.188@gmail.com> writes:
>
>> +test_expect_success 'setup some history and refs' '
>> + test_commit one &&
>> + test_commit two &&
>> + test_commit three &&
>> + git checkout -b side &&
>> + test_commit four &&
>> + git checkout master &&
>> + git update-ref refs/odd/spot master
>
> I think you want more corner-cases here. For example,
> refs/headsfoo/master should not match refs/heads, and it's easy to write
> an incorrect implementation for this => test.
Like you mentioned below, currently it's redundant with t6300 and its
purpose is to add tests for new functionality we provide to for-each-ref
via ref-filter. This is done in the next few patches in this series.
>
>> +'
>> +test_expect_success 'filtering by leading name' '
>
> Blank line between tests please.
Noted. Thanks.
>
>> + cat >expect <<-\EOF &&
>> + refs/heads/master
>> + refs/heads/side
>> + EOF
>> + git for-each-ref --format="%(refname)" refs/heads >actual &&
>> + test_cmp expect actual
>> +'
>
> Isn't this test redundant with the content of t6300-for-each-ref.sh?
>
> At this point, you've done only internal refactoring, so you shouldn't
> need new tests (except to fix coverage holes in existing tests).
>
> I guess you're adding this to build more tests on top, but the commit
> message should clarify this.
>
I'll add a note to the commit message about how this test file is so
that we can integrate
more tests in the future for functionality given to for-each-ref via
ref-filter APIs.
--
Regards,
Karthik Nayak
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 09/11] parse-options.h: add macros for '--contains' option
2015-06-14 6:13 ` Christian Couder
2015-06-14 6:58 ` karthik nayak
@ 2015-06-15 19:27 ` Junio C Hamano
2015-06-15 20:49 ` karthik nayak
1 sibling, 1 reply; 20+ messages in thread
From: Junio C Hamano @ 2015-06-15 19:27 UTC (permalink / raw)
To: Christian Couder; +Cc: Karthik Nayak, git, Matthieu Moy
Christian Couder <christian.couder@gmail.com> writes:
> The PARSE_OPT_HIDDEN flag is removed below. This means that "--with"
> will appear in the "git tag -h" output, which means that "--with"
> should appear in the documentation...
> The commit message may also want to tell that with is not hidden any more.
Or why is it a good idea to stop hiding.
I would prefer to keep it hidden to avoid "what's the difference
between the two" confusion.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 09/11] parse-options.h: add macros for '--contains' option
2015-06-15 19:27 ` Junio C Hamano
@ 2015-06-15 20:49 ` karthik nayak
0 siblings, 0 replies; 20+ messages in thread
From: karthik nayak @ 2015-06-15 20:49 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Christian Couder, git, Matthieu Moy
On Tue, Jun 16, 2015 at 12:57 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Christian Couder <christian.couder@gmail.com> writes:
>
>> The PARSE_OPT_HIDDEN flag is removed below. This means that "--with"
>> will appear in the "git tag -h" output, which means that "--with"
>> should appear in the documentation...
>> The commit message may also want to tell that with is not hidden any more.
>
> Or why is it a good idea to stop hiding.
>
> I would prefer to keep it hidden to avoid "what's the difference
> between the two" confusion.
Ok than, will do that.
--
Regards,
Karthik Nayak
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2015-06-15 20:49 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-13 20:17 [PATCH v2 00/11] add options to for-each-ref karthik nayak
2015-06-13 20:18 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 02/11] tag: libify parse_opt_points_at() Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 03/11] ref-filter: implement '--points-at' option Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 04/11] for-each-ref: add " Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 05/11] ref-filter: add parse_opt_merge_filter() Karthik Nayak
2015-06-14 5:49 ` Christian Couder
2015-06-14 6:49 ` karthik nayak
2015-06-13 20:18 ` [PATCH v2 06/11] ref-filter: implement '--merged' and '--no-merged' options Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 07/11] for-each-ref: add " Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 08/11] parse-option: rename parse_opt_with_commit() Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 09/11] parse-options.h: add macros for '--contains' option Karthik Nayak
2015-06-14 6:13 ` Christian Couder
2015-06-14 6:58 ` karthik nayak
2015-06-15 19:27 ` Junio C Hamano
2015-06-15 20:49 ` karthik nayak
2015-06-13 20:18 ` [PATCH v2 10/11] ref-filter: implement " Karthik Nayak
2015-06-13 20:18 ` [PATCH v2 11/11] for-each-ref: add " Karthik Nayak
2015-06-14 8:12 ` [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs Matthieu Moy
2015-06-14 8:32 ` karthik nayak
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.