git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v10 09/21] stash: convert drop and clear to builtin

From
Paul-Sebastian Ungureanu <ungureanupaulsebastian@gmail.com>
Date
Oct 14, 2018, 22:11 UTC
Message-ID
<97e3fef686fdd1659f193819ec8c14bf753aa7cb.1539553398.git.ungureanupaulsebastian@gmail.com>
In-Reply-To
<cover.1539553398.git.ungureanupaulsebastian@gmail.com>
From: Joel Teichroeb <joel@teichroeb.net>

Add the drop and clear commands to the builtin helper. These two are each simple, but are being added together as they are quite related.

We have to unfortunately keep the drop and clear functions in the shell script as functions are called with parameters internally that are not valid when the commands are called externally. Once pop is converted they can both be removed.

Signed-off-by: Joel Teichroeb <joel@teichroeb.net>
Signed-off-by: Paul-Sebastian Ungureanu <ungureanupaulsebastian@gmail.com>
---
 builtin/stash--helper.c | 117 ++++++++++++++++++++++++++++++++++++++++
 git-stash.sh            |   4 +-
 2 files changed, 119 insertions(+), 2 deletions(-)
diff --git a/builtin/stash--helper.c b/builtin/stash--helper.c
index c43e0aacbb..aff6cda4c9 100644
--- a/builtin/stash--helper.c
+++ b/builtin/stash--helper.c
@@ -12,7 +12,14 @@
 #include "rerere.h"
 
 static const char * const git_stash_helper_usage[] = {
+	N_("git stash--helper drop [-q|--quiet] [<stash>]"),
 	N_("git stash--helper apply [--index] [-q|--quiet] [<stash>]"),
+	N_("git stash--helper clear"),
+	NULL
+};
+
+static const char * const git_stash_helper_drop_usage[] = {
+	N_("git stash--helper drop [-q|--quiet] [<stash>]"),
 	NULL
 };
 
@@ -21,6 +28,11 @@ static const char * const git_stash_helper_apply_usage[] = {
 	NULL
 };
 
+static const char * const git_stash_helper_clear_usage[] = {
+	N_("git stash--helper clear"),
+	NULL
+};
+
 static const char *ref_stash = "refs/stash";
 static struct strbuf stash_index_path = STRBUF_INIT;
 
@@ -139,6 +151,32 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
 	return !(ret == 0 || ret == 1);
 }
 
+static int do_clear_stash(void)
+{
+	struct object_id obj;
+	if (get_oid(ref_stash, &obj))
+		return 0;
+
+	return delete_ref(NULL, ref_stash, &obj, 0);
+}
+
+static int clear_stash(int argc, const char **argv, const char *prefix)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+
+	argc = parse_options(argc, argv, prefix, options,
+			     git_stash_helper_clear_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+
+	if (argc)
+		return error(_("git stash clear with parameters is "
+			       "unimplemented"));
+
+	return do_clear_stash();
+}
+
 static int reset_tree(struct object_id *i_tree, int update, int reset)
 {
 	int nr_trees = 1;
@@ -426,6 +464,81 @@ static int apply_stash(int argc, const char **argv, const char *prefix)
 	return ret;
 }
 
+static int do_drop_stash(const char *prefix, struct stash_info *info, int quiet)
+{
+	int ret;
+	struct child_process cp_reflog = CHILD_PROCESS_INIT;
+	struct child_process cp = CHILD_PROCESS_INIT;
+
+	/*
+	 * reflog does not provide a simple function for deleting refs. One will
+	 * need to be added to avoid implementing too much reflog code here
+	 */
+
+	cp_reflog.git_cmd = 1;
+	argv_array_pushl(&cp_reflog.args, "reflog", "delete", "--updateref",
+			 "--rewrite", NULL);
+	argv_array_push(&cp_reflog.args, info->revision.buf);
+	ret = run_command(&cp_reflog);
+	if (!ret) {
+		if (!quiet)
+			printf_ln(_("Dropped %s (%s)"), info->revision.buf,
+				  oid_to_hex(&info->w_commit));
+	} else {
+		return error(_("%s: Could not drop stash entry"),
+			     info->revision.buf);
+	}
+
+	/*
+	 * This could easily be replaced by get_oid, but currently it will throw
+	 * a fatal error when a reflog is empty, which we can not recover from.
+	 */
+	cp.git_cmd = 1;
+	/* Even though --quiet is specified, rev-parse still outputs the hash */
+	cp.no_stdout = 1;
+	argv_array_pushl(&cp.args, "rev-parse", "--verify", "--quiet", NULL);
+	argv_array_pushf(&cp.args, "%s@{0}", ref_stash);
+	ret = run_command(&cp);
+
+	/* do_clear_stash if we just dropped the last stash entry */
+	if (ret)
+		do_clear_stash();
+
+	return 0;
+}
+
+static void assert_stash_ref(struct stash_info *info)
+{
+	if (!info->is_stash_ref) {
+		free_stash_info(info);
+		error(_("'%s' is not a stash reference"), info->revision.buf);
+		exit(128);
+	}
+}
+
+static int drop_stash(int argc, const char **argv, const char *prefix)
+{
+	int ret;
+	int quiet = 0;
+	struct stash_info info;
+	struct option options[] = {
+		OPT__QUIET(&quiet, N_("be quiet, only report errors")),
+		OPT_END()
+	};
+
+	argc = parse_options(argc, argv, prefix, options,
+			     git_stash_helper_drop_usage, 0);
+
+	if (get_stash_info(&info, argc, argv))
+		return -1;
+
+	assert_stash_ref(&info);
+
+	ret = do_drop_stash(prefix, &info, quiet);
+	free_stash_info(&info);
+	return ret;
+}
+
 int cmd_stash__helper(int argc, const char **argv, const char *prefix)
 {
 	pid_t pid = getpid();
@@ -448,6 +561,10 @@ int cmd_stash__helper(int argc, const char **argv, const char *prefix)
 		usage_with_options(git_stash_helper_usage, options);
 	if (!strcmp(argv[0], "apply"))
 		return !!apply_stash(argc, argv, prefix);
+	else if (!strcmp(argv[0], "clear"))
+		return !!clear_stash(argc, argv, prefix);
+	else if (!strcmp(argv[0], "drop"))
+		return !!drop_stash(argc, argv, prefix);
 
 	usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv[0]),
 		      git_stash_helper_usage, options);
