All of lore.kernel.org
 help / color / mirror / Atom feed
From: Karthik Nayak <karthik.188@gmail.com>
To: git@vger.kernel.org
Cc: christian.couder@gmail.com, Matthieu.Moy@grenoble-inp.fr,
	Karthik Nayak <karthik.188@gmail.com>
Subject: [PATCH v4 06/19] ref-filter: implement '--merged' and '--no-merged' options
Date: Mon, 22 Jun 2015 02:18:20 +0530	[thread overview]
Message-ID: <1434919705-4884-6-git-send-email-karthik.188@gmail.com> (raw)
In-Reply-To: <1434919705-4884-1-git-send-email-karthik.188@gmail.com>

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 6502179..d62fa63 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_list *p, *to_clear = NULL;
+
+	init_revisions(&revs, NULL);
+
+	for (i = 0; i < array->nr; i++) {
+		struct ref_array_item *item = array->items[i];
+		add_pending_object(&revs, &item->commit->object, item->refname);
+		commit_list_insert(item->commit, &to_clear);
+	}
+
+	filter->merge_commit->object.flags |= UNINTERESTING;
+	add_pending_object(&revs, &filter->merge_commit->object, "");
+
+	revs.limited = 1;
+	if (prepare_revision_walk(&revs))
+		die(_("revision walk setup failed"));
+
+	old_nr = array->nr;
+	array->nr = 0;
+
+	for (i = 0; i < old_nr; i++) {
+		struct ref_array_item *item = array->items[i];
+		struct commit *commit = item->commit;
+
+		int is_merged = !!(commit->object.flags & UNINTERESTING);
+
+		if (is_merged == (filter->merge == REF_FILTER_MERGED_INCLUDE))
+			array->items[array->nr++] = array->items[i];
+		else
+			free_array_item(item);
+	}
+
+	for (p = to_clear; p; p = p->next)
+		clear_commit_marks(p->item, ALL_REV_FLAGS);
+	clear_commit_marks(filter->merge_commit, ALL_REV_FLAGS);
+	free_commit_list(to_clear);
+}
+
 /*
  * API for filtering a set of refs. Based on the type of refs the user
  * has requested, we iterate through those refs and apply filters
@@ -941,17 +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.3.439.gfea0c2a.dirty

  parent reply	other threads:[~2015-06-21 20:49 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-21 20:45 [PATCH v4 00/11] add options to for-each-ref Karthik Nayak
2015-06-21 20:48 ` [PATCH v4 01/19] t6301: for-each-ref tests for ref-filter APIs Karthik Nayak
2015-06-21 20:48   ` [PATCH v4 02/19] tag: libify parse_opt_points_at() Karthik Nayak
2015-06-21 20:48   ` [PATCH v4 03/19] ref-filter: implement '--points-at' option Karthik Nayak
2015-06-22 22:36     ` Eric Sunshine
2015-06-23 10:49       ` Karthik Nayak
2015-06-21 20:48   ` [PATCH v4 04/19] for-each-ref: add " Karthik Nayak
2015-06-22  0:45     ` Junio C Hamano
2015-06-22 19:03       ` Karthik Nayak
2015-06-22 19:21         ` Matthieu Moy
2015-06-22 19:24           ` Junio C Hamano
2015-06-22 19:27             ` Karthik Nayak
2015-06-22 19:51             ` Junio C Hamano
2015-06-22 22:38     ` Eric Sunshine
2015-06-23 10:52       ` Karthik Nayak
2015-06-21 20:48   ` [PATCH v4 05/19] ref-filter: add parse_opt_merge_filter() Karthik Nayak
2015-06-22  0:55     ` Junio C Hamano
2015-06-22 11:13       ` Matthieu Moy
2015-06-22 16:15         ` Junio C Hamano
2015-06-22 19:00       ` Karthik Nayak
2015-06-21 20:48   ` Karthik Nayak [this message]
2015-06-22  1:00     ` [PATCH v4 06/19] ref-filter: implement '--merged' and '--no-merged' options Junio C Hamano
2015-06-22 15:11       ` Karthik Nayak
2015-06-21 20:48   ` [PATCH v4 07/19] for-each-ref: add " Karthik Nayak
2015-06-22 22:41     ` Eric Sunshine
2015-06-23 11:05       ` Karthik Nayak
2015-06-21 20:48   ` [PATCH v4 08/19] parse-option: rename parse_opt_with_commit() Karthik Nayak
2015-06-22  1:04     ` Junio C Hamano
2015-06-22 15:38       ` Karthik Nayak
2015-06-22 16:27         ` Junio C Hamano
2015-06-22 16:37           ` Karthik Nayak
2015-06-21 20:48   ` [PATCH v4 09/19] parse-options.h: add macros for '--contains' option Karthik Nayak
2015-06-21 20:48   ` [PATCH v4 10/19] ref-filter: implement " Karthik Nayak
2015-06-21 20:48   ` [PATCH v4 11/19] for-each-ref: add " Karthik Nayak
2015-06-21 20:51 ` [PATCH v4 00/11] add options to for-each-ref Karthik Nayak
2015-06-22  0:41   ` Junio C Hamano
2015-06-22 14:48     ` Karthik Nayak

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1434919705-4884-6-git-send-email-karthik.188@gmail.com \
    --to=karthik.188@gmail.com \
    --cc=Matthieu.Moy@grenoble-inp.fr \
    --cc=christian.couder@gmail.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.