Skip to content

Commit 503dd0f

Browse files
author
Vicent Martí
committed
Merge pull request libgit2#1560 from carlosmn/ref-dwim
Expose git_reference_dwim
2 parents ddc5c05 + 98d633c commit 503dd0f

File tree

3 files changed

+78
-65
lines changed

3 files changed

+78
-65
lines changed

include/git2/refs.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,19 @@ GIT_EXTERN(int) git_reference_lookup(git_reference **out, git_repository *repo,
5454
GIT_EXTERN(int) git_reference_name_to_id(
5555
git_oid *out, git_repository *repo, const char *name);
5656

57+
/**
58+
* Lookup a reference by DWIMing its short name
59+
*
60+
* Apply the git precendence rules to the given shorthand to determine
61+
* which reference the user is refering to.
62+
*
63+
* @param out pointer in which to store the reference
64+
* @param repo the repository in which to look
65+
* @param shrothand the short name for the reference
66+
* @return 0 or an error code
67+
*/
68+
GIT_EXTERN(int) git_reference_dwim(git_reference **out, git_repository *repo, const char *shorthand);
69+
5770
/**
5871
* Create a new symbolic reference.
5972
*

src/refs.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,67 @@ int git_reference_lookup_resolved(
290290
return 0;
291291
}
292292

293+
int git_reference_dwim(git_reference **out, git_repository *repo, const char *refname)
294+
{
295+
int error = 0, i;
296+
bool fallbackmode = true, foundvalid = false;
297+
git_reference *ref;
298+
git_buf refnamebuf = GIT_BUF_INIT, name = GIT_BUF_INIT;
299+
300+
static const char* formatters[] = {
301+
"%s",
302+
GIT_REFS_DIR "%s",
303+
GIT_REFS_TAGS_DIR "%s",
304+
GIT_REFS_HEADS_DIR "%s",
305+
GIT_REFS_REMOTES_DIR "%s",
306+
GIT_REFS_REMOTES_DIR "%s/" GIT_HEAD_FILE,
307+
NULL
308+
};
309+
310+
if (*refname)
311+
git_buf_puts(&name, refname);
312+
else {
313+
git_buf_puts(&name, GIT_HEAD_FILE);
314+
fallbackmode = false;
315+
}
316+
317+
for (i = 0; formatters[i] && (fallbackmode || i == 0); i++) {
318+
319+
git_buf_clear(&refnamebuf);
320+
321+
if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0)
322+
goto cleanup;
323+
324+
if (!git_reference_is_valid_name(git_buf_cstr(&refnamebuf))) {
325+
error = GIT_EINVALIDSPEC;
326+
continue;
327+
}
328+
foundvalid = true;
329+
330+
error = git_reference_lookup_resolved(&ref, repo, git_buf_cstr(&refnamebuf), -1);
331+
332+
if (!error) {
333+
*out = ref;
334+
error = 0;
335+
goto cleanup;
336+
}
337+
338+
if (error != GIT_ENOTFOUND)
339+
goto cleanup;
340+
}
341+
342+
cleanup:
343+
if (error && !foundvalid) {
344+
/* never found a valid reference name */
345+
giterr_set(GITERR_REFERENCE,
346+
"Could not use '%s' as valid reference name", git_buf_cstr(&name));
347+
}
348+
349+
git_buf_free(&name);
350+
git_buf_free(&refnamebuf);
351+
return error;
352+
}
353+
293354
/**
294355
* Getters
295356
*/

src/revparse.c

Lines changed: 4 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -14,67 +14,6 @@
1414

1515
#include "git2.h"
1616

