mirror of
https://github.com/git/git.git
synced 2024-11-24 02:17:02 +08:00
get_sha1: support $commit^{/regex} syntax
This works like ":/regex" syntax that finds a recently created commit starting from all refs, but limits the discovery to those reachable from the named commit. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
84baa31bcb
commit
32574b68c5
@ -106,6 +106,12 @@ the `$GIT_DIR/refs` directory or from the `$GIT_DIR/packed-refs` file.
|
||||
and dereference the tag recursively until a non-tag object is
|
||||
found.
|
||||
|
||||
* A suffix '{caret}' to a revision parameter followed by a brace
|
||||
pair that contains a text led by a slash (e.g. `HEAD^{/fix nasty bug}`):
|
||||
this is the same as `:/fix nasty bug` syntax below except that
|
||||
it returns the youngest matching commit which is reachable from
|
||||
the ref before '{caret}'.
|
||||
|
||||
* A colon, followed by a slash, followed by a text (e.g. `:/fix nasty bug`): this names
|
||||
a commit whose commit message matches the specified regular expression.
|
||||
This name returns the youngest matching commit which is
|
||||
|
25
sha1_name.c
25
sha1_name.c
@ -7,6 +7,8 @@
|
||||
#include "refs.h"
|
||||
#include "remote.h"
|
||||
|
||||
static int get_sha1_oneline(const char *, unsigned char *, struct commit_list *);
|
||||
|
||||
static int find_short_object_filename(int len, const char *name, unsigned char *sha1)
|
||||
{
|
||||
struct alternate_object_database *alt;
|
||||
@ -562,6 +564,8 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
|
||||
expected_type = OBJ_BLOB;
|
||||
else if (sp[0] == '}')
|
||||
expected_type = OBJ_NONE;
|
||||
else if (sp[0] == '/')
|
||||
expected_type = OBJ_COMMIT;
|
||||
else
|
||||
return -1;
|
||||
|
||||
@ -576,19 +580,30 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
|
||||
if (!o || (!o->parsed && !parse_object(o->sha1)))
|
||||
return -1;
|
||||
hashcpy(sha1, o->sha1);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
|
||||
/*
|
||||
* At this point, the syntax look correct, so
|
||||
* if we do not get the needed object, we should
|
||||
* barf.
|
||||
*/
|
||||
o = peel_to_type(name, len, o, expected_type);
|
||||
if (o) {
|
||||
hashcpy(sha1, o->sha1);
|
||||
return 0;
|
||||
}
|
||||
if (!o)
|
||||
return -1;
|
||||
|
||||
hashcpy(sha1, o->sha1);
|
||||
if (sp[0] == '/') {
|
||||
/* "$commit^{/foo}" */
|
||||
char *prefix;
|
||||
int ret;
|
||||
struct commit_list *list = NULL;
|
||||
|
||||
prefix = xstrndup(sp + 1, name + len - 1 - (sp + 1));
|
||||
commit_list_insert((struct commit *)o, &list);
|
||||
ret = get_sha1_oneline(prefix, sha1, list);
|
||||
free(prefix);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
73
t/t1511-rev-parse-caret.sh
Executable file
73
t/t1511-rev-parse-caret.sh
Executable file
@ -0,0 +1,73 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='tests for ref^{stuff}'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'setup' '
|
||||
echo blob >a-blob &&
|
||||
git tag -a -m blob blob-tag `git hash-object -w a-blob`
|
||||
mkdir a-tree &&
|
||||
echo moreblobs >a-tree/another-blob &&
|
||||
git add . &&
|
||||
TREE_SHA1=`git write-tree` &&
|
||||
git tag -a -m tree tree-tag "$TREE_SHA1" &&
|
||||
git commit -m Initial &&
|
||||
git tag -a -m commit commit-tag &&
|
||||
git branch ref &&
|
||||
git checkout master &&
|
||||
echo modified >>a-blob &&
|
||||
git add -u &&
|
||||
git commit -m Modified
|
||||
'
|
||||
|
||||
test_expect_success 'ref^{non-existent}' '
|
||||
test_must_fail git rev-parse ref^{non-existent}
|
||||
'
|
||||
|
||||
test_expect_success 'ref^{}' '
|
||||
git rev-parse ref >expected &&
|
||||
git rev-parse ref^{} >actual &&
|
||||
test_cmp expected actual &&
|
||||
git rev-parse commit-tag^{} >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'ref^{commit}' '
|
||||
git rev-parse ref >expected &&
|
||||
git rev-parse ref^{commit} >actual &&
|
||||
test_cmp expected actual &&
|
||||
git rev-parse commit-tag^{commit} >actual &&
|
||||
test_cmp expected actual &&
|
||||
test_must_fail git rev-parse tree-tag^{commit} &&
|
||||
test_must_fail git rev-parse blob-tag^{commit}
|
||||
'
|
||||
|
||||
test_expect_success 'ref^{tree}' '
|
||||
echo $TREE_SHA1 >expected &&
|
||||
git rev-parse ref^{tree} >actual &&
|
||||
test_cmp expected actual &&
|
||||
git rev-parse commit-tag^{tree} >actual &&
|
||||
test_cmp expected actual &&
|
||||
git rev-parse tree-tag^{tree} >actual &&
|
||||
test_cmp expected actual &&
|
||||
test_must_fail git rev-parse blob-tag^{tree}
|
||||
'
|
||||
|
||||
test_expect_success 'ref^{/.}' '
|
||||
git rev-parse master >expected &&
|
||||
git rev-parse master^{/.} >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'ref^{/non-existent}' '
|
||||
test_must_fail git rev-parse master^{/non-existent}
|
||||
'
|
||||
|
||||
test_expect_success 'ref^{/Initial}' '
|
||||
git rev-parse ref >expected &&
|
||||
git rev-parse master^{/Initial} >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_done
|
Loading…
Reference in New Issue
Block a user