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 */
nextat = copyfrom + len;
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 */
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 {
*/
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);
+ }
+ }
+ strbuf_add(&sb, start, copyfrom - start);
strbuf_addstr(&sb, match);
item->original = strbuf_detach(&sb, NULL);
} else