Re: [PATCH 1/4] magic pathspec: add tentative ":/path/from/top/level" pathspec support
From: Junio C Hamano <hidden>
Date: 2016-06-15 22:50:59
Junio C Hamano [off-list ref] writes:
This patch implements only "top" magic because it is the only kind of magic that can be hacked into the system without such a refactoring. Other types of magic that are envisioned (e.g. "icase") needs to be able to express more than what a simple string can encode and needs to wait.
Actually "icase" could be implemented inside get_pathspec() by doing something like the attached patch. But "noglob" needs support from the "struct pathspec_item" infrastructure. It is insufficient to parse the magic signature at get_pathspec() level, as I do not see a way to encode these magic in the match string. I suspect that Duy's favourite "negate" cannot be done if we discard the magic information at the get_pathspec() level, either. --- Documentation/glossary-content.txt | 7 +++++-- setup.c | 31 +++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
index e51d7e6..0ca029b 100644
--- a/Documentation/glossary-content.txt
+++ b/Documentation/glossary-content.txt@@ -319,10 +319,13 @@ top `/`;; The magic word `top` (mnemonic: `/`) makes the pattern match from the root of the working tree, even when you are running the command from inside a subdirectory. +icase;; + The magic word `icase` (there is no mnemonic for it) makes the + pattern match case insensitively. E.g. `:(icase)makefile` matches + both `Makefile` and `makefile`. -- + -Currently only the slash `/` is recognized as the "magic signature", -but it is envisioned that we will support more types of magic in later +It is envisioned that we will support more types of magic in later versions of git. [[def_parent]]parent::
diff --git a/setup.c b/setup.c
index 820ed05..e66ffbe 100644
--- a/setup.c
+++ b/setup.c@@ -136,12 +136,12 @@ void verify_non_filename(const char *prefix, const char *arg) * Possible future magic semantics include stuff like: * * { PATHSPEC_NOGLOB, '!', "noglob" }, - * { PATHSPEC_ICASE, '\0', "icase" }, * { PATHSPEC_RECURSIVE, '*', "recursive" }, * { PATHSPEC_REGEXP, '\0', "regexp" }, * */ #define PATHSPEC_FROMTOP (1<<0) +#define PATHSPEC_ICASE (1<<1) struct pathspec_magic { unsigned bit;
@@ -149,6 +149,7 @@ struct pathspec_magic { const char *name; } pathspec_magic[] = { { PATHSPEC_FROMTOP, '/', "top" }, + { PATHSPEC_ICASE, '\0', "icase" }, }; /*
@@ -168,7 +169,8 @@ const char *prefix_pathspec(const char *prefix, int prefixlen, const char *elt) { unsigned magic = 0; const char *copyfrom = elt; - int i; + const char *retval; + int i, free_source = 0; if (elt[0] != ':') { ; /* nothing to do */
@@ -215,10 +217,31 @@ const char *prefix_pathspec(const char *prefix, int prefixlen, const char *elt) copyfrom++; } + if (magic & PATHSPEC_ICASE) { + struct strbuf sb = STRBUF_INIT; + for (i = 0; copyfrom[i]; i++) { + int ch = copyfrom[i]; + if (('a' <= ch && ch <= 'z') || + ('A' <= ch && ch <= 'Z')) { + strbuf_addf(&sb, "[%c%c]", + tolower(ch), toupper(ch)); + } else { + strbuf_addch(&sb, ch); + } + } + if (sb.len) { + free_source = 1; + copyfrom = strbuf_detach(&sb, NULL); + } + } + if (magic & PATHSPEC_FROMTOP) - return xstrdup(copyfrom); + retval = xstrdup(copyfrom); else - return prefix_path(prefix, prefixlen, copyfrom); + retval = prefix_path(prefix, prefixlen, copyfrom); + if (free_source) + free((char *)copyfrom); + return retval; } const char **get_pathspec(const char *prefix, const char **pathspec)