Re: [PATCH 2/4] add -u: get rid of "treewideupdate" configuration

Subsystems: the rest

5 messages, 2 authors, 2016-06-15 · open the first message on its own page

Re: [PATCH 2/4] add -u: get rid of "treewideupdate" configuration

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:51:00

Junio C Hamano [off-list ref] writes:
Jeff King [off-list ref] writes:
quoted
... I thought there was interest in full-tree grep
(OK, _I_ had some interst in it).  But the same transition pain
arguments apply there, and we should be able to do "git grep pattern :/"
soon, right?
I never tested it myself, but the earlier "support :/ at a wrong level
get_pathspec()" patch should take care of "git grep" as well.  It is
equivalent to the "alternative approach" Michael posted as RFC as a
follow-up to his earlier "grep --full-tree" thread.
It appears that we might want to further tweak the code that tries to
disambiguate between revs and paths (we error out when argv[i] does not
name a rev and lstat(argv[i]) fails), but other than that, this command
sequence

    $ cd Documentation
    $ git grep -e purple -- :

seems to hit ../contrib/emacs/git.el and ../gitk-git/gitk correctly.

Of course, from the same directory:

    $ git grep -e purple -- :/*.el

hits ../contrib/emacs/git.el as expected.

The following patch will apply on top of 8a42c98 (magic pathspec: add
tentative ":/path/from/top/level" pathspec support, 2011-04-06).

Per our discussion, I think 'add -u' migration topics should be scrapped
for now, and rethought after giving time for people to get familiar with
the new :/ facility.

Thanks.

-- >8 --
Subject: [PATCH] magic pathspec: futureproof shorthand form

The earlier design was to take whatever non-alnum that the short format
parser happens to support, leaving the rest as part of the pattern, so a
version of git that knows '*' magic and a version that does not would have
behaved differently when given ":*Makefile".  The former would have
applied the '*' magic to the pattern "Makefile", while the latter would
used no magic to the pattern "*Makefile".

Instead, just reserve all non-alnum ASCII letters that are neither glob
nor regexp special as potential magic signature, and when we see a magic
that is not supported, die with an error message, just like the longhand
codepath does.

With this, ":%#!*Makefile" will always mean "%#!" magic applied to the
pattern "*Makefile", no matter what version of git is used (it is a
different matter if the version of git supports all of these three magic
matching rules).

Also make ':' without anything else to mean "there is no pathspec".  This
would allow differences between "git log" and "git log ." run from the top
level of the working tree (the latter simplifies no-op commits away from
the history) to be expressed from a subdirectory by saying "git log :".

Helped-by: Nguyễn Thái Ngọc Duy [off-list ref]
Signed-off-by: Junio C Hamano <redacted>
---
 ctype.c           |   15 ++++++++-------
 git-compat-util.h |    2 ++
 setup.c           |    9 ++++++++-
 3 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/ctype.c b/ctype.c
index de60027..b5d856f 100644
--- a/ctype.c
+++ b/ctype.c
@@ -10,17 +10,18 @@ enum {
 	A = GIT_ALPHA,
 	D = GIT_DIGIT,
 	G = GIT_GLOB_SPECIAL,	/* *, ?, [, \\ */
-	R = GIT_REGEX_SPECIAL	/* $, (, ), +, ., ^, {, | */
+	R = GIT_REGEX_SPECIAL,	/* $, (, ), +, ., ^, {, | */
+	P = GIT_PATHSPEC_MAGIC  /* other non-alnum, except for ] and } */
 };
 
 unsigned char sane_ctype[256] = {
 	0, 0, 0, 0, 0, 0, 0, 0, 0, S, S, 0, 0, S, 0, 0,		/*   0.. 15 */
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,		/*  16.. 31 */
-	S, 0, 0, 0, R, 0, 0, 0, R, R, G, R, 0, 0, R, 0,		/*  32.. 47 */
-	D, D, D, D, D, D, D, D, D, D, 0, 0, 0, 0, 0, G,		/*  48.. 63 */
-	0, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A,		/*  64.. 79 */
-	A, A, A, A, A, A, A, A, A, A, A, G, G, 0, R, 0,		/*  80.. 95 */
-	0, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A,		/*  96..111 */
-	A, A, A, A, A, A, A, A, A, A, A, R, R, 0, 0, 0,		/* 112..127 */
+	S, P, P, P, R, P, P, P, R, R, G, R, P, P, R, P,		/*  32.. 47 */
+	D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, G,		/*  48.. 63 */
+	P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A,		/*  64.. 79 */
+	A, A, A, A, A, A, A, A, A, A, A, G, G, 0, R, P,		/*  80.. 95 */
+	P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A,		/*  96..111 */
+	A, A, A, A, A, A, A, A, A, A, A, R, R, 0, P, 0,		/* 112..127 */
 	/* Nothing in the 128.. range */
 };
diff --git a/git-compat-util.h b/git-compat-util.h
index 49b50ee..d88cf8a 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -462,6 +462,7 @@ extern unsigned char sane_ctype[256];
 #define GIT_ALPHA 0x04
 #define GIT_GLOB_SPECIAL 0x08
 #define GIT_REGEX_SPECIAL 0x10
+#define GIT_PATHSPEC_MAGIC 0x20
 #define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
 #define isascii(x) (((x) & ~0x7f) == 0)
 #define isspace(x) sane_istest(x,GIT_SPACE)
@@ -472,6 +473,7 @@ extern unsigned char sane_ctype[256];
 #define is_regex_special(x) sane_istest(x,GIT_GLOB_SPECIAL | GIT_REGEX_SPECIAL)
 #define tolower(x) sane_case((unsigned char)(x), 0x20)
 #define toupper(x) sane_case((unsigned char)(x), 0)
