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
This commit is contained in:
Junio C Hamano 2011-10-21 16:04:36 -07:00
Родитель 2f18b4642d 5595635002
Коммит 0445ba2457
3 изменённых файлов: 104 добавлений и 100 удалений

114
refs.c
Просмотреть файл

@ -4,9 +4,8 @@
#include "tag.h"
#include "dir.h"
/* ISSYMREF=01 and ISPACKED=02 are public interfaces */
#define REF_KNOWS_PEELED 04
#define REF_BROKEN 010
/* ISSYMREF=0x01, ISPACKED=0x02 and ISBROKEN=0x04 are public interfaces */
#define REF_KNOWS_PEELED 0x10
struct ref_entry {
unsigned char flag; /* ISSYMREF? ISPACKED? */
@ -332,12 +331,12 @@ static void get_ref_dir(const char *submodule, const char *base,
flag = 0;
if (resolve_gitlink_ref(submodule, ref, sha1) < 0) {
hashclr(sha1);
flag |= REF_BROKEN;
flag |= REF_ISBROKEN;
}
} else
if (!resolve_ref(ref, sha1, 1, &flag)) {
hashclr(sha1);
flag |= REF_BROKEN;
flag |= REF_ISBROKEN;
}
add_ref(ref, sha1, flag, array, NULL);
}
@ -504,7 +503,6 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
ssize_t len;
char buffer[256];
static char ref_buffer[256];
char path[PATH_MAX];
if (flag)
*flag = 0;
@ -513,6 +511,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
return NULL;
for (;;) {
char path[PATH_MAX];
struct stat st;
char *buf;
int fd;
@ -585,21 +584,22 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
*/
if (prefixcmp(buffer, "ref:"))
break;
if (flag)
*flag |= REF_ISSYMREF;
buf = buffer + 4;
while (isspace(*buf))
buf++;
if (check_refname_format(buf, REFNAME_ALLOW_ONELEVEL)) {
warning("symbolic reference in %s is formatted incorrectly",
path);
if (flag)
*flag |= REF_ISBROKEN;
return NULL;
}
ref = strcpy(ref_buffer, buf);
if (flag)
*flag |= REF_ISSYMREF;
}
/* Please note that FETCH_HEAD has a second line containing other data. */
if (get_sha1_hex(buffer, sha1) || (buffer[40] != '\0' && !isspace(buffer[40]))) {
warning("reference in %s is formatted incorrectly", path);
if (flag)
*flag |= REF_ISBROKEN;
return NULL;
}
return ref;
@ -627,8 +627,8 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim,
return 0;
if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
if (entry->flag & REF_BROKEN)
return 0; /* ignore dangling symref */
if (entry->flag & REF_ISBROKEN)
return 0; /* ignore broken refs e.g. dangling symref */
if (!has_sha1_file(entry->sha1)) {
error("%s does not point to a valid object!", entry->name);
return 0;
@ -1078,6 +1078,94 @@ static int is_refname_available(const char *ref, const char *oldref,
return 1;
}
/*
* *string and *len will only be substituted, and *string returned (for
* later free()ing) if the string passed in is a magic short-hand form
* to name a branch.
*/
static char *substitute_branch_name(const char **string, int *len)
{
struct strbuf buf = STRBUF_INIT;
int ret = interpret_branch_name(*string, &buf);
if (ret == *len) {
size_t size;
*string = strbuf_detach(&buf, &size);
*len = size;
return (char *)*string;
}
return NULL;
}
int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
{
char *last_branch = substitute_branch_name(&str, &len);
const char **p, *r;
int refs_found = 0;
*ref = NULL;
for (p = ref_rev_parse_rules; *p; p++) {
char fullref[PATH_MAX];
unsigned char sha1_from_ref[20];
unsigned char *this_result;
int flag;
this_result = refs_found ? sha1_from_ref : sha1;
mksnpath(fullref, sizeof(fullref), *p, len, str);
r = resolve_ref(fullref, this_result, 1, &flag);
if (r) {
if (!refs_found++)
*ref = xstrdup(r);
if (!warn_ambiguous_refs)
break;
} else if ((flag & REF_ISSYMREF) && strcmp(fullref, "HEAD")) {
warning("ignoring dangling symref %s.", fullref);
} else if ((flag & REF_ISBROKEN) && strchr(fullref, '/')) {
warning("ignoring broken ref %s.", fullref);
}
}
free(last_branch);
return refs_found;
}
int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
{
char *last_branch = substitute_branch_name(&str, &len);
const char **p;
int logs_found = 0;
*log = NULL;
for (p = ref_rev_parse_rules; *p; p++) {
struct stat st;
unsigned char hash[20];
char path[PATH_MAX];
const char *ref, *it;
mksnpath(path, sizeof(path), *p, len, str);
ref = resolve_ref(path, hash, 1, NULL);
if (!ref)
continue;
if (!stat(git_path("logs/%s", path), &st) &&
S_ISREG(st.st_mode))
it = path;
else if (strcmp(ref, path) &&
!stat(git_path("logs/%s", ref), &st) &&
S_ISREG(st.st_mode))
it = ref;
else
continue;
if (!logs_found++) {
*log = xstrdup(it);
hashcpy(sha1, hash);
}
if (!warn_ambiguous_refs)
break;
}
free(last_branch);
return logs_found;
}
static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char *old_sha1, int flags, int *type_p)
{
char *ref_file;

5
refs.h
Просмотреть файл

@ -10,8 +10,9 @@ struct ref_lock {
int force_write;
};
#define REF_ISSYMREF 01
#define REF_ISPACKED 02
#define REF_ISSYMREF 0x01
#define REF_ISPACKED 0x02
#define REF_ISBROKEN 0x04
/*
* Calls the specified function for each ref file until it returns nonzero,

Просмотреть файл

@ -241,91 +241,6 @@ static int ambiguous_path(const char *path, int len)
return slash;
}
/*
* *string and *len will only be substituted, and *string returned (for
* later free()ing) if the string passed in is a magic short-hand form
* to name a branch.
*/
static char *substitute_branch_name(const char **string, int *len)
{
struct strbuf buf = STRBUF_INIT;
int ret = interpret_branch_name(*string, &buf);
if (ret == *len) {
size_t size;
*string = strbuf_detach(&buf, &size);
*len = size;
return (char *)*string;
}
return NULL;
}
int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
{
char *last_branch = substitute_branch_name(&str, &len);
const char **p, *r;
int refs_found = 0;
*ref = NULL;
for (p = ref_rev_parse_rules; *p; p++) {
char fullref[PATH_MAX];
unsigned char sha1_from_ref[20];
unsigned char *this_result;
int flag;
this_result = refs_found ? sha1_from_ref : sha1;
mksnpath(fullref, sizeof(fullref), *p, len, str);
r = resolve_ref(fullref, this_result, 1, &flag);
if (r) {
if (!refs_found++)
*ref = xstrdup(r);
if (!warn_ambiguous_refs)
break;
} else if ((flag & REF_ISSYMREF) && strcmp(fullref, "HEAD"))
warning("ignoring dangling symref %s.", fullref);
}
free(last_branch);
return refs_found;
}
int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
{
char *last_branch = substitute_branch_name(&str, &len);
const char **p;
int logs_found = 0;
*log = NULL;
for (p = ref_rev_parse_rules; *p; p++) {
struct stat st;
unsigned char hash[20];
char path[PATH_MAX];
const char *ref, *it;
mksnpath(path, sizeof(path), *p, len, str);
ref = resolve_ref(path, hash, 1, NULL);
if (!ref)
continue;
if (!stat(git_path("logs/%s", path), &st) &&
S_ISREG(st.st_mode))
it = path;
else if (strcmp(ref, path) &&
!stat(git_path("logs/%s", ref), &st) &&
S_ISREG(st.st_mode))
it = ref;
else
continue;
if (!logs_found++) {
*log = xstrdup(it);
hashcpy(sha1, hash);
}
if (!warn_ambiguous_refs)
break;
}
free(last_branch);
return logs_found;
}
static inline int upstream_mark(const char *string, int len)
{
const char *suffix[] = { "@{upstream}", "@{u}" };