README.md: move down historical explanation about the name
[gitweb.git] / sha1_name.c
index 892db21813bc484628e940274e742d103629b0ed..89918ca158379a02368b0604b14465fa14855c8e 100644 (file)
@@ -848,8 +848,12 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned l
  * through history and returning the first commit whose message starts
  * the given regular expression.
  *
- * For future extension, ':/!' is reserved. If you want to match a message
- * beginning with a '!', you have to repeat the exclamation mark.
+ * For negative-matching, prefix the pattern-part with '!-', like: ':/!-WIP'.
+ *
+ * For a literal '!' character at the beginning of a pattern, you have to repeat
+ * that, like: ':/!!foo'
+ *
+ * For future extension, all other sequences beginning with ':/!' are reserved.
  */
 
 /* Remember to update object flag allocation in object.h */
@@ -878,12 +882,18 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1,
 {
        struct commit_list *backup = NULL, *l;
        int found = 0;
+       int negative = 0;
        regex_t regex;
 
        if (prefix[0] == '!') {
-               if (prefix[1] != '!')
-                       die ("Invalid search pattern: %s", prefix);
                prefix++;
+
+               if (prefix[0] == '-') {
+                       prefix++;
+                       negative = 1;
+               } else if (prefix[0] != '!') {
+                       die ("Invalid search pattern: %s", prefix);
+               }
        }
 
        if (regcomp(&regex, prefix, REG_EXTENDED))
@@ -903,7 +913,7 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1,
                        continue;
                buf = get_commit_buffer(commit, NULL);
                p = strstr(buf, "\n\n");
-               matches = p && !regexec(&regex, p + 2, 0, NULL, 0);
+               matches = negative ^ (p && !regexec(&regex, p + 2, 0, NULL, 0));
                unuse_commit_buffer(commit, buf);
 
                if (matches) {