Skip to content

Commit 0445ba2

Browse files
committed
Merge branch 'jc/broken-ref-dwim-fix'
* jc/broken-ref-dwim-fix: resolve_ref(): report breakage to the caller without warning resolve_ref(): expose REF_ISBROKEN flag refs.c: move dwim_ref()/dwim_log() from sha1_name.c
2 parents 2f18b46 + 5595635 commit 0445ba2

File tree

3 files changed

+104
-100
lines changed

3 files changed

+104
-100
lines changed

refs.c

Lines changed: 101 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44
#include "tag.h"
55
#include "dir.h"
66

7-
/* ISSYMREF=01 and ISPACKED=02 are public interfaces */
8-
#define REF_KNOWS_PEELED 04
9-
#define REF_BROKEN 010
7+
/* ISSYMREF=0x01, ISPACKED=0x02 and ISBROKEN=0x04 are public interfaces */
8+
#define REF_KNOWS_PEELED 0x10
109

1110
struct ref_entry {
1211
unsigned char flag; /* ISSYMREF? ISPACKED? */
@@ -332,12 +331,12 @@ static void get_ref_dir(const char *submodule, const char *base,
332331
flag = 0;
333332
if (resolve_gitlink_ref(submodule, ref, sha1) < 0) {
334333
hashclr(sha1);
335-
flag |= REF_BROKEN;
334+
flag |= REF_ISBROKEN;
336335
}
337336
} else
338337
if (!resolve_ref(ref, sha1, 1, &flag)) {
339338
hashclr(sha1);
340-
flag |= REF_BROKEN;
339+
flag |= REF_ISBROKEN;
341340
}
342341
add_ref(ref, sha1, flag, array, NULL);
343342
}
@@ -504,7 +503,6 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
504503
ssize_t len;
505504
char buffer[256];
506505
static char ref_buffer[256];
507-
char path[PATH_MAX];
508506

509507
if (flag)
510508
*flag = 0;
@@ -513,6 +511,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
513511
return NULL;
514512

515513
for (;;) {
514+
char path[PATH_MAX];
516515
struct stat st;
517516
char *buf;
518517
int fd;
@@ -585,21 +584,22 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
585584
*/
586585
if (prefixcmp(buffer, "ref:"))
587586
break;
587+
if (flag)
588+
*flag |= REF_ISSYMREF;
588589
buf = buffer + 4;
589590
while (isspace(*buf))
590591
buf++;
591592
if (check_refname_format(buf, REFNAME_ALLOW_ONELEVEL)) {
592-
warning("symbolic reference in %s is formatted incorrectly",
593-
path);
593+
if (flag)
594+
*flag |= REF_ISBROKEN;
594595
return NULL;
595596
}
596597
ref = strcpy(ref_buffer, buf);
597-
if (flag)
598-
*flag |= REF_ISSYMREF;
599598
}
600599
/* Please note that FETCH_HEAD has a second line containing other data. */
601600
if (get_sha1_hex(buffer, sha1) || (buffer[40] != '\0' && !isspace(buffer[40]))) {
602-
warning("reference in %s is formatted incorrectly", path);
601+
if (flag)
602+
*flag |= REF_ISBROKEN;
603603
return NULL;
604604
}
605605
return ref;
@@ -627,8 +627,8 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim,
627627
return 0;
628628

