Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- backup-log.c | 71 ++++++++++++++++++++++++++++++++++++++++++++ backup-log.h | 3 ++ builtin/backup-log.c | 17 +++++++++++ 3 files changed, 91 insertions(+) diff --git a/backup-log.c b/backup-log.c index 49f2ce68fe..5e38725981 100644 --- a/backup-log.c +++ b/backup-log.c @@ -1,6 +1,8 @@ #include "cache.h" #include "backup-log.h" +#include "blob.h" #include "lockfile.h" +#include "object-store.h" #include "strbuf.h" void bkl_append(struct strbuf *output, const char *path, @@ -217,3 +219,72 @@ int bkl_parse_file(const char *path, strbuf_release(&sb); return ret; } + +struct prune_options { + struct repository *repo; + FILE *fp; + timestamp_t expire; + struct strbuf copy; +}; + +static int good_oid(struct repository *r, const struct object_id *oid) +{ + if (is_null_oid(oid)) + return 1; + + return oid_object_info(r, oid, NULL) == OBJ_BLOB; +} + +static int prune_parse(struct strbuf *line, void *data) +{ + struct prune_options *opts = data; + struct bkl_entry entry; + + strbuf_reset(&opts->copy); + strbuf_addbuf(&opts->copy, line); + + if (bkl_parse_entry(line, &entry)) + return -1; + + if (entry.timestamp < opts->expire) + return 0; + + if (oideq(&entry.old_oid, &entry.new_oid)) + return 0; + + if (!good_oid(opts->repo, &entry.old_oid) || + !good_oid(opts->repo, &entry.new_oid)) + return 0; + + if (!opts->fp) + return -1; + + fputs(opts->copy.buf, opts->fp); + return 0; +} + +int bkl_prune(struct repository *r, const char *path, timestamp_t expire) +{ + struct lock_file lk; + struct prune_options opts; + int ret; + + ret = hold_lock_file_for_update(&lk, path, 0); + if (ret == -1) { + if (errno == ENOTDIR || errno == ENOENT) + return 0; + return error(_("failed to lock '%s'"), path); + } + opts.repo = r; + opts.expire = expire; + opts.fp = fdopen_lock_file(&lk, "w"); + strbuf_init(&opts.copy, 0); + + ret = bkl_parse_file(path, prune_parse, &opts); + if (ret < 0) + rollback_lock_file(&lk); + else + ret = commit_lock_file(&lk); + strbuf_release(&opts.copy); + return ret; +} diff --git a/backup-log.h b/backup-log.h index c9de9c687c..06fe706f81 100644 --- a/backup-log.h +++ b/backup-log.h @@ -3,6 +3,7 @@ #include "cache.h" +struct repository; struct strbuf; struct bkl_entry @@ -29,4 +30,6 @@ int bkl_parse_file(const char *path, int (*parse)(struct strbuf *line, void *data), void *data); +int bkl_prune(struct repository *r, const char *id, timestamp_t expire); + #endif diff --git a/builtin/backup-log.c b/builtin/backup-log.c index 2496d73ba5..2291124c38 100644 --- a/builtin/backup-log.c +++ b/builtin/backup-log.c @@ -301,6 +301,21 @@ static int log_(int argc, const char **argv, return ret; } +static int prune(int argc, const char **argv, + const char *prefix, const char *log_path) +{ + timestamp_t expire = time(NULL) - 90 * 24 * 3600; + struct option options[] = { + OPT_EXPIRY_DATE(0, "expire", &expire, + N_("expire objects older than <time>")), + OPT_END() + }; + + argc = parse_options(argc, argv, prefix, options, backup_log_usage, 0); + + return bkl_prune(the_repository, log_path, expire); +} + static char *log_id_to_path(const char *id) { if (!strcmp(id, "index")) @@ -346,6 +361,8 @@ int cmd_backup_log(int argc, const char **argv, const char *prefix) return diff(argc, argv, prefix, log_path); else if (!strcmp(argv[0], "log")) return log_(argc, argv, prefix, log_path); + else if (!strcmp(argv[0], "prune")) + return prune(argc, argv, prefix, log_path); else die(_("unknown subcommand: %s"), argv[0]); -- 2.20.0.rc2.486.g9832c05c3d