+#define is_pathspec_magic(x) sane_istest(x,GIT_PATHSPEC_MAGIC)
 
 static inline int sane_case(int x, int high)
 {
diff --git a/setup.c b/setup.c
index 820ed05..5048252 100644
--- a/setup.c
+++ b/setup.c
@@ -197,19 +197,26 @@ const char *prefix_pathspec(const char *prefix, int prefixlen, const char *elt)
 		}
 		if (*copyfrom == ')')
 			copyfrom++;
+	} else if (!elt[1]) {
+		/* Just ':' -- no element! */
+		return NULL;
 	} else {
 		/* shorthand */
 		for (copyfrom = elt + 1;
 		     *copyfrom && *copyfrom != ':';
 		     copyfrom++) {
 			char ch = *copyfrom;
+
+			if (!is_pathspec_magic(ch))
+				break;
 			for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
 				if (pathspec_magic[i].mnemonic == ch) {
 					magic |= pathspec_magic[i].bit;
 					break;
 				}
 			if (ARRAY_SIZE(pathspec_magic) <= i)
-				break;
+				die("Unimplemented pathspec magic '%c' in '%s'",
+				    ch, elt);
 		}
 		if (*copyfrom == ':')
 			copyfrom++;
-- 
1.7.5.rc1

Re: [PATCH 2/4] add -u: get rid of "treewideupdate" configuration

From: Nguyen Thai Ngoc Duy <hidden>
Date: 2016-06-15 22:51:00

On Fri, Apr 08, 2011 at 04:18:46PM -0700, Junio C Hamano wrote:
It appears that we might want to further tweak the code that tries to
disambiguate between revs and paths (we error out when argv[i] does not
name a rev and lstat(argv[i]) fails)
Something like below? The additional goodness is, instead of writing

git grep foo -- '*.a'

I can now write a shorter version

git grep foo :./*.a

Perhaps we can use the first pathspec with magic as a mark of
pathspec arguments, equivalent to "--"

--8<--
diff --git a/setup.c b/setup.c
index 03cd84f..a00a23f 100644
--- a/setup.c
+++ b/setup.c
@@ -73,6 +73,8 @@ int check_filename(const char *prefix, const char *arg)
 	const char *name;
 	struct stat st;
 
+	if (*arg == ':')	/* pathspec magic */
+		return 1;
 	name = prefix ? prefix_filename(prefix, strlen(prefix), arg) : arg;
 	if (!lstat(name, &st))
 		return 1; /* file exists */
--8<--
-- 
Duy

Re: [PATCH 2/4] add -u: get rid of "treewideupdate" configuration

From: Nguyen Thai Ngoc Duy <hidden>
Date: 2016-06-15 22:51:00

On Sat, Apr 9, 2011 at 6:18 AM, Junio C Hamano [off-list ref] wrote:
Also make ':' without anything else to mean "there is no pathspec".  This
would allow differences between "git log" and "git log ." run from the top
level of the working tree (the latter simplifies no-op commits away from
the history) to be expressed from a subdirectory by saying "git log :".
The intention is good, but reality may need more work. I assume that
"git add -u :" is equivalent to "git add -u" (or "git add -u ." to be
precise). Unfortunately, cmd_add() checks argc for no arguments to
turn "add -u <nothing>" to "add -u .", not the result from
get_pathspec(). It can be fixed. Just heads up as there can be similar
traps elsewhere.
-- 
Duy

Re: [PATCH 2/4] add -u: get rid of "treewideupdate" configuration

From: Nguyen Thai Ngoc Duy <hidden>
Date: 2016-06-15 22:51:00

On Sat, Apr 9, 2011 at 11:58 AM, Nguyen Thai Ngoc Duy [off-list ref] wrote:
On Sat, Apr 9, 2011 at 6:18 AM, Junio C Hamano [off-list ref] wrote:
quoted
Also make ':' without anything else to mean "there is no pathspec".  This
would allow differences between "git log" and "git log ." run from the top
level of the working tree (the latter simplifies no-op commits away from
the history) to be expressed from a subdirectory by saying "git log :".
The intention is good, but reality may need more work.
Wait, what if I say "git grep -- : foo : bar"? I take it we should
reject on this case?
-- 
Duy

Re: [PATCH 2/4] add -u: get rid of "treewideupdate" configuration

From: Nguyen Thai Ngoc Duy <hidden>
Date: 2016-06-15 22:51:08

On Sat, Apr 9, 2011 at 6:18 AM, Junio C Hamano [off-list ref] wrote:
Subject: [PATCH] magic pathspec: futureproof shorthand form

...

Also make ':' without anything else to mean "there is no pathspec".  This
would allow differences between "git log" and "git log ." run from the top
level of the working tree (the latter simplifies no-op commits away from
the history) to be expressed from a subdirectory by saying "git log :".
I need someone to enlighten me again. Why do we need ":" for "no
pathspec" when we can simply specify no pathspec for the same effect?

"git log" and "git log ." at top worktree are not different because
any changes in the tree will make top tree object different, hence no
pruning (unless someone commits the same tree, which is really rare).
So

 - "git log" in subdirectory is exactly the same as "git log" at top.
 - "git log :/" in subdir can do whatever "git log ." at top can.
 - "git log ." in subdir will prune commits that does not change
subdir (current behavior)

I don't (or no longer) see the point of reserving ":" for "no pathspec".
-- 
Duy
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help