Merge branch 'nd/negative-pathspec'
authorJunio C Hamano <gitster@pobox.com>
Fri, 10 Jan 2014 18:31:48 +0000 (10:31 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 10 Jan 2014 18:31:48 +0000 (10:31 -0800)
Introduce "negative pathspec" magic, to allow "git log -- . ':!dir'" to
tell us "I am interested in everything but 'dir' directory".

* nd/negative-pathspec:
pathspec.c: support adding prefix magic to a pathspec with mnemonic magic
Support pathspec magic :(exclude) and its short form :!
glossary-content.txt: rephrase magic signature part

1  2 
pathspec.c
diff --combined pathspec.c
index 52d38a4b4fb6cbb4928bf3084b773651f14d7e72,2b7f2e2e09cbaf742970e3e20b7eb9c491933c6f..6cb9fd3014a424d11647e48de3b841012ccc2ffe
@@@ -71,8 -71,23 +71,23 @@@ static struct pathspec_magic 
        { PATHSPEC_LITERAL,   0, "literal" },
        { PATHSPEC_GLOB,   '\0', "glob" },
        { PATHSPEC_ICASE,  '\0', "icase" },
+       { PATHSPEC_EXCLUDE, '!', "exclude" },
  };
  
+ static void prefix_short_magic(struct strbuf *sb, int prefixlen,
+                              unsigned short_magic)
+ {
+       int i;
+       strbuf_addstr(sb, ":(");
+       for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
+               if (short_magic & pathspec_magic[i].bit) {
+                       if (sb->buf[sb->len - 1] != '(')
+                               strbuf_addch(sb, ',');
+                       strbuf_addstr(sb, pathspec_magic[i].name);
+               }
+       strbuf_addf(sb, ",prefix:%d)", prefixlen);
+ }
  /*
   * Take an element of a pathspec and check for magic signatures.
   * Append the result to the prefix. Return the magic bitmap.
@@@ -154,7 -169,7 +169,7 @@@ static unsigned prefix_pathspec(struct 
                                        magic |= pathspec_magic[i].bit;
                                        break;
                                }
 -                              if (!prefixcmp(copyfrom, "prefix:")) {
 +                              if (starts_with(copyfrom, "prefix:")) {
                                        char *endptr;
                                        pathspec_prefix = strtol(copyfrom + 7,
                                                                 &endptr, 10);
         */
        if (flags & PATHSPEC_PREFIX_ORIGIN) {
                struct strbuf sb = STRBUF_INIT;
-               const char *start = elt;
                if (prefixlen && !literal_global) {
                        /* Preserve the actual prefix length of each pattern */
                        if (short_magic)
-                               die("BUG: prefixing on short magic is not supported");
+                               prefix_short_magic(&sb, prefixlen, short_magic);
                        else 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_add(&sb, elt, long_magic_end - elt);
+                               strbuf_addf(&sb, ",prefix:%d)", prefixlen);
+                       } else
                                strbuf_addf(&sb, ":(prefix:%d)", prefixlen);
-                       }
                }
-               strbuf_add(&sb, start, copyfrom - start);
                strbuf_addstr(&sb, match);
                item->original = strbuf_detach(&sb, NULL);
        } else
@@@ -355,7 -364,7 +364,7 @@@ void parse_pathspec(struct pathspec *pa
  {
        struct pathspec_item *item;
        const char *entry = argv ? *argv : NULL;
-       int i, n, prefixlen;
+       int i, n, prefixlen, nr_exclude = 0;
  
        memset(pathspec, 0, sizeof(*pathspec));
  
                if ((flags & PATHSPEC_LITERAL_PATH) &&
                    !(magic_mask & PATHSPEC_LITERAL))
                        item[i].magic |= PATHSPEC_LITERAL;
+               if (item[i].magic & PATHSPEC_EXCLUDE)
+                       nr_exclude++;
                if (item[i].magic & magic_mask)
                        unsupported_magic(entry,
                                          item[i].magic & magic_mask,
                pathspec->magic |= item[i].magic;
        }
  
+       if (nr_exclude == n)
+               die(_("There is nothing to exclude from by :(exclude) patterns.\n"
+                     "Perhaps you forgot to add either ':/' or '.' ?"));
  
        if (pathspec->magic & PATHSPEC_MAXDEPTH) {
                if (flags & PATHSPEC_KEEP_ORDER)