static 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 = 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; } 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; giterr_set(GITERR_REFERENCE, "Refspec '%s' not found.", spec); return GIT_ENOTFOUND; }
static int maybe_sha(git_object** out, git_repository *repo, const char *spec) { size_t speclen = strlen(spec); if (speclen != GIT_OID_HEXSZ) return GIT_ENOTFOUND; return maybe_sha_or_abbrev(out, repo, spec, speclen); }
static int maybe_describe(git_object**out, git_repository *repo, const char *spec) { const char *substr; int error; regex_t regex; substr = strstr(spec, "-g"); if (substr == NULL) return GIT_ENOTFOUND; if (build_regex(®ex, ".+-[0-9]+-g[0-9a-fA-F]+") < 0) return -1; error = regexec(®ex, spec, 0, NULL, 0); regfree(®ex); if (error) return GIT_ENOTFOUND; return maybe_sha_or_abbrev(out, repo, substr+2); }
static int maybe_abbrev(git_object** out, git_repository *repo, const char *spec) { size_t speclen = strlen(spec); return maybe_sha_or_abbrev(out, repo, spec, speclen); }
static int retrieve_previously_checked_out_branch_or_revision(git_object **out, git_reference **base_ref, git_repository *repo, const char *spec, const char *identifier, unsigned int position) { git_reference *ref = NULL; git_reflog *reflog = NULL; regex_t preg; int numentries, i, cur, error = -1; const git_reflog_entry *entry; const char *msg; regmatch_t regexmatches[2]; git_buf buf = GIT_BUF_INIT; cur = position; if (*identifier != '\0' || *base_ref != NULL) return revspec_error(spec); if (build_regex(&preg, "checkout: moving from (.*) to .*") < 0) return -1; if (git_reference_lookup(&ref, repo, GIT_HEAD_FILE) < 0) goto cleanup; if (git_reflog_read(&reflog, ref) < 0) goto cleanup; numentries = git_reflog_entrycount(reflog); for (i = numentries - 1; i >= 0; i--) { entry = git_reflog_entry_byindex(reflog, i); msg = git_reflog_entry_msg(entry); if (regexec(&preg, msg, 2, regexmatches, 0)) continue; cur--; if (cur > 0) continue; git_buf_put(&buf, msg+regexmatches[1].rm_so, regexmatches[1].rm_eo - regexmatches[1].rm_so); if ((error = disambiguate_refname(base_ref, repo, git_buf_cstr(&buf))) == 0) goto cleanup; if (error < 0 && error != GIT_ENOTFOUND) goto cleanup; error = maybe_sha_or_abbrev(out, repo, git_buf_cstr(&buf)); goto cleanup; } error = GIT_ENOTFOUND; cleanup: git_reference_free(ref); git_buf_free(&buf); regfree(&preg); git_reflog_free(reflog); return error; }