diff options
author | Patrick Steinhardt <ps@pks.im> | 2020-06-30 09:35:21 +0200 |
---|---|---|
committer | Patrick Steinhardt <ps@pks.im> | 2020-07-12 16:01:21 +0200 |
commit | b895547ca135158bf1582b50f6c09f8f78066e87 (patch) | |
tree | fa51c0a0a694fab55769126003a7596c205a3d23 | |
parent | cf7dd05bdab243e1150f771359be6c2a766a0a3a (diff) | |
download | libgit2-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.c | 67 |
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); |