Skip to content

Commit 0df670b

Browse files
committed
Merge branch 'jt/interpret-branch-name-fallback'
"git status" has trouble showing where it came from by interpreting reflog entries that recordcertain events, e.g. "checkout @{u}", and gives a hard/fatal error. Even though it inherently is impossible to give a correct answer because the reflog entries lose some information (e.g. "@{u}" does not record what branch the user was on hence which branch 'the upstream' needs to be computed, and even if the record were available, the relationship between branches may have changed), at least hide the error to allow "status" show its output. * jt/interpret-branch-name-fallback: wt-status: tolerate dangling marks refs: move dwim_ref() to header file sha1-name: replace unsigned int with option struct
2 parents 7364aee + f24c30e commit 0df670b

20 files changed

+98
-53
lines changed

archive.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,10 +397,10 @@ static void parse_treeish_arg(const char **argv,
397397
const char *colon = strchrnul(name, ':');
398398
int refnamelen = colon - name;
399399

400-
if (!dwim_ref(name, refnamelen, &oid, &ref))
400+
if (!dwim_ref(name, refnamelen, &oid, &ref, 0))
401401
die(_("no such ref: %.*s"), refnamelen, name);
402402
} else {
403-
dwim_ref(name, strlen(name), &oid, &ref);
403+
dwim_ref(name, strlen(name), &oid, &ref, 0);
404404
}
405405

406406
if (get_oid(name, &oid))

branch.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ void create_branch(struct repository *r,
281281
die(_("Not a valid object name: '%s'."), start_name);
282282
}
283283

