Merge branch 'jp/get-ref-dir-unsorted'
* jp/get-ref-dir-unsorted: refs.c: free duplicate entries in the ref array instead of leaking them refs.c: abort ref search if ref array is empty refs.c: ensure struct whose member may be passed to realloc is initialized refs: Use binary search to lookup refs faster Don't sort ref_list too early Conflicts: refs.c
This commit is contained in:
commit
2c5c66be6e
349
refs.c
349
refs.c
@ -8,14 +8,18 @@
|
|||||||
#define REF_KNOWS_PEELED 04
|
#define REF_KNOWS_PEELED 04
|
||||||
#define REF_BROKEN 010
|
#define REF_BROKEN 010
|
||||||
|
|
||||||
struct ref_list {
|
struct ref_entry {
|
||||||
struct ref_list *next;
|
|
||||||
unsigned char flag; /* ISSYMREF? ISPACKED? */
|
unsigned char flag; /* ISSYMREF? ISPACKED? */
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
unsigned char peeled[20];
|
unsigned char peeled[20];
|
||||||
char name[FLEX_ARRAY];
|
char name[FLEX_ARRAY];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ref_array {
|
||||||
|
int nr, alloc;
|
||||||
|
struct ref_entry **refs;
|
||||||
|
};
|
||||||
|
|
||||||
static const char *parse_ref_line(char *line, unsigned char *sha1)
|
static const char *parse_ref_line(char *line, unsigned char *sha1)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -44,110 +48,86 @@ static const char *parse_ref_line(char *line, unsigned char *sha1)
|
|||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ref_list *add_ref(const char *name, const unsigned char *sha1,
|
static void add_ref(const char *name, const unsigned char *sha1,
|
||||||
int flag, struct ref_list *list,
|
int flag, struct ref_array *refs,
|
||||||
struct ref_list **new_entry)
|
struct ref_entry **new_entry)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
struct ref_list *entry;
|
struct ref_entry *entry;
|
||||||
|
|
||||||
/* Allocate it and add it in.. */
|
/* Allocate it and add it in.. */
|
||||||
len = strlen(name) + 1;
|
len = strlen(name) + 1;
|
||||||
entry = xmalloc(sizeof(struct ref_list) + len);
|
entry = xmalloc(sizeof(struct ref_entry) + len);
|
||||||
hashcpy(entry->sha1, sha1);
|
hashcpy(entry->sha1, sha1);
|
||||||
hashclr(entry->peeled);
|
hashclr(entry->peeled);
|
||||||
if (check_refname_format(name, REFNAME_ALLOW_ONELEVEL|REFNAME_DOT_COMPONENT))
|
if (check_refname_format(name, REFNAME_ALLOW_ONELEVEL|REFNAME_DOT_COMPONENT))
|
||||||
die("Reference has invalid format: '%s'", name);
|
die("Reference has invalid format: '%s'", name);
|
||||||
memcpy(entry->name, name, len);
|
memcpy(entry->name, name, len);
|
||||||
entry->flag = flag;
|
entry->flag = flag;
|
||||||
entry->next = list;
|
|
||||||
if (new_entry)
|
if (new_entry)
|
||||||
*new_entry = entry;
|
*new_entry = entry;
|
||||||
return entry;
|
ALLOC_GROW(refs->refs, refs->nr + 1, refs->alloc);
|
||||||
|
refs->refs[refs->nr++] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* merge sort the ref list */
|
static int ref_entry_cmp(const void *a, const void *b)
|
||||||
static struct ref_list *sort_ref_list(struct ref_list *list)
|
|
||||||
{
|
{
|
||||||
int psize, qsize, last_merge_count, cmp;
|
struct ref_entry *one = *(struct ref_entry **)a;
|
||||||
struct ref_list *p, *q, *l, *e;
|
struct ref_entry *two = *(struct ref_entry **)b;
|
||||||
struct ref_list *new_list = list;
|
return strcmp(one->name, two->name);
|
||||||
int k = 1;
|
}
|
||||||
int merge_count = 0;
|
|
||||||
|
|
||||||
if (!list)
|
static void sort_ref_array(struct ref_array *array)
|
||||||
return list;
|
{
|
||||||
|
int i = 0, j = 1;
|
||||||
|
|
||||||
do {
|
/* Nothing to sort unless there are at least two entries */
|
||||||
last_merge_count = merge_count;
|
if (array->nr < 2)
|
||||||
merge_count = 0;
|
return;
|
||||||
|
|
||||||
psize = 0;
|
qsort(array->refs, array->nr, sizeof(*array->refs), ref_entry_cmp);
|
||||||
|
|
||||||
p = new_list;
|
/* Remove any duplicates from the ref_array */
|
||||||
q = new_list;
|
for (; j < array->nr; j++) {
|
||||||
new_list = NULL;
|
struct ref_entry *a = array->refs[i];
|
||||||
l = NULL;
|
struct ref_entry *b = array->refs[j];
|
||||||
|
if (!strcmp(a->name, b->name)) {
|
||||||
|
if (hashcmp(a->sha1, b->sha1))
|
||||||
|
die("Duplicated ref, and SHA1s don't match: %s",
|
||||||
|
a->name);
|
||||||
|
warning("Duplicated ref: %s", a->name);
|
||||||
|
free(b);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
array->refs[i] = array->refs[j];
|
||||||
|
}
|
||||||
|
array->nr = i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
while (p) {
|
static struct ref_entry *search_ref_array(struct ref_array *array, const char *name)
|
||||||
merge_count++;
|
{
|
||||||
|
struct ref_entry *e, **r;
|
||||||
|
int len;
|
||||||
|
|
||||||
while (psize < k && q->next) {
|
if (name == NULL)
|
||||||
q = q->next;
|
return NULL;
|
||||||
psize++;
|
|
||||||
}
|
|
||||||
qsize = k;
|
|
||||||
|
|
||||||
while ((psize > 0) || (qsize > 0 && q)) {
|
if (!array->nr)
|
||||||
if (qsize == 0 || !q) {
|
return NULL;
|
||||||
e = p;
|
|
||||||
p = p->next;
|
|
||||||
psize--;
|
|
||||||
} else if (psize == 0) {
|
|
||||||
e = q;
|
|
||||||
q = q->next;
|
|
||||||
qsize--;
|
|
||||||
} else {
|
|
||||||
cmp = strcmp(q->name, p->name);
|
|
||||||
if (cmp < 0) {
|
|
||||||
e = q;
|
|
||||||
q = q->next;
|
|
||||||
qsize--;
|
|
||||||
} else if (cmp > 0) {
|
|
||||||
e = p;
|
|
||||||
p = p->next;
|
|
||||||
psize--;
|
|
||||||
} else {
|
|
||||||
if (hashcmp(q->sha1, p->sha1))
|
|
||||||
die("Duplicated ref, and SHA1s don't match: %s",
|
|
||||||
q->name);
|
|
||||||
warning("Duplicated ref: %s", q->name);
|
|
||||||
e = q;
|
|
||||||
q = q->next;
|
|
||||||
qsize--;
|
|
||||||
free(e);
|
|
||||||
e = p;
|
|
||||||
p = p->next;
|
|
||||||
psize--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
e->next = NULL;
|
len = strlen(name) + 1;
|
||||||
|
e = xmalloc(sizeof(struct ref_entry) + len);
|
||||||
|
memcpy(e->name, name, len);
|
||||||
|
|
||||||
if (l)
|
r = bsearch(&e, array->refs, array->nr, sizeof(*array->refs), ref_entry_cmp);
|
||||||
l->next = e;
|
|
||||||
if (!new_list)
|
|
||||||
new_list = e;
|
|
||||||
l = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = q;
|
free(e);
|
||||||
};
|
|
||||||
|
|
||||||
k = k * 2;
|
if (r == NULL)
|
||||||
} while ((last_merge_count != merge_count) || (last_merge_count != 1));
|
return NULL;
|
||||||
|
|
||||||
return new_list;
|
return *r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -158,32 +138,32 @@ static struct cached_refs {
|
|||||||
struct cached_refs *next;
|
struct cached_refs *next;
|
||||||
char did_loose;
|
char did_loose;
|
||||||
char did_packed;
|
char did_packed;
|
||||||
struct ref_list *loose;
|
struct ref_array loose;
|
||||||
struct ref_list *packed;
|
struct ref_array packed;
|
||||||
/* The submodule name, or "" for the main repo. */
|
/* The submodule name, or "" for the main repo. */
|
||||||
char name[FLEX_ARRAY];
|
char name[FLEX_ARRAY];
|
||||||
} *cached_refs;
|
} *cached_refs;
|
||||||
|
|
||||||
static struct ref_list *current_ref;
|
static struct ref_entry *current_ref;
|
||||||
|
|
||||||
static struct ref_list *extra_refs;
|
static struct ref_array extra_refs;
|
||||||
|
|
||||||
static void free_ref_list(struct ref_list *list)
|
static void free_ref_array(struct ref_array *array)
|
||||||
{
|
{
|
||||||
struct ref_list *next;
|
int i;
|
||||||
for ( ; list; list = next) {
|
for (i = 0; i < array->nr; i++)
|
||||||
next = list->next;
|
free(array->refs[i]);
|
||||||
free(list);
|
free(array->refs);
|
||||||
}
|
array->nr = array->alloc = 0;
|
||||||
|
array->refs = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_cached_refs(struct cached_refs *ca)
|
static void clear_cached_refs(struct cached_refs *ca)
|
||||||
{
|
{
|
||||||
if (ca->did_loose && ca->loose)
|
if (ca->did_loose)
|
||||||
free_ref_list(ca->loose);
|
free_ref_array(&ca->loose);
|
||||||
if (ca->did_packed && ca->packed)
|
if (ca->did_packed)
|
||||||
free_ref_list(ca->packed);
|
free_ref_array(&ca->packed);
|
||||||
ca->loose = ca->packed = NULL;
|
|
||||||
ca->did_loose = ca->did_packed = 0;
|
ca->did_loose = ca->did_packed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,10 +174,7 @@ static struct cached_refs *create_cached_refs(const char *submodule)
|
|||||||
if (!submodule)
|
if (!submodule)
|
||||||
submodule = "";
|
submodule = "";
|
||||||
len = strlen(submodule) + 1;
|
len = strlen(submodule) + 1;
|
||||||
refs = xmalloc(sizeof(struct cached_refs) + len);
|
refs = xcalloc(1, sizeof(struct cached_refs) + len);
|
||||||
refs->next = NULL;
|
|
||||||
refs->did_loose = refs->did_packed = 0;
|
|
||||||
refs->loose = refs->packed = NULL;
|
|
||||||
memcpy(refs->name, submodule, len);
|
memcpy(refs->name, submodule, len);
|
||||||
return refs;
|
return refs;
|
||||||
}
|
}
|
||||||
@ -234,10 +211,9 @@ static void invalidate_cached_refs(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ref_list *read_packed_refs(FILE *f)
|
static void read_packed_refs(FILE *f, struct ref_array *array)
|
||||||
{
|
{
|
||||||
struct ref_list *list = NULL;
|
struct ref_entry *last = NULL;
|
||||||
struct ref_list *last = NULL;
|
|
||||||
char refline[PATH_MAX];
|
char refline[PATH_MAX];
|
||||||
int flag = REF_ISPACKED;
|
int flag = REF_ISPACKED;
|
||||||
|
|
||||||
@ -256,7 +232,7 @@ static struct ref_list *read_packed_refs(FILE *f)
|
|||||||
|
|
||||||
name = parse_ref_line(refline, sha1);
|
name = parse_ref_line(refline, sha1);
|
||||||
if (name) {
|
if (name) {
|
||||||
list = add_ref(name, sha1, flag, list, &last);
|
add_ref(name, sha1, flag, array, &last);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (last &&
|
if (last &&
|
||||||
@ -266,21 +242,20 @@ static struct ref_list *read_packed_refs(FILE *f)
|
|||||||
!get_sha1_hex(refline + 1, sha1))
|
!get_sha1_hex(refline + 1, sha1))
|
||||||
hashcpy(last->peeled, sha1);
|
hashcpy(last->peeled, sha1);
|
||||||
}
|
}
|
||||||
return sort_ref_list(list);
|
sort_ref_array(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_extra_ref(const char *name, const unsigned char *sha1, int flag)
|
void add_extra_ref(const char *name, const unsigned char *sha1, int flag)
|
||||||
{
|
{
|
||||||
extra_refs = add_ref(name, sha1, flag, extra_refs, NULL);
|
add_ref(name, sha1, flag, &extra_refs, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_extra_refs(void)
|
void clear_extra_refs(void)
|
||||||
{
|
{
|
||||||
free_ref_list(extra_refs);
|
free_ref_array(&extra_refs);
|
||||||
extra_refs = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ref_list *get_packed_refs(const char *submodule)
|
static struct ref_array *get_packed_refs(const char *submodule)
|
||||||
{
|
{
|
||||||
struct cached_refs *refs = get_cached_refs(submodule);
|
struct cached_refs *refs = get_cached_refs(submodule);
|
||||||
|
|
||||||
@ -293,18 +268,17 @@ static struct ref_list *get_packed_refs(const char *submodule)
|
|||||||
else
|
else
|
||||||
packed_refs_file = git_path("packed-refs");
|
packed_refs_file = git_path("packed-refs");
|
||||||
f = fopen(packed_refs_file, "r");
|
f = fopen(packed_refs_file, "r");
|
||||||
refs->packed = NULL;
|
|
||||||
if (f) {
|
if (f) {
|
||||||
refs->packed = read_packed_refs(f);
|
read_packed_refs(f, &refs->packed);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
refs->did_packed = 1;
|
refs->did_packed = 1;
|
||||||
}
|
}
|
||||||
return refs->packed;
|
return &refs->packed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ref_list *get_ref_dir(const char *submodule, const char *base,
|
static void get_ref_dir(const char *submodule, const char *base,
|
||||||
struct ref_list *list)
|
struct ref_array *array)
|
||||||
{
|
{
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
const char *path;
|
const char *path;
|
||||||
@ -347,7 +321,7 @@ static struct ref_list *get_ref_dir(const char *submodule, const char *base,
|
|||||||
if (stat(refdir, &st) < 0)
|
if (stat(refdir, &st) < 0)
|
||||||
continue;
|
continue;
|
||||||
if (S_ISDIR(st.st_mode)) {
|
if (S_ISDIR(st.st_mode)) {
|
||||||
list = get_ref_dir(submodule, ref, list);
|
get_ref_dir(submodule, ref, array);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (submodule) {
|
if (submodule) {
|
||||||
@ -362,12 +336,11 @@ static struct ref_list *get_ref_dir(const char *submodule, const char *base,
|
|||||||
hashclr(sha1);
|
hashclr(sha1);
|
||||||
flag |= REF_BROKEN;
|
flag |= REF_BROKEN;
|
||||||
}
|
}
|
||||||
list = add_ref(ref, sha1, flag, list, NULL);
|
add_ref(ref, sha1, flag, array, NULL);
|
||||||
}
|
}
|
||||||
free(ref);
|
free(ref);
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
}
|
}
|
||||||
return sort_ref_list(list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct warn_if_dangling_data {
|
struct warn_if_dangling_data {
|
||||||
@ -404,15 +377,16 @@ void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
|
|||||||
for_each_rawref(warn_if_dangling_symref, &data);
|
for_each_rawref(warn_if_dangling_symref, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ref_list *get_loose_refs(const char *submodule)
|
static struct ref_array *get_loose_refs(const char *submodule)
|
||||||
{
|
{
|
||||||
struct cached_refs *refs = get_cached_refs(submodule);
|
struct cached_refs *refs = get_cached_refs(submodule);
|
||||||
|
|
||||||
if (!refs->did_loose) {
|
if (!refs->did_loose) {
|
||||||
refs->loose = get_ref_dir(submodule, "refs", NULL);
|
get_ref_dir(submodule, "refs", &refs->loose);
|
||||||
|
sort_ref_array(&refs->loose);
|
||||||
refs->did_loose = 1;
|
refs->did_loose = 1;
|
||||||
}
|
}
|
||||||
return refs->loose;
|
return &refs->loose;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We allow "recursive" symbolic refs. Only within reason, though */
|
/* We allow "recursive" symbolic refs. Only within reason, though */
|
||||||
@ -421,28 +395,15 @@ static struct ref_list *get_loose_refs(const char *submodule)
|
|||||||
|
|
||||||
static int resolve_gitlink_packed_ref(char *name, int pathlen, const char *refname, unsigned char *result)
|
static int resolve_gitlink_packed_ref(char *name, int pathlen, const char *refname, unsigned char *result)
|
||||||
{
|
{
|
||||||
FILE *f;
|
int retval = -1;
|
||||||
struct ref_list *packed_refs;
|
struct ref_entry *ref;
|
||||||
struct ref_list *ref;
|
struct ref_array *array = get_packed_refs(name);
|
||||||
int retval;
|
|
||||||
|
|
||||||
strcpy(name + pathlen, "packed-refs");
|
ref = search_ref_array(array, refname);
|
||||||
f = fopen(name, "r");
|
if (ref != NULL) {
|
||||||
if (!f)
|
memcpy(result, ref->sha1, 20);
|
||||||
return -1;
|
retval = 0;
|
||||||
packed_refs = read_packed_refs(f);
|
|
||||||
fclose(f);
|
|
||||||
ref = packed_refs;
|
|
||||||
retval = -1;
|
|
||||||
while (ref) {
|
|
||||||
if (!strcmp(ref->name, refname)) {
|
|
||||||
retval = 0;
|
|
||||||
memcpy(result, ref->sha1, 20);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ref = ref->next;
|
|
||||||
}
|
}
|
||||||
free_ref_list(packed_refs);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,13 +476,11 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *re
|
|||||||
*/
|
*/
|
||||||
static int get_packed_ref(const char *ref, unsigned char *sha1)
|
static int get_packed_ref(const char *ref, unsigned char *sha1)
|
||||||
{
|
{
|
||||||
struct ref_list *list = get_packed_refs(NULL);
|
struct ref_array *packed = get_packed_refs(NULL);
|
||||||
while (list) {
|
struct ref_entry *entry = search_ref_array(packed, ref);
|
||||||
if (!strcmp(ref, list->name)) {
|
if (entry) {
|
||||||
hashcpy(sha1, list->sha1);
|
hashcpy(sha1, entry->sha1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
list = list->next;
|
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -649,7 +608,7 @@ int read_ref(const char *ref, unsigned char *sha1)
|
|||||||
|
|
||||||
#define DO_FOR_EACH_INCLUDE_BROKEN 01
|
#define DO_FOR_EACH_INCLUDE_BROKEN 01
|
||||||
static int do_one_ref(const char *base, each_ref_fn fn, int trim,
|
static int do_one_ref(const char *base, each_ref_fn fn, int trim,
|
||||||
int flags, void *cb_data, struct ref_list *entry)
|
int flags, void *cb_data, struct ref_entry *entry)
|
||||||
{
|
{
|
||||||
if (prefixcmp(entry->name, base))
|
if (prefixcmp(entry->name, base))
|
||||||
return 0;
|
return 0;
|
||||||
@ -695,18 +654,12 @@ int peel_ref(const char *ref, unsigned char *sha1)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ((flag & REF_ISPACKED)) {
|
if ((flag & REF_ISPACKED)) {
|
||||||
struct ref_list *list = get_packed_refs(NULL);
|
struct ref_array *array = get_packed_refs(NULL);
|
||||||
|
struct ref_entry *r = search_ref_array(array, ref);
|
||||||
|
|
||||||
while (list) {
|
if (r != NULL && r->flag & REF_KNOWS_PEELED) {
|
||||||
if (!strcmp(list->name, ref)) {
|
hashcpy(sha1, r->peeled);
|
||||||
if (list->flag & REF_KNOWS_PEELED) {
|
return 0;
|
||||||
hashcpy(sha1, list->peeled);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* older pack-refs did not leave peeled ones */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
list = list->next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -725,36 +678,39 @@ fallback:
|
|||||||
static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn fn,
|
static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn fn,
|
||||||
int trim, int flags, void *cb_data)
|
int trim, int flags, void *cb_data)
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0, i, p = 0, l = 0;
|
||||||
struct ref_list *packed = get_packed_refs(submodule);
|
struct ref_array *packed = get_packed_refs(submodule);
|
||||||
struct ref_list *loose = get_loose_refs(submodule);
|
struct ref_array *loose = get_loose_refs(submodule);
|
||||||
|
|
||||||
struct ref_list *extra;
|
struct ref_array *extra = &extra_refs;
|
||||||
|
|
||||||
for (extra = extra_refs; extra; extra = extra->next)
|
for (i = 0; i < extra->nr; i++)
|
||||||
retval = do_one_ref(base, fn, trim, flags, cb_data, extra);
|
retval = do_one_ref(base, fn, trim, flags, cb_data, extra->refs[i]);
|
||||||
|
|
||||||
while (packed && loose) {
|
while (p < packed->nr && l < loose->nr) {
|
||||||
struct ref_list *entry;
|
struct ref_entry *entry;
|
||||||
int cmp = strcmp(packed->name, loose->name);
|
int cmp = strcmp(packed->refs[p]->name, loose->refs[l]->name);
|
||||||
if (!cmp) {
|
if (!cmp) {
|
||||||
packed = packed->next;
|
p++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (cmp > 0) {
|
if (cmp > 0) {
|
||||||
entry = loose;
|
entry = loose->refs[l++];
|
||||||
loose = loose->next;
|
|
||||||
} else {
|
} else {
|
||||||
entry = packed;
|
entry = packed->refs[p++];
|
||||||
packed = packed->next;
|
|
||||||
}
|
}
|
||||||
retval = do_one_ref(base, fn, trim, flags, cb_data, entry);
|
retval = do_one_ref(base, fn, trim, flags, cb_data, entry);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto end_each;
|
goto end_each;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (packed = packed ? packed : loose; packed; packed = packed->next) {
|
if (l < loose->nr) {
|
||||||
retval = do_one_ref(base, fn, trim, flags, cb_data, packed);
|
p = l;
|
||||||
|
packed = loose;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; p < packed->nr; p++) {
|
||||||
|
retval = do_one_ref(base, fn, trim, flags, cb_data, packed->refs[p]);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto end_each;
|
goto end_each;
|
||||||
}
|
}
|
||||||
@ -1087,24 +1043,24 @@ static int remove_empty_directories(const char *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int is_refname_available(const char *ref, const char *oldref,
|
static int is_refname_available(const char *ref, const char *oldref,
|
||||||
struct ref_list *list, int quiet)
|
struct ref_array *array, int quiet)
|
||||||
{
|
{
|
||||||
int namlen = strlen(ref); /* e.g. 'foo/bar' */
|
int i, namlen = strlen(ref); /* e.g. 'foo/bar' */
|
||||||
while (list) {
|
for (i = 0; i < array->nr; i++ ) {
|
||||||
/* list->name could be 'foo' or 'foo/bar/baz' */
|
struct ref_entry *entry = array->refs[i];
|
||||||
if (!oldref || strcmp(oldref, list->name)) {
|
/* entry->name could be 'foo' or 'foo/bar/baz' */
|
||||||
int len = strlen(list->name);
|
if (!oldref || strcmp(oldref, entry->name)) {
|
||||||
|
int len = strlen(entry->name);
|
||||||
int cmplen = (namlen < len) ? namlen : len;
|
int cmplen = (namlen < len) ? namlen : len;
|
||||||
const char *lead = (namlen < len) ? list->name : ref;
|
const char *lead = (namlen < len) ? entry->name : ref;
|
||||||
if (!strncmp(ref, list->name, cmplen) &&
|
if (!strncmp(ref, entry->name, cmplen) &&
|
||||||
lead[cmplen] == '/') {
|
lead[cmplen] == '/') {
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
error("'%s' exists; cannot create '%s'",
|
error("'%s' exists; cannot create '%s'",
|
||||||
list->name, ref);
|
entry->name, ref);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list = list->next;
|
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1207,18 +1163,13 @@ static struct lock_file packlock;
|
|||||||
|
|
||||||
static int repack_without_ref(const char *refname)
|
static int repack_without_ref(const char *refname)
|
||||||
{
|
{
|
||||||
struct ref_list *list, *packed_ref_list;
|
struct ref_array *packed;
|
||||||
int fd;
|
struct ref_entry *ref;
|
||||||
int found = 0;
|
int fd, i;
|
||||||
|
|
||||||
packed_ref_list = get_packed_refs(NULL);
|
packed = get_packed_refs(NULL);
|
||||||
for (list = packed_ref_list; list; list = list->next) {
|
ref = search_ref_array(packed, refname);
|
||||||
if (!strcmp(refname, list->name)) {
|
if (ref == NULL)
|
||||||
found = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
return 0;
|
return 0;
|
||||||
fd = hold_lock_file_for_update(&packlock, git_path("packed-refs"), 0);
|
fd = hold_lock_file_for_update(&packlock, git_path("packed-refs"), 0);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
@ -1226,17 +1177,19 @@ static int repack_without_ref(const char *refname)
|
|||||||
return error("cannot delete '%s' from packed refs", refname);
|
return error("cannot delete '%s' from packed refs", refname);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (list = packed_ref_list; list; list = list->next) {
|
for (i = 0; i < packed->nr; i++) {
|
||||||
char line[PATH_MAX + 100];
|
char line[PATH_MAX + 100];
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (!strcmp(refname, list->name))
|
ref = packed->refs[i];
|
||||||
|
|
||||||
|
if (!strcmp(refname, ref->name))
|
||||||
continue;
|
continue;
|
||||||
len = snprintf(line, sizeof(line), "%s %s\n",
|
len = snprintf(line, sizeof(line), "%s %s\n",
|
||||||
sha1_to_hex(list->sha1), list->name);
|
sha1_to_hex(ref->sha1), ref->name);
|
||||||
/* this should not happen but just being defensive */
|
/* this should not happen but just being defensive */
|
||||||
if (len > sizeof(line))
|
if (len > sizeof(line))
|
||||||
die("too long a refname '%s'", list->name);
|
die("too long a refname '%s'", ref->name);
|
||||||
write_or_die(fd, line, len);
|
write_or_die(fd, line, len);
|
||||||
}
|
}
|
||||||
return commit_lock_file(&packlock);
|
return commit_lock_file(&packlock);
|
||||||
@ -1931,7 +1884,7 @@ int update_ref(const char *action, const char *refname,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ref_exists(char *refname)
|
int ref_exists(const char *refname)
|
||||||
{
|
{
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
return !!resolve_ref(refname, sha1, 1, NULL);
|
return !!resolve_ref(refname, sha1, 1, NULL);
|
||||||
|
2
refs.h
2
refs.h
@ -57,7 +57,7 @@ extern void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refn
|
|||||||
*/
|
*/
|
||||||
extern void add_extra_ref(const char *refname, const unsigned char *sha1, int flags);
|
extern void add_extra_ref(const char *refname, const unsigned char *sha1, int flags);
|
||||||
extern void clear_extra_refs(void);
|
extern void clear_extra_refs(void);
|
||||||
extern int ref_exists(char *);
|
extern int ref_exists(const char *);
|
||||||
|
|
||||||
extern int peel_ref(const char *, unsigned char *);
|
extern int peel_ref(const char *, unsigned char *);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user