summaryrefslogtreecommitdiff
path: root/sha1_name.c
diff options
context:
space:
mode:
authorWill Palmer <wmpalmer@gmail.com>2016-01-31 00:06:01 (GMT)
committerJunio C Hamano <gitster@pobox.com>2016-02-01 21:40:37 (GMT)
commit0769854f3db2c09c8b5993ea023ea07ddc1eb6eb (patch)
tree335f735c80d71a956c2ae4e46127043cd66315bf /sha1_name.c
parent06b6b68ff943de9e5c2f537807c054cd536731d1 (diff)
downloadgit-0769854f3db2c09c8b5993ea023ea07ddc1eb6eb.zip
git-0769854f3db2c09c8b5993ea023ea07ddc1eb6eb.tar.gz
git-0769854f3db2c09c8b5993ea023ea07ddc1eb6eb.tar.bz2
object name: introduce '^{/!-<negative pattern>}' notation
To name a commit, you can now use the :/!-<negative pattern> regex style, and consequentially, say $ git rev-parse HEAD^{/!-foo} and it will return the hash of the first commit reachable from HEAD, whose commit message does not contain "foo". This is the opposite of the existing <rev>^{/<pattern>} syntax. The specific use-case this is intended for is to perform an operation, excluding the most-recent commits containing a particular marker. For example, if you tend to make "work in progress" commits, with messages beginning with "WIP", you work, then it could be useful to diff against "the most recent commit which was not a WIP commit". That sort of thing now possible, via commands such as: $ git diff @^{/!-^WIP} The leader '/!-', rather than simply '/!', to denote a negative match, is chosen to leave room for additional modifiers in the future. Signed-off-by: Will Palmer <wmpalmer@gmail.com> Signed-off-by: Stephen P. Smith <ischis2@cox.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'sha1_name.c')
-rw-r--r--sha1_name.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/sha1_name.c b/sha1_name.c
index 6d10f05..fc5c60d 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -824,8 +824,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 */
@@ -854,12 +858,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))
@@ -879,7 +889,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) {