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>

David Turner committed Sep 4, 2016 at 18:08 UTC e3688bd6cf159f6026a6bca7a6f53d0a22fe21a2
3 files changed +150 -27
refs.c
+63
@@ -1461,3 +1461,66 @@ int verify_refname_available(const char *refname,
1461
1462 return refs->be->verify_refname_available(refs, refname, extra, skip, err);
1463 }
1464 +
1465 +int for_each_reflog(each_ref_fn fn, void *cb_data)
1466 +{
1467 + struct ref_store *refs = get_ref_store(NULL);
1468 + struct ref_iterator *iter;
1469 +
1470 + iter = refs->be->reflog_iterator_begin(refs);
1471 +
1472 + return do_for_each_ref_iterator(iter, fn, cb_data);
1473 +}
1474 +
1475 +int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,
1476 + void *cb_data)
1477 +{
1478 + struct ref_store *refs = get_ref_store(NULL);
1479 +
1480 + return refs->be->for_each_reflog_ent_reverse(refs, refname,
1481 + fn, cb_data);
1482 +}
1483 +
1484 +int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn,
1485 + void *cb_data)
1486 +{
1487 + struct ref_store *refs = get_ref_store(NULL);
1488 +
1489 + return refs->be->for_each_reflog_ent(refs, refname, fn, cb_data);
1490 +}
1491 +
1492 +int reflog_exists(const char *refname)
1493 +{
1494 + struct ref_store *refs = get_ref_store(NULL);
1495 +
1496 + return refs->be->reflog_exists(refs, refname);
1497 +}
1498 +
1499 +int safe_create_reflog(const char *refname, int force_create,
1500 + struct strbuf *err)
1501 +{
1502 + struct ref_store *refs = get_ref_store(NULL);
1503 +
1504 + return refs->be->create_reflog(refs, refname, force_create, err);
1505 +}
1506 +
1507 +int delete_reflog(const char *refname)
1508 +{
1509 + struct ref_store *refs = get_ref_store(NULL);
1510 +
1511 + return refs->be->delete_reflog(refs, refname);
1512 +}
1513 +
1514 +int reflog_expire(const char *refname, const unsigned char *sha1,
1515 + unsigned int flags,
1516 + reflog_expiry_prepare_fn prepare_fn,
1517 + reflog_expiry_should_prune_fn should_prune_fn,
1518 + reflog_expiry_cleanup_fn cleanup_fn,
1519 + void *policy_cb_data)
1520 +{
1521 + struct ref_store *refs = get_ref_store(NULL);
1522 +
1523 + return refs->be->reflog_expire(refs, refname, sha1, flags,
1524 + prepare_fn, should_prune_fn,
1525 + cleanup_fn, policy_cb_data);
1526 +}
refs/files-backend.c
+50 -20
@@ -2777,11 +2777,16 @@ static int log_ref_setup(const char *refname, struct strbuf *logfile, struct str
2777 }
2778
2779
2780 -int safe_create_reflog(const char *refname, int force_create, struct strbuf *err)
2780 +static int files_create_reflog(struct ref_store *ref_store,
2781 + const char *refname, int force_create,
2782 + struct strbuf *err)
2783 {
2784 int ret;
2785 struct strbuf sb = STRBUF_INIT;
2786
2787 + /* Check validity (but we don't need the result): */
2788 + files_downcast(ref_store, 0, "create_reflog");
2789 +
2790 ret = log_ref_setup(refname, &sb, err, force_create);
2791 strbuf_release(&sb);
2792 return ret;
@@ -3075,16 +3080,24 @@ int set_worktree_head_symref(const char *gitdir, const char *target)
3080 return ret;
3081 }
3082
3078 -int reflog_exists(const char *refname)
3083 +static int files_reflog_exists(struct ref_store *ref_store,
3084 + const char *refname)
3085 {
3086 struct stat st;
3087
3088 + /* Check validity (but we don't need the result): */
3089 + files_downcast(ref_store, 0, "reflog_exists");
3090 +
3091 return !lstat(git_path("logs/%s", refname), &st) &&
3092 S_ISREG(st.st_mode);
3093 }
3094
3086 -int delete_reflog(const char *refname)
3095 +static int files_delete_reflog(struct ref_store *ref_store,
3096 + const char *refname)
3097 {
3098 + /* Check validity (but we don't need the result): */
3099 + files_downcast(ref_store, 0, "delete_reflog");
3100 +
3101 return remove_path(git_path("logs/%s", refname));
3102 }
3103
@@ -3127,13 +3140,19 @@ static char *find_beginning_of_line(char *bob, char *scan)
3140 return scan;
3141 }
3142
3130 -int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void *cb_data)
3143 +static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store,
3144 + const char *refname,
3145 + each_reflog_ent_fn fn,
3146 + void *cb_data)
3147 {
3148 struct strbuf sb = STRBUF_INIT;
3149 FILE *logfp;
3150 long pos;
3151 int ret = 0, at_tail = 1;
3152
3153 + /* Check validity (but we don't need the result): */
3154 + files_downcast(ref_store, 0, "for_each_reflog_ent_reverse");
3155 +
3156 logfp = fopen(git_path("logs/%s", refname), "r");
3157 if (!logfp)
3158 return -1;
@@ -3229,12 +3248,17 @@ int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void
3248 return ret;
3249 }
3250
3232 -int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_data)
3251 +static int files_for_each_reflog_ent(struct ref_store *ref_store,
3252 + const char *refname,
3253 + each_reflog_ent_fn fn, void *cb_data)
3254 {
3255 FILE *logfp;
3256 struct strbuf sb = STRBUF_INIT;
3257 int ret = 0;
3258
3259 + /* Check validity (but we don't need the result): */
3260 + files_downcast(ref_store, 0, "for_each_reflog_ent");
3261 +
3262 logfp = fopen(git_path("logs/%s", refname), "r");
3263 if (!logfp)
3264 return -1;
@@ -3313,22 +3337,19 @@ static struct ref_iterator_vtable files_reflog_iterator_vtable = {
3337 files_reflog_iterator_abort
3338 };
3339
3316 -struct ref_iterator *files_reflog_iterator_begin(void)
3340 +static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_store)
3341 {
3342 struct files_reflog_iterator *iter = xcalloc(1, sizeof(*iter));
3343 struct ref_iterator *ref_iterator = &iter->base;
3344
3345 + /* Check validity (but we don't need the result): */
3346 + files_downcast(ref_store, 0, "reflog_iterator_begin");
3347 +
3348 base_ref_iterator_init(ref_iterator, &files_reflog_iterator_vtable);
3349 iter->dir_iterator = dir_iterator_begin(git_path("logs"));
3350 return ref_iterator;
3351 }
3352
3326 -int for_each_reflog(each_ref_fn fn, void *cb_data)
3327 -{
3328 - return do_for_each_ref_iterator(files_reflog_iterator_begin(),
3329 - fn, cb_data);
3330 -}
3331 -
3353 static int ref_update_reject_duplicates(struct string_list *refnames,
3354 struct strbuf *err)
3355 {
@@ -3925,15 +3946,16 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
3946 return 0;
3947 }
3948
3928 -int reflog_expire(const char *refname, const unsigned char *sha1,
3929 - unsigned int flags,
3930 - reflog_expiry_prepare_fn prepare_fn,
3931 - reflog_expiry_should_prune_fn should_prune_fn,
3932 - reflog_expiry_cleanup_fn cleanup_fn,
3933 - void *policy_cb_data)
3949 +static int files_reflog_expire(struct ref_store *ref_store,
3950 + const char *refname, const unsigned char *sha1,
3951 + unsigned int flags,
3952 + reflog_expiry_prepare_fn prepare_fn,
3953 + reflog_expiry_should_prune_fn should_prune_fn,
3954 + reflog_expiry_cleanup_fn cleanup_fn,
3955 + void *policy_cb_data)
3956 {
3957 struct files_ref_store *refs =
3936 - get_files_ref_store(NULL, "reflog_expire");
3958 + files_downcast(ref_store, 0, "reflog_expire");
3959 static struct lock_file reflog_lock;
3960 struct expire_reflog_cb cb;
3961 struct ref_lock *lock;
@@ -4046,5 +4068,13 @@ struct ref_storage_be refs_be_files = {
4068
4069 files_ref_iterator_begin,
4070 files_read_raw_ref,
4049 - files_verify_refname_available
4071 + files_verify_refname_available,
4072 +
4073 + files_reflog_iterator_begin,
4074 + files_for_each_reflog_ent,
4075 + files_for_each_reflog_ent_reverse,
4076 + files_reflog_exists,
4077 + files_create_reflog,
4078 + files_delete_reflog,
4079 + files_reflog_expire
4080 };
refs/refs-internal.h
+37 -7
@@ -404,13 +404,6 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
404 const char *prefix,
405 int trim);
406
407 -/*
408 - * Iterate over the references in the main ref_store that have a
409 - * reflog. The paths within a directory are iterated over in arbitrary
410 - * order.
411 - */
412 -struct ref_iterator *files_reflog_iterator_begin(void);
413 -
407 /* Internal implementation of reference iteration: */
408
409 /*
@@ -507,6 +500,35 @@ typedef struct ref_iterator *ref_iterator_begin_fn(
500 struct ref_store *ref_store,
501 const char *prefix, unsigned int flags);
502
503 +/* reflog functions */
504 +
505 +/*
506 + * Iterate over the references in the specified ref_store that have a
507 + * reflog. The refs are iterated over in arbitrary order.
508 + */
509 +typedef struct ref_iterator *reflog_iterator_begin_fn(
510 + struct ref_store *ref_store);
511 +
512 +typedef int for_each_reflog_ent_fn(struct ref_store *ref_store,
513 + const char *refname,
514 + each_reflog_ent_fn fn,
515 + void *cb_data);
516 +typedef int for_each_reflog_ent_reverse_fn(struct ref_store *ref_store,
517 + const char *refname,
518 + each_reflog_ent_fn fn,
519 + void *cb_data);
520 +typedef int reflog_exists_fn(struct ref_store *ref_store, const char *refname);
521 +typedef int create_reflog_fn(struct ref_store *ref_store, const char *refname,
522 + int force_create, struct strbuf *err);
523 +typedef int delete_reflog_fn(struct ref_store *ref_store, const char *refname);
524 +typedef int reflog_expire_fn(struct ref_store *ref_store,
525 + const char *refname, const unsigned char *sha1,
526 + unsigned int flags,
527 + reflog_expiry_prepare_fn prepare_fn,
528 + reflog_expiry_should_prune_fn should_prune_fn,
529 + reflog_expiry_cleanup_fn cleanup_fn,
530 + void *policy_cb_data);
531 +
532 /*
533 * Read a reference from the specified reference store, non-recursively.
534 * Set type to describe the reference, and:
@@ -568,6 +590,14 @@ struct ref_storage_be {
590 ref_iterator_begin_fn *iterator_begin;
591 read_raw_ref_fn *read_raw_ref;
592 verify_refname_available_fn *verify_refname_available;
593 +
594 + reflog_iterator_begin_fn *reflog_iterator_begin;
595 + for_each_reflog_ent_fn *for_each_reflog_ent;
596 + for_each_reflog_ent_reverse_fn *for_each_reflog_ent_reverse;
597 + reflog_exists_fn *reflog_exists;
598 + create_reflog_fn *create_reflog;
599 + delete_reflog_fn *delete_reflog;
600 + reflog_expire_fn *reflog_expire;
601 };
602
603 extern struct ref_storage_be refs_be_files;