Commit c54f40e4 by Patrick Steinhardt

refs: move resolving of references into the refdb

Resolving of symbolic references is currently implemented inside the
"refs" layer. As a result, it's hard to call this function from
low-level parts that only have a refdb available, but no repository, as
the "refs" layer always operates on the repository-level. So let's move
the function into the generic "refdb" implementation to lift this
restriction.
parent 9703d26f
......@@ -17,6 +17,9 @@
#include "reflog.h"
#include "posix.h"
#define DEFAULT_NESTING_LEVEL 5
#define MAX_NESTING_LEVEL 10
int git_refdb_new(git_refdb **out, git_repository *repo)
{
git_refdb *db;
......@@ -134,6 +137,51 @@ int git_refdb_lookup(git_reference **out, git_refdb *db, const char *ref_name)
return 0;
}
int git_refdb_resolve(
git_reference **out,
git_refdb *db,
const char *ref_name,
int max_nesting)
{
git_reference *ref = NULL;
int error = 0, nesting;
*out = NULL;
if (max_nesting > MAX_NESTING_LEVEL)
max_nesting = MAX_NESTING_LEVEL;
else if (max_nesting < 0)
max_nesting = DEFAULT_NESTING_LEVEL;
if ((error = git_refdb_lookup(&ref, db, ref_name)) < 0)
goto out;
for (nesting = 0; nesting < max_nesting; nesting++) {
git_reference *resolved;
if (ref->type == GIT_REFERENCE_DIRECT)
break;
if ((error = git_refdb_lookup(&resolved, db, git_reference_symbolic_target(ref))) < 0)
goto out;
git_reference_free(ref);
ref = resolved;
}
if (ref->type != GIT_REFERENCE_DIRECT && max_nesting != 0) {
git_error_set(GIT_ERROR_REFERENCE,
"cannot resolve reference (>%u levels deep)", max_nesting);
error = -1;
goto out;
}
*out = ref;
ref = NULL;
out:
git_reference_free(ref);
return error;
}
int git_refdb_iterator(git_reference_iterator **out, git_refdb *db, const char *glob)
{
int error;
......
......@@ -30,6 +30,12 @@ int git_refdb_lookup(
git_refdb *refdb,
const char *ref_name);
int git_refdb_resolve(
git_reference **out,
git_refdb *db,
const char *ref_name,
int max_nesting);
int git_refdb_rename(
git_reference **out,
git_refdb *db,
......
......@@ -214,52 +214,17 @@ int git_reference_lookup_resolved(
const char *name,
int max_nesting)
{
git_refname_t scan_name;
git_reference_t scan_type;
int error = 0, nesting;
git_reference *ref = NULL;
git_refname_t normalized;
git_refdb *refdb;
int error = 0;
assert(ref_out && repo && name);
*ref_out = NULL;
if (max_nesting > MAX_NESTING_LEVEL)
max_nesting = MAX_NESTING_LEVEL;
else if (max_nesting < 0)
max_nesting = DEFAULT_NESTING_LEVEL;
scan_type = GIT_REFERENCE_SYMBOLIC;
if ((error = reference_normalize_for_repo(scan_name, repo, name, true)) < 0)
if ((error = reference_normalize_for_repo(normalized, repo, name, true)) < 0 ||
(error = git_repository_refdb__weakptr(&refdb, repo)) < 0 ||
(error = git_refdb_resolve(ref_out, refdb, normalized, max_nesting)) < 0)
return error;
if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
return error;
for (nesting = max_nesting;
nesting >= 0 && scan_type == GIT_REFERENCE_SYMBOLIC;
nesting--)
{
if (nesting != max_nesting) {
strncpy(scan_name, ref->target.symbolic, sizeof(scan_name));
git_reference_free(ref);
}
if ((error = git_refdb_lookup(&ref, refdb, scan_name)) < 0)
return error;
scan_type = ref->type;
}
if (scan_type != GIT_REFERENCE_DIRECT && max_nesting != 0) {
git_error_set(GIT_ERROR_REFERENCE,
"cannot resolve reference (>%u levels deep)", max_nesting);
git_reference_free(ref);
return -1;
}
*ref_out = ref;
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