Store peeled refs in packed-refs file.
This would speed up "show-ref -d" in a repository with mostly packed tags. Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
73
refs.c
73
refs.c
@ -1,16 +1,18 @@
|
||||
#include "refs.h"
|
||||
#include "cache.h"
|
||||
#include "object.h"
|
||||
#include "tag.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
struct ref_list {
|
||||
struct ref_list *next;
|
||||
unsigned char flag; /* ISSYMREF? ISPACKED? */
|
||||
unsigned char flag; /* ISSYMREF? ISPACKED? ISPEELED? */
|
||||
unsigned char sha1[20];
|
||||
char name[FLEX_ARRAY];
|
||||
};
|
||||
|
||||
static const char *parse_ref_line(char *line, unsigned char *sha1)
|
||||
static const char *parse_ref_line(char *line, unsigned char *sha1, int *flag)
|
||||
{
|
||||
/*
|
||||
* 42: the answer to everything.
|
||||
@ -21,6 +23,7 @@ static const char *parse_ref_line(char *line, unsigned char *sha1)
|
||||
* +1 (newline at the end of the line)
|
||||
*/
|
||||
int len = strlen(line) - 42;
|
||||
int peeled = 0;
|
||||
|
||||
if (len <= 0)
|
||||
return NULL;
|
||||
@ -29,11 +32,24 @@ static const char *parse_ref_line(char *line, unsigned char *sha1)
|
||||
if (!isspace(line[40]))
|
||||
return NULL;
|
||||
line += 41;
|
||||
if (isspace(*line))
|
||||
return NULL;
|
||||
|
||||
if (isspace(*line)) {
|
||||
/* "SHA-1 SP SP refs/tags/tagname^{} LF"? */
|
||||
line++;
|
||||
len--;
|
||||
peeled = 1;
|
||||
}
|
||||
if (line[len] != '\n')
|
||||
return NULL;
|
||||
line[len] = 0;
|
||||
|
||||
if (peeled && (len < 3 || strcmp(line + len - 3, "^{}")))
|
||||
return NULL;
|
||||
|
||||
if (!peeled)
|
||||
*flag &= ~REF_ISPEELED;
|
||||
else
|
||||
*flag |= REF_ISPEELED;
|
||||
return line;
|
||||
}
|
||||
|
||||
@ -108,10 +124,12 @@ static struct ref_list *get_packed_refs(void)
|
||||
char refline[PATH_MAX];
|
||||
while (fgets(refline, sizeof(refline), f)) {
|
||||
unsigned char sha1[20];
|
||||
const char *name = parse_ref_line(refline, sha1);
|
||||
int flag = REF_ISPACKED;
|
||||
const char *name =
|
||||
parse_ref_line(refline, sha1, &flag);
|
||||
if (!name)
|
||||
continue;
|
||||
list = add_ref(name, sha1, REF_ISPACKED, list);
|
||||
list = add_ref(name, sha1, flag, list);
|
||||
}
|
||||
fclose(f);
|
||||
refs = list;
|
||||
@ -207,7 +225,8 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
|
||||
if (lstat(path, &st) < 0) {
|
||||
struct ref_list *list = get_packed_refs();
|
||||
while (list) {
|
||||
if (!strcmp(ref, list->name)) {
|
||||
if (!(list->flag & REF_ISPEELED) &&
|
||||
!strcmp(ref, list->name)) {
|
||||
hashcpy(sha1, list->sha1);
|
||||
if (flag)
|
||||
*flag |= REF_ISPACKED;
|
||||
@ -329,6 +348,8 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim,
|
||||
return 0;
|
||||
if (is_null_sha1(entry->sha1))
|
||||
return 0;
|
||||
if (entry->flag & REF_ISPEELED)
|
||||
return 0;
|
||||
if (!has_sha1_file(entry->sha1)) {
|
||||
error("%s does not point to a valid object!", entry->name);
|
||||
return 0;
|
||||
@ -336,6 +357,44 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim,
|
||||
return fn(entry->name + trim, entry->sha1, entry->flag, cb_data);
|
||||
}
|
||||
|
||||
int peel_ref(const char *ref, unsigned char *sha1)
|
||||
{
|
||||
int flag;
|
||||
unsigned char base[20];
|
||||
struct object *o;
|
||||
|
||||
if (!resolve_ref(ref, base, 1, &flag))
|
||||
return -1;
|
||||
|
||||
if ((flag & REF_ISPACKED)) {
|
||||
struct ref_list *list = get_packed_refs();
|
||||
int len = strlen(ref);
|
||||
|
||||
while (list) {
|
||||
if ((list->flag & REF_ISPEELED) &&
|
||||
!strncmp(list->name, ref, len) &&
|
||||
strlen(list->name) == len + 3 &&
|
||||
!strcmp(list->name + len, "^{}")) {
|
||||
hashcpy(sha1, list->sha1);
|
||||
return 0;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
/* older pack-refs did not leave peeled ones in */
|
||||
}
|
||||
|
||||
/* otherwise ... */
|
||||
o = parse_object(base);
|
||||
if (o->type == OBJ_TAG) {
|
||||
o = deref_tag(o, ref, 0);
|
||||
if (o) {
|
||||
hashcpy(sha1, o->sha1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int do_for_each_ref(const char *base, each_ref_fn fn, int trim,
|
||||
void *cb_data)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user