diff options
| author | Ben Straub <bstraub@github.com> | 2012-06-01 14:18:52 -0700 |
|---|---|---|
| committer | Ben Straub <bstraub@github.com> | 2012-06-01 14:18:52 -0700 |
| commit | 734efe4b8e8f6cfc820c7f88b3fb4e4221cec0ab (patch) | |
| tree | 6b8a9e46d87f89a0ee14dab4791d897fb3d0f37d /src/revparse.c | |
| parent | 2497106f91f1eea363c173a53b17416e3191c9d7 (diff) | |
| download | libgit2-734efe4b8e8f6cfc820c7f88b3fb4e4221cec0ab.tar.gz | |
Rev-parse: implement ":/foo" syntax.
Diffstat (limited to 'src/revparse.c')
| -rw-r--r-- | src/revparse.c | 52 |
1 files changed, 47 insertions, 5 deletions
diff --git a/src/revparse.c b/src/revparse.c index 60e819c00..6d88a1d38 100644 --- a/src/revparse.c +++ b/src/revparse.c @@ -432,9 +432,6 @@ static int handle_caret_syntax(git_object **out, git_repository *repo, git_objec } else { while(!git_revwalk_next(&oid, walk)) { git_object *walkobj; - char str[41]; - git_oid_fmt(str, &oid); - str[40] = 0; /* Fetch the commit object, and check for matches in the message */ if (!git_object_lookup(&walkobj, repo, &oid, GIT_OBJ_COMMIT)) { @@ -580,6 +577,49 @@ static int handle_colon_syntax(git_object **out, return git_tree_entry_2object(out, repo, entry); } +static int git__revparse_global_grep(git_object **out, git_repository *repo, const char *pattern) +{ + git_revwalk *walk; + int retcode = GIT_ERROR; + + if (!git_revwalk_new(&walk, repo)) { + regex_t preg; + int reg_error; + git_oid oid; + + git_revwalk_sorting(walk, GIT_SORT_TIME); + git_revwalk_push_glob(walk, "refs/heads/*"); + + reg_error = regcomp(&preg, pattern, REG_EXTENDED); + if (reg_error != 0) { + giterr_set_regex(&preg, reg_error); + } else { + git_object *walkobj = NULL, *resultobj = NULL; + while(!git_revwalk_next(&oid, walk)) { + /* Fetch the commit object, and check for matches in the message */ + if (walkobj != resultobj) git_object_free(walkobj); + if (!git_object_lookup(&walkobj, repo, &oid, GIT_OBJ_COMMIT)) { + if (!regexec(&preg, git_commit_message((git_commit*)walkobj), 0, NULL, 0)) { + /* Match! */ + resultobj = walkobj; + retcode = 0; + break; + } + } + } + if (!resultobj) { + giterr_set(GITERR_REFERENCE, "Couldn't find a match for %s", pattern); + } else { + *out = resultobj; + } + regfree(&preg); + git_revwalk_free(walk); + } + } + + return retcode; +} + int git_revparse_single(git_object **out, git_repository *repo, const char *spec) { revparse_state current_state = REVPARSE_STATE_INIT, next_state = REVPARSE_STATE_INIT; @@ -591,8 +631,10 @@ int git_revparse_single(git_object **out, git_repository *repo, const char *spec assert(out && repo && spec); if (spec[0] == ':') { - /* Either a global grep (":/foo") or a merge-stage path lookup (":2:Makefile"). - Neither of these are handled just yet. */ + if (spec[1] == '/') { + return git__revparse_global_grep(out, repo, spec+2); + } + /* TODO: support merge-stage path lookup (":2:Makefile"). */ giterr_set(GITERR_INVALID, "Unimplemented"); return GIT_ERROR; } |
