From 55dfc8de1844e4295bc02d4a279a432e26dc4740 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:43 +0100 Subject: expire_reflog(): it's not an each_ref_fn anymore Prior to v1.5.4~14, expire_reflog() had to be an each_ref_fn because it was passed to for_each_reflog(). Since then, there has been no reason for it to implement the each_ref_fn interface. So... * Remove the "unused" parameter (which took the place of "flags", but was really unused). * Declare the last parameter to be (struct cmd_reflog_expire_cb *) rather than (void *). Helped-by: Jonathan Nieder Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- builtin/reflog.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index 2d85d260ca..160541aa2f 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -349,9 +349,9 @@ static int push_tip_to_list(const char *refname, const unsigned char *sha1, int return 0; } -static int expire_reflog(const char *ref, const unsigned char *sha1, int unused, void *cb_data) +static int expire_reflog(const char *ref, const unsigned char *sha1, + struct cmd_reflog_expire_cb *cmd) { - struct cmd_reflog_expire_cb *cmd = cb_data; struct expire_reflog_cb cb; struct ref_lock *lock; char *log_file, *newlog_path = NULL; @@ -663,7 +663,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) for (i = 0; i < collected.nr; i++) { struct collected_reflog *e = collected.e[i]; set_reflog_expiry_param(&cb, explicit_expiry, e->reflog); - status |= expire_reflog(e->reflog, e->sha1, 0, &cb); + status |= expire_reflog(e->reflog, e->sha1, &cb); free(e); } free(collected.e); @@ -677,7 +677,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) continue; } set_reflog_expiry_param(&cb, explicit_expiry, ref); - status |= expire_reflog(ref, sha1, 0, &cb); + status |= expire_reflog(ref, sha1, &cb); } return status; } @@ -748,7 +748,7 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) cb.expire_total = 0; } - status |= expire_reflog(ref, sha1, 0, &cb); + status |= expire_reflog(ref, sha1, &cb); free(ref); } return status; -- cgit v1.2.3 From 524127afbf8b98350bcebe3fc1f7600fce191716 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:44 +0100 Subject: expire_reflog(): rename "ref" parameter to "refname" This is our usual convention. Signed-off-by: Michael Haggerty Reviewed-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- builtin/reflog.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index 160541aa2f..ff51dbfc0a 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -349,7 +349,7 @@ static int push_tip_to_list(const char *refname, const unsigned char *sha1, int return 0; } -static int expire_reflog(const char *ref, const unsigned char *sha1, +static int expire_reflog(const char *refname, const unsigned char *sha1, struct cmd_reflog_expire_cb *cmd) { struct expire_reflog_cb cb; @@ -365,20 +365,20 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, * we take the lock for the ref itself to prevent it from * getting updated. */ - lock = lock_any_ref_for_update(ref, sha1, 0, NULL); + lock = lock_any_ref_for_update(refname, sha1, 0, NULL); if (!lock) - return error("cannot lock ref '%s'", ref); - log_file = git_pathdup("logs/%s", ref); - if (!reflog_exists(ref)) + return error("cannot lock ref '%s'", refname); + log_file = git_pathdup("logs/%s", refname); + if (!reflog_exists(refname)) goto finish; if (!cmd->dry_run) { - newlog_path = git_pathdup("logs/%s.lock", ref); + newlog_path = git_pathdup("logs/%s.lock", refname); cb.newlog = fopen(newlog_path, "w"); } cb.cmd = cmd; - if (!cmd->expire_unreachable || !strcmp(ref, "HEAD")) { + if (!cmd->expire_unreachable || !strcmp(refname, "HEAD")) { tip_commit = NULL; cb.unreachable_expire_kind = UE_HEAD; } else { @@ -407,7 +407,7 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, mark_reachable(&cb); } - for_each_reflog_ent(ref, expire_reflog_ent, &cb); + for_each_reflog_ent(refname, expire_reflog_ent, &cb); if (cb.unreachable_expire_kind != UE_ALWAYS) { if (cb.unreachable_expire_kind == UE_HEAD) { -- cgit v1.2.3 From 2e376b3156ff30dcd359b7c424fcbdbab5ec7709 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:45 +0100 Subject: expire_reflog(): return early if the reference has no reflog There is very little cleanup needed if the reference has no reflog. If we move the initialization of log_file down a bit, there's even less. So instead of jumping to the cleanup code at the end of the function, just do the cleanup and return inline. Signed-off-by: Michael Haggerty Reviewed-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- builtin/reflog.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index ff51dbfc0a..37b33c9d70 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -368,9 +368,11 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, lock = lock_any_ref_for_update(refname, sha1, 0, NULL); if (!lock) return error("cannot lock ref '%s'", refname); + if (!reflog_exists(refname)) { + unlock_ref(lock); + return 0; + } log_file = git_pathdup("logs/%s", refname); - if (!reflog_exists(refname)) - goto finish; if (!cmd->dry_run) { newlog_path = git_pathdup("logs/%s.lock", refname); cb.newlog = fopen(newlog_path, "w"); @@ -419,7 +421,7 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, clear_commit_marks(tip_commit, REACHABLE); } } - finish: + if (cb.newlog) { if (fclose(cb.newlog)) { status |= error("%s: %s", strerror(errno), -- cgit v1.2.3 From f3b661f766c1525265d065fdd0529985979c80c6 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:46 +0100 Subject: expire_reflog(): use a lock_file for rewriting the reflog file We don't actually need the locking functionality, because we already hold the lock on the reference itself, which is how the reflog file is locked. But the lock_file code can do some of the bookkeeping for us, and it is more careful than the old code here was. For example: * It correctly handles the case that the reflog lock file already exists for some reason or cannot be opened. * It correctly cleans up the lockfile if the program dies. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- builtin/reflog.c | 60 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 19 deletions(-) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index 37b33c9d70..ba5b3d378f 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -352,9 +352,10 @@ static int push_tip_to_list(const char *refname, const unsigned char *sha1, int static int expire_reflog(const char *refname, const unsigned char *sha1, struct cmd_reflog_expire_cb *cmd) { + static struct lock_file reflog_lock; struct expire_reflog_cb cb; struct ref_lock *lock; - char *log_file, *newlog_path = NULL; + char *log_file; struct commit *tip_commit; struct commit_list *tips; int status = 0; @@ -362,8 +363,9 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, memset(&cb, 0, sizeof(cb)); /* - * we take the lock for the ref itself to prevent it from - * getting updated. + * The reflog file is locked by holding the lock on the + * reference itself, plus we might need to update the + * reference if --updateref was specified: */ lock = lock_any_ref_for_update(refname, sha1, 0, NULL); if (!lock) @@ -372,10 +374,29 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, unlock_ref(lock); return 0; } + log_file = git_pathdup("logs/%s", refname); if (!cmd->dry_run) { - newlog_path = git_pathdup("logs/%s.lock", refname); - cb.newlog = fopen(newlog_path, "w"); + /* + * Even though holding $GIT_DIR/logs/$reflog.lock has + * no locking implications, we use the lock_file + * machinery here anyway because it does a lot of the + * work we need, including cleaning up if the program + * exits unexpectedly. + */ + if (hold_lock_file_for_update(&reflog_lock, log_file, 0) < 0) { + struct strbuf err = STRBUF_INIT; + unable_to_lock_message(log_file, errno, &err); + error("%s", err.buf); + strbuf_release(&err); + goto failure; + } + cb.newlog = fdopen_lock_file(&reflog_lock, "w"); + if (!cb.newlog) { + error("cannot fdopen %s (%s)", + reflog_lock.filename.buf, strerror(errno)); + goto failure; + } } cb.cmd = cmd; @@ -423,32 +444,33 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, } if (cb.newlog) { - if (fclose(cb.newlog)) { - status |= error("%s: %s", strerror(errno), - newlog_path); - unlink(newlog_path); + if (close_lock_file(&reflog_lock)) { + status |= error("couldn't write %s: %s", log_file, + strerror(errno)); } else if (cmd->updateref && (write_in_full(lock->lock_fd, sha1_to_hex(cb.last_kept_sha1), 40) != 40 || write_str_in_full(lock->lock_fd, "\n") != 1 || close_ref(lock) < 0)) { - status |= error("Couldn't write %s", + status |= error("couldn't write %s", lock->lk->filename.buf); - unlink(newlog_path); - } else if (rename(newlog_path, log_file)) { - status |= error("cannot rename %s to %s", - newlog_path, log_file); - unlink(newlog_path); + rollback_lock_file(&reflog_lock); + } else if (commit_lock_file(&reflog_lock)) { + status |= error("unable to commit reflog '%s' (%s)", + log_file, strerror(errno)); } else if (cmd->updateref && commit_ref(lock)) { - status |= error("Couldn't set %s", lock->ref_name); - } else { - adjust_shared_perm(log_file); + status |= error("couldn't set %s", lock->ref_name); } } - free(newlog_path); free(log_file); unlock_ref(lock); return status; + + failure: + rollback_lock_file(&reflog_lock); + free(log_file); + unlock_ref(lock); + return -1; } static int collect_reflog(const char *ref, const unsigned char *sha1, int unused, void *cb_data) -- cgit v1.2.3 From 60cc3c4072259609aefbdbc762d1f72bcbd97783 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:47 +0100 Subject: Extract function should_expire_reflog_ent() Extract from expire_reflog_ent() a function that is solely responsible for deciding whether a reflog entry should be expired. By separating this "business logic" from the mechanics of actually expiring entries, we are working towards the goal of encapsulating reflog expiry within the refs API, with policy decided by a callback function passed to it by its caller. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- builtin/reflog.c | 70 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 28 deletions(-) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index ba5b3d378f..06ce8b174c 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -288,51 +288,65 @@ static int unreachable(struct expire_reflog_cb *cb, struct commit *commit, unsig return !(commit->object.flags & REACHABLE); } -static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, - const char *email, unsigned long timestamp, int tz, - const char *message, void *cb_data) +/* + * Return true iff the specified reflog entry should be expired. + */ +static int should_expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, + const char *email, unsigned long timestamp, int tz, + const char *message, void *cb_data) { struct expire_reflog_cb *cb = cb_data; struct commit *old, *new; if (timestamp < cb->cmd->expire_total) - goto prune; - - if (cb->cmd->rewrite) - osha1 = cb->last_kept_sha1; + return 1; old = new = NULL; if (cb->cmd->stalefix && (!keep_entry(&old, osha1) || !keep_entry(&new, nsha1))) - goto prune; + return 1; if (timestamp < cb->cmd->expire_unreachable) { if (cb->unreachable_expire_kind == UE_ALWAYS) - goto prune; + return 1; if (unreachable(cb, old, osha1) || unreachable(cb, new, nsha1)) - goto prune; + return 1; } if (cb->cmd->recno && --(cb->cmd->recno) == 0) - goto prune; - - if (cb->newlog) { - char sign = (tz < 0) ? '-' : '+'; - int zone = (tz < 0) ? (-tz) : tz; - fprintf(cb->newlog, "%s %s %s %lu %c%04d\t%s", - sha1_to_hex(osha1), sha1_to_hex(nsha1), - email, timestamp, sign, zone, - message); - hashcpy(cb->last_kept_sha1, nsha1); - } - if (cb->cmd->verbose) - printf("keep %s", message); + return 1; + return 0; - prune: - if (!cb->newlog) - printf("would prune %s", message); - else if (cb->cmd->verbose) - printf("prune %s", message); +} + +static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, + const char *email, unsigned long timestamp, int tz, + const char *message, void *cb_data) +{ + struct expire_reflog_cb *cb = cb_data; + + if (cb->cmd->rewrite) + osha1 = cb->last_kept_sha1; + + if (should_expire_reflog_ent(osha1, nsha1, email, timestamp, tz, + message, cb_data)) { + if (!cb->newlog) + printf("would prune %s", message); + else if (cb->cmd->verbose) + printf("prune %s", message); + } else { + if (cb->newlog) { + char sign = (tz < 0) ? '-' : '+'; + int zone = (tz < 0) ? (-tz) : tz; + fprintf(cb->newlog, "%s %s %s %lu %c%04d\t%s", + sha1_to_hex(osha1), sha1_to_hex(nsha1), + email, timestamp, sign, zone, + message); + hashcpy(cb->last_kept_sha1, nsha1); + } + if (cb->cmd->verbose) + printf("keep %s", message); + } return 0; } -- cgit v1.2.3 From c48a1635355118d490fef5af14d8296a8e6f92df Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:48 +0100 Subject: expire_reflog(): extract two policy-related functions Extract two functions, reflog_expiry_prepare() and reflog_expiry_cleanup(), from expire_reflog(). This is a further step towards separating the code for deciding on expiration policy from the code that manages the physical deletion of reflog entries. This change requires a couple of local variables from expire_reflog() to be turned into fields of "struct expire_reflog_cb". More reorganization of the callback data will follow in later commits. Signed-off-by: Michael Haggerty Reviewed-by: Stefan Beller Signed-off-by: Junio C Hamano --- builtin/reflog.c | 94 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 52 insertions(+), 42 deletions(-) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index 06ce8b174c..8db52d7e50 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -43,6 +43,8 @@ struct expire_reflog_cb { unsigned long mark_limit; struct cmd_reflog_expire_cb *cmd; unsigned char last_kept_sha1[20]; + struct commit *tip_commit; + struct commit_list *tips; }; struct collected_reflog { @@ -363,6 +365,54 @@ static int push_tip_to_list(const char *refname, const unsigned char *sha1, int return 0; } +static void reflog_expiry_prepare(const char *refname, + const unsigned char *sha1, + struct expire_reflog_cb *cb) +{ + if (!cb->cmd->expire_unreachable || !strcmp(refname, "HEAD")) { + cb->tip_commit = NULL; + cb->unreachable_expire_kind = UE_HEAD; + } else { + cb->tip_commit = lookup_commit_reference_gently(sha1, 1); + if (!cb->tip_commit) + cb->unreachable_expire_kind = UE_ALWAYS; + else + cb->unreachable_expire_kind = UE_NORMAL; + } + + if (cb->cmd->expire_unreachable <= cb->cmd->expire_total) + cb->unreachable_expire_kind = UE_ALWAYS; + + cb->mark_list = NULL; + cb->tips = NULL; + if (cb->unreachable_expire_kind != UE_ALWAYS) { + if (cb->unreachable_expire_kind == UE_HEAD) { + struct commit_list *elem; + for_each_ref(push_tip_to_list, &cb->tips); + for (elem = cb->tips; elem; elem = elem->next) + commit_list_insert(elem->item, &cb->mark_list); + } else { + commit_list_insert(cb->tip_commit, &cb->mark_list); + } + cb->mark_limit = cb->cmd->expire_total; + mark_reachable(cb); + } +} + +static void reflog_expiry_cleanup(struct expire_reflog_cb *cb) +{ + if (cb->unreachable_expire_kind != UE_ALWAYS) { + if (cb->unreachable_expire_kind == UE_HEAD) { + struct commit_list *elem; + for (elem = cb->tips; elem; elem = elem->next) + clear_commit_marks(elem->item, REACHABLE); + free_commit_list(cb->tips); + } else { + clear_commit_marks(cb->tip_commit, REACHABLE); + } + } +} + static int expire_reflog(const char *refname, const unsigned char *sha1, struct cmd_reflog_expire_cb *cmd) { @@ -370,8 +420,6 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, struct expire_reflog_cb cb; struct ref_lock *lock; char *log_file; - struct commit *tip_commit; - struct commit_list *tips; int status = 0; memset(&cb, 0, sizeof(cb)); @@ -415,47 +463,9 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, cb.cmd = cmd; - if (!cmd->expire_unreachable || !strcmp(refname, "HEAD")) { - tip_commit = NULL; - cb.unreachable_expire_kind = UE_HEAD; - } else { - tip_commit = lookup_commit_reference_gently(sha1, 1); - if (!tip_commit) - cb.unreachable_expire_kind = UE_ALWAYS; - else - cb.unreachable_expire_kind = UE_NORMAL; - } - - if (cmd->expire_unreachable <= cmd->expire_total) - cb.unreachable_expire_kind = UE_ALWAYS; - - cb.mark_list = NULL; - tips = NULL; - if (cb.unreachable_expire_kind != UE_ALWAYS) { - if (cb.unreachable_expire_kind == UE_HEAD) { - struct commit_list *elem; - for_each_ref(push_tip_to_list, &tips); - for (elem = tips; elem; elem = elem->next) - commit_list_insert(elem->item, &cb.mark_list); - } else { - commit_list_insert(tip_commit, &cb.mark_list); - } - cb.mark_limit = cmd->expire_total; - mark_reachable(&cb); - } - + reflog_expiry_prepare(refname, sha1, &cb); for_each_reflog_ent(refname, expire_reflog_ent, &cb); - - if (cb.unreachable_expire_kind != UE_ALWAYS) { - if (cb.unreachable_expire_kind == UE_HEAD) { - struct commit_list *elem; - for (elem = tips; elem; elem = elem->next) - clear_commit_marks(elem->item, REACHABLE); - free_commit_list(tips); - } else { - clear_commit_marks(tip_commit, REACHABLE); - } - } + reflog_expiry_cleanup(&cb); if (cb.newlog) { if (close_lock_file(&reflog_lock)) { -- cgit v1.2.3 From aba56c89b21ebe64f38c521c0962c45eb4d23749 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:49 +0100 Subject: expire_reflog(): add a "flags" argument We want to separate the options relevant to the expiry machinery from the options affecting the expiration policy. So add a "flags" argument to expire_reflog() to hold the former. The argument doesn't yet do anything. Signed-off-by: Michael Haggerty Reviewed-by: Stefan Beller Signed-off-by: Junio C Hamano --- builtin/reflog.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index 8db52d7e50..dfff5f2fe8 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -414,7 +414,7 @@ static void reflog_expiry_cleanup(struct expire_reflog_cb *cb) } static int expire_reflog(const char *refname, const unsigned char *sha1, - struct cmd_reflog_expire_cb *cmd) + unsigned int flags, struct cmd_reflog_expire_cb *cmd) { static struct lock_file reflog_lock; struct expire_reflog_cb cb; @@ -642,6 +642,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) unsigned long now = time(NULL); int i, status, do_all; int explicit_expiry = 0; + unsigned int flags = 0; default_reflog_expire_unreachable = now - 30 * 24 * 3600; default_reflog_expire = now - 90 * 24 * 3600; @@ -711,7 +712,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) for (i = 0; i < collected.nr; i++) { struct collected_reflog *e = collected.e[i]; set_reflog_expiry_param(&cb, explicit_expiry, e->reflog); - status |= expire_reflog(e->reflog, e->sha1, &cb); + status |= expire_reflog(e->reflog, e->sha1, flags, &cb); free(e); } free(collected.e); @@ -725,7 +726,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) continue; } set_reflog_expiry_param(&cb, explicit_expiry, ref); - status |= expire_reflog(ref, sha1, &cb); + status |= expire_reflog(ref, sha1, flags, &cb); } return status; } @@ -744,6 +745,7 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) { struct cmd_reflog_expire_cb cb; int i, status = 0; + unsigned int flags = 0; memset(&cb, 0, sizeof(cb)); @@ -796,7 +798,7 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) cb.expire_total = 0; } - status |= expire_reflog(ref, sha1, &cb); + status |= expire_reflog(ref, sha1, flags, &cb); free(ref); } return status; -- cgit v1.2.3 From 98f31d8589d5a26b1b3ab4f30ec9cc81aa625872 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:50 +0100 Subject: expire_reflog(): move dry_run to flags argument The policy objects don't care about "--dry-run". So move it to expire_reflog()'s flags parameter. Signed-off-by: Michael Haggerty Reviewed-by: Stefan Beller Signed-off-by: Junio C Hamano --- builtin/reflog.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index dfff5f2fe8..2f21735be9 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -20,9 +20,12 @@ static const char reflog_delete_usage[] = static unsigned long default_reflog_expire; static unsigned long default_reflog_expire_unreachable; +enum expire_reflog_flags { + EXPIRE_REFLOGS_DRY_RUN = 1 << 0 +}; + struct cmd_reflog_expire_cb { struct rev_info revs; - int dry_run; int stalefix; int rewrite; int updateref; @@ -438,7 +441,7 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, } log_file = git_pathdup("logs/%s", refname); - if (!cmd->dry_run) { + if (!(flags & EXPIRE_REFLOGS_DRY_RUN)) { /* * Even though holding $GIT_DIR/logs/$reflog.lock has * no locking implications, we use the lock_file @@ -467,7 +470,7 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, for_each_reflog_ent(refname, expire_reflog_ent, &cb); reflog_expiry_cleanup(&cb); - if (cb.newlog) { + if (!(flags & EXPIRE_REFLOGS_DRY_RUN)) { if (close_lock_file(&reflog_lock)) { status |= error("couldn't write %s: %s", log_file, strerror(errno)); @@ -658,7 +661,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n")) - cb.dry_run = 1; + flags |= EXPIRE_REFLOGS_DRY_RUN; else if (starts_with(arg, "--expire=")) { if (parse_expiry_date(arg + 9, &cb.expire_total)) die(_("'%s' is not a valid timestamp"), arg); @@ -752,7 +755,7 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n")) - cb.dry_run = 1; + flags |= EXPIRE_REFLOGS_DRY_RUN; else if (!strcmp(arg, "--rewrite")) cb.rewrite = 1; else if (!strcmp(arg, "--updateref")) -- cgit v1.2.3 From c4c4fbf86cd6f3d4fee629629d1f7e2e5d81d592 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:51 +0100 Subject: expire_reflog(): move updateref to flags argument The policy objects don't care about "--updateref". So move it to expire_reflog()'s flags parameter. Signed-off-by: Michael Haggerty Reviewed-by: Stefan Beller Signed-off-by: Junio C Hamano --- builtin/reflog.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index 2f21735be9..e238fe036c 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -21,14 +21,14 @@ static unsigned long default_reflog_expire; static unsigned long default_reflog_expire_unreachable; enum expire_reflog_flags { - EXPIRE_REFLOGS_DRY_RUN = 1 << 0 + EXPIRE_REFLOGS_DRY_RUN = 1 << 0, + EXPIRE_REFLOGS_UPDATE_REF = 1 << 1 }; struct cmd_reflog_expire_cb { struct rev_info revs; int stalefix; int rewrite; - int updateref; int verbose; unsigned long expire_total; unsigned long expire_unreachable; @@ -474,7 +474,7 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, if (close_lock_file(&reflog_lock)) { status |= error("couldn't write %s: %s", log_file, strerror(errno)); - } else if (cmd->updateref && + } else if ((flags & EXPIRE_REFLOGS_UPDATE_REF) && (write_in_full(lock->lock_fd, sha1_to_hex(cb.last_kept_sha1), 40) != 40 || write_str_in_full(lock->lock_fd, "\n") != 1 || @@ -485,7 +485,7 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, } else if (commit_lock_file(&reflog_lock)) { status |= error("unable to commit reflog '%s' (%s)", log_file, strerror(errno)); - } else if (cmd->updateref && commit_ref(lock)) { + } else if ((flags & EXPIRE_REFLOGS_UPDATE_REF) && commit_ref(lock)) { status |= error("couldn't set %s", lock->ref_name); } } @@ -677,7 +677,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) else if (!strcmp(arg, "--rewrite")) cb.rewrite = 1; else if (!strcmp(arg, "--updateref")) - cb.updateref = 1; + flags |= EXPIRE_REFLOGS_UPDATE_REF; else if (!strcmp(arg, "--all")) do_all = 1; else if (!strcmp(arg, "--verbose")) @@ -759,7 +759,7 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) else if (!strcmp(arg, "--rewrite")) cb.rewrite = 1; else if (!strcmp(arg, "--updateref")) - cb.updateref = 1; + flags |= EXPIRE_REFLOGS_UPDATE_REF; else if (!strcmp(arg, "--verbose")) cb.verbose = 1; else if (!strcmp(arg, "--")) { -- cgit v1.2.3 From ea7b4f6d3368654b1bd751193eaad4eca71991e4 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:52 +0100 Subject: Rename expire_reflog_cb to expire_reflog_policy_cb This is the first step towards separating the data needed by the policy code from the data needed by the reflog expiration machinery. (In a moment we will add a *new* "struct expire_reflog_cb" for the use of expire_reflog() itself, then move fields selectively from expire_reflog_policy_cb to expire_reflog_cb.) Signed-off-by: Michael Haggerty Reviewed-by: Stefan Beller Signed-off-by: Junio C Hamano --- builtin/reflog.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index e238fe036c..94c34fc5d8 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -35,7 +35,7 @@ struct cmd_reflog_expire_cb { int recno; }; -struct expire_reflog_cb { +struct expire_reflog_policy_cb { FILE *newlog; enum { UE_NORMAL, @@ -225,7 +225,7 @@ static int keep_entry(struct commit **it, unsigned char *sha1) * the expire_limit and queue them back, so that the caller can call * us again to restart the traversal with longer expire_limit. */ -static void mark_reachable(struct expire_reflog_cb *cb) +static void mark_reachable(struct expire_reflog_policy_cb *cb) { struct commit *commit; struct commit_list *pending; @@ -264,7 +264,7 @@ static void mark_reachable(struct expire_reflog_cb *cb) cb->mark_list = leftover; } -static int unreachable(struct expire_reflog_cb *cb, struct commit *commit, unsigned char *sha1) +static int unreachable(struct expire_reflog_policy_cb *cb, struct commit *commit, unsigned char *sha1) { /* * We may or may not have the commit yet - if not, look it @@ -300,7 +300,7 @@ static int should_expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, const char *email, unsigned long timestamp, int tz, const char *message, void *cb_data) { - struct expire_reflog_cb *cb = cb_data; + struct expire_reflog_policy_cb *cb = cb_data; struct commit *old, *new; if (timestamp < cb->cmd->expire_total) @@ -328,7 +328,7 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, const char *email, unsigned long timestamp, int tz, const char *message, void *cb_data) { - struct expire_reflog_cb *cb = cb_data; + struct expire_reflog_policy_cb *cb = cb_data; if (cb->cmd->rewrite) osha1 = cb->last_kept_sha1; @@ -355,7 +355,8 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, return 0; } -static int push_tip_to_list(const char *refname, const unsigned char *sha1, int flags, void *cb_data) +static int push_tip_to_list(const char *refname, const unsigned char *sha1, + int flags, void *cb_data) { struct commit_list **list = cb_data; struct commit *tip_commit; @@ -370,7 +371,7 @@ static int push_tip_to_list(const char *refname, const unsigned char *sha1, int static void reflog_expiry_prepare(const char *refname, const unsigned char *sha1, - struct expire_reflog_cb *cb) + struct expire_reflog_policy_cb *cb) { if (!cb->cmd->expire_unreachable || !strcmp(refname, "HEAD")) { cb->tip_commit = NULL; @@ -402,7 +403,7 @@ static void reflog_expiry_prepare(const char *refname, } } -static void reflog_expiry_cleanup(struct expire_reflog_cb *cb) +static void reflog_expiry_cleanup(struct expire_reflog_policy_cb *cb) { if (cb->unreachable_expire_kind != UE_ALWAYS) { if (cb->unreachable_expire_kind == UE_HEAD) { @@ -420,7 +421,7 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, unsigned int flags, struct cmd_reflog_expire_cb *cmd) { static struct lock_file reflog_lock; - struct expire_reflog_cb cb; + struct expire_reflog_policy_cb cb; struct ref_lock *lock; char *log_file; int status = 0; -- cgit v1.2.3 From ddd64c566d0b9d110ec51e269b8ce8630fa36348 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:53 +0100 Subject: struct expire_reflog_cb: a new callback data type Add a new data type, "struct expire_reflog_cb", for holding the data that expire_reflog() passes to expire_reflog_ent() via for_each_reflog_ent(). For now it only holds a pointer to a "struct expire_reflog_policy_cb", which still contains all of the actual data. In future commits we will move some fields from the latter to the former. Signed-off-by: Michael Haggerty Reviewed-by: Stefan Beller Signed-off-by: Junio C Hamano --- builtin/reflog.c | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index 94c34fc5d8..9ee66d4eb2 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -50,10 +50,15 @@ struct expire_reflog_policy_cb { struct commit_list *tips; }; +struct expire_reflog_cb { + void *policy_cb; +}; + struct collected_reflog { unsigned char sha1[20]; char reflog[FLEX_ARRAY]; }; + struct collect_reflog_cb { struct collected_reflog **e; int alloc; @@ -328,28 +333,29 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, const char *email, unsigned long timestamp, int tz, const char *message, void *cb_data) { - struct expire_reflog_policy_cb *cb = cb_data; + struct expire_reflog_cb *cb = cb_data; + struct expire_reflog_policy_cb *policy_cb = cb->policy_cb; - if (cb->cmd->rewrite) - osha1 = cb->last_kept_sha1; + if (policy_cb->cmd->rewrite) + osha1 = policy_cb->last_kept_sha1; if (should_expire_reflog_ent(osha1, nsha1, email, timestamp, tz, - message, cb_data)) { - if (!cb->newlog) + message, policy_cb)) { + if (!policy_cb->newlog) printf("would prune %s", message); - else if (cb->cmd->verbose) + else if (policy_cb->cmd->verbose) printf("prune %s", message); } else { - if (cb->newlog) { + if (policy_cb->newlog) { char sign = (tz < 0) ? '-' : '+'; int zone = (tz < 0) ? (-tz) : tz; - fprintf(cb->newlog, "%s %s %s %lu %c%04d\t%s", + fprintf(policy_cb->newlog, "%s %s %s %lu %c%04d\t%s", sha1_to_hex(osha1), sha1_to_hex(nsha1), email, timestamp, sign, zone, message); - hashcpy(cb->last_kept_sha1, nsha1); + hashcpy(policy_cb->last_kept_sha1, nsha1); } - if (cb->cmd->verbose) + if (policy_cb->cmd->verbose) printf("keep %s", message); } return 0; @@ -421,12 +427,15 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, unsigned int flags, struct cmd_reflog_expire_cb *cmd) { static struct lock_file reflog_lock; - struct expire_reflog_policy_cb cb; + struct expire_reflog_cb cb; + struct expire_reflog_policy_cb policy_cb; struct ref_lock *lock; char *log_file; int status = 0; memset(&cb, 0, sizeof(cb)); + memset(&policy_cb, 0, sizeof(policy_cb)); + cb.policy_cb = &policy_cb; /* * The reflog file is locked by holding the lock on the @@ -457,19 +466,19 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, strbuf_release(&err); goto failure; } - cb.newlog = fdopen_lock_file(&reflog_lock, "w"); - if (!cb.newlog) { + policy_cb.newlog = fdopen_lock_file(&reflog_lock, "w"); + if (!policy_cb.newlog) { error("cannot fdopen %s (%s)", reflog_lock.filename.buf, strerror(errno)); goto failure; } } - cb.cmd = cmd; + policy_cb.cmd = cmd; - reflog_expiry_prepare(refname, sha1, &cb); + reflog_expiry_prepare(refname, sha1, &policy_cb); for_each_reflog_ent(refname, expire_reflog_ent, &cb); - reflog_expiry_cleanup(&cb); + reflog_expiry_cleanup(&policy_cb); if (!(flags & EXPIRE_REFLOGS_DRY_RUN)) { if (close_lock_file(&reflog_lock)) { @@ -477,7 +486,7 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, strerror(errno)); } else if ((flags & EXPIRE_REFLOGS_UPDATE_REF) && (write_in_full(lock->lock_fd, - sha1_to_hex(cb.last_kept_sha1), 40) != 40 || + sha1_to_hex(policy_cb.last_kept_sha1), 40) != 40 || write_str_in_full(lock->lock_fd, "\n") != 1 || close_ref(lock) < 0)) { status |= error("couldn't write %s", -- cgit v1.2.3 From 8c22dd325437337064108409ff2241a842561a4b Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:54 +0100 Subject: expire_reflog(): pass flags through to expire_reflog_ent() Add a flags field to "struct expire_reflog_cb", and pass the flags argument through to expire_reflog_ent(). In a moment we will start using it to pass through flags that expire_reflog_ent() needs. Signed-off-by: Michael Haggerty Reviewed-by: Stefan Beller Signed-off-by: Junio C Hamano --- builtin/reflog.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index 9ee66d4eb2..08867a2891 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -51,6 +51,7 @@ struct expire_reflog_policy_cb { }; struct expire_reflog_cb { + unsigned int flags; void *policy_cb; }; @@ -435,6 +436,7 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, memset(&cb, 0, sizeof(cb)); memset(&policy_cb, 0, sizeof(policy_cb)); + cb.flags = flags; cb.policy_cb = &policy_cb; /* -- cgit v1.2.3 From bc11155cea8642ba08f37989a91c8a801953d331 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:55 +0100 Subject: expire_reflog(): move verbose to flags argument The policy objects don't care about "--verbose". So move it to expire_reflog()'s flags parameter. Signed-off-by: Michael Haggerty Reviewed-by: Stefan Beller Signed-off-by: Junio C Hamano --- builtin/reflog.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index 08867a2891..15d3cd5de7 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -22,14 +22,14 @@ static unsigned long default_reflog_expire_unreachable; enum expire_reflog_flags { EXPIRE_REFLOGS_DRY_RUN = 1 << 0, - EXPIRE_REFLOGS_UPDATE_REF = 1 << 1 + EXPIRE_REFLOGS_UPDATE_REF = 1 << 1, + EXPIRE_REFLOGS_VERBOSE = 1 << 2 }; struct cmd_reflog_expire_cb { struct rev_info revs; int stalefix; int rewrite; - int verbose; unsigned long expire_total; unsigned long expire_unreachable; int recno; @@ -344,7 +344,7 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, message, policy_cb)) { if (!policy_cb->newlog) printf("would prune %s", message); - else if (policy_cb->cmd->verbose) + else if (cb->flags & EXPIRE_REFLOGS_VERBOSE) printf("prune %s", message); } else { if (policy_cb->newlog) { @@ -356,7 +356,7 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, message); hashcpy(policy_cb->last_kept_sha1, nsha1); } - if (policy_cb->cmd->verbose) + if (cb->flags & EXPIRE_REFLOGS_VERBOSE) printf("keep %s", message); } return 0; @@ -693,7 +693,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) else if (!strcmp(arg, "--all")) do_all = 1; else if (!strcmp(arg, "--verbose")) - cb.verbose = 1; + flags |= EXPIRE_REFLOGS_VERBOSE; else if (!strcmp(arg, "--")) { i++; break; @@ -711,10 +711,10 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) */ if (cb.stalefix) { init_revisions(&cb.revs, prefix); - if (cb.verbose) + if (flags & EXPIRE_REFLOGS_VERBOSE) printf("Marking reachable objects..."); mark_reachable_objects(&cb.revs, 0, 0, NULL); - if (cb.verbose) + if (flags & EXPIRE_REFLOGS_VERBOSE) putchar('\n'); } @@ -773,7 +773,7 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) else if (!strcmp(arg, "--updateref")) flags |= EXPIRE_REFLOGS_UPDATE_REF; else if (!strcmp(arg, "--verbose")) - cb.verbose = 1; + flags |= EXPIRE_REFLOGS_VERBOSE; else if (!strcmp(arg, "--")) { i++; break; -- cgit v1.2.3 From 553daf13ea25735ad60fa15c74c2bd266ab8e215 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:56 +0100 Subject: expire_reflog(): move rewrite to flags argument The policy objects don't care about "--rewrite". So move it to expire_reflog()'s flags parameter. Signed-off-by: Michael Haggerty Reviewed-by: Stefan Beller Signed-off-by: Junio C Hamano --- builtin/reflog.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index 15d3cd5de7..f86e7de069 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -23,13 +23,13 @@ static unsigned long default_reflog_expire_unreachable; enum expire_reflog_flags { EXPIRE_REFLOGS_DRY_RUN = 1 << 0, EXPIRE_REFLOGS_UPDATE_REF = 1 << 1, - EXPIRE_REFLOGS_VERBOSE = 1 << 2 + EXPIRE_REFLOGS_VERBOSE = 1 << 2, + EXPIRE_REFLOGS_REWRITE = 1 << 3 }; struct cmd_reflog_expire_cb { struct rev_info revs; int stalefix; - int rewrite; unsigned long expire_total; unsigned long expire_unreachable; int recno; @@ -337,7 +337,7 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, struct expire_reflog_cb *cb = cb_data; struct expire_reflog_policy_cb *policy_cb = cb->policy_cb; - if (policy_cb->cmd->rewrite) + if (cb->flags & EXPIRE_REFLOGS_REWRITE) osha1 = policy_cb->last_kept_sha1; if (should_expire_reflog_ent(osha1, nsha1, email, timestamp, tz, @@ -687,7 +687,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) else if (!strcmp(arg, "--stale-fix")) cb.stalefix = 1; else if (!strcmp(arg, "--rewrite")) - cb.rewrite = 1; + flags |= EXPIRE_REFLOGS_REWRITE; else if (!strcmp(arg, "--updateref")) flags |= EXPIRE_REFLOGS_UPDATE_REF; else if (!strcmp(arg, "--all")) @@ -769,7 +769,7 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n")) flags |= EXPIRE_REFLOGS_DRY_RUN; else if (!strcmp(arg, "--rewrite")) - cb.rewrite = 1; + flags |= EXPIRE_REFLOGS_REWRITE; else if (!strcmp(arg, "--updateref")) flags |= EXPIRE_REFLOGS_UPDATE_REF; else if (!strcmp(arg, "--verbose")) -- cgit v1.2.3 From 82a645a73f07b19c0d70861929ebd6178e80e3e9 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:57 +0100 Subject: Move newlog and last_kept_sha1 to "struct expire_reflog_cb" These members are not needed by the policy functions. Signed-off-by: Michael Haggerty Reviewed-by: Stefan Beller Signed-off-by: Junio C Hamano --- builtin/reflog.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index f86e7de069..d36c2c6f2f 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -36,7 +36,6 @@ struct cmd_reflog_expire_cb { }; struct expire_reflog_policy_cb { - FILE *newlog; enum { UE_NORMAL, UE_ALWAYS, @@ -45,7 +44,6 @@ struct expire_reflog_policy_cb { struct commit_list *mark_list; unsigned long mark_limit; struct cmd_reflog_expire_cb *cmd; - unsigned char last_kept_sha1[20]; struct commit *tip_commit; struct commit_list *tips; }; @@ -53,6 +51,8 @@ struct expire_reflog_policy_cb { struct expire_reflog_cb { unsigned int flags; void *policy_cb; + FILE *newlog; + unsigned char last_kept_sha1[20]; }; struct collected_reflog { @@ -338,23 +338,23 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, struct expire_reflog_policy_cb *policy_cb = cb->policy_cb; if (cb->flags & EXPIRE_REFLOGS_REWRITE) - osha1 = policy_cb->last_kept_sha1; + osha1 = cb->last_kept_sha1; if (should_expire_reflog_ent(osha1, nsha1, email, timestamp, tz, message, policy_cb)) { - if (!policy_cb->newlog) + if (!cb->newlog) printf("would prune %s", message); else if (cb->flags & EXPIRE_REFLOGS_VERBOSE) printf("prune %s", message); } else { - if (policy_cb->newlog) { + if (cb->newlog) { char sign = (tz < 0) ? '-' : '+'; int zone = (tz < 0) ? (-tz) : tz; - fprintf(policy_cb->newlog, "%s %s %s %lu %c%04d\t%s", + fprintf(cb->newlog, "%s %s %s %lu %c%04d\t%s", sha1_to_hex(osha1), sha1_to_hex(nsha1), email, timestamp, sign, zone, message); - hashcpy(policy_cb->last_kept_sha1, nsha1); + hashcpy(cb->last_kept_sha1, nsha1); } if (cb->flags & EXPIRE_REFLOGS_VERBOSE) printf("keep %s", message); @@ -468,8 +468,8 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, strbuf_release(&err); goto failure; } - policy_cb.newlog = fdopen_lock_file(&reflog_lock, "w"); - if (!policy_cb.newlog) { + cb.newlog = fdopen_lock_file(&reflog_lock, "w"); + if (!cb.newlog) { error("cannot fdopen %s (%s)", reflog_lock.filename.buf, strerror(errno)); goto failure; @@ -488,7 +488,7 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, strerror(errno)); } else if ((flags & EXPIRE_REFLOGS_UPDATE_REF) && (write_in_full(lock->lock_fd, - sha1_to_hex(policy_cb.last_kept_sha1), 40) != 40 || + sha1_to_hex(cb.last_kept_sha1), 40) != 40 || write_str_in_full(lock->lock_fd, "\n") != 1 || close_ref(lock) < 0)) { status |= error("couldn't write %s", -- cgit v1.2.3 From b729effbdbc9ae2d087a83b9e2a165fb8cc04641 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:58 +0100 Subject: expire_reflog(): treat the policy callback data as opaque Now that expire_reflog() doesn't actually look in the expire_reflog_policy_cb data structure, we can make it opaque: * Change the callers of expire_reflog() to pass it a pointer to an entire "struct expire_reflog_policy_cb" rather than a pointer to a "struct cmd_reflog_expire_cb". * Change expire_reflog() to accept the argument as a "void *" and simply pass it through to the policy functions. * Change the policy functions, reflog_expiry_prepare(), reflog_expiry_cleanup(), and should_expire_reflog_ent(), to accept "void *cb_data" arguments and cast them back to "struct expire_reflog_policy_cb" internally. Signed-off-by: Michael Haggerty Reviewed-by: Stefan Beller Signed-off-by: Junio C Hamano --- builtin/reflog.c | 72 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index d36c2c6f2f..0df5721c88 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -43,7 +43,7 @@ struct expire_reflog_policy_cb { } unreachable_expire_kind; struct commit_list *mark_list; unsigned long mark_limit; - struct cmd_reflog_expire_cb *cmd; + struct cmd_reflog_expire_cb cmd; struct commit *tip_commit; struct commit_list *tips; }; @@ -309,22 +309,22 @@ static int should_expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, struct expire_reflog_policy_cb *cb = cb_data; struct commit *old, *new; - if (timestamp < cb->cmd->expire_total) + if (timestamp < cb->cmd.expire_total) return 1; old = new = NULL; - if (cb->cmd->stalefix && + if (cb->cmd.stalefix && (!keep_entry(&old, osha1) || !keep_entry(&new, nsha1))) return 1; - if (timestamp < cb->cmd->expire_unreachable) { + if (timestamp < cb->cmd.expire_unreachable) { if (cb->unreachable_expire_kind == UE_ALWAYS) return 1; if (unreachable(cb, old, osha1) || unreachable(cb, new, nsha1)) return 1; } - if (cb->cmd->recno && --(cb->cmd->recno) == 0) + if (cb->cmd.recno && --(cb->cmd.recno) == 0) return 1; return 0; @@ -378,9 +378,11 @@ static int push_tip_to_list(const char *refname, const unsigned char *sha1, static void reflog_expiry_prepare(const char *refname, const unsigned char *sha1, - struct expire_reflog_policy_cb *cb) + void *cb_data) { - if (!cb->cmd->expire_unreachable || !strcmp(refname, "HEAD")) { + struct expire_reflog_policy_cb *cb = cb_data; + + if (!cb->cmd.expire_unreachable || !strcmp(refname, "HEAD")) { cb->tip_commit = NULL; cb->unreachable_expire_kind = UE_HEAD; } else { @@ -391,7 +393,7 @@ static void reflog_expiry_prepare(const char *refname, cb->unreachable_expire_kind = UE_NORMAL; } - if (cb->cmd->expire_unreachable <= cb->cmd->expire_total) + if (cb->cmd.expire_unreachable <= cb->cmd.expire_total) cb->unreachable_expire_kind = UE_ALWAYS; cb->mark_list = NULL; @@ -405,13 +407,15 @@ static void reflog_expiry_prepare(const char *refname, } else { commit_list_insert(cb->tip_commit, &cb->mark_list); } - cb->mark_limit = cb->cmd->expire_total; + cb->mark_limit = cb->cmd.expire_total; mark_reachable(cb); } } -static void reflog_expiry_cleanup(struct expire_reflog_policy_cb *cb) +static void reflog_expiry_cleanup(void *cb_data) { + struct expire_reflog_policy_cb *cb = cb_data; + if (cb->unreachable_expire_kind != UE_ALWAYS) { if (cb->unreachable_expire_kind == UE_HEAD) { struct commit_list *elem; @@ -425,19 +429,17 @@ static void reflog_expiry_cleanup(struct expire_reflog_policy_cb *cb) } static int expire_reflog(const char *refname, const unsigned char *sha1, - unsigned int flags, struct cmd_reflog_expire_cb *cmd) + unsigned int flags, void *policy_cb_data) { static struct lock_file reflog_lock; struct expire_reflog_cb cb; - struct expire_reflog_policy_cb policy_cb; struct ref_lock *lock; char *log_file; int status = 0; memset(&cb, 0, sizeof(cb)); - memset(&policy_cb, 0, sizeof(policy_cb)); cb.flags = flags; - cb.policy_cb = &policy_cb; + cb.policy_cb = policy_cb_data; /* * The reflog file is locked by holding the lock on the @@ -476,11 +478,9 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, } } - policy_cb.cmd = cmd; - - reflog_expiry_prepare(refname, sha1, &policy_cb); + reflog_expiry_prepare(refname, sha1, cb.policy_cb); for_each_reflog_ent(refname, expire_reflog_ent, &cb); - reflog_expiry_cleanup(&policy_cb); + reflog_expiry_cleanup(cb.policy_cb); if (!(flags & EXPIRE_REFLOGS_DRY_RUN)) { if (close_lock_file(&reflog_lock)) { @@ -653,7 +653,7 @@ static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, int slot, c static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) { - struct cmd_reflog_expire_cb cb; + struct expire_reflog_policy_cb cb; unsigned long now = time(NULL); int i, status, do_all; int explicit_expiry = 0; @@ -667,25 +667,25 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) do_all = status = 0; memset(&cb, 0, sizeof(cb)); - cb.expire_total = default_reflog_expire; - cb.expire_unreachable = default_reflog_expire_unreachable; + cb.cmd.expire_total = default_reflog_expire; + cb.cmd.expire_unreachable = default_reflog_expire_unreachable; for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n")) flags |= EXPIRE_REFLOGS_DRY_RUN; else if (starts_with(arg, "--expire=")) { - if (parse_expiry_date(arg + 9, &cb.expire_total)) + if (parse_expiry_date(arg + 9, &cb.cmd.expire_total)) die(_("'%s' is not a valid timestamp"), arg); explicit_expiry |= EXPIRE_TOTAL; } else if (starts_with(arg, "--expire-unreachable=")) { - if (parse_expiry_date(arg + 21, &cb.expire_unreachable)) + if (parse_expiry_date(arg + 21, &cb.cmd.expire_unreachable)) die(_("'%s' is not a valid timestamp"), arg); explicit_expiry |= EXPIRE_UNREACH; } else if (!strcmp(arg, "--stale-fix")) - cb.stalefix = 1; + cb.cmd.stalefix = 1; else if (!strcmp(arg, "--rewrite")) flags |= EXPIRE_REFLOGS_REWRITE; else if (!strcmp(arg, "--updateref")) @@ -709,11 +709,11 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) * even in older repository. We cannot trust what's reachable * from reflog if the repository was pruned with older git. */ - if (cb.stalefix) { - init_revisions(&cb.revs, prefix); + if (cb.cmd.stalefix) { + init_revisions(&cb.cmd.revs, prefix); if (flags & EXPIRE_REFLOGS_VERBOSE) printf("Marking reachable objects..."); - mark_reachable_objects(&cb.revs, 0, 0, NULL); + mark_reachable_objects(&cb.cmd.revs, 0, 0, NULL); if (flags & EXPIRE_REFLOGS_VERBOSE) putchar('\n'); } @@ -726,7 +726,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) for_each_reflog(collect_reflog, &collected); for (i = 0; i < collected.nr; i++) { struct collected_reflog *e = collected.e[i]; - set_reflog_expiry_param(&cb, explicit_expiry, e->reflog); + set_reflog_expiry_param(&cb.cmd, explicit_expiry, e->reflog); status |= expire_reflog(e->reflog, e->sha1, flags, &cb); free(e); } @@ -740,7 +740,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) status |= error("%s points nowhere!", argv[i]); continue; } - set_reflog_expiry_param(&cb, explicit_expiry, ref); + set_reflog_expiry_param(&cb.cmd, explicit_expiry, ref); status |= expire_reflog(ref, sha1, flags, &cb); } return status; @@ -750,15 +750,15 @@ static int count_reflog_ent(unsigned char *osha1, unsigned char *nsha1, const char *email, unsigned long timestamp, int tz, const char *message, void *cb_data) { - struct cmd_reflog_expire_cb *cb = cb_data; - if (!cb->expire_total || timestamp < cb->expire_total) - cb->recno++; + struct expire_reflog_policy_cb *cb = cb_data; + if (!cb->cmd.expire_total || timestamp < cb->cmd.expire_total) + cb->cmd.recno++; return 0; } static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) { - struct cmd_reflog_expire_cb cb; + struct expire_reflog_policy_cb cb; int i, status = 0; unsigned int flags = 0; @@ -805,12 +805,12 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) recno = strtoul(spec + 2, &ep, 10); if (*ep == '}') { - cb.recno = -recno; + cb.cmd.recno = -recno; for_each_reflog_ent(ref, count_reflog_ent, &cb); } else { - cb.expire_total = approxidate(spec + 2); + cb.cmd.expire_total = approxidate(spec + 2); for_each_reflog_ent(ref, count_reflog_ent, &cb); - cb.expire_total = 0; + cb.cmd.expire_total = 0; } status |= expire_reflog(ref, sha1, flags, &cb); -- cgit v1.2.3 From fa5b1830b0605b39295631f6e167ddb133f2dbde Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 12 Dec 2014 09:56:59 +0100 Subject: reflog_expire(): new function in the reference API Move expire_reflog() into refs.c and rename it to reflog_expire(). Turn the three policy functions into function pointers that are passed into reflog_expire(). Add function prototypes and documentation to refs.h. [jc: squashed in $gmane/261582, drop "extern" in function definition] Signed-off-by: Michael Haggerty Reviewed-by: Stefan Beller Tweaked-by: Ramsay Jones Signed-off-by: Junio C Hamano --- builtin/reflog.c | 148 ++++++------------------------------------------------- 1 file changed, 15 insertions(+), 133 deletions(-) (limited to 'builtin') diff --git a/builtin/reflog.c b/builtin/reflog.c index 0df5721c88..49c64f96d8 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -20,13 +20,6 @@ static const char reflog_delete_usage[] = static unsigned long default_reflog_expire; static unsigned long default_reflog_expire_unreachable; -enum expire_reflog_flags { - EXPIRE_REFLOGS_DRY_RUN = 1 << 0, - EXPIRE_REFLOGS_UPDATE_REF = 1 << 1, - EXPIRE_REFLOGS_VERBOSE = 1 << 2, - EXPIRE_REFLOGS_REWRITE = 1 << 3 -}; - struct cmd_reflog_expire_cb { struct rev_info revs; int stalefix; @@ -48,13 +41,6 @@ struct expire_reflog_policy_cb { struct commit_list *tips; }; -struct expire_reflog_cb { - unsigned int flags; - void *policy_cb; - FILE *newlog; - unsigned char last_kept_sha1[20]; -}; - struct collected_reflog { unsigned char sha1[20]; char reflog[FLEX_ARRAY]; @@ -330,38 +316,6 @@ static int should_expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, return 0; } -static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, - const char *email, unsigned long timestamp, int tz, - const char *message, void *cb_data) -{ - struct expire_reflog_cb *cb = cb_data; - struct expire_reflog_policy_cb *policy_cb = cb->policy_cb; - - if (cb->flags & EXPIRE_REFLOGS_REWRITE) - osha1 = cb->last_kept_sha1; - - if (should_expire_reflog_ent(osha1, nsha1, email, timestamp, tz, - message, policy_cb)) { - if (!cb->newlog) - printf("would prune %s", message); - else if (cb->flags & EXPIRE_REFLOGS_VERBOSE) - printf("prune %s", message); - } else { - if (cb->newlog) { - char sign = (tz < 0) ? '-' : '+'; - int zone = (tz < 0) ? (-tz) : tz; - fprintf(cb->newlog, "%s %s %s %lu %c%04d\t%s", - sha1_to_hex(osha1), sha1_to_hex(nsha1), - email, timestamp, sign, zone, - message); - hashcpy(cb->last_kept_sha1, nsha1); - } - if (cb->flags & EXPIRE_REFLOGS_VERBOSE) - printf("keep %s", message); - } - return 0; -} - static int push_tip_to_list(const char *refname, const unsigned char *sha1, int flags, void *cb_data) { @@ -428,90 +382,6 @@ static void reflog_expiry_cleanup(void *cb_data) } } -static int expire_reflog(const char *refname, const unsigned char *sha1, - unsigned int flags, void *policy_cb_data) -{ - static struct lock_file reflog_lock; - struct expire_reflog_cb cb; - struct ref_lock *lock; - char *log_file; - int status = 0; - - memset(&cb, 0, sizeof(cb)); - cb.flags = flags; - cb.policy_cb = policy_cb_data; - - /* - * The reflog file is locked by holding the lock on the - * reference itself, plus we might need to update the - * reference if --updateref was specified: - */ - lock = lock_any_ref_for_update(refname, sha1, 0, NULL); - if (!lock) - return error("cannot lock ref '%s'", refname); - if (!reflog_exists(refname)) { - unlock_ref(lock); - return 0; - } - - log_file = git_pathdup("logs/%s", refname); - if (!(flags & EXPIRE_REFLOGS_DRY_RUN)) { - /* - * Even though holding $GIT_DIR/logs/$reflog.lock has - * no locking implications, we use the lock_file - * machinery here anyway because it does a lot of the - * work we need, including cleaning up if the program - * exits unexpectedly. - */ - if (hold_lock_file_for_update(&reflog_lock, log_file, 0) < 0) { - struct strbuf err = STRBUF_INIT; - unable_to_lock_message(log_file, errno, &err); - error("%s", err.buf); - strbuf_release(&err); - goto failure; - } - cb.newlog = fdopen_lock_file(&reflog_lock, "w"); - if (!cb.newlog) { - error("cannot fdopen %s (%s)", - reflog_lock.filename.buf, strerror(errno)); - goto failure; - } - } - - reflog_expiry_prepare(refname, sha1, cb.policy_cb); - for_each_reflog_ent(refname, expire_reflog_ent, &cb); - reflog_expiry_cleanup(cb.policy_cb); - - if (!(flags & EXPIRE_REFLOGS_DRY_RUN)) { - if (close_lock_file(&reflog_lock)) { - status |= error("couldn't write %s: %s", log_file, - strerror(errno)); - } else if ((flags & EXPIRE_REFLOGS_UPDATE_REF) && - (write_in_full(lock->lock_fd, - sha1_to_hex(cb.last_kept_sha1), 40) != 40 || - write_str_in_full(lock->lock_fd, "\n") != 1 || - close_ref(lock) < 0)) { - status |= error("couldn't write %s", - lock->lk->filename.buf); - rollback_lock_file(&reflog_lock); - } else if (commit_lock_file(&reflog_lock)) { - status |= error("unable to commit reflog '%s' (%s)", - log_file, strerror(errno)); - } else if ((flags & EXPIRE_REFLOGS_UPDATE_REF) && commit_ref(lock)) { - status |= error("couldn't set %s", lock->ref_name); - } - } - free(log_file); - unlock_ref(lock); - return status; - - failure: - rollback_lock_file(&reflog_lock); - free(log_file); - unlock_ref(lock); - return -1; -} - static int collect_reflog(const char *ref, const unsigned char *sha1, int unused, void *cb_data) { struct collected_reflog *e; @@ -727,7 +597,11 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) for (i = 0; i < collected.nr; i++) { struct collected_reflog *e = collected.e[i]; set_reflog_expiry_param(&cb.cmd, explicit_expiry, e->reflog); - status |= expire_reflog(e->reflog, e->sha1, flags, &cb); + status |= reflog_expire(e->reflog, e->sha1, flags, + reflog_expiry_prepare, + should_expire_reflog_ent, + reflog_expiry_cleanup, + &cb); free(e); } free(collected.e); @@ -741,7 +615,11 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) continue; } set_reflog_expiry_param(&cb.cmd, explicit_expiry, ref); - status |= expire_reflog(ref, sha1, flags, &cb); + status |= reflog_expire(ref, sha1, flags, + reflog_expiry_prepare, + should_expire_reflog_ent, + reflog_expiry_cleanup, + &cb); } return status; } @@ -813,7 +691,11 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) cb.cmd.expire_total = 0; } - status |= expire_reflog(ref, sha1, flags, &cb); + status |= reflog_expire(ref, sha1, flags, + reflog_expiry_prepare, + should_expire_reflog_ent, + reflog_expiry_cleanup, + &cb); free(ref); } return status; -- cgit v1.2.3