629629
if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
630-
if (entry->flag & REF_BROKEN)
631-
return 0; /* ignore dangling symref */
630+
if (entry->flag & REF_ISBROKEN)
631+
return 0; /* ignore broken refs e.g. dangling symref */
632632
if (!has_sha1_file(entry->sha1)) {
633633
error("%s does not point to a valid object!", entry->name);
634634
return 0;
@@ -1078,6 +1078,94 @@ static int is_refname_available(const char *ref, const char *oldref,
10781078
return 1;
10791079
}
10801080

1081+
/*
1082+
* *string and *len will only be substituted, and *string returned (for
1083+
* later free()ing) if the string passed in is a magic short-hand form
1084+
* to name a branch.
1085+
*/
1086+
static char *substitute_branch_name(const char **string, int *len)
1087+
{
1088+
struct strbuf buf = STRBUF_INIT;
1089+
int ret = interpret_branch_name(*string, &buf);
1090+
1091+
if (ret == *len) {
1092+
size_t size;
1093+
*string = strbuf_detach(&buf, &size);
1094+
*len = size;
1095+
return (char *)*string;
1096+
}
1097+
1098+
return NULL;
1099+
}
1100+
1101+
int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
1102+
{
1103+
char *last_branch = substitute_branch_name(&str, &len);
1104+
const char **p, *r;
1105+
int refs_found = 0;
1106+
1107+
*ref = NULL;
1108+
for (p = ref_rev_parse_rules; *p; p++) {
1109+
char fullref[PATH_MAX];
1110+
unsigned char sha1_from_ref[20];
1111+
unsigned char *this_result;
1112+
int flag;
1113+
1114+
this_result = refs_found ? sha1_from_ref : sha1;
1115+
mksnpath(fullref, sizeof(fullref), *p, len, str);
1116+
r = resolve_ref(fullref, this_result, 1, &flag);
1117+
if (r) {
1118+
if (!refs_found++)
1119+
*ref = xstrdup(r);
1120+
if (!warn_ambiguous_refs)
1121+
break;
1122+
} else if ((flag & REF_ISSYMREF) && strcmp(fullref, "HEAD")) {
1123+
warning("ignoring dangling symref %s.", fullref);
1124+
} else if ((flag & REF_ISBROKEN) && strchr(fullref, '/')) {
1125+
warning("ignoring broken ref %s.", fullref);
1126+
}
1127+
}
1128+
free(last_branch);
1129+
return refs_found;
1130+
}
1131+
1132+
int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
1133+
{
1134+
char *last_branch = substitute_branch_name(&str, &len);
1135+
const char **p;
1136+
int logs_found = 0;
1137+
1138+
*log = NULL;
1139+
for (p = ref_rev_parse_rules; *p; p++) {
1140+
struct stat st;
1141+
unsigned char hash[20];
1142+
char path[PATH_MAX];
1143+
const char *ref, *it;
1144+
1145+
mksnpath(path, sizeof(path), *p, len, str);
1146+
ref = resolve_ref(path, hash, 1, NULL);
1147+
if (!ref)
1148+
continue;
1149+
if (!stat(git_path("logs/%s", path), &st) &&
1150+
S_ISREG(st.st_mode))
1151+
it = path;
1152+
else if (strcmp(ref, path) &&
1153+
!stat(git_path("logs/%s", ref), &st) &&
1154+
S_ISREG(st.st_mode))
1155+
it = ref;
1156+
else
1157+
continue;
1158+
if (!logs_found++) {
1159+
*log = xstrdup(it);
1160+
hashcpy(sha1, hash);
1161+
}
1162+
if (!warn_ambiguous_refs)
1163+
break;
1164+
}
1165+
free(last_branch);
1166+
return logs_found;
1167+
}
1168+
10811169
static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char *old_sha1, int flags, int *type_p)
10821170
{
10831171
char *ref_file;

refs.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ struct ref_lock {
1010
int force_write;
1111
};
1212

13-
#define REF_ISSYMREF 01
14-
#define REF_ISPACKED 02
13+
#define REF_ISSYMREF 0x01
14+
#define REF_ISPACKED 0x02
15+
#define REF_ISBROKEN 0x04
1516

1617
/*
1718
* Calls the specified function for each ref file until it returns nonzero,

sha1_name.c

Lines changed: 0 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -241,91 +241,6 @@ static int ambiguous_path(const char *path, int len)
241241
return slash;
242242
}
243243

244-
/*
245-
* *string and *len will only be substituted, and *string returned (for
246-
* later free()ing) if the string passed in is a magic short-hand form
247-
* to name a branch.
248-
*/
249-
static char *substitute_branch_name(const char **string, int *len)
250-
{
251-
struct strbuf buf = STRBUF_INIT;
252-
int ret = interpret_branch_name(*string, &buf);
253-
254-
if (ret == *len) {
255-
size_t size;
256-
*string = strbuf_detach(&buf, &size);
257-
*len = size;
258-
return (char *)*string;
259-
}
260-
261-
return NULL;
262-
}
263-
264-
int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
265-
{
266-
char *last_branch = substitute_branch_name(&str, &len);
267-
const char **p, *r;
268-
int refs_found = 0;
269-
270-
*ref = NULL;
271-
for (p = ref_rev_parse_rules; *p; p++) {
272-
char fullref[PATH_MAX];
273-
unsigned char sha1_from_ref[20];
274-
unsigned char *this_result;
275-
int flag;
276-
277-
this_result = refs_found ? sha1_from_ref : sha1;
278-
mksnpath(fullref, sizeof(fullref), *p, len, str);
279-
r = resolve_ref(fullref, this_result, 1, &flag);
280-
if (r) {
281-
if (!refs_found++)
282-
*ref = xstrdup(r);
283-
if (!warn_ambiguous_refs)
284-
break;
285-
} else if ((flag & REF_ISSYMREF) && strcmp(fullref, "HEAD"))
286-
warning("ignoring dangling symref %s.", fullref);
287-
}
288-
free(last_branch);
289-
return refs_found;
290-
}
291-
292-
int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
293-
{
294-
char *last_branch = substitute_branch_name(&str, &len);
295-
const char **p;
296-
int logs_found = 0;
297-
298-
*log = NULL;
299-
for (p = ref_rev_parse_rules; *p; p++) {
300-
struct stat st;
301-
unsigned char hash[20];
302-
char path[PATH_MAX];
303-
const char *ref, *it;
304-
305-
mksnpath(path, sizeof(path), *p, len, str);
306-
ref = resolve_ref(path, hash, 1, NULL);
307-
if (!ref)
308-
continue;
309-
if (!stat(git_path("logs/%s", path), &st) &&
310-
S_ISREG(st.st_mode))
311-
it = path;
312-
else if (strcmp(ref, path) &&
313-
!stat(git_path("logs/%s", ref), &st) &&
314-
S_ISREG(st.st_mode))
315-
it = ref;
316-
else
317-
continue;
318-
if (!logs_found++) {
319-
*log = xstrdup(it);
320-
hashcpy(sha1, hash);
321-
}
322-
if (!warn_ambiguous_refs)
323-
break;
324-
}
325-
free(last_branch);
326-
return logs_found;
327-
}
328-
329244
static inline int upstream_mark(const char *string, int len)
330245
{
331246
const char *suffix[] = { "@{upstream}", "@{u}" };

0 commit comments

Comments
 (0)