17-
static int disambiguate_refname(git_reference **out, git_repository *repo, const char *refname)
18-
{
19-
int error = 0, i;
20-
bool fallbackmode = true, foundvalid = false;
21-
git_reference *ref;
22-
git_buf refnamebuf = GIT_BUF_INIT, name = GIT_BUF_INIT;
23-
24-
static const char* formatters[] = {
25-
"%s",
26-
GIT_REFS_DIR "%s",
27-
GIT_REFS_TAGS_DIR "%s",
28-
GIT_REFS_HEADS_DIR "%s",
29-
GIT_REFS_REMOTES_DIR "%s",
30-
GIT_REFS_REMOTES_DIR "%s/" GIT_HEAD_FILE,
31-
NULL
32-
};
33-
34-
if (*refname)
35-
git_buf_puts(&name, refname);
36-
else {
37-
git_buf_puts(&name, GIT_HEAD_FILE);
38-
fallbackmode = false;
39-
}
40-
41-
for (i = 0; formatters[i] && (fallbackmode || i == 0); i++) {
42-
43-
git_buf_clear(&refnamebuf);
44-
45-
if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0)
46-
goto cleanup;
47-
48-
if (!git_reference_is_valid_name(git_buf_cstr(&refnamebuf))) {
49-
error = GIT_EINVALIDSPEC;
50-
continue;
51-
}
52-
foundvalid = true;
53-
54-
error = git_reference_lookup_resolved(&ref, repo, git_buf_cstr(&refnamebuf), -1);
55-
56-
if (!error) {
57-
*out = ref;
58-
error = 0;
59-
goto cleanup;
60-
}
61-
62-
if (error != GIT_ENOTFOUND)
63-
goto cleanup;
64-
}
65-
66-
cleanup:
67-
if (error && !foundvalid) {
68-
/* never found a valid reference name */
69-
giterr_set(GITERR_REFERENCE,
70-
"Could not use '%s' as valid reference name", git_buf_cstr(&name));
71-
}
72-
73-
git_buf_free(&name);
74-
git_buf_free(&refnamebuf);
75-
return error;
76-
}
77-
7817
static int maybe_sha_or_abbrev(git_object** out, git_repository *repo, const char *spec, size_t speclen)
7918
{
8019
git_oid oid;
@@ -157,7 +96,7 @@ static int revparse_lookup_object(git_object **out, git_repository *repo, const
15796
if (error < 0 && error != GIT_ENOTFOUND)
15897
return error;
15998

160-
error = disambiguate_refname(&ref, repo, spec);
99+
error = git_reference_dwim(&ref, repo, spec);
161100
if (!error) {
162101
error = git_object_lookup(out, repo, git_reference_target(ref), GIT_OBJ_ANY);
163102
git_reference_free(ref);
@@ -242,7 +181,7 @@ static int retrieve_previously_checked_out_branch_or_revision(git_object **out,
242181

243182
git_buf_put(&buf, msg+regexmatches[1].rm_so, regexmatches[1].rm_eo - regexmatches[1].rm_so);
244183

245-
if ((error = disambiguate_refname(base_ref, repo, git_buf_cstr(&buf))) == 0)
184+
if ((error = git_reference_dwim(base_ref, repo, git_buf_cstr(&buf))) == 0)
246185
goto cleanup;
247186

248187
if (error < 0 && error != GIT_ENOTFOUND)
@@ -323,7 +262,7 @@ static int retrieve_revobject_from_reflog(git_object **out, git_reference **base
323262
int error = -1;
324263

325264
if (*base_ref == NULL) {
326-
if ((error = disambiguate_refname(&ref, repo, identifier)) < 0)
265+
if ((error = git_reference_dwim(&ref, repo, identifier)) < 0)
327266
return error;
328267
} else {
329268
ref = *base_ref;
@@ -351,7 +290,7 @@ static int retrieve_remote_tracking_reference(git_reference **base_ref, const ch
351290
int error = -1;
352291

353292
if (*base_ref == NULL) {
354-
if ((error = disambiguate_refname(&ref, repo, identifier)) < 0)
293+
if ((error = git_reference_dwim(&ref, repo, identifier)) < 0)
355294
return error;
356295
} else {
357296
ref = *base_ref;

0 commit comments

Comments
 (0)