diff options
Diffstat (limited to 'builtin-reflog.c')
-rw-r--r-- | builtin-reflog.c | 82 |
1 files changed, 44 insertions, 38 deletions
diff --git a/builtin-reflog.c b/builtin-reflog.c index fb37984ae6..341555139e 100644 --- a/builtin-reflog.c +++ b/builtin-reflog.c @@ -13,7 +13,7 @@ */ static const char reflog_expire_usage[] = -"git-reflog expire [--verbose] [--dry-run] [--fix-stale] [--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>..."; +"git-reflog (show|expire) [--verbose] [--dry-run] [--stale-fix] [--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>..."; static unsigned long default_reflog_expire; static unsigned long default_reflog_expire_unreachable; @@ -173,7 +173,6 @@ static int keep_entry(struct commit **it, unsigned char *sha1) { struct commit *commit; - *it = NULL; if (is_null_sha1(sha1)) return 1; commit = lookup_commit_reference_gently(sha1, 1); @@ -195,41 +194,46 @@ static int keep_entry(struct commit **it, unsigned char *sha1) } static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, - char *data, void *cb_data) + const char *email, unsigned long timestamp, int tz, + const char *message, void *cb_data) { struct expire_reflog_cb *cb = cb_data; - unsigned long timestamp; - char *cp, *ep; struct commit *old, *new; - cp = strchr(data, '>'); - if (!cp || *++cp != ' ') - goto prune; - timestamp = strtoul(cp, &ep, 10); - if (*ep != ' ') - goto prune; if (timestamp < cb->cmd->expire_total) goto prune; + old = new = NULL; if (cb->cmd->stalefix && (!keep_entry(&old, osha1) || !keep_entry(&new, nsha1))) goto prune; - if ((timestamp < cb->cmd->expire_unreachable) && - (!cb->ref_commit || - (old && !in_merge_bases(old, &cb->ref_commit, 1)) || - (new && !in_merge_bases(new, &cb->ref_commit, 1)))) - goto prune; + if (timestamp < cb->cmd->expire_unreachable) { + if (!cb->ref_commit) + goto prune; + if (!old && !is_null_sha1(osha1)) + old = lookup_commit_reference_gently(osha1, 1); + if (!new && !is_null_sha1(nsha1)) + new = lookup_commit_reference_gently(nsha1, 1); + if ((old && !in_merge_bases(old, &cb->ref_commit, 1)) || + (new && !in_merge_bases(new, &cb->ref_commit, 1))) + goto prune; + } - if (cb->newlog) - fprintf(cb->newlog, "%s %s %s", - sha1_to_hex(osha1), sha1_to_hex(nsha1), data); + 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); + } if (cb->cmd->verbose) - printf("keep %s", data); + printf("keep %s", message); return 0; prune: if (!cb->newlog || cb->cmd->verbose) - printf("%sprune %s", cb->newlog ? "" : "would ", data); + printf("%sprune %s", cb->newlog ? "" : "would ", message); return 0; } @@ -238,20 +242,18 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused, struct cmd_reflog_expire_cb *cmd = cb_data; struct expire_reflog_cb cb; struct ref_lock *lock; - char *newlog_path = NULL; + char *log_file, *newlog_path = NULL; int status = 0; - if (strncmp(ref, "refs/", 5)) - return error("not a ref '%s'", ref); - memset(&cb, 0, sizeof(cb)); /* we take the lock for the ref itself to prevent it from * getting updated. */ - lock = lock_ref_sha1(ref + 5, sha1); + lock = lock_any_ref_for_update(ref, sha1); if (!lock) return error("cannot lock ref '%s'", ref); - if (!file_exists(lock->log_file)) + log_file = xstrdup(git_path("logs/%s", ref)); + if (!file_exists(log_file)) goto finish; if (!cmd->dry_run) { newlog_path = xstrdup(git_path("logs/%s.lock", ref)); @@ -259,9 +261,6 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused, } cb.ref_commit = lookup_commit_reference_gently(sha1, 1); - if (!cb.ref_commit) - fprintf(stderr, - "warning: ref '%s' does not point at a commit\n", ref); cb.ref = ref; cb.cmd = cmd; for_each_reflog_ent(ref, expire_reflog_ent, &cb); @@ -270,13 +269,14 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused, if (fclose(cb.newlog)) status |= error("%s: %s", strerror(errno), newlog_path); - if (rename(newlog_path, lock->log_file)) { + if (rename(newlog_path, log_file)) { status |= error("cannot rename %s to %s", - newlog_path, lock->log_file); + newlog_path, log_file); unlink(newlog_path); } } free(newlog_path); + free(log_file); unlock_ref(lock); return status; } @@ -350,7 +350,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) } if (do_all) - status |= for_each_ref(expire_reflog, &cb); + status |= for_each_reflog(expire_reflog, &cb); while (i < argc) { const char *ref = argv[i++]; unsigned char sha1[20]; @@ -372,10 +372,16 @@ static const char reflog_usage[] = int cmd_reflog(int argc, const char **argv, const char *prefix) { - if (argc < 2) - usage(reflog_usage); - else if (!strcmp(argv[1], "expire")) + /* With no command, we default to showing it. */ + if (argc < 2 || *argv[1] == '-') + return cmd_log_reflog(argc, argv, prefix); + + if (!strcmp(argv[1], "show")) + return cmd_log_reflog(argc - 1, argv + 1, prefix); + + if (!strcmp(argv[1], "expire")) return cmd_reflog_expire(argc - 1, argv + 1, prefix); - else - usage(reflog_usage); + + /* Not a recognized reflog command..*/ + usage(reflog_usage); } |