revparse: unfound reference return ENOTFOUND
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
diff --git a/src/revparse.c b/src/revparse.c
index 3194cc4..f9859b1 100644
--- a/src/revparse.c
+++ b/src/revparse.c
@@ -47,8 +47,9 @@ static int spec_looks_like_describe_output(const char *spec)
regex_error = regcomp(®ex, ".+-[0-9]+-g[0-9a-fA-F]+", REG_EXTENDED);
if (regex_error != 0) {
giterr_set_regex(®ex, regex_error);
- return 1; /* To be safe */
+ return regex_error;
}
+
retcode = regexec(®ex, spec, 0, NULL, 0);
regfree(®ex);
return retcode == 0;
@@ -103,39 +104,66 @@ cleanup:
return error;
}
-static int revparse_lookup_object(git_object **out, git_repository *repo, const char *spec)
+extern int revparse_lookup_object(git_object **out, git_repository *repo, const char *spec);
+
+static int maybe_describe(git_object**out, git_repository *repo, const char *spec)
{
- size_t speclen = strlen(spec);
- git_object *obj = NULL;
- git_oid oid;
- int error;
- git_reference *ref;
const char *substr;
+ int match;
/* "git describe" output; snip everything before/including "-g" */
substr = strstr(spec, "-g");
- if (substr &&
- spec_looks_like_describe_output(spec) &&
- !revparse_lookup_object(out, repo, substr+2)) {
- return 0;
- }
- /* SHA or prefix */
- if (!git_oid_fromstrn(&oid, spec, speclen)) {
- if (!git_object_lookup_prefix(&obj, repo, &oid, speclen, GIT_OBJ_ANY)) {
- *out = obj;
- return 0;
- }
- }
+ if (substr == NULL)
+ return GIT_ENOTFOUND;
+
+ if ((match = spec_looks_like_describe_output(spec)) < 0)
+ return match;
+
+ if (!match)
+ return GIT_ENOTFOUND;
+
+ return revparse_lookup_object(out, repo, substr+2);
+}
+
+static int maybe_sha_or_abbrev(git_object**out, git_repository *repo, const char *spec)
+{
+ git_oid oid;
+ size_t speclen = strlen(spec);
+
+ if (git_oid_fromstrn(&oid, spec, speclen) < 0)
+ return GIT_ENOTFOUND;
+
+ return git_object_lookup_prefix(out, repo, &oid, speclen, GIT_OBJ_ANY);
+}
+
+int revparse_lookup_object(git_object **out, git_repository *repo, const char *spec)
+{
+ int error;
+ git_reference *ref;
+
+ error = maybe_describe(out, repo, spec);
+ if (!error)
+ return 0;
+
+ if (error < 0 && error != GIT_ENOTFOUND)
+ return error;
+
+ error = maybe_sha_or_abbrev(out, repo, spec);
+ if (!error)
+ return 0;
+
+ if (error < 0 && error != GIT_ENOTFOUND)
+ return error;
error = disambiguate_refname(&ref, repo, spec);
if (!error) {
error = git_object_lookup(out, repo, git_reference_oid(ref), GIT_OBJ_ANY);
git_reference_free(ref);
- return error;
+ return 0;
}
- if (error < 0)
+ if (error < 0 && error != GIT_ENOTFOUND)
return error;
giterr_set(GITERR_REFERENCE, "Refspec '%s' not found.", spec);
@@ -711,10 +739,8 @@ int git_revparse_single(git_object **out, git_repository *repo, const char *spec
if (current_state != next_state && next_state != REVPARSE_STATE_DONE) {
/* Leaving INIT state, find the object specified, in case that state needs it */
- if (revparse_lookup_object(&next_obj, repo, git_buf_cstr(&specbuffer)) < 0) {
- retcode = GIT_ERROR;
+ if ((retcode = revparse_lookup_object(&next_obj, repo, git_buf_cstr(&specbuffer))) < 0)
next_state = REVPARSE_STATE_DONE;
- }
}
break;
diff --git a/tests-clar/refs/revparse.c b/tests-clar/refs/revparse.c
index 31029f7..dbc002d 100644
--- a/tests-clar/refs/revparse.c
+++ b/tests-clar/refs/revparse.c
@@ -55,6 +55,8 @@ void test_refs_revparse__cleanup(void)
void test_refs_revparse__nonexistant_object(void)
{
test_object("this-does-not-exist", NULL);
+ test_object("this-does-not-exist^1", NULL);
+ test_object("this-does-not-exist~2", NULL);
}
void test_refs_revparse__invalid_reference_name(void)