Commit cf7dd05b by Patrick Steinhardt

refdb: return resolved symbolic refs pointing to nonexistent refs

In some cases, resolving references requires us to also know about the
final symbolic reference that's pointing to a nonexistent branch, e.g.
in an empty repository where the main branch is yet unborn but HEAD
already points to it. Right now, the resolving logic is thus split up
into two, where one is the new refdb implementation and the second one
is an ad-hoc implementation inside "refs.c".

Let's extend `git_refdb_resolve` to also return such final dangling
references pointing to nonexistent branches so we can deduplicate the
resolving logic.
parent c54f40e4
......@@ -161,8 +161,16 @@ int git_refdb_resolve(
if (ref->type == GIT_REFERENCE_DIRECT)
break;
if ((error = git_refdb_lookup(&resolved, db, git_reference_symbolic_target(ref))) < 0)
if ((error = git_refdb_lookup(&resolved, db, git_reference_symbolic_target(ref))) < 0) {
/* If we found a symbolic reference with a nonexistent target, return it. */
if (error == GIT_ENOTFOUND) {
error = 0;
*out = ref;
ref = NULL;
}
goto out;
}
git_reference_free(ref);
ref = resolved;
......
......@@ -30,6 +30,25 @@ int git_refdb_lookup(
git_refdb *refdb,
const char *ref_name);
/**
* Resolve the reference by following symbolic references.
*
* Given a reference name, this function will follow any symbolic references up
* to `max_nesting` deep and return the resolved direct reference. If any of
* the intermediate symbolic references points to a non-existing reference,
* then that symbolic reference is returned instead with an error code of `0`.
* If the given reference is a direct reference already, it is returned
* directly.
*
* If `max_nesting` is `0`, the reference will not be resolved. If it's
* negative, it will be set to the default resolve depth which is `5`.
*
* @param out Pointer to store the result in.
* @param db The refdb to use for resolving the reference.
* @param ref_name The reference name to lookup and resolve.
* @param max_nesting The maximum nesting depth.
* @return `0` on success, a negative error code otherwise.
*/
int git_refdb_resolve(
git_reference **out,
git_refdb *db,
......
......@@ -225,6 +225,18 @@ int git_reference_lookup_resolved(
(error = git_refdb_resolve(ref_out, refdb, normalized, max_nesting)) < 0)
return error;
/*
* The resolved reference may be a symbolic reference in case its
* target doesn't exist. If the user asked us to resolve (e.g.
* `max_nesting != 0`), then we need to return an error in case we got
* a symbolic reference back.
*/
if (max_nesting && git_reference_type(*ref_out) == GIT_REFERENCE_SYMBOLIC) {
git_reference_free(*ref_out);
*ref_out = NULL;
return GIT_ENOTFOUND;
}
return 0;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment