* [PATCH v6 00/11] add options to for-each-ref
@ 2015-06-25 8:46 Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Karthik Nayak
0 siblings, 1 reply; 25+ messages in thread
From: Karthik Nayak @ 2015-06-25 8:46 UTC (permalink / raw)
To: Git; +Cc: Junio C Hamano, Christian Couder, Matthieu Moy
v5 of this patch series can be found here :
http://article.gmane.org/gmane.comp.version-control.git/272590
This is a continuation of my GSoC project to unify git tag -l, git
branch -l and for-each-ref. Continued from this patch series :
http://thread.gmane.org/gmane.comp.version-control.git/271563
Changes in v5:
03/11: grammatical changes.
04/11: grammatical changes.
05/11: remove unnecessary if statement and remove caps used in commit message.
06/11: use xcalloc instead of using a commit_list as we know the size
of the array.
07/11: s/<object>/[<object>]/ as the object is optional.
08/11: rename parse_opt_commit_object_name() to parse_opt_commits().
09/11: make branch.c also to use the macros.
11/11: s/<object>/[<object>]/ as the object is optional.
Changes in v6:
Renamed the test file from t6301 to t6302 to avoid conflicts.
Thanks to Matthieu, Christian, Junio and Eric for the input on the
last iteration.
--
Regards,
Karthik Nayak
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs
2015-06-25 8:46 [PATCH v6 00/11] add options to for-each-ref Karthik Nayak
@ 2015-06-25 8:57 ` Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 02/11] tag: libify parse_opt_points_at() Karthik Nayak
` (10 more replies)
0 siblings, 11 replies; 25+ messages in thread
From: Karthik Nayak @ 2015-06-25 8:57 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, gitster, Karthik Nayak
Add a test suite for testing the ref-filter APIs used
by for-each-ref. We just intialize the test suite for now.
More tests will be added in the following patches as more
options are added to for-each-ref.
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/t6302-for-each-ref-filter.sh | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
create mode 100644 t/t6302-for-each-ref-filter.sh
diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
new file mode 100644
index 0000000..b1fa8d4
--- /dev/null
+++ b/t/t6302-for-each-ref-filter.sh
@@ -0,0 +1,19 @@
+#!/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 tag -s -m "A signed tag message" signed-tag &&
+ git checkout master &&
+ git update-ref refs/odd/spot master
+'
+
+test_done
--
2.4.4
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v6 02/11] tag: libify parse_opt_points_at()
2015-06-25 8:57 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Karthik Nayak
@ 2015-06-25 8:57 ` Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 03/11] ref-filter: implement '--points-at' option Karthik Nayak
` (9 subsequent siblings)
10 siblings, 0 replies; 25+ messages in thread
From: Karthik Nayak @ 2015-06-25 8:57 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, gitster, 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.4
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v6 03/11] ref-filter: implement '--points-at' option
2015-06-25 8:57 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 02/11] tag: libify parse_opt_points_at() Karthik Nayak
@ 2015-06-25 8:57 ` Karthik Nayak
2015-06-29 17:40 ` Junio C Hamano
2015-06-25 8:57 ` [PATCH v6 04/11] for-each-ref: add " Karthik Nayak
` (8 subsequent siblings)
10 siblings, 1 reply; 25+ messages in thread
From: Karthik Nayak @ 2015-06-25 8:57 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, gitster, 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..f40f06e 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 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.4
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v6 04/11] for-each-ref: add '--points-at' option
2015-06-25 8:57 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 02/11] tag: libify parse_opt_points_at() Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 03/11] ref-filter: implement '--points-at' option Karthik Nayak
@ 2015-06-25 8:57 ` Karthik Nayak
2015-06-29 17:46 ` Junio C Hamano
2015-06-29 18:38 ` Junio C Hamano
2015-06-25 8:57 ` [PATCH v6 05/11] ref-filter: add parse_opt_merge_filter() Karthik Nayak
` (7 subsequent siblings)
10 siblings, 2 replies; 25+ messages in thread
From: Karthik Nayak @ 2015-06-25 8:57 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, gitster, 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/t6302-for-each-ref-filter.sh | 20 ++++++++++++++++++++
3 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index 7f8d9a5..0ede41d 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 pointing to the given object.
FIELD NAMES
-----------
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 7919206..46f9b05 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 pointing to the given 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/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
index b1fa8d4..7269a66 100644
--- a/t/t6302-for-each-ref-filter.sh
+++ b/t/t6302-for-each-ref-filter.sh
@@ -16,4 +16,24 @@ test_expect_success 'setup some history and refs' '
git update-ref refs/odd/spot master
'
+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_expect_success 'check signed tags with --points-at' '
+ cat >expect <<-\EOF &&
+ refs/heads/side
+ refs/tags/four
+ refs/tags/signed-tag four
+ EOF
+ git for-each-ref --format="%(refname) %(*subject)" --points-at=side >actual &&
+ test_cmp expect actual
+'
+
test_done
--
2.4.4
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v6 05/11] ref-filter: add parse_opt_merge_filter()
2015-06-25 8:57 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Karthik Nayak
` (2 preceding siblings ...)
2015-06-25 8:57 ` [PATCH v6 04/11] for-each-ref: add " Karthik Nayak
@ 2015-06-25 8:57 ` Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options Karthik Nayak
` (6 subsequent siblings)
10 siblings, 0 replies; 25+ messages in thread
From: Karthik Nayak @ 2015-06-25 8:57 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, gitster, 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 | 19 +++++++++++++++++++
ref-filter.h | 11 +++++++++++
3 files changed, 34 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 f40f06e..0c2d67c 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1125,3 +1125,22 @@ 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 (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..ad2902b 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -50,6 +50,15 @@ struct ref_filter_cbdata {
struct ref_filter *filter;
};
+/* Macros for checking --merged and --no-merged options */
+#define _OPT_MERGED_NO_MERGED(option, filter, h) \
+ { OPTION_CALLBACK, 0, option, (filter), N_("commit"), (h), \
+ PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \
+ parse_opt_merge_filter, (intptr_t) "HEAD" \
+ }
+#define OPT_MERGED(f, h) _OPT_MERGED_NO_MERGED("merged", f, h)
+#define OPT_NO_MERGED(f, h) _OPT_MERGED_NO_MERGED("no-merged", f, h)
+
/*
* 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 +80,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.4
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options
2015-06-25 8:57 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Karthik Nayak
` (3 preceding siblings ...)
2015-06-25 8:57 ` [PATCH v6 05/11] ref-filter: add parse_opt_merge_filter() Karthik Nayak
@ 2015-06-25 8:57 ` Karthik Nayak
2015-06-29 18:03 ` Junio C Hamano
2015-06-25 8:57 ` [PATCH v6 07/11] for-each-ref: add " Karthik Nayak
` (5 subsequent siblings)
10 siblings, 1 reply; 25+ messages in thread
From: Karthik Nayak @ 2015-06-25 8:57 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, gitster, 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 | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
ref-filter.h | 8 +++++++
2 files changed, 77 insertions(+), 4 deletions(-)
diff --git a/ref-filter.c b/ref-filter.c
index 0c2d67c..2f20cb3 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);
@@ -902,11 +904,23 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,
return 0;
/*
+ * A merge filter is applied on refs pointing to commits. Hence
+ * obtain the commit using the 'oid' available and discard all
+ * non-commits early. The actual filtering is done later.
+ */
+ 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 +946,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 **to_clear = xcalloc(sizeof(struct commit *), array->nr);
+
+ 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);
+ to_clear[i] = item->commit;
+ }
+
+ 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 (i = 0; i < old_nr; i++)
+ clear_commit_marks(to_clear[i], ALL_REV_FLAGS);
+ clear_commit_marks(filter->merge_commit, ALL_REV_FLAGS);
+ free(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 +999,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 ad2902b..7241a1d 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.4
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v6 07/11] for-each-ref: add '--merged' and '--no-merged' options
2015-06-25 8:57 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Karthik Nayak
` (4 preceding siblings ...)
2015-06-25 8:57 ` [PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options Karthik Nayak
@ 2015-06-25 8:57 ` Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 08/11] parse-option: rename parse_opt_with_commit() Karthik Nayak
` (4 subsequent siblings)
10 siblings, 0 replies; 25+ messages in thread
From: Karthik Nayak @ 2015-06-25 8:57 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, gitster, 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/t6302-for-each-ref-filter.sh | 22 ++++++++++++++++++++++
3 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index 0ede41d..290a5c1 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 pointing to 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).
+
FIELD NAMES
-----------
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 46f9b05..ba70798 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 pointing to 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_END(),
};
diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
index 7269a66..f5ccfb9 100644
--- a/t/t6302-for-each-ref-filter.sh
+++ b/t/t6302-for-each-ref-filter.sh
@@ -36,4 +36,26 @@ test_expect_success 'check signed tags 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
+ refs/tags/signed-tag
+ EOF
+ git for-each-ref --format="%(refname)" --no-merged=master >actual &&
+ test_cmp expect actual
+'
+
test_done
--
2.4.4
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v6 08/11] parse-option: rename parse_opt_with_commit()
2015-06-25 8:57 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Karthik Nayak
` (5 preceding siblings ...)
2015-06-25 8:57 ` [PATCH v6 07/11] for-each-ref: add " Karthik Nayak
@ 2015-06-25 8:57 ` Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 09/11] parse-options.h: add macros for '--contains' option Karthik Nayak
` (3 subsequent siblings)
10 siblings, 0 replies; 25+ messages in thread
From: Karthik Nayak @ 2015-06-25 8:57 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, gitster, Karthik Nayak
Rename parse_opt_with_commit() to parse_opt_commits() 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..a008b0d 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_commits, (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_commits, (intptr_t) "HEAD",
},
OPT__ABBREV(&abbrev),
diff --git a/builtin/tag.c b/builtin/tag.c
index 280981f..7af45a0 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_commits, (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_commits, (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..632f10f 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_commits(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..2ffd857 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_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);
--
2.4.4
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v6 09/11] parse-options.h: add macros for '--contains' option
2015-06-25 8:57 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Karthik Nayak
` (6 preceding siblings ...)
2015-06-25 8:57 ` [PATCH v6 08/11] parse-option: rename parse_opt_with_commit() Karthik Nayak
@ 2015-06-25 8:57 ` Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 10/11] ref-filter: implement " Karthik Nayak
` (2 subsequent siblings)
10 siblings, 0 replies; 25+ messages in thread
From: Karthik Nayak @ 2015-06-25 8:57 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, gitster, 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 and branch.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/branch.c | 14 ++------------
builtin/tag.c | 14 ++------------
parse-options.h | 7 +++++++
3 files changed, 11 insertions(+), 24 deletions(-)
diff --git a/builtin/branch.c b/builtin/branch.c
index a008b0d..b04e341 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -824,18 +824,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_commits, (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_commits, (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:")),
diff --git a/builtin/tag.c b/builtin/tag.c
index 7af45a0..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_commits, (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_commits, (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 2ffd857..627423f 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, 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
--
2.4.4
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v6 10/11] ref-filter: implement '--contains' option
2015-06-25 8:57 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Karthik Nayak
` (7 preceding siblings ...)
2015-06-25 8:57 ` [PATCH v6 09/11] parse-options.h: add macros for '--contains' option Karthik Nayak
@ 2015-06-25 8:57 ` Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 11/11] for-each-ref: add " Karthik Nayak
2015-06-29 18:14 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Junio C Hamano
10 siblings, 0 replies; 25+ messages in thread
From: Karthik Nayak @ 2015-06-25 8:57 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, gitster, 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 | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
ref-filter.h | 3 ++
2 files changed, 116 insertions(+), 1 deletion(-)
diff --git a/ref-filter.c b/ref-filter.c
index 2f20cb3..f793386 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -818,6 +818,114 @@ 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"
@@ -908,10 +1016,14 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,
* obtain the commit using the 'oid' available and discard all
* non-commits early. The actual filtering is done later.
*/
- if (filter->merge_commit) {
+ if (filter->merge_commit || filter->with_commit) {
commit = lookup_commit_reference_gently(oid->hash, 1);
if (!commit)
return 0;
+ /* We perform the filtering for the '--contains' option */
+ if (filter->with_commit &&
+ !commit_contains(filter, commit))
+ return 0;
}
/*
diff --git a/ref-filter.h b/ref-filter.h
index 7241a1d..3c59431 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.4
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v6 11/11] for-each-ref: add '--contains' option
2015-06-25 8:57 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Karthik Nayak
` (8 preceding siblings ...)
2015-06-25 8:57 ` [PATCH v6 10/11] ref-filter: implement " Karthik Nayak
@ 2015-06-25 8:57 ` Karthik Nayak
2015-06-29 18:14 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Junio C Hamano
10 siblings, 0 replies; 25+ messages in thread
From: Karthik Nayak @ 2015-06-25 8:57 UTC (permalink / raw)
To: git; +Cc: christian.couder, Matthieu.Moy, gitster, Karthik Nayak
Add the '--contains' option provided by 'ref-filter'. The '--contains'
option lists only refs which 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/t6302-for-each-ref-filter.sh | 14 ++++++++++++++
3 files changed, 21 insertions(+)
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index 290a5c1..94bb5bd 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 [<object>]::
+ 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 ba70798..5868c48 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/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
index f5ccfb9..50ee115 100644
--- a/t/t6302-for-each-ref-filter.sh
+++ b/t/t6302-for-each-ref-filter.sh
@@ -58,4 +58,18 @@ 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/signed-tag
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" --contains=two >actual &&
+ test_cmp expect actual
+'
+
test_done
--
2.4.4
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH v6 03/11] ref-filter: implement '--points-at' option
2015-06-25 8:57 ` [PATCH v6 03/11] ref-filter: implement '--points-at' option Karthik Nayak
@ 2015-06-29 17:40 ` Junio C Hamano
2015-06-29 19:37 ` Karthik Nayak
0 siblings, 1 reply; 25+ messages in thread
From: Junio C Hamano @ 2015-06-29 17:40 UTC (permalink / raw)
To: Karthik Nayak; +Cc: git, christian.couder, Matthieu.Moy
Karthik Nayak <karthik.188@gmail.com> writes:
> +/*
> + * Given a ref (sha1, refname) see if it points to 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;
> +}
> +
Interesting. I think the change done while copying the code does
not change anything from the original (other than that the helper
lost its ability to return the peeled object name), and I think you
shouldn't make any change while copying the code that would change
the benaviour, but I notice a few things that we might want to keep
in mind and revisit them later (i.e. might be a good idea to add
NEEDSWORK comment to record them near the function):
- The original only peeled one level of indirection, so does this
implementation. But is that really what we want, I wonder?
After doing:
$ git tag -a -m 'annotated' atag $commit
$ git tag -a -m 'annotated doubly' dtag atag
atag^0, dtag^0 and $commit all refer to the same commit object.
Do we want to miss dtag with --point-at=$commit?
- As we are in for-each-ref (or eventually tag -l) that is walking
the cached refs, we may know what refname peels to without
parsing the object at all. Could it be more efficient to ask
peel_ref() for the pointee without doing parse_object()
ourselves?
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v6 04/11] for-each-ref: add '--points-at' option
2015-06-25 8:57 ` [PATCH v6 04/11] for-each-ref: add " Karthik Nayak
@ 2015-06-29 17:46 ` Junio C Hamano
2015-06-29 19:55 ` Karthik Nayak
2015-06-29 18:38 ` Junio C Hamano
1 sibling, 1 reply; 25+ messages in thread
From: Junio C Hamano @ 2015-06-29 17:46 UTC (permalink / raw)
To: Karthik Nayak; +Cc: git, christian.couder, Matthieu.Moy
Karthik Nayak <karthik.188@gmail.com> writes:
> Add the '--points-at' option provided by 'ref-filter'. The option
> lets the user to pick only refs which point to a particular
> commit.
It somehow feels strange that the option name is points-at and all
the explanation (like the above and also in the doc) talks about
pointing to an object. Not limited to this patch but the previous
one had the same, I think.
> diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
> index b1fa8d4..7269a66 100644
> --- a/t/t6302-for-each-ref-filter.sh
> +++ b/t/t6302-for-each-ref-filter.sh
> @@ -16,4 +16,24 @@ test_expect_success 'setup some history and refs' '
> git update-ref refs/odd/spot master
> '
>
> +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_expect_success 'check signed tags with --points-at' '
> + cat >expect <<-\EOF &&
> + refs/heads/side
> + refs/tags/four
> + refs/tags/signed-tag four
> + EOF
> + git for-each-ref --format="%(refname) %(*subject)" --points-at=side >actual &&
> + test_cmp expect actual
> +'
This shows that we would want to add a "annotated doubly" tag in the
preparation step 01/11; the expected outcome is that it will not
show in the output, I think.
Thanks.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options
2015-06-25 8:57 ` [PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options Karthik Nayak
@ 2015-06-29 18:03 ` Junio C Hamano
2015-06-29 18:28 ` Junio C Hamano
2015-06-30 13:38 ` Karthik Nayak
0 siblings, 2 replies; 25+ messages in thread
From: Junio C Hamano @ 2015-06-29 18:03 UTC (permalink / raw)
To: Karthik Nayak; +Cc: git, christian.couder, Matthieu.Moy
Karthik Nayak <karthik.188@gmail.com> writes:
> +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 **to_clear = xcalloc(sizeof(struct commit *), array->nr);
> +
> + 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);
> + to_clear[i] = item->commit;
> + }
> +
> + 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 (i = 0; i < old_nr; i++)
> + clear_commit_marks(to_clear[i], ALL_REV_FLAGS);
> + clear_commit_marks(filter->merge_commit, ALL_REV_FLAGS);
> + free(to_clear);
> +}
Did this come from somewhere else (e.g. tag -l or branch -l)? If
so, you'd need a note similar to what you added in [02/11] to the
original.
I also have a feeling that compared to an implementation based on
paint_down_to_common(), including is_descendant_of(), this may be
less precise (e.g. it would be confused with clock skew that lasts
more than SLOP commits). If we are inventing a new helper (as
opposed to moving an existing one), we'd probably be better off
doing a thin wrapper around paint_down_to_common() than calling
revision-walk machinery.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs
2015-06-25 8:57 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Karthik Nayak
` (9 preceding siblings ...)
2015-06-25 8:57 ` [PATCH v6 11/11] for-each-ref: add " Karthik Nayak
@ 2015-06-29 18:14 ` Junio C Hamano
2015-06-29 18:43 ` Karthik Nayak
10 siblings, 1 reply; 25+ messages in thread
From: Junio C Hamano @ 2015-06-29 18:14 UTC (permalink / raw)
To: Karthik Nayak; +Cc: git, christian.couder, Matthieu.Moy
Karthik Nayak <karthik.188@gmail.com> writes:
> t/t6302-for-each-ref-filter.sh | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
> create mode 100644 t/t6302-for-each-ref-filter.sh
non-executable tests: t6302-for-each-ref-filter.sh
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options
2015-06-29 18:03 ` Junio C Hamano
@ 2015-06-29 18:28 ` Junio C Hamano
2015-06-30 13:38 ` Karthik Nayak
1 sibling, 0 replies; 25+ messages in thread
From: Junio C Hamano @ 2015-06-29 18:28 UTC (permalink / raw)
To: Karthik Nayak; +Cc: git, christian.couder, Matthieu.Moy
Junio C Hamano <gitster@pobox.com> writes:
> Karthik Nayak <karthik.188@gmail.com> writes:
>
>> +static void do_merge_filter(struct ref_filter_cbdata *ref_cbdata)
>> +{
>> ...
>> + for (i = 0; i < array->nr; i++) {
>> + struct ref_array_item *item = array->items[i];
>> + add_pending_object(&revs, &item->commit->object, item->refname);
>> + to_clear[i] = item->commit;
>> + }
>> +
>> + 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"));
>> + ...
>
> Did this come from somewhere else (e.g. tag -l or branch -l)? If
> so, you'd need a note similar to what you added in [02/11] to the
> original.
Ah, now I see this came from a part of print_ref_list in
builtin/branch.c; you would want to leave a note there.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v6 04/11] for-each-ref: add '--points-at' option
2015-06-25 8:57 ` [PATCH v6 04/11] for-each-ref: add " Karthik Nayak
2015-06-29 17:46 ` Junio C Hamano
@ 2015-06-29 18:38 ` Junio C Hamano
2015-06-29 19:11 ` Karthik Nayak
1 sibling, 1 reply; 25+ messages in thread
From: Junio C Hamano @ 2015-06-29 18:38 UTC (permalink / raw)
To: Karthik Nayak; +Cc: git, christian.couder, Matthieu.Moy
Karthik Nayak <karthik.188@gmail.com> writes:
> +test_expect_success 'check signed tags with --points-at' '
> + cat >expect <<-\EOF &&
> + refs/heads/side
> + refs/tags/four
> + refs/tags/signed-tag four
> + EOF
> + git for-each-ref --format="%(refname) %(*subject)" --points-at=side >actual &&
> + test_cmp expect actual
> +'
This piece seems to fail without a trailing whitespace in the
expected file. I initially suspected that they were dropped
on my end while applying with "git am --whitespace=fix", but going
back to my mailbox, it seems that what gmane received does not have
them in the first place:
sed -e "s/Z$//" <<-\EOF &&
refs/heads/side Z
refs/tags/four Z
refs/tags/signed-tag four
EOF
or something like that to make the EOL more visible to those who are
reading the tests, perhaps?
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs
2015-06-29 18:14 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Junio C Hamano
@ 2015-06-29 18:43 ` Karthik Nayak
0 siblings, 0 replies; 25+ messages in thread
From: Karthik Nayak @ 2015-06-29 18:43 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git, Christian Couder, Matthieu Moy
On Mon, Jun 29, 2015 at 11:44 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Karthik Nayak <karthik.188@gmail.com> writes:
>
>> t/t6302-for-each-ref-filter.sh | 19 +++++++++++++++++++
>> 1 file changed, 19 insertions(+)
>> create mode 100644 t/t6302-for-each-ref-filter.sh
>
> non-executable tests: t6302-for-each-ref-filter.sh
Renaming it defaulted to 644, will change, thanks :)
--
Regards,
Karthik Nayak
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v6 04/11] for-each-ref: add '--points-at' option
2015-06-29 18:38 ` Junio C Hamano
@ 2015-06-29 19:11 ` Karthik Nayak
0 siblings, 0 replies; 25+ messages in thread
From: Karthik Nayak @ 2015-06-29 19:11 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git, Christian Couder, Matthieu Moy
On Tue, Jun 30, 2015 at 12:08 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Karthik Nayak <karthik.188@gmail.com> writes:
>
>> +test_expect_success 'check signed tags with --points-at' '
>> + cat >expect <<-\EOF &&
>> + refs/heads/side
>> + refs/tags/four
>> + refs/tags/signed-tag four
>> + EOF
>> + git for-each-ref --format="%(refname) %(*subject)" --points-at=side >actual &&
>> + test_cmp expect actual
>> +'
>
> This piece seems to fail without a trailing whitespace in the
> expected file. I initially suspected that they were dropped
> on my end while applying with "git am --whitespace=fix", but going
> back to my mailbox, it seems that what gmane received does not have
> them in the first place:
>
> sed -e "s/Z$//" <<-\EOF &&
> refs/heads/side Z
> refs/tags/four Z
> refs/tags/signed-tag four
> EOF
>
> or something like that to make the EOL more visible to those who are
> reading the tests, perhaps?
Thanks, will use sed like you suggested.
--
Regards,
Karthik Nayak
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v6 03/11] ref-filter: implement '--points-at' option
2015-06-29 17:40 ` Junio C Hamano
@ 2015-06-29 19:37 ` Karthik Nayak
0 siblings, 0 replies; 25+ messages in thread
From: Karthik Nayak @ 2015-06-29 19:37 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git, Christian Couder, Matthieu Moy
On Mon, Jun 29, 2015 at 11:10 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Karthik Nayak <karthik.188@gmail.com> writes:
>
>> +/*
>> + * Given a ref (sha1, refname) see if it points to 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;
>> +}
>> +
>
> Interesting. I think the change done while copying the code does
> not change anything from the original (other than that the helper
> lost its ability to return the peeled object name), and I think you
> shouldn't make any change while copying the code that would change
> the benaviour, but I notice a few things that we might want to keep
> in mind and revisit them later (i.e. might be a good idea to add
> NEEDSWORK comment to record them near the function):
Reverted the change.
OK will do and add this, I will work on this after GSoC is done.
But like you said I'll add a comment so if someone wants to they can
work on it for now.
>
> - The original only peeled one level of indirection, so does this
> implementation. But is that really what we want, I wonder?
>
> After doing:
>
> $ git tag -a -m 'annotated' atag $commit
> $ git tag -a -m 'annotated doubly' dtag atag
>
> atag^0, dtag^0 and $commit all refer to the same commit object.
> Do we want to miss dtag with --point-at=$commit?
>
> - As we are in for-each-ref (or eventually tag -l) that is walking
> the cached refs, we may know what refname peels to without
> parsing the object at all. Could it be more efficient to ask
> peel_ref() for the pointee without doing parse_object()
> ourselves?
>
Shouldn't both these scenarios be solved together by using peel_ref()?
After what you said I just tried a hacked up version of using peel_ref()
rather than parsing the object, tried it out on the Linux tree.
$time git tag -l --points-at=HEAD~501
git tag -l --points-at=HEAD~501 0.03s user 0.01s system 97% cpu 0.044 total
*Using the modified version which uses peel_ref() *
$time ../git/git tag -l --points-at=HEAD~501
../git/git tag -l --points-at=HEAD~501 0.01s user 0.02s system 90%
cpu 0.033 total
This was the average of around 5 tests, Might not be the best way to check, but
I'm sure there's an improvement.
Thanks :)
--
Regards,
Karthik Nayak
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v6 04/11] for-each-ref: add '--points-at' option
2015-06-29 17:46 ` Junio C Hamano
@ 2015-06-29 19:55 ` Karthik Nayak
0 siblings, 0 replies; 25+ messages in thread
From: Karthik Nayak @ 2015-06-29 19:55 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git, Christian Couder, Matthieu Moy
On Mon, Jun 29, 2015 at 11:16 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Karthik Nayak <karthik.188@gmail.com> writes:
>
>> Add the '--points-at' option provided by 'ref-filter'. The option
>> lets the user to pick only refs which point to a particular
>> commit.
>
> It somehow feels strange that the option name is points-at and all
> the explanation (like the above and also in the doc) talks about
> pointing to an object. Not limited to this patch but the previous
> one had the same, I think.
>
Will have a look and change, thanks :)
>> diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
>> index b1fa8d4..7269a66 100644
>> --- a/t/t6302-for-each-ref-filter.sh
>> +++ b/t/t6302-for-each-ref-filter.sh
>> @@ -16,4 +16,24 @@ test_expect_success 'setup some history and refs' '
>> git update-ref refs/odd/spot master
>> '
>>
>> +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_expect_success 'check signed tags with --points-at' '
>> + cat >expect <<-\EOF &&
>> + refs/heads/side
>> + refs/tags/four
>> + refs/tags/signed-tag four
>> + EOF
>> + git for-each-ref --format="%(refname) %(*subject)" --points-at=side >actual &&
>> + test_cmp expect actual
>> +'
>
> This shows that we would want to add a "annotated doubly" tag in the
> preparation step 01/11; the expected outcome is that it will not
> show in the output, I think.
>
> Thanks.
Will add!
--
Regards,
Karthik Nayak
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options
2015-06-29 18:03 ` Junio C Hamano
2015-06-29 18:28 ` Junio C Hamano
@ 2015-06-30 13:38 ` Karthik Nayak
2015-06-30 15:58 ` Junio C Hamano
1 sibling, 1 reply; 25+ messages in thread
From: Karthik Nayak @ 2015-06-30 13:38 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git, Christian Couder, Matthieu Moy
On Mon, Jun 29, 2015 at 11:33 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Karthik Nayak <karthik.188@gmail.com> writes:
>
>> +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 **to_clear = xcalloc(sizeof(struct commit *), array->nr);
>> +
>> + 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);
>> + to_clear[i] = item->commit;
>> + }
>> +
>> + 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 (i = 0; i < old_nr; i++)
>> + clear_commit_marks(to_clear[i], ALL_REV_FLAGS);
>> + clear_commit_marks(filter->merge_commit, ALL_REV_FLAGS);
>> + free(to_clear);
>> +}
>
> Did this come from somewhere else (e.g. tag -l or branch -l)? If
> so, you'd need a note similar to what you added in [02/11] to the
> original.
>
Will do this, thanks.
> I also have a feeling that compared to an implementation based on
> paint_down_to_common(), including is_descendant_of(), this may be
> less precise (e.g. it would be confused with clock skew that lasts
> more than SLOP commits). If we are inventing a new helper (as
> opposed to moving an existing one), we'd probably be better off
> doing a thin wrapper around paint_down_to_common() than calling
> revision-walk machinery.
>
I'll have a look and get back to you.
--
Regards,
Karthik Nayak
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options
2015-06-30 13:38 ` Karthik Nayak
@ 2015-06-30 15:58 ` Junio C Hamano
2015-06-30 16:04 ` Karthik Nayak
0 siblings, 1 reply; 25+ messages in thread
From: Junio C Hamano @ 2015-06-30 15:58 UTC (permalink / raw)
To: Karthik Nayak; +Cc: Git, Christian Couder, Matthieu Moy
Karthik Nayak <karthik.188@gmail.com> writes:
>> I also have a feeling that compared to an implementation based on
>> paint_down_to_common(), including is_descendant_of(), this may be
>> less precise (e.g. it would be confused with clock skew that lasts
>> more than SLOP commits). If we are inventing a new helper (as
>> opposed to moving an existing one), we'd probably be better off
>> doing a thin wrapper around paint_down_to_common() than calling
>> revision-walk machinery.
>
> I'll have a look and get back to you.
Not as part of this series, now I know it is a straight-forward port
of what we already have for "branch --merged". This series is not
yet about improving counting logic but first unifying the three.
Thanks.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options
2015-06-30 15:58 ` Junio C Hamano
@ 2015-06-30 16:04 ` Karthik Nayak
0 siblings, 0 replies; 25+ messages in thread
From: Karthik Nayak @ 2015-06-30 16:04 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git, Christian Couder, Matthieu Moy
On Tue, Jun 30, 2015 at 9:28 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Karthik Nayak <karthik.188@gmail.com> writes:
>
>>> I also have a feeling that compared to an implementation based on
>>> paint_down_to_common(), including is_descendant_of(), this may be
>>> less precise (e.g. it would be confused with clock skew that lasts
>>> more than SLOP commits). If we are inventing a new helper (as
>>> opposed to moving an existing one), we'd probably be better off
>>> doing a thin wrapper around paint_down_to_common() than calling
>>> revision-walk machinery.
>>
>> I'll have a look and get back to you.
>
> Not as part of this series, now I know it is a straight-forward port
> of what we already have for "branch --merged". This series is not
> yet about improving counting logic but first unifying the three.
>
> Thanks.
>
Sure, added this to my personal TODO :)
--
Regards,
Karthik Nayak
^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2015-06-30 16:05 UTC | newest]
Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-25 8:46 [PATCH v6 00/11] add options to for-each-ref Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 02/11] tag: libify parse_opt_points_at() Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 03/11] ref-filter: implement '--points-at' option Karthik Nayak
2015-06-29 17:40 ` Junio C Hamano
2015-06-29 19:37 ` Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 04/11] for-each-ref: add " Karthik Nayak
2015-06-29 17:46 ` Junio C Hamano
2015-06-29 19:55 ` Karthik Nayak
2015-06-29 18:38 ` Junio C Hamano
2015-06-29 19:11 ` Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 05/11] ref-filter: add parse_opt_merge_filter() Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options Karthik Nayak
2015-06-29 18:03 ` Junio C Hamano
2015-06-29 18:28 ` Junio C Hamano
2015-06-30 13:38 ` Karthik Nayak
2015-06-30 15:58 ` Junio C Hamano
2015-06-30 16:04 ` Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 07/11] for-each-ref: add " Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 08/11] parse-option: rename parse_opt_with_commit() Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 09/11] parse-options.h: add macros for '--contains' option Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 10/11] ref-filter: implement " Karthik Nayak
2015-06-25 8:57 ` [PATCH v6 11/11] for-each-ref: add " Karthik Nayak
2015-06-29 18:14 ` [PATCH v6 01/11] t6302: for-each-ref tests for ref-filter APIs Junio C Hamano
2015-06-29 18:43 ` Karthik Nayak
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).