scan reflogs independently from refs
Currently, the search for all reflogs depends on the existence of corresponding refs under the .git/refs/ directory. Let's scan the .git/logs/ directory directly instead. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
a7e4fbf990
commit
eb8381c885
@ -245,14 +245,11 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,
|
|||||||
char *log_file, *newlog_path = NULL;
|
char *log_file, *newlog_path = NULL;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
if (strncmp(ref, "refs/", 5))
|
|
||||||
return error("not a ref '%s'", ref);
|
|
||||||
|
|
||||||
memset(&cb, 0, sizeof(cb));
|
memset(&cb, 0, sizeof(cb));
|
||||||
/* we take the lock for the ref itself to prevent it from
|
/* we take the lock for the ref itself to prevent it from
|
||||||
* getting updated.
|
* getting updated.
|
||||||
*/
|
*/
|
||||||
lock = lock_ref_sha1(ref + 5, sha1);
|
lock = lock_any_ref_for_update(ref, sha1);
|
||||||
if (!lock)
|
if (!lock)
|
||||||
return error("cannot lock ref '%s'", ref);
|
return error("cannot lock ref '%s'", ref);
|
||||||
log_file = xstrdup(git_path("logs/%s", ref));
|
log_file = xstrdup(git_path("logs/%s", ref));
|
||||||
@ -353,7 +350,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (do_all)
|
if (do_all)
|
||||||
status |= for_each_ref(expire_reflog, &cb);
|
status |= for_each_reflog(expire_reflog, &cb);
|
||||||
while (i < argc) {
|
while (i < argc) {
|
||||||
const char *ref = argv[i++];
|
const char *ref = argv[i++];
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
|
@ -477,6 +477,12 @@ static int fsck_handle_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int fsck_handle_reflog(const char *logname, const unsigned char *sha1, int flag, void *cb_data)
|
||||||
|
{
|
||||||
|
for_each_reflog_ent(logname, fsck_handle_reflog_ent, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int fsck_handle_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
|
static int fsck_handle_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
|
||||||
{
|
{
|
||||||
struct object *obj;
|
struct object *obj;
|
||||||
@ -495,14 +501,13 @@ static int fsck_handle_ref(const char *refname, const unsigned char *sha1, int f
|
|||||||
obj->used = 1;
|
obj->used = 1;
|
||||||
mark_reachable(obj, REACHABLE);
|
mark_reachable(obj, REACHABLE);
|
||||||
|
|
||||||
for_each_reflog_ent(refname, fsck_handle_reflog_ent, NULL);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_default_heads(void)
|
static void get_default_heads(void)
|
||||||
{
|
{
|
||||||
for_each_ref(fsck_handle_ref, NULL);
|
for_each_ref(fsck_handle_ref, NULL);
|
||||||
|
for_each_reflog(fsck_handle_reflog, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Not having any default heads isn't really fatal, but
|
* Not having any default heads isn't really fatal, but
|
||||||
|
@ -188,9 +188,9 @@ void mark_reachable_objects(struct rev_info *revs, int mark_reflog)
|
|||||||
/* Add all external refs */
|
/* Add all external refs */
|
||||||
for_each_ref(add_one_ref, revs);
|
for_each_ref(add_one_ref, revs);
|
||||||
|
|
||||||
/* Add all reflog info from refs */
|
/* Add all reflog info */
|
||||||
if (mark_reflog)
|
if (mark_reflog)
|
||||||
for_each_ref(add_one_reflog, revs);
|
for_each_reflog(add_one_reflog, revs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up the revision walk - this will move all commits
|
* Set up the revision walk - this will move all commits
|
||||||
|
50
refs.c
50
refs.c
@ -1201,3 +1201,53 @@ int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_for_each_reflog(const char *base, each_ref_fn fn, void *cb_data)
|
||||||
|
{
|
||||||
|
DIR *dir = opendir(git_path("logs/%s", base));
|
||||||
|
int retval = errno;
|
||||||
|
|
||||||
|
if (dir) {
|
||||||
|
struct dirent *de;
|
||||||
|
int baselen = strlen(base);
|
||||||
|
char *log = xmalloc(baselen + 257);
|
||||||
|
|
||||||
|
memcpy(log, base, baselen);
|
||||||
|
if (baselen && base[baselen-1] != '/')
|
||||||
|
log[baselen++] = '/';
|
||||||
|
|
||||||
|
while ((de = readdir(dir)) != NULL) {
|
||||||
|
struct stat st;
|
||||||
|
int namelen;
|
||||||
|
|
||||||
|
if (de->d_name[0] == '.')
|
||||||
|
continue;
|
||||||
|
namelen = strlen(de->d_name);
|
||||||
|
if (namelen > 255)
|
||||||
|
continue;
|
||||||
|
if (has_extension(de->d_name, ".lock"))
|
||||||
|
continue;
|
||||||
|
memcpy(log + baselen, de->d_name, namelen+1);
|
||||||
|
if (stat(git_path("logs/%s", log), &st) < 0)
|
||||||
|
continue;
|
||||||
|
if (S_ISDIR(st.st_mode)) {
|
||||||
|
retval = do_for_each_reflog(log, fn, cb_data);
|
||||||
|
} else {
|
||||||
|
unsigned char sha1[20];
|
||||||
|
if (!resolve_ref(log, sha1, 0, NULL))
|
||||||
|
retval = error("bad ref for %s", log);
|
||||||
|
else
|
||||||
|
retval = fn(log, sha1, 0, cb_data);
|
||||||
|
}
|
||||||
|
if (retval)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(log);
|
||||||
|
closedir(dir);
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int for_each_reflog(each_ref_fn fn, void *cb_data)
|
||||||
|
{
|
||||||
|
return do_for_each_reflog("", fn, cb_data);
|
||||||
|
}
|
||||||
|
6
refs.h
6
refs.h
@ -48,6 +48,12 @@ extern int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned
|
|||||||
typedef int each_reflog_ent_fn(unsigned char *osha1, unsigned char *nsha1, const char *, unsigned long, int, const char *, void *);
|
typedef int each_reflog_ent_fn(unsigned char *osha1, unsigned char *nsha1, const char *, unsigned long, int, const char *, void *);
|
||||||
int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data);
|
int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calls the specified function for each reflog file until it returns nonzero,
|
||||||
|
* and returns the value
|
||||||
|
*/
|
||||||
|
extern int for_each_reflog(each_ref_fn, void *);
|
||||||
|
|
||||||
/** Returns 0 if target has the right format for a ref. **/
|
/** Returns 0 if target has the right format for a ref. **/
|
||||||
extern int check_ref_format(const char *target);
|
extern int check_ref_format(const char *target);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user