Merge branch 'wp/sha1-name-negative-match'

A new "<branch>^{/!-<pattern>}" notation can be used to name a
commit that is reachable from <branch> that does not match the
given <pattern>.

* wp/sha1-name-negative-match:
  object name: introduce '^{/!-<negative pattern>}' notation
  test for '!' handling in rev-parse's named commits
maint
Junio C Hamano 2016-02-10 14:20:10 -08:00
commit fb795323ce
3 changed files with 73 additions and 11 deletions

View File

@ -176,11 +176,12 @@ existing tag object.
A colon, followed by a slash, followed by a text, names A colon, followed by a slash, followed by a text, names
a commit whose commit message matches the specified regular expression. a commit whose commit message matches the specified regular expression.
This name returns the youngest matching commit which is This name returns the youngest matching commit which is
reachable from any ref. If the commit message starts with a reachable from any ref. The regular expression can match any part of the
'!' you have to repeat that; the special sequence ':/!', commit message. To match messages starting with a string, one can use
followed by something else than '!', is reserved for now. e.g. ':/^foo'. The special sequence ':/!' is reserved for modifiers to what
The regular expression can match any part of the commit message. To is matched. ':/!-foo' performs a negative match, while ':/!!foo' matches a
match messages starting with a string, one can use e.g. ':/^foo'. literal '!' character, followed by 'foo'. Any other sequence beginning with
':/!' is reserved for now.


'<rev>:<path>', e.g. 'HEAD:README', ':README', 'master:./README':: '<rev>:<path>', e.g. 'HEAD:README', ':README', 'master:./README'::
A suffix ':' followed by a path names the blob or tree A suffix ':' followed by a path names the blob or tree

View 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 * through history and returning the first commit whose message starts
* the given regular expression. * the given regular expression.
* *
* For future extension, ':/!' is reserved. If you want to match a message * For negative-matching, prefix the pattern-part with '!-', like: ':/!-WIP'.
* beginning with a '!', you have to repeat the exclamation mark. *
* 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 */ /* 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; struct commit_list *backup = NULL, *l;
int found = 0; int found = 0;
int negative = 0;
regex_t regex; regex_t regex;


if (prefix[0] == '!') { if (prefix[0] == '!') {
if (prefix[1] != '!')
die ("Invalid search pattern: %s", prefix);
prefix++; prefix++;

if (prefix[0] == '-') {
prefix++;
negative = 1;
} else if (prefix[0] != '!') {
die ("Invalid search pattern: %s", prefix);
}
} }


if (regcomp(&regex, prefix, REG_EXTENDED)) if (regcomp(&regex, prefix, REG_EXTENDED))
@ -903,7 +913,7 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1,
continue; continue;
buf = get_commit_buffer(commit, NULL); buf = get_commit_buffer(commit, NULL);
p = strstr(buf, "\n\n"); 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); unuse_commit_buffer(commit, buf);


if (matches) { if (matches) {

View File

@ -18,7 +18,18 @@ test_expect_success 'setup' '
git checkout master && git checkout master &&
echo modified >>a-blob && echo modified >>a-blob &&
git add -u && 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}' ' test_expect_success 'ref^{non-existent}' '
@ -77,4 +88,44 @@ test_expect_success 'ref^{/Initial}' '
test_cmp expected actual 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 test_done