@matheusbsbs / matheus-bagliano / commits / 32574b68c5
Fork 0

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>

Nguyễn Thái Ngọc Duy committed Dec 13, 2010 at 10:01 UTC 32574b68c57f3b34e58216a4c9c6d570d11ec47b
3 files changed +105 -11
Documentation/revisions.txt
+6
@@ -106,6 +106,12 @@ the `$GIT_DIR/refs` directory or from the `$GIT_DIR/packed-refs` file.
106 and dereference the tag recursively until a non-tag object is
107 found.
108
109 +* A suffix '{caret}' to a revision parameter followed by a brace
110 + pair that contains a text led by a slash (e.g. `HEAD^{/fix nasty bug}`):
111 + this is the same as `:/fix nasty bug` syntax below except that
112 + it returns the youngest matching commit which is reachable from
113 + the ref before '{caret}'.
114 +
115 * A colon, followed by a slash, followed by a text (e.g. `:/fix nasty bug`): this names
116 a commit whose commit message matches the specified regular expression.
117 This name returns the youngest matching commit which is
sha1_name.c
+26 -11
@@ -7,6 +7,8 @@
7 #include "refs.h"
8 #include "remote.h"
9
10 +static int get_sha1_oneline(const char *, unsigned char *, struct commit_list *);
11 +
12 static int find_short_object_filename(int len, const char *name, unsigned char *sha1)
13 {
14 struct alternate_object_database *alt;
@@ -562,6 +564,8 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
564 expected_type = OBJ_BLOB;
565 else if (sp[0] == '}')
566 expected_type = OBJ_NONE;
567 + else if (sp[0] == '/')
568 + expected_type = OBJ_COMMIT;
569 else
570 return -1;
571
@@ -576,19 +580,30 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
580 if (!o || (!o->parsed && !parse_object(o->sha1)))
581 return -1;
582 hashcpy(sha1, o->sha1);
583 + return 0;
584 }
580 - else {
581 - /*
582 - * At this point, the syntax look correct, so
583 - * if we do not get the needed object, we should
584 - * barf.
585 - */
586 - o = peel_to_type(name, len, o, expected_type);
587 - if (o) {
588 - hashcpy(sha1, o->sha1);
589 - return 0;
590 - }
585 +
586 + /*
587 + * At this point, the syntax look correct, so
588 + * if we do not get the needed object, we should
589 + * barf.
590 + */
591 + o = peel_to_type(name, len, o, expected_type);
592 + if (!o)
593 return -1;
594 +
595 + hashcpy(sha1, o->sha1);
596 + if (sp[0] == '/') {
597 + /* "$commit^{/foo}" */
598 + char *prefix;
599 + int ret;
600 + struct commit_list *list = NULL;
601 +
602 + prefix = xstrndup(sp + 1, name + len - 1 - (sp + 1));
603 + commit_list_insert((struct commit *)o, &list);
604 + ret = get_sha1_oneline(prefix, sha1, list);
605 + free(prefix);
606 + return ret;
607 }
608 return 0;
609 }
t/t1511-rev-parse-caret.sh new
+73
@@ -0,0 +1,73 @@
1 +#!/bin/sh
2 +
3 +test_description='tests for ref^{stuff}'
4 +
5 +. ./test-lib.sh
6 +
7 +test_expect_success 'setup' '
8 + echo blob >a-blob &&
9 + git tag -a -m blob blob-tag `git hash-object -w a-blob`
10 + mkdir a-tree &&
11 + echo moreblobs >a-tree/another-blob &&
12 + git add . &&
13 + TREE_SHA1=`git write-tree` &&
14 + git tag -a -m tree tree-tag "$TREE_SHA1" &&
15 + git commit -m Initial &&
16 + git tag -a -m commit commit-tag &&
17 + git branch ref &&
18 + git checkout master &&
19 + echo modified >>a-blob &&
20 + git add -u &&
21 + git commit -m Modified
22 +'
23 +
24 +test_expect_success 'ref^{non-existent}' '
25 + test_must_fail git rev-parse ref^{non-existent}
26 +'
27 +
28 +test_expect_success 'ref^{}' '
29 + git rev-parse ref >expected &&
30 + git rev-parse ref^{} >actual &&
31 + test_cmp expected actual &&
32 + git rev-parse commit-tag^{} >actual &&
33 + test_cmp expected actual
34 +'
35 +
36 +test_expect_success 'ref^{commit}' '
37 + git rev-parse ref >expected &&
38 + git rev-parse ref^{commit} >actual &&
39 + test_cmp expected actual &&
40 + git rev-parse commit-tag^{commit} >actual &&
41 + test_cmp expected actual &&
42 + test_must_fail git rev-parse tree-tag^{commit} &&
43 + test_must_fail git rev-parse blob-tag^{commit}
44 +'
45 +
46 +test_expect_success 'ref^{tree}' '
47 + echo $TREE_SHA1 >expected &&
48 + git rev-parse ref^{tree} >actual &&
49 + test_cmp expected actual &&
50 + git rev-parse commit-tag^{tree} >actual &&
51 + test_cmp expected actual &&
52 + git rev-parse tree-tag^{tree} >actual &&
53 + test_cmp expected actual &&
54 + test_must_fail git rev-parse blob-tag^{tree}
55 +'
56 +
57 +test_expect_success 'ref^{/.}' '
58 + git rev-parse master >expected &&
59 + git rev-parse master^{/.} >actual &&
60 + test_cmp expected actual
61 +'
62 +
63 +test_expect_success 'ref^{/non-existent}' '
64 + test_must_fail git rev-parse master^{/non-existent}
65 +'
66 +
67 +test_expect_success 'ref^{/Initial}' '
68 + git rev-parse ref >expected &&
69 + git rev-parse master^{/Initial} >actual &&
70 + test_cmp expected actual
71 +'
72 +
73 +test_done