[PATCH 2/2] get_sha1: support ref^{/regex} syntax
This works like :/ syntax, but only limited to one ref.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
Documentation/revisions.txt | 7 +++++++
sha1_name.c | 26 ++++++++++++++++++++++----
2 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt
index 3d4b79c..fbe6245 100644
--- a/Documentation/revisions.txt
+++ b/Documentation/revisions.txt
@@ -106,6 +106,13 @@ 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 names a commit whose commit message matches the specified
+ regular expression. This name returns the youngest matching commit
+ which is reachable from the dereferenced commit. The leading '!'
+ in the text is treated especially like in `:/` syntax below.
+
* 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
diff --git a/sha1_name.c b/sha1_name.c
index f4ccdc5..00e52b0 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -527,6 +527,7 @@ struct object *peel_to_type(const char *name, int namelen,
}
}
+static int get_sha1_oneline(const char *, unsigned char *, struct commit_list *);
static int peel_onion(const char *name, int len, unsigned char *sha1)
{
unsigned char outer[20];
@@ -562,6 +563,11 @@ 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] == '/') {
+ if (sp[1] == '}')
+ return -1;
+ expected_type = OBJ_COMMIT;
+ }
else
return -1;
@@ -584,11 +590,23 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
* 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] == '/') { /* ^{/foo} */
+ struct commit_list *list = NULL;
+ char *prefix;
+ int ret;
+
+ commit_list_insert((struct commit *)o, &list);
+ prefix = xstrndup(sp + 1, name + len - 1 - (sp + 1));
+ ret = get_sha1_oneline(prefix, sha1, list);
+ free(prefix);
+ free_commit_list(list);
+ return ret;
}
- return -1;
+ return 0;
}
return 0;
}
--
1.7.3.2.316.gda8b3