284-
switch (dwim_ref(start_name, strlen(start_name), &oid, &real_ref)) {
284+
switch (dwim_ref(start_name, strlen(start_name), &oid, &real_ref, 0)) {
285285
case 0:
286286
/* Not branching from any existing branch */
287287
if (explicit_tracking)

builtin/checkout.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ static void setup_branch_path(struct branch_info *branch)
651651
* If this is a ref, resolve it; otherwise, look up the OID for our
652652
* expression. Failure here is okay.
653653
*/
654-
if (!dwim_ref(branch->name, strlen(branch->name), &branch->oid, &branch->refname))
654+
if (!dwim_ref(branch->name, strlen(branch->name), &branch->oid, &branch->refname, 0))
655655
repo_get_oid_committish(the_repository, branch->name, &branch->oid);
656656

657657
strbuf_branchname(&buf, branch->name, INTERPRET_BRANCH_LOCAL);
@@ -1345,7 +1345,7 @@ static void die_expecting_a_branch(const struct branch_info *branch_info)
13451345
struct object_id oid;
13461346
char *to_free;
13471347

1348-
if (dwim_ref(branch_info->name, strlen(branch_info->name), &oid, &to_free) == 1) {
1348+
if (dwim_ref(branch_info->name, strlen(branch_info->name), &oid, &to_free, 0) == 1) {
13491349
const char *ref = to_free;
13501350

13511351
if (skip_prefix(ref, "refs/tags/", &ref))

builtin/fast-export.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
943943
if (e->flags & UNINTERESTING)
944944
continue;
945945

946-
if (dwim_ref(e->name, strlen(e->name), &oid, &full_name) != 1)
946+
if (dwim_ref(e->name, strlen(e->name), &oid, &full_name, 0) != 1)
947947
continue;
948948

949949
if (refspecs.nr) {

builtin/log.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,7 @@ static char *find_branch_name(struct rev_info *rev)
10611061
return NULL;
10621062
ref = rev->cmdline.rev[positive].name;
10631063
tip_oid = &rev->cmdline.rev[positive].item->oid;
1064-
if (dwim_ref(ref, strlen(ref), &branch_oid, &full_ref) &&
1064+
if (dwim_ref(ref, strlen(ref), &branch_oid, &full_ref, 0) &&
10651065
skip_prefix(full_ref, "refs/heads/", &v) &&
10661066
oideq(tip_oid, &branch_oid))
10671067
branch = xstrdup(v);

builtin/merge.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
500500
if (!remote_head)
501501
die(_("'%s' does not point to a commit"), remote);
502502

503-
if (dwim_ref(remote, strlen(remote), &branch_head, &found_ref) > 0) {
503+
if (dwim_ref(remote, strlen(remote), &branch_head, &found_ref, 0) > 0) {
504504
if (starts_with(found_ref, "refs/heads/")) {
505505
strbuf_addf(msg, "%s\t\tbranch '%s' of .\n",
506506
oid_to_hex(&branch_head), remote);

builtin/reset.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
423423
char *ref = NULL;
424424
int err;
425425

426-
dwim_ref(rev, strlen(rev), &dummy, &ref);
426+
dwim_ref(rev, strlen(rev), &dummy, &ref, 0);
427427
if (ref && !starts_with(ref, "refs/"))
428428
ref = NULL;
429429

builtin/rev-parse.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ static void show_rev(int type, const struct object_id *oid, const char *name)
136136
struct object_id discard;
137137
char *full;
138138

139-
switch (dwim_ref(name, strlen(name), &discard, &full)) {
139+
switch (dwim_ref(name, strlen(name), &discard, &full, 0)) {
140140
case 0:
141141
/*
142142
* Not found -- not a ref. We could

builtin/show-branch.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
741741
die(Q_("only %d entry can be shown at one time.",
742742
"only %d entries can be shown at one time.",
743743
MAX_REVS), MAX_REVS);
744-
if (!dwim_ref(*av, strlen(*av), &oid, &ref))
744+
if (!dwim_ref(*av, strlen(*av), &oid, &ref, 0))
745745
die(_("no such ref %s"), *av);
746746

747747
/* Has the base been specified? */

builtin/stash.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
185185
end_of_rev = strchrnul(revision, '@');
186186
strbuf_add(&symbolic, revision, end_of_rev - revision);
187187

188-
ret = dwim_ref(symbolic.buf, symbolic.len, &dummy, &expanded_ref);
188+
ret = dwim_ref(symbolic.buf, symbolic.len, &dummy, &expanded_ref, 0);
189189
strbuf_release(&symbolic);
190190
switch (ret) {
191191
case 0: /* Not found, but valid ref */

bundle.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs)
403403

404404
if (e->item->flags & UNINTERESTING)
405405
continue;
406-
if (dwim_ref(e->name, strlen(e->name), &oid, &ref) != 1)
406+
if (dwim_ref(e->name, strlen(e->name), &oid, &ref, 0) != 1)
407407
goto skip_write_ref;
408408
if (read_ref_full(e->name, RESOLVE_REF_READING, &oid, &flag))
409409
flag = 0;

cache.h

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,21 +1557,32 @@ int parse_oid_hex_any(const char *hex, struct object_id *oid, const char **end);
15571557
*
15581558
* If the input was ok but there are not N branch switches in the
15591559
* reflog, it returns 0.
1560-
*
1561-
* If "allowed" is non-zero, it is a treated as a bitfield of allowable
1562-
* expansions: local branches ("refs/heads/"), remote branches
1563-
* ("refs/remotes/"), or "HEAD". If no "allowed" bits are set, any expansion is
1564-
* allowed, even ones to refs outside of those namespaces.
15651560
*/
15661561
#define INTERPRET_BRANCH_LOCAL (1<<0)
15671562
#define INTERPRET_BRANCH_REMOTE (1<<1)
15681563
#define INTERPRET_BRANCH_HEAD (1<<2)
1564+
struct interpret_branch_name_options {
1565+
/*
1566+
* If "allowed" is non-zero, it is a treated as a bitfield of allowable
1567+
* expansions: local branches ("refs/heads/"), remote branches
1568+
* ("refs/remotes/"), or "HEAD". If no "allowed" bits are set, any expansion is
1569+
* allowed, even ones to refs outside of those namespaces.
1570+
*/
1571+
unsigned allowed;
1572+
1573+
/*
1574+
* If ^{upstream} or ^{push} (or equivalent) is requested, and the
1575+
* branch in question does not have such a reference, return -1 instead
1576+
* of die()-ing.
1577+
*/
1578+
unsigned nonfatal_dangling_mark : 1;
1579+
};
15691580
int repo_interpret_branch_name(struct repository *r,
15701581
const char *str, int len,
15711582
struct strbuf *buf,
1572-
unsigned allowed);
1573-
#define interpret_branch_name(str, len, buf, allowed) \
1574-
repo_interpret_branch_name(the_repository, str, len, buf, allowed)
1583+
const struct interpret_branch_name_options *options);
1584+
#define interpret_branch_name(str, len, buf, options) \
1585+
repo_interpret_branch_name(the_repository, str, len, buf, options)
15751586

15761587
int validate_headref(const char *ref);
15771588

commit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -921,7 +921,7 @@ struct commit *get_fork_point(const char *refname, struct commit *commit)
921921
struct commit *ret = NULL;
922922
char *full_refname;
923923

924-
switch (dwim_ref(refname, strlen(refname), &oid, &full_refname)) {
924+
switch (dwim_ref(refname, strlen(refname), &oid, &full_refname, 0)) {
925925
case 0:
926926
die("No such ref: '%s'", refname);
927927
case 1:

refs.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -598,10 +598,14 @@ const char *git_default_branch_name(void)
598598
* to name a branch.
599599
*/
600600
static char *substitute_branch_name(struct repository *r,
601-
const char **string, int *len)
601+
const char **string, int *len,
602+
int nonfatal_dangling_mark)
602603
{
603604
struct strbuf buf = STRBUF_INIT;
604-
int ret = repo_interpret_branch_name(r, *string, *len, &buf, 0);
605+
struct interpret_branch_name_options options = {
606+
.nonfatal_dangling_mark = nonfatal_dangling_mark
607+
};
608+
int ret = repo_interpret_branch_name(r, *string, *len, &buf, &options);
605609

606610
if (ret == *len) {
607611
size_t size;
@@ -614,19 +618,15 @@ static char *substitute_branch_name(struct repository *r,
614618
}
615619

616620
int repo_dwim_ref(struct repository *r, const char *str, int len,
617-
struct object_id *oid, char **ref)
621+
struct object_id *oid, char **ref, int nonfatal_dangling_mark)
618622
{
619-
char *last_branch = substitute_branch_name(r, &str, &len);
623+
char *last_branch = substitute_branch_name(r, &str, &len,
624+
nonfatal_dangling_mark);
620625
int refs_found = expand_ref(r, str, len, oid, ref);
621626
free(last_branch);
622627
return refs_found;
623628
}
624629

625-
int dwim_ref(const char *str, int len, struct object_id *oid, char **ref)
626-
{
627-
return repo_dwim_ref(the_repository, str, len, oid, ref);
628-
}
629-
630630
int expand_ref(struct repository *repo, const char *str, int len,
631631
struct object_id *oid, char **ref)
632632
{
@@ -665,7 +665,7 @@ int repo_dwim_log(struct repository *r, const char *str, int len,
665665
struct object_id *oid, char **log)
666666
{
667667
struct ref_store *refs = get_main_ref_store(r);
668-
char *last_branch = substitute_branch_name(r, &str, &len);
668+
char *last_branch = substitute_branch_name(r, &str, &len, 0);
669669
const char **p;
670670
int logs_found = 0;
671671
struct strbuf path = STRBUF_INIT;

refs.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef REFS_H
22
#define REFS_H
33

4+
#include "cache.h"
5+
46
struct object_id;
57
struct ref_store;
68
struct repository;
@@ -151,9 +153,15 @@ struct strvec;
151153
void expand_ref_prefix(struct strvec *prefixes, const char *prefix);
152154

153155
int expand_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
154-
int repo_dwim_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
156+
int repo_dwim_ref(struct repository *r, const char *str, int len,
157+
struct object_id *oid, char **ref, int nonfatal_dangling_mark);
155158
int repo_dwim_log(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
156-
int dwim_ref(const char *str, int len, struct object_id *oid, char **ref);
159+
static inline int dwim_ref(const char *str, int len, struct object_id *oid,
160+
char **ref, int nonfatal_dangling_mark)
161+
{
162+
return repo_dwim_ref(the_repository, str, len, oid, ref,
163+
nonfatal_dangling_mark);
164+
}
157165
int dwim_log(const char *str, int len, struct object_id *oid, char **ref);
158166

159167
/*

remote.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1558,7 +1558,7 @@ static void set_merge(struct branch *ret)
15581558
strcmp(ret->remote_name, "."))
15591559
continue;
15601560
if (dwim_ref(ret->merge_name[i], strlen(ret->merge_name[i]),
1561-
&oid, &ref) == 1)
1561+
&oid, &ref, 0) == 1)
15621562
ret->merge[i]->dst = ref;
15631563
else
15641564
ret->merge[i]->dst = xstrdup(ret->merge_name[i]);

revision.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,13 +315,14 @@ static void add_pending_object_with_path(struct rev_info *revs,
315315
const char *name, unsigned mode,
316316
const char *path)
317317
{
318+
struct interpret_branch_name_options options = { 0 };
318319
if (!obj)
319320
return;
320321
if (revs->no_walk && (obj->flags & UNINTERESTING))
321322
revs->no_walk = 0;
322323
if (revs->reflog_info && obj->type == OBJ_COMMIT) {
323324
struct strbuf buf = STRBUF_INIT;
324-
int len = interpret_branch_name(name, 0, &buf, 0);
325+
int len = interpret_branch_name(name, 0, &buf, &options);
325326

326327
if (0 < len && name[len] && buf.len)
327328
strbuf_addstr(&buf, name + len);

sha1-name.c

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
809809

810810
if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) {
811811
if (warn_ambiguous_refs && warn_on_object_refname_ambiguity) {
812-
refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref);
812+
refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0);
813813
if (refs_found > 0) {
814814
warning(warn_msg, len, str);
815815
if (advice_object_name_warning)
@@ -860,11 +860,11 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
860860

861861
if (!len && reflog_len)
862862
/* allow "@{...}" to mean the current branch reflog */
863-
refs_found = repo_dwim_ref(r, "HEAD", 4, oid, &real_ref);
863+
refs_found = repo_dwim_ref(r, "HEAD", 4, oid, &real_ref, 0);
864864
else if (reflog_len)
865865
refs_found = repo_dwim_log(r, str, len, oid, &real_ref);
866866
else
867-
refs_found = repo_dwim_ref(r, str, len, oid, &real_ref);
867+
refs_found = repo_dwim_ref(r, str, len, oid, &real_ref, 0);
868868

869869
if (!refs_found)
870870
return -1;
@@ -1427,9 +1427,12 @@ static int reinterpret(struct repository *r,
14271427
struct strbuf tmp = STRBUF_INIT;
14281428
int used = buf->len;
14291429
int ret;
1430+
struct interpret_branch_name_options options = {
1431+
.allowed = allowed
1432+
};
14301433

14311434
strbuf_add(buf, name + len, namelen - len);
1432-
ret = repo_interpret_branch_name(r, buf->buf, buf->len, &tmp, allowed);
1435+
ret = repo_interpret_branch_name(r, buf->buf, buf->len, &tmp, &options);
14331436
/* that data was not interpreted, remove our cruft */
14341437
if (ret < 0) {
14351438
strbuf_setlen(buf, used);
@@ -1471,7 +1474,7 @@ static int interpret_branch_mark(struct repository *r,
14711474
int (*get_mark)(const char *, int),
14721475
const char *(*get_data)(struct branch *,
14731476
struct strbuf *),
1474-
unsigned allowed)
1477+
const struct interpret_branch_name_options *options)
14751478
{
14761479
int len;
14771480
struct branch *branch;
@@ -1493,10 +1496,16 @@ static int interpret_branch_mark(struct repository *r,
14931496
branch = branch_get(NULL);
14941497

14951498
value = get_data(branch, &err);
1496-
if (!value)
1497-
die("%s", err.buf);
1499+
if (!value) {
1500+
if (options->nonfatal_dangling_mark) {
1501+
strbuf_release(&err);
1502+
return -1;
1503+
} else {
1504+
die("%s", err.buf);
1505+
}
1506+
}
14981507

1499-
if (!branch_interpret_allowed(value, allowed))
1508+
if (!branch_interpret_allowed(value, options->allowed))
15001509
return -1;
15011510

15021511
set_shortened_ref(r, buf, value);
@@ -1506,7 +1515,7 @@ static int interpret_branch_mark(struct repository *r,
15061515
int repo_interpret_branch_name(struct repository *r,
15071516
const char *name, int namelen,
15081517
struct strbuf *buf,
1509-
unsigned allowed)
1518+
const struct interpret_branch_name_options *options)
15101519
{
15111520
char *at;
15121521
const char *start;
@@ -1515,38 +1524,39 @@ int repo_interpret_branch_name(struct repository *r,
15151524
if (!namelen)
15161525
namelen = strlen(name);
15171526

1518-
if (!allowed || (allowed & INTERPRET_BRANCH_LOCAL)) {
1527+
if (!options->allowed || (options->allowed & INTERPRET_BRANCH_LOCAL)) {
15191528
len = interpret_nth_prior_checkout(r, name, namelen, buf);
15201529
if (!len) {
15211530
return len; /* syntax Ok, not enough switches */
15221531
} else if (len > 0) {
15231532
if (len == namelen)
15241533
return len; /* consumed all */
15251534
else
1526-
return reinterpret(r, name, namelen, len, buf, allowed);
1535+
return reinterpret(r, name, namelen, len, buf,
1536+
options->allowed);
15271537
}
15281538
}
15291539

15301540
for (start = name;
15311541
(at = memchr(start, '@', namelen - (start - name)));
15321542
start = at + 1) {
15331543

1534-
if (!allowed || (allowed & INTERPRET_BRANCH_HEAD)) {
1544+
if (!options->allowed || (options->allowed & INTERPRET_BRANCH_HEAD)) {
15351545
len = interpret_empty_at(name, namelen, at - name, buf);
15361546
if (len > 0)
15371547
return reinterpret(r, name, namelen, len, buf,
1538-
allowed);
1548+
options->allowed);
15391549
}
15401550

15411551
len = interpret_branch_mark(r, name, namelen, at - name, buf,
15421552
upstream_mark, branch_get_upstream,
1543-
allowed);
1553+
options);
15441554
if (len > 0)
15451555
return len;
15461556

15471557
len = interpret_branch_mark(r, name, namelen, at - name, buf,
15481558
push_mark, branch_get_push,
1549-
allowed);
1559+
options);
15501560
if (len > 0)
15511561
return len;
15521562
}
@@ -1557,7 +1567,10 @@ int repo_interpret_branch_name(struct repository *r,
15571567
void strbuf_branchname(struct strbuf *sb, const char *name, unsigned allowed)
15581568
{
15591569
int len = strlen(name);
1560-
int used = interpret_branch_name(name, len, sb, allowed);
1570+
struct interpret_branch_name_options options = {
1571+
.allowed = allowed
1572+
};
1573+
int used = interpret_branch_name(name, len, sb, &options);
15611574

15621575
if (used < 0)
15631576
used = 0;

0 commit comments

Comments
 (0)