refs: add methods for reflog
In the file-based backend, the reflog piggybacks on the ref lock. Since other backends won't have the same sort of ref lock, ref backends must also handle reflogs. Signed-off-by: Ronnie Sahlberg <rsahlberg@google.com> Signed-off-by: David Turner <dturner@twopensource.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
1a769003c1
commit
e3688bd6cf
63
refs.c
63
refs.c
@ -1461,3 +1461,66 @@ int verify_refname_available(const char *refname,
|
||||
|
||||
return refs->be->verify_refname_available(refs, refname, extra, skip, err);
|
||||
}
|
||||
|
||||
int for_each_reflog(each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
struct ref_iterator *iter;
|
||||
|
||||
iter = refs->be->reflog_iterator_begin(refs);
|
||||
|
||||
return do_for_each_ref_iterator(iter, fn, cb_data);
|
||||
}
|
||||
|
||||
int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,
|
||||
void *cb_data)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
|
||||
return refs->be->for_each_reflog_ent_reverse(refs, refname,
|
||||
fn, cb_data);
|
||||
}
|
||||
|
||||
int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn,
|
||||
void *cb_data)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
|
||||
return refs->be->for_each_reflog_ent(refs, refname, fn, cb_data);
|
||||
}
|
||||
|
||||
int reflog_exists(const char *refname)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
|
||||
return refs->be->reflog_exists(refs, refname);
|
||||
}
|
||||
|
||||
int safe_create_reflog(const char *refname, int force_create,
|
||||
struct strbuf *err)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
|
||||
return refs->be->create_reflog(refs, refname, force_create, err);
|
||||
}
|
||||
|
||||
int delete_reflog(const char *refname)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
|
||||
return refs->be->delete_reflog(refs, refname);
|
||||
}
|
||||
|
||||
int reflog_expire(const char *refname, const unsigned char *sha1,
|
||||
unsigned int flags,
|
||||
reflog_expiry_prepare_fn prepare_fn,
|
||||
reflog_expiry_should_prune_fn should_prune_fn,
|
||||
reflog_expiry_cleanup_fn cleanup_fn,
|
||||
void *policy_cb_data)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
|
||||
return refs->be->reflog_expire(refs, refname, sha1, flags,
|
||||
prepare_fn, should_prune_fn,
|
||||
cleanup_fn, policy_cb_data);
|
||||
}
|
||||
|
@ -2777,11 +2777,16 @@ static int log_ref_setup(const char *refname, struct strbuf *logfile, struct str
|
||||
}
|
||||
|
||||
|
||||
int safe_create_reflog(const char *refname, int force_create, struct strbuf *err)
|
||||
static int files_create_reflog(struct ref_store *ref_store,
|
||||
const char *refname, int force_create,
|
||||
struct strbuf *err)
|
||||
{
|
||||
int ret;
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
|
||||
/* Check validity (but we don't need the result): */
|
||||
files_downcast(ref_store, 0, "create_reflog");
|
||||
|
||||
ret = log_ref_setup(refname, &sb, err, force_create);
|
||||
strbuf_release(&sb);
|
||||
return ret;
|
||||
@ -3075,16 +3080,24 @@ int set_worktree_head_symref(const char *gitdir, const char *target)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int reflog_exists(const char *refname)
|
||||
static int files_reflog_exists(struct ref_store *ref_store,
|
||||
const char *refname)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
/* Check validity (but we don't need the result): */
|
||||
files_downcast(ref_store, 0, "reflog_exists");
|
||||
|
||||
return !lstat(git_path("logs/%s", refname), &st) &&
|
||||
S_ISREG(st.st_mode);
|
||||
}
|
||||
|
||||
int delete_reflog(const char *refname)
|
||||
static int files_delete_reflog(struct ref_store *ref_store,
|
||||
const char *refname)
|
||||
{
|
||||
/* Check validity (but we don't need the result): */
|
||||
files_downcast(ref_store, 0, "delete_reflog");
|
||||
|
||||
return remove_path(git_path("logs/%s", refname));
|
||||
}
|
||||
|
||||
@ -3127,13 +3140,19 @@ static char *find_beginning_of_line(char *bob, char *scan)
|
||||
return scan;
|
||||
}
|
||||
|
||||
int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void *cb_data)
|
||||
static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store,
|
||||
const char *refname,
|
||||
each_reflog_ent_fn fn,
|
||||
void *cb_data)
|
||||
{
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
FILE *logfp;
|
||||
long pos;
|
||||
int ret = 0, at_tail = 1;
|
||||
|
||||
/* Check validity (but we don't need the result): */
|
||||
files_downcast(ref_store, 0, "for_each_reflog_ent_reverse");
|
||||
|
||||
logfp = fopen(git_path("logs/%s", refname), "r");
|
||||
if (!logfp)
|
||||
return -1;
|
||||
@ -3229,12 +3248,17 @@ int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void
|
||||
return ret;
|
||||
}
|
||||
|
||||
int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_data)
|
||||
static int files_for_each_reflog_ent(struct ref_store *ref_store,
|
||||
const char *refname,
|
||||
each_reflog_ent_fn fn, void *cb_data)
|
||||
{
|
||||
FILE *logfp;
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
int ret = 0;
|
||||
|
||||
/* Check validity (but we don't need the result): */
|
||||
files_downcast(ref_store, 0, "for_each_reflog_ent");
|
||||
|
||||
logfp = fopen(git_path("logs/%s", refname), "r");
|
||||
if (!logfp)
|
||||
return -1;
|
||||
@ -3313,22 +3337,19 @@ static struct ref_iterator_vtable files_reflog_iterator_vtable = {
|
||||
files_reflog_iterator_abort
|
||||
};
|
||||
|
||||
struct ref_iterator *files_reflog_iterator_begin(void)
|
||||
static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_store)
|
||||
{
|
||||
struct files_reflog_iterator *iter = xcalloc(1, sizeof(*iter));
|
||||
struct ref_iterator *ref_iterator = &iter->base;
|
||||
|
||||
/* Check validity (but we don't need the result): */
|
||||
files_downcast(ref_store, 0, "reflog_iterator_begin");
|
||||
|
||||
base_ref_iterator_init(ref_iterator, &files_reflog_iterator_vtable);
|
||||
iter->dir_iterator = dir_iterator_begin(git_path("logs"));
|
||||
return ref_iterator;
|
||||
}
|
||||
|
||||
int for_each_reflog(each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref_iterator(files_reflog_iterator_begin(),
|
||||
fn, cb_data);
|
||||
}
|
||||
|
||||
static int ref_update_reject_duplicates(struct string_list *refnames,
|
||||
struct strbuf *err)
|
||||
{
|
||||
@ -3925,15 +3946,16 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int reflog_expire(const char *refname, const unsigned char *sha1,
|
||||
unsigned int flags,
|
||||
reflog_expiry_prepare_fn prepare_fn,
|
||||
reflog_expiry_should_prune_fn should_prune_fn,
|
||||
reflog_expiry_cleanup_fn cleanup_fn,
|
||||
void *policy_cb_data)
|
||||
static int files_reflog_expire(struct ref_store *ref_store,
|
||||
const char *refname, const unsigned char *sha1,
|
||||
unsigned int flags,
|
||||
reflog_expiry_prepare_fn prepare_fn,
|
||||
reflog_expiry_should_prune_fn should_prune_fn,
|
||||
reflog_expiry_cleanup_fn cleanup_fn,
|
||||
void *policy_cb_data)
|
||||
{
|
||||
struct files_ref_store *refs =
|
||||
get_files_ref_store(NULL, "reflog_expire");
|
||||
files_downcast(ref_store, 0, "reflog_expire");
|
||||
static struct lock_file reflog_lock;
|
||||
struct expire_reflog_cb cb;
|
||||
struct ref_lock *lock;
|
||||
@ -4046,5 +4068,13 @@ struct ref_storage_be refs_be_files = {
|
||||
|
||||
files_ref_iterator_begin,
|
||||
files_read_raw_ref,
|
||||
files_verify_refname_available
|
||||
files_verify_refname_available,
|
||||
|
||||
files_reflog_iterator_begin,
|
||||
files_for_each_reflog_ent,
|
||||
files_for_each_reflog_ent_reverse,
|
||||
files_reflog_exists,
|
||||
files_create_reflog,
|
||||
files_delete_reflog,
|
||||
files_reflog_expire
|
||||
};
|
||||
|
@ -404,13 +404,6 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
|
||||
const char *prefix,
|
||||
int trim);
|
||||
|
||||
/*
|
||||
* Iterate over the references in the main ref_store that have a
|
||||
* reflog. The paths within a directory are iterated over in arbitrary
|
||||
* order.
|
||||
*/
|
||||
struct ref_iterator *files_reflog_iterator_begin(void);
|
||||
|
||||
/* Internal implementation of reference iteration: */
|
||||
|
||||
/*
|
||||
@ -507,6 +500,35 @@ typedef struct ref_iterator *ref_iterator_begin_fn(
|
||||
struct ref_store *ref_store,
|
||||
const char *prefix, unsigned int flags);
|
||||
|
||||
/* reflog functions */
|
||||
|
||||
/*
|
||||
* Iterate over the references in the specified ref_store that have a
|
||||
* reflog. The refs are iterated over in arbitrary order.
|
||||
*/
|
||||
typedef struct ref_iterator *reflog_iterator_begin_fn(
|
||||
struct ref_store *ref_store);
|
||||
|
||||
typedef int for_each_reflog_ent_fn(struct ref_store *ref_store,
|
||||
const char *refname,
|
||||
each_reflog_ent_fn fn,
|
||||
void *cb_data);
|
||||
typedef int for_each_reflog_ent_reverse_fn(struct ref_store *ref_store,
|
||||
const char *refname,
|
||||
each_reflog_ent_fn fn,
|
||||
void *cb_data);
|
||||
typedef int reflog_exists_fn(struct ref_store *ref_store, const char *refname);
|
||||
typedef int create_reflog_fn(struct ref_store *ref_store, const char *refname,
|
||||
int force_create, struct strbuf *err);
|
||||
typedef int delete_reflog_fn(struct ref_store *ref_store, const char *refname);
|
||||
typedef int reflog_expire_fn(struct ref_store *ref_store,
|
||||
const char *refname, const unsigned char *sha1,
|
||||
unsigned int flags,
|
||||
reflog_expiry_prepare_fn prepare_fn,
|
||||
reflog_expiry_should_prune_fn should_prune_fn,
|
||||
reflog_expiry_cleanup_fn cleanup_fn,
|
||||
void *policy_cb_data);
|
||||
|
||||
/*
|
||||
* Read a reference from the specified reference store, non-recursively.
|
||||
* Set type to describe the reference, and:
|
||||
@ -568,6 +590,14 @@ struct ref_storage_be {
|
||||
ref_iterator_begin_fn *iterator_begin;
|
||||
read_raw_ref_fn *read_raw_ref;
|
||||
verify_refname_available_fn *verify_refname_available;
|
||||
|
||||
reflog_iterator_begin_fn *reflog_iterator_begin;
|
||||
for_each_reflog_ent_fn *for_each_reflog_ent;
|
||||
for_each_reflog_ent_reverse_fn *for_each_reflog_ent_reverse;
|
||||
reflog_exists_fn *reflog_exists;
|
||||
create_reflog_fn *create_reflog;
|
||||
delete_reflog_fn *delete_reflog;
|
||||
reflog_expire_fn *reflog_expire;
|
||||
};
|
||||
|
||||
extern struct ref_storage_be refs_be_files;
|
||||
|
Loading…
Reference in New Issue
Block a user