Re: [PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options

2015-06-30 Thread Karthik Nayak
On Mon, Jun 29, 2015 at 11:33 PM, Junio C Hamano gits...@pobox.com wrote:
 Karthik Nayak karthik@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
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options

2015-06-30 Thread Junio C Hamano
Karthik Nayak karthik@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.

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options

2015-06-30 Thread Karthik Nayak
On Tue, Jun 30, 2015 at 9:28 PM, Junio C Hamano gits...@pobox.com wrote:
 Karthik Nayak karthik@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
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options

2015-06-29 Thread Junio C Hamano
Karthik Nayak karthik@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.




--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options

2015-06-29 Thread Junio C Hamano
Junio C Hamano gits...@pobox.com writes:

 Karthik Nayak karthik@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.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options

2015-06-25 Thread 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 p...@peff.net
Mentored-by: Christian Couder christian.cou...@gmail.com
Mentored-by: Matthieu Moy matthieu@grenoble-inp.fr
Signed-off-by: Karthik Nayak karthik@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)
+