Re: [PATCH v6 06/11] ref-filter: implement '--merged' and '--no-merged' options
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
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
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
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
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
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) +