Skip to content

Commit

Permalink
Merge branch 'wp/sha1-name-negative-match' into pu
Browse files Browse the repository at this point in the history
Introduce "branch^{/!-<pattern>}" notation to name a commit
reachable from branch that does not match the given pattern.

* wp/sha1-name-negative-match:
  sha1_name.c: introduce '^{/!-<negative pattern>}' notation
  test for '!' handling in rev-parse's named commits
  • Loading branch information
gitster committed Aug 3, 2015
2 parents c652c24 + bfdf86e commit e09b75c
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 11 deletions.
11 changes: 6 additions & 5 deletions Documentation/revisions.txt
Expand Up @@ -176,11 +176,12 @@ existing tag object.
A colon, followed by a slash, followed by a text, names
a commit whose commit message matches the specified regular expression.
This name returns the youngest matching commit which is
reachable from any ref. If the commit message starts with a
'!' you have to repeat that; the special sequence ':/!',
followed by something else than '!', is reserved for now.
The regular expression can match any part of the commit message. To
match messages starting with a string, one can use e.g. ':/^foo'.
reachable from any ref. The regular expression can match any part of the
commit message. To match messages starting with a string, one can use
e.g. ':/^foo'. The special sequence ':/!' is reserved for modifiers to what
is matched. ':/!-foo' performs a negative match, while ':/!!foo' matches a
literal '!' character, followed by 'foo'. Any other sequence beginning with
':/!' is reserved for now.

'<rev>:<path>', e.g. 'HEAD:README', ':README', 'master:./README'::
A suffix ':' followed by a path names the blob or tree
Expand Down
20 changes: 15 additions & 5 deletions sha1_name.c
Expand Up @@ -838,8 +838,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 */
Expand Down Expand Up @@ -868,12 +872,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))
Expand All @@ -893,7 +903,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 = p && (negative ^ !regexec(&regex, p + 2, 0, NULL, 0));
unuse_commit_buffer(commit, buf);

if (matches) {
Expand Down
53 changes: 52 additions & 1 deletion t/t1511-rev-parse-caret.sh
Expand Up @@ -18,7 +18,18 @@ test_expect_success 'setup' '
git checkout master &&
echo modified >>a-blob &&
git add -u &&
git commit -m Modified
git commit -m Modified &&
git branch modref &&
echo changed! >>a-blob &&
git add -u &&
git commit -m !Exp &&
git branch expref &&
echo changed >>a-blob &&
git add -u &&
git commit -m Changed &&
echo changed-again >>a-blob &&
git add -u &&
git commit -m Changed-again
'

test_expect_success 'ref^{non-existent}' '
Expand Down Expand Up @@ -77,4 +88,44 @@ test_expect_success 'ref^{/Initial}' '
test_cmp expected actual
'

test_expect_success 'ref^{/!Exp}' '
test_must_fail git rev-parse master^{/!Exp}
'

test_expect_success 'ref^{/!}' '
test_must_fail git rev-parse master^{/!}
'

test_expect_success 'ref^{/!!Exp}' '
git rev-parse expref >expected &&
git rev-parse master^{/!!Exp} >actual &&
test_cmp expected actual
'

test_expect_success 'ref^{/!-}' '
test_must_fail git rev-parse master^{/!-}
'

test_expect_success 'ref^{/!-.}' '
test_must_fail git rev-parse master^{/!-.}
'

test_expect_success 'ref^{/!-non-existent}' '
git rev-parse master >expected &&
git rev-parse master^{/!-non-existent} >actual &&
test_cmp expected actual
'

test_expect_success 'ref^{/!-Changed}' '
git rev-parse expref >expected &&
git rev-parse master^{/!-Changed} >actual &&
test_cmp expected actual
'

test_expect_success 'ref^{/!-!Exp}' '
git rev-parse modref >expected &&
git rev-parse expref^{/!-!Exp} >actual &&
test_cmp expected actual
'

test_done

0 comments on commit e09b75c

Please sign in to comment.