Skip to content

Commit 233c3e6

Browse files
pcloudsgitster
authored andcommitted
parse_pathspec: preserve prefix length via PATHSPEC_PREFIX_ORIGIN
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 know 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 by quoting the prefix part, then dequoting 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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 645a29c commit 233c3e6

File tree

1 file changed

+36
-5
lines changed

1 file changed

+36
-5
lines changed

pathspec.c

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
9292
const char *elt)
9393
{
9494
unsigned magic = 0, short_magic = 0;
95-
const char *copyfrom = elt;
95+
const char *copyfrom = elt, *long_magic_end = NULL;
9696
char *match;
97-
int i;
97+
int i, pathspec_prefix = -1;
9898

9999
if (elt[0] != ':') {
100100
; /* nothing to do */
@@ -112,18 +112,29 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
112112
nextat = copyfrom + len;
113113
if (!len)
114114
continue;
115-
for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
115+
for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++) {
116116
if (strlen(pathspec_magic[i].name) == len &&
117117
!strncmp(pathspec_magic[i].name, copyfrom, len)) {
118118
magic |= pathspec_magic[i].bit;
119119
break;
120120
}
121+
if (!prefixcmp(copyfrom, "prefix:")) {
122+
char *endptr;
123+
pathspec_prefix = strtol(copyfrom + 7,
124+
&endptr, 10);
125+
if (endptr - copyfrom != len)
126+
die(_("invalid parameter for pathspec magic 'prefix'"));
127+
/* "i" would be wrong, but it does not matter */
128+
break;
129+
}
130+
}
121131
if (ARRAY_SIZE(pathspec_magic) <= i)
122132
die(_("Invalid pathspec magic '%.*s' in '%s'"),
123133
(int) len, copyfrom, elt);
124134
}
125135
if (*copyfrom != ')')
126136
die(_("Missing ')' at the end of pathspec magic in '%s'"), elt);
137+
long_magic_end = copyfrom;
127138
copyfrom++;
128139
} else {
129140
/* shorthand */
@@ -150,7 +161,14 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
150161
magic |= short_magic;
151162
*p_short_magic = short_magic;
152163

153-
if (magic & PATHSPEC_FROMTOP) {
164+
if (pathspec_prefix >= 0 &&
165+
(prefixlen || (prefix && *prefix)))
166+
die("BUG: 'prefix' magic is supposed to be used at worktree's root");
167+
168+
if (pathspec_prefix >= 0) {
169+
match = xstrdup(copyfrom);
170+
prefixlen = pathspec_prefix;
171+
} else if (magic & PATHSPEC_FROMTOP) {
154172
match = xstrdup(copyfrom);
155173
prefixlen = 0;
156174
} else {
@@ -165,7 +183,20 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
165183
*/
166184
if (flags & PATHSPEC_PREFIX_ORIGIN) {
167185
struct strbuf sb = STRBUF_INIT;
168-
strbuf_add(&sb, elt, copyfrom - elt);
186+
const char *start = elt;
187+
if (prefixlen && !limit_pathspec_to_literal()) {
188+
/* Preserve the actual prefix length of each pattern */
189+
if (long_magic_end) {
190+
strbuf_add(&sb, start, long_magic_end - start);
191+
strbuf_addf(&sb, ",prefix:%d", prefixlen);
192+
start = long_magic_end;
193+
} else {
194+
if (*start == ':')
195+
start++;
196+
strbuf_addf(&sb, ":(prefix:%d)", prefixlen);
197+
}
198+
}
199+
strbuf_add(&sb, start, copyfrom - start);
169200
strbuf_addstr(&sb, match);
170201
item->original = strbuf_detach(&sb, NULL);
171202
} else

0 commit comments

Comments
 (0)