{"thread":{"id":"54546","subject":"[PATCH RESEND] stash: simplify reflog emptiness check","startedAt":"2020-11-01T07:34:20Z","lastAt":"2020-11-01T07:34:20Z","messageCount":1,"participants":["René Scharfe"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"408806","messageId":"532cf383-913c-5f33-e143-687f6d51a8da@web.de","threadId":"54546","inReplyTo":null,"subject":"[PATCH RESEND] stash: simplify reflog emptiness check","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2020-11-01T07:34:07Z","receivedAt":"2020-11-01T07:34:20Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Calling rev-parse to check if the drop subcommand removed the last stash\nand treating its failure as confirmation is fragile, as the command can\nfail for other reasons, e.g. because the system is out of memory.\nDirectly check if the reflog is empty instead, which is more robust.\n\nReported-by: Marek Mrva <mrva@eof-studios.com>\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\nOriginal submission:\nhttps://public-inbox.org/git/618d66a8-e2c1-241c-5200-2298bfe24ac0@web.de/\n\n builtin/stash.c | 27 +++++++++++++--------------\n 1 file changed, 13 insertions(+), 14 deletions(-)\n\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex 3f811f3050..24ddb1bffa 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -534,11 +534,22 @@ static int apply_stash(int argc, const char **argv, const char *prefix)\n \treturn ret;\n }\n\n+static int reject_reflog_ent(struct object_id *ooid, struct object_id *noid,\n+\t\t\t     const char *email, timestamp_t timestamp, int tz,\n+\t\t\t     const char *message, void *cb_data)\n+{\n+\treturn 1;\n+}\n+\n+static int reflog_is_empty(const char *refname)\n+{\n+\treturn !for_each_reflog_ent(refname, reject_reflog_ent, NULL);\n+}\n+\n static int do_drop_stash(struct stash_info *info, int quiet)\n {\n \tint ret;\n \tstruct child_process cp_reflog = CHILD_PROCESS_INIT;\n-\tstruct child_process cp = CHILD_PROCESS_INIT;\n\n \t/*\n \t * reflog does not provide a simple function for deleting refs. One will\n@@ -559,19 +570,7 @@ static int do_drop_stash(struct stash_info *info, int quiet)\n \t\t\t     info->revision.buf);\n \t}\n\n-\t/*\n-\t * This could easily be replaced by get_oid, but currently it will throw\n-\t * a fatal error when a reflog is empty, which we can not recover from.\n-\t */\n-\tcp.git_cmd = 1;\n-\t/* Even though --quiet is specified, rev-parse still outputs the hash */\n-\tcp.no_stdout = 1;\n-\tstrvec_pushl(&cp.args, \"rev-parse\", \"--verify\", \"--quiet\", NULL);\n-\tstrvec_pushf(&cp.args, \"%s@{0}\", ref_stash);\n-\tret = run_command(&cp);\n-\n-\t/* do_clear_stash if we just dropped the last stash entry */\n-\tif (ret)\n+\tif (reflog_is_empty(ref_stash))\n \t\tdo_clear_stash();\n\n \treturn 0;\n--\n2.28.0\n"}]}