[PATCH v1 40/45] parse_pathspec: preserve prefix length via PATHSPEC_PREFIX_ORIGIN

2013-03-15 Thread Nguyễn Thái Ngọc Duy
The prefix length is passed from one command to another via the new
magic 'prefix'. The magic is for parse_pathspec's internal use only,
not visible to parse_pathspec's callers.

Prefix length is not preserved across commands when --literal-pathspecs
is specified (no magic is allowed, including 'prefix'). That's OK
because we all paths are literal. No magic, no special treatment
regarding prefix. (This may be no longer true if we make :(glob)
default)

Other options to preserve the prefix include saving it to env variable
or quoting. Env var way (at least _one_ env var) is not suitable
because the prefix is not the same for all pathspecs. Pathspecs
starting with ../ will eat into the prefix part.

We could also preserve 'prefix' across commands is quote the prefix
part, then dequote on receiving. But it may not be 100% accurate, we
may dequote longer than the original prefix part, for example. That
may be good or not, but it's not the purpose.

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 pathspec.c | 41 -
 1 file changed, 36 insertions(+), 5 deletions(-)

diff --git a/pathspec.c b/pathspec.c
index bc27692..3291b58 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -92,9 +92,9 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
const char *elt)
 {
unsigned magic = 0, short_magic = 0;
-   const char *copyfrom = elt;
+   const char *copyfrom = elt, *long_magic_end = NULL;
char *match;
-   int i;
+   int i, pathspec_prefix = -1;
 
if (elt[0] != ':') {
; /* nothing to do */
@@ -111,18 +111,29 @@ static unsigned prefix_pathspec(struct pathspec_item 
*item,
nextat = copyfrom + len + 1;
if (!len)
continue;
-   for (i = 0; i  ARRAY_SIZE(pathspec_magic); i++)
+   for (i = 0; i  ARRAY_SIZE(pathspec_magic); i++) {
if (strlen(pathspec_magic[i].name) == len 
!strncmp(pathspec_magic[i].name, copyfrom, 
len)) {
magic |= pathspec_magic[i].bit;
break;
}
+   if (!prefixcmp(copyfrom, prefix:)) {
+   char *endptr;
+   pathspec_prefix = strtol(copyfrom + 7,
+endptr, 10);
+   if (endptr - copyfrom != len)
+   die(invalid parameter for 
pathspec magic 'prefix');
+   /* i would be wrong, but it does not 
matter */
+   break;
+   }
+   }
if (ARRAY_SIZE(pathspec_magic) = i)
die(_(Invalid pathspec magic '%.*s' in '%s'),
(int) len, copyfrom, elt);
}
if (*copyfrom != ')')
die(_(Missing ')' at the end of pathspec magic in 
'%s'), elt);
+   long_magic_end = copyfrom;
copyfrom++;
} else {
/* shorthand */
@@ -149,7 +160,14 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
magic |= short_magic;
*p_short_magic = short_magic;
 
-   if (magic  PATHSPEC_FROMTOP) {
+   if (pathspec_prefix = 0 
+   (prefixlen || (prefix  *prefix)))
+   die(BUG: 'prefix' magic is supposed to be used at worktree's 
root);
+
+   if (pathspec_prefix = 0) {
+   match = xstrdup(copyfrom);
+   prefixlen = pathspec_prefix;
+   } else if (magic  PATHSPEC_FROMTOP) {
match = xstrdup(copyfrom);
prefixlen = 0;
} else {
@@ -164,7 +182,20 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
 */
if (flags  PATHSPEC_PREFIX_ORIGIN) {
struct strbuf sb = STRBUF_INIT;
-   strbuf_add(sb, elt, copyfrom - elt);
+   const char *start = elt;
+   if (prefixlen  !limit_pathspec_to_literal()) {
+   /* Preserve the actual prefix length of each pattern */
+   if (long_magic_end) {
+   strbuf_add(sb, start, long_magic_end - start);
+   strbuf_addf(sb, ,prefix:%d, prefixlen);
+   start = long_magic_end;
+   } else {
+   if (*start == ':')
+   start++;
+   strbuf_addf(sb, :(prefix:%d), prefixlen);
+   }
+   }
+   

Re: [PATCH v1 40/45] parse_pathspec: preserve prefix length via PATHSPEC_PREFIX_ORIGIN

2013-03-15 Thread Eric Sunshine
On Fri, Mar 15, 2013 at 2:06 AM, Nguyễn Thái Ngọc Duy pclo...@gmail.com wrote:
 Prefix length is not preserved across commands when --literal-pathspecs
 is specified (no magic is allowed, including 'prefix'). That's OK
 because we all paths are literal. No magic, no special treatment

s/we all/we know all/
...or...
s/we all/all/

 We could also preserve 'prefix' across commands is quote the prefix
 part, then dequote on receiving. But it may not be 100% accurate, we

s/is quote/by quoting/
s/dequote/dequoting/

 may dequote longer than the original prefix part, for example. That
 may be good or not, but it's not the purpose.
--
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