git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
To: skimo@liacs.nl
Cc: Junio C Hamano <gitster@pobox.com>, git@vger.kernel.org
Subject: Re: [PATCH v3] revision: allow selection of commits that do not match a pattern
Date: Sun, 8 Jul 2007 15:22:06 +0100 (BST)	[thread overview]
Message-ID: <Pine.LNX.4.64.0707081519230.4248@racer.site> (raw)
In-Reply-To: <20070708105719.GH1528MdfPADPa@greensroom.kotnet.org>

Hi,

just to give you an impression of what I had in mind, here is a WIP.  It 
is not completely thought through, for example I did not make up my mind 
how to handle something like "--not --not-at-all <pattern>".  Oh, and the 
code for non-status_only is not there.  And builtin-grep does not see any 
of this, yet. But you'll get the idea:

---

 grep.c     |   19 +++++++++++++++----
 grep.h     |    3 +++
 revision.c |   13 ++++++++++++-
 3 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/grep.c b/grep.c
index f67d671..40a2620 100644
--- a/grep.c
+++ b/grep.c
@@ -66,20 +66,24 @@ static struct grep_expr *compile_pattern_atom(struct grep_pat **list)
 
 static struct grep_expr *compile_pattern_not(struct grep_pat **list)
 {
+	const char *what;
 	struct grep_pat *p;
 	struct grep_expr *x;
 
 	p = *list;
 	switch (p->token) {
 	case GREP_NOT:
+	case GREP_NOT_AT_ALL:
+		what = p->token == GREP_NOT ? "--not" : "--not-at-all";
 		if (!p->next)
-			die("--not not followed by pattern expression");
+			die("%s not followed by pattern expression", what);
 		*list = p->next;
 		x = xcalloc(1, sizeof (struct grep_expr));
-		x->node = GREP_NODE_NOT;
+		x->node = p->token == GREP_NOT ?
+			GREP_NODE_NOT : GREP_NODE_NOT_AT_ALL;
 		x->u.unary = compile_pattern_not(list);
 		if (!x->u.unary)
-			die("--not followed by non pattern expression");
+			die("%s followed by non pattern expression", what);
 		return x;
 	default:
 		return compile_pattern_atom(list);
@@ -173,6 +177,7 @@ static void free_pattern_expr(struct grep_expr *x)
 	case GREP_NODE_ATOM:
 		break;
 	case GREP_NODE_NOT:
+	case GREP_NODE_NOT_AT_ALL:
 		free_pattern_expr(x->u.unary);
 		break;
 	case GREP_NODE_AND:
@@ -316,6 +321,10 @@ static int match_expr_eval(struct grep_opt *o,
 	case GREP_NODE_NOT:
 		h = !match_expr_eval(o, x->u.unary, bol, eol, ctx, 0);
 		break;
+	case GREP_NODE_NOT_AT_ALL:
+		if (match_expr_eval(o, x->u.unary, bol, eol, ctx, 0))
+			o->not_at_all = 1;
+		break;
 	case GREP_NODE_AND:
 		if (!collect_hits)
 			return (match_expr_eval(o, x->u.binary.left,
@@ -382,6 +391,8 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
 	unsigned count = 0;
 	enum grep_context ctx = GREP_CONTEXT_HEAD;
 
+	opt->not_at_all = 0;
+
 	if (buffer_is_binary(buf, size)) {
 		switch (opt->binary) {
 		case GREP_BINARY_DEFAULT:
@@ -500,7 +511,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
 		return 0;
 
 	if (opt->status_only)
-		return 0;
+		return !opt->not_at_all;
 	if (opt->unmatch_name_only) {
 		/* We did not see any hit, so we want to show this */
 		printf("%s\n", name);
diff --git a/grep.h b/grep.h
index d252dd2..f80a1c2 100644
--- a/grep.h
+++ b/grep.h
@@ -10,6 +10,7 @@ enum grep_pat_token {
 	GREP_CLOSE_PAREN,
 	GREP_NOT,
 	GREP_OR,
+	GREP_NOT_AT_ALL,
 };
 
 enum grep_context {
@@ -31,6 +32,7 @@ enum grep_expr_node {
 	GREP_NODE_NOT,
 	GREP_NODE_AND,
 	GREP_NODE_OR,
+	GREP_NODE_NOT_AT_ALL,
 };
 
 struct grep_expr {
@@ -68,6 +70,7 @@ struct grep_opt {
 	unsigned extended:1;
 	unsigned relative:1;
 	unsigned pathname:1;
+	unsigned not_at_all:1; /* is set if the pattern was seen */
 	int regflags;
 	unsigned pre_context;
 	unsigned post_context;
diff --git a/revision.c b/revision.c
index 5184716..3df8a57 100644
--- a/revision.c
+++ b/revision.c
@@ -823,6 +823,7 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
 
 static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what)
 {
+	int negate = *ptn == '!';
 	if (!revs->grep_filter) {
 		struct grep_opt *opt = xcalloc(1, sizeof(*opt));
 		opt->status_only = 1;
@@ -830,6 +831,13 @@ static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token
 		opt->regflags = REG_NEWLINE;
 		revs->grep_filter = opt;
 	}
+	if (negate) {
+		revs->grep_filter->extended = 1;
+		append_grep_pattern(revs->grep_filter, ptn,
+				"command line", 0, GREP_NOT_AT_ALL);
+	}
+	if (negate || ( *ptn == '\\' && ptn[1] == '!'))
+		ptn++;
 	append_grep_pattern(revs->grep_filter, ptn,
 			    "command line", 0, what);
 }
@@ -839,7 +847,10 @@ static void add_header_grep(struct rev_info *revs, const char *field, const char
 	char *pat;
 	const char *prefix;
 	int patlen, fldlen;
+	int negate = *pattern == '!';
 
+	if (negate || (*pattern == '\\' && pattern[1] == '!'))
+		pattern++;
 	fldlen = strlen(field);
 	patlen = strlen(pattern);
 	pat = xmalloc(patlen + fldlen + 10);
@@ -848,7 +859,7 @@ static void add_header_grep(struct rev_info *revs, const char *field, const char
 		prefix = "";
 		pattern++;
 	}
-	sprintf(pat, "^%s %s%s", field, prefix, pattern);
+	sprintf(pat, "%s^%s %s%s", negate ? "!" : "", field, prefix, pattern);
 	add_grep(revs, pat, GREP_PATTERN_HEAD);
 }
 

  reply	other threads:[~2007-07-08 14:29 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-07-07 15:30 [PATCH] revision: allow selection of commits that do not match a pattern Sven Verdoolaege
2007-07-07 16:27 ` Johannes Schindelin
2007-07-07 16:52   ` Sven Verdoolaege
2007-07-07 17:33     ` Johannes Schindelin
2007-07-07 18:42       ` Sven Verdoolaege
2007-07-07 19:35         ` Johannes Schindelin
2007-07-07 20:22           ` Sven Verdoolaege
2007-07-08 10:57           ` [PATCH v3] " Sven Verdoolaege
2007-07-08 14:22             ` Johannes Schindelin [this message]
2007-07-08 14:57               ` Sven Verdoolaege
2007-07-11 17:42             ` Jeff King

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=Pine.LNX.4.64.0707081519230.4248@racer.site \
    --to=johannes.schindelin@gmx.de \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=skimo@liacs.nl \
    /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 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 NNTP newsgroup(s).