diff options
author | Johannes Schindelin <Johannes.Schindelin@gmx.de> | 2007-10-17 02:50:45 +0100 |
---|---|---|
committer | Shawn O. Pearce <spearce@spearce.org> | 2007-10-17 02:54:51 -0400 |
commit | 552cecc21447efe9d5f9a86d55b5e428d56a0c53 (patch) | |
tree | c6dd9228628bd4db04a50539eee64a18f37c56b5 /builtin-reflog.c | |
parent | 207f1a75e7e4d14286aeed107af7c56dc811797b (diff) | |
download | git-552cecc21447efe9d5f9a86d55b5e428d56a0c53.tar.gz |
Teach "git reflog" a subcommand to delete single entries
This commit implements the "delete" subcommand:
git reflog delete master@{2}
will delete the second reflog entry of the "master" branch.
With this, it should be easy to implement "git stash pop" everybody
seems to want these days.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Diffstat (limited to 'builtin-reflog.c')
-rw-r--r-- | builtin-reflog.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/builtin-reflog.c b/builtin-reflog.c index ce093cad78..f4226939a9 100644 --- a/builtin-reflog.c +++ b/builtin-reflog.c @@ -25,6 +25,7 @@ struct cmd_reflog_expire_cb { int verbose; unsigned long expire_total; unsigned long expire_unreachable; + int recno; }; struct expire_reflog_cb { @@ -220,6 +221,9 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, goto prune; } + if (cb->cmd->recno && --(cb->cmd->recno) == 0) + goto prune; + if (cb->newlog) { char sign = (tz < 0) ? '-' : '+'; int zone = (tz < 0) ? (-tz) : tz; @@ -363,6 +367,58 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) return status; } +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++; + return 0; +} + +static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) +{ + struct cmd_reflog_expire_cb cb; + int i, status = 0; + + if (argc < 2) + return error("Nothing to delete?"); + + memset(&cb, 0, sizeof(cb)); + + for (i = 1; i < argc; i++) { + const char *spec = strstr(argv[i], "@{"); + unsigned char sha1[20]; + char *ep, *ref; + int recno; + + if (!spec) { + status |= error("Not a reflog: %s", ref); + continue; + } + + if (!dwim_ref(argv[i], spec - argv[i], sha1, &ref)) { + status |= error("%s points nowhere!", argv[i]); + continue; + } + + recno = strtoul(spec + 2, &ep, 10); + if (*ep == '}') { + cb.recno = -recno; + for_each_reflog_ent(ref, count_reflog_ent, &cb); + } else { + cb.expire_total = approxidate(spec + 2); + for_each_reflog_ent(ref, count_reflog_ent, &cb); + cb.expire_total = 0; + } + + status |= expire_reflog(ref, sha1, 0, &cb); + free(ref); + } + return status; +} + /* * main "reflog" */ @@ -382,6 +438,9 @@ int cmd_reflog(int argc, const char **argv, const char *prefix) if (!strcmp(argv[1], "expire")) return cmd_reflog_expire(argc - 1, argv + 1, prefix); + if (!strcmp(argv[1], "delete")) + return cmd_reflog_delete(argc - 1, argv + 1, prefix); + /* Not a recognized reflog command..*/ usage(reflog_usage); } |