diff --git a/git-stash.sh b/git-stash.sh
index 809b1c2d1d..a99d5dc9e5 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -653,7 +653,7 @@ apply)
 	;;
 clear)
 	shift
-	clear_stash "$@"
+	git stash--helper clear "$@"
 	;;
 create)
 	shift
@@ -665,7 +665,7 @@ store)
 	;;
 drop)
 	shift
-	drop_stash "$@"
+	git stash--helper drop "$@"
 	;;
 pop)
 	shift
-- 
2.19.0.rc0.23.g10a62394e7
Previous: Paul-Sebastian UngureanuNext: Paul-Sebastian Ungureanu
Message 8 of 30 in “Convert "git stash" to C builtin”
  1. 00/21 Convert "git stash" to C builtinPaul-Sebastian Ungureanu, Oct 14, 2018
  2. 01/21 sha1-name.c: add `get_oidf()` which acts like `get_oid()`Paul-Sebastian Ungureanu, Oct 14, 2018
  3. 02/21 strbuf.c: add `strbuf_join_argv()`Paul-Sebastian Ungureanu, Oct 14, 2018
  4. 03/21 stash: improve option parsing test coveragePaul-Sebastian Ungureanu, Oct 14, 2018
  5. 04/21 t3903: modernize stylePaul-Sebastian Ungureanu, Oct 14, 2018
  6. 05/21 stash: rename test cases to be more descriptivePaul-Sebastian Ungureanu, Oct 14, 2018
  7. 06/21 stash: add tests for `git stash show` configPaul-Sebastian Ungureanu, Oct 14, 2018
  8. 09/21 stash: convert drop and clear to builtinPaul-Sebastian Ungureanu, Oct 14, 2018
  9. 07/21 stash: mention options in `show` synopsisPaul-Sebastian Ungureanu, Oct 14, 2018
  10. 10/21 stash: convert branch to builtinPaul-Sebastian Ungureanu, Oct 14, 2018
  11. 11/21 stash: convert pop to builtinPaul-Sebastian Ungureanu, Oct 14, 2018
  12. 12/21 stash: convert list to builtinPaul-Sebastian Ungureanu, Oct 14, 2018
  13. 13/21 stash: convert show to builtinPaul-Sebastian Ungureanu, Oct 14, 2018
  14. 14/21 stash: convert store to builtinPaul-Sebastian Ungureanu, Oct 14, 2018
  15. 15/21 stash: convert create to builtinPaul-Sebastian Ungureanu, Oct 14, 2018
  16. 16/21 stash: convert push to builtinPaul-Sebastian Ungureanu, Oct 14, 2018
  17. 20/21 stash: optimize `get_untracked_files()` and `check_changes()`Paul-Sebastian Ungureanu, Oct 14, 2018
  18. 21/21 stash: replace all `write-tree` child processes with API callsPaul-Sebastian Ungureanu, Oct 14, 2018
  19. 17/21 stash: make push -q quietPaul-Sebastian Ungureanu, Oct 14, 2018
  20. 19/21 stash: convert `stash--helper.c` into `stash.c`Paul-Sebastian Ungureanu, Oct 14, 2018
  21. Thomas GummererOct 15, 2018
  22. 18/21 stash: convert save to builtinPaul-Sebastian Ungureanu, Oct 14, 2018
  23. Thomas GummererOct 15, 2018
  24. 08/21 stash: convert apply to builtinPaul-Sebastian Ungureanu, Oct 14, 2018
  25. Johannes SchindelinOct 15, 2018
  26. Thomas GummererOct 15, 2018
  27. Thomas GummererOct 15, 2018
  28. Junio C HamanoOct 16, 2018
  29. Johannes SchindelinOct 16, 2018
  30. Thomas GummererOct 16, 2018

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.