summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2020-06-30 09:35:21 +0200
committerPatrick Steinhardt <ps@pks.im>2020-07-12 16:01:21 +0200
commitb895547ca135158bf1582b50f6c09f8f78066e87 (patch)
treefa51c0a0a694fab55769126003a7596c205a3d23
parentcf7dd05bdab243e1150f771359be6c2a766a0a3a (diff)
downloadlibgit2-b895547ca135158bf1582b50f6c09f8f78066e87.tar.gz
refs: replace reimplementation of reference resolver
The refs code currently has a second implementation that resolves references in order to find any final symbolic reference pointing to a nonexistent target branch. As we've just extended `git_refdb_resolve` to also return such references, let's use that one instead in order to reduce code duplication.
-rw-r--r--src/refs.c67
1 files changed, 18 insertions, 49 deletions
diff --git a/src/refs.c b/src/refs.c
index ddbfd7e41..9ef167739 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -27,9 +27,6 @@
bool git_reference__enable_symbolic_ref_target_validation = true;
-#define DEFAULT_NESTING_LEVEL 5
-#define MAX_NESTING_LEVEL 10
-
enum {
GIT_PACKREF_HAS_PEEL = 1,
GIT_PACKREF_WAS_LOOSE = 2
@@ -1131,40 +1128,6 @@ int git_reference_cmp(
return git_oid__cmp(&ref1->target.oid, &ref2->target.oid);
}
-/**
- * Get the end of a chain of references. If the final one is not
- * found, we return the reference just before that.
- */
-static int get_terminal(git_reference **out, git_repository *repo, const char *ref_name, int nesting)
-{
- git_reference *ref;
- int error = 0;
-
- if (nesting > MAX_NESTING_LEVEL) {
- git_error_set(GIT_ERROR_REFERENCE, "reference chain too deep (%d)", nesting);
- return GIT_ENOTFOUND;
- }
-
- /* set to NULL to let the caller know that they're at the end of the chain */
- if ((error = git_reference_lookup(&ref, repo, ref_name)) < 0) {
- *out = NULL;
- return error;
- }
-
- if (git_reference_type(ref) == GIT_REFERENCE_DIRECT) {
- *out = ref;
- error = 0;
- } else {
- error = get_terminal(out, repo, git_reference_symbolic_target(ref), nesting + 1);
- if (error == GIT_ENOTFOUND && !*out)
- *out = ref;
- else
- git_reference_free(ref);
- }
-
- return error;
-}
-
/*
* Starting with the reference given by `ref_name`, follows symbolic
* references until a direct reference is found and updated the OID
@@ -1179,31 +1142,37 @@ int git_reference__update_terminal(
{
git_reference *ref = NULL, *ref2 = NULL;
git_signature *who = NULL;
+ git_refdb *refdb = NULL;
const git_signature *to_use;
int error = 0;
if (!sig && (error = git_reference__log_signature(&who, repo)) < 0)
- return error;
+ goto out;
to_use = sig ? sig : who;
- error = get_terminal(&ref, repo, ref_name, 0);
- /* found a dangling symref */
- if (error == GIT_ENOTFOUND && ref) {
- assert(git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC);
- git_error_clear();
+ if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
+ goto out;
+
+ if ((error = git_refdb_resolve(&ref, refdb, ref_name, -1)) < 0) {
+ if (error == GIT_ENOTFOUND) {
+ git_error_clear();
+ error = reference__create(&ref2, repo, ref_name, oid, NULL, 0, to_use,
+ log_message, NULL, NULL);
+ }
+ goto out;
+ }
+
+ /* In case the resolved reference is symbolic, then it's a dangling symref. */
+ if (git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC) {
error = reference__create(&ref2, repo, ref->target.symbolic, oid, NULL, 0, to_use,
log_message, NULL, NULL);
- } else if (error == GIT_ENOTFOUND) {
- git_error_clear();
- error = reference__create(&ref2, repo, ref_name, oid, NULL, 0, to_use,
- log_message, NULL, NULL);
- } else if (error == 0) {
- assert(git_reference_type(ref) == GIT_REFERENCE_DIRECT);
+ } else {
error = reference__create(&ref2, repo, ref->name, oid, NULL, 1, to_use,
log_message, &ref->target.oid, NULL);
}
+out:
git_reference_free(ref2);
git_reference_free(ref);
git_signature_free(who);