Skip to content

Commit c54f40e

Browse files
committed
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.
1 parent 9703d26 commit c54f40e

File tree

3 files changed

+59
-40
lines changed

3 files changed

+59
-40
lines changed

src/refdb.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#include "reflog.h"
1818
#include "posix.h"
1919

20+
#define DEFAULT_NESTING_LEVEL 5
21+
#define MAX_NESTING_LEVEL 10
22+
2023
int git_refdb_new(git_refdb **out, git_repository *repo)
2124
{
2225
git_refdb *db;
@@ -134,6 +137,51 @@ int git_refdb_lookup(git_reference **out, git_refdb *db, const char *ref_name)
134137
return 0;
135138
}
136139

140+
int git_refdb_resolve(
141+
git_reference **out,
142+
git_refdb *db,
143+
const char *ref_name,
144+
int max_nesting)
145+
{
146+
git_reference *ref = NULL;
147+
int error = 0, nesting;
148+
149+
*out = NULL;
150+
151+
if (max_nesting > MAX_NESTING_LEVEL)
152+
max_nesting = MAX_NESTING_LEVEL;
153+
else if (max_nesting < 0)
154+
max_nesting = DEFAULT_NESTING_LEVEL;
155+
156+
if ((error = git_refdb_lookup(&ref, db, ref_name)) < 0)
157+
goto out;
158+
159+
for (nesting = 0; nesting < max_nesting; nesting++) {
160+
git_reference *resolved;
161+
162+
if (ref->type == GIT_REFERENCE_DIRECT)
163+
break;
164+
if ((error = git_refdb_lookup(&resolved, db, git_reference_symbolic_target(ref))) < 0)
165+
goto out;
166+
167+
git_reference_free(ref);
168+
ref = resolved;
169+
}
170+
171+
if (ref->type != GIT_REFERENCE_DIRECT && max_nesting != 0) {
172+
git_error_set(GIT_ERROR_REFERENCE,
173+
"cannot resolve reference (>%u levels deep)", max_nesting);
174+
error = -1;
175+
goto out;
176+
}
177+
178+
*out = ref;
179+
ref = NULL;
180+
out:
181+
git_reference_free(ref);
182+
return error;
183+
}
184+
137185
int git_refdb_iterator(git_reference_iterator **out, git_refdb *db, const char *glob)
138186
{
139187
int error;

src/refdb.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ int git_refdb_lookup(
3030
git_refdb *refdb,
3131
const char *ref_name);
3232

33+
int git_refdb_resolve(
34+
git_reference **out,
35+
git_refdb *db,
36+
const char *ref_name,
37+
int max_nesting);
38+
3339
int git_refdb_rename(
3440
git_reference **out,
3541
git_refdb *db,

src/refs.c

Lines changed: 5 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -214,52 +214,17 @@ int git_reference_lookup_resolved(
214214
const char *name,
215215
int max_nesting)
216216
{
217-
git_refname_t scan_name;
218-
git_reference_t scan_type;
219-
int error = 0, nesting;
220-
git_reference *ref = NULL;
217+
git_refname_t normalized;
221218
git_refdb *refdb;
219+
int error = 0;
222220

223221
assert(ref_out && repo && name);
224222

225-
*ref_out = NULL;
226-
227-
if (max_nesting > MAX_NESTING_LEVEL)
228-
max_nesting = MAX_NESTING_LEVEL;
229-
else if (max_nesting < 0)
230-
max_nesting = DEFAULT_NESTING_LEVEL;
231-
232-
scan_type = GIT_REFERENCE_SYMBOLIC;
233-
234-
if ((error = reference_normalize_for_repo(scan_name, repo, name, true)) < 0)
223+
if ((error = reference_normalize_for_repo(normalized, repo, name, true)) < 0 ||
224+
(error = git_repository_refdb__weakptr(&refdb, repo)) < 0 ||
225+
(error = git_refdb_resolve(ref_out, refdb, normalized, max_nesting)) < 0)
235226
return error;
236227

237-
if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
238-
return error;
239-
240-
for (nesting = max_nesting;
241-
nesting >= 0 && scan_type == GIT_REFERENCE_SYMBOLIC;
242-
nesting--)
243-
{
244-
if (nesting != max_nesting) {
245-
strncpy(scan_name, ref->target.symbolic, sizeof(scan_name));
246-
git_reference_free(ref);
247-
}
248-
249-
if ((error = git_refdb_lookup(&ref, refdb, scan_name)) < 0)
250-
return error;
251-
252-
scan_type = ref->type;
253-
}
254-
255-
if (scan_type != GIT_REFERENCE_DIRECT && max_nesting != 0) {
256-
git_error_set(GIT_ERROR_REFERENCE,
257-
"cannot resolve reference (>%u levels deep)", max_nesting);
258-
git_reference_free(ref);
259-
return -1;
260-
}
261-
262-
*ref_out = ref;
263228
return 0;
264229
}
265230

0 commit comments

Comments
 (0)