[PATCH 2/2] Treat MERGE_AUTOSTASH and friends as a pseudoref

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Han-Wen Nienhuys <hanwen@xxxxxxxxxx>

In t7600-merge.sh, we can see

        git stash show -p MERGE_AUTOSTASH

which yields

        error: MERGE_AUTOSTASH is not a valid reference

in reftable. stash.c further confirms the stash should be treated as a
revision, by calling setup_revisions() on the first argument to
show_stash()

Signed-off-by: Han-Wen Nienhuys <hanwen@xxxxxxxxxx>
---
 branch.c         |  2 +-
 builtin/commit.c |  2 +-
 builtin/merge.c  | 29 ++++++++++++++---------------
 builtin/rebase.c | 34 ++++++++++++++++++++++++++++------
 path.c           |  1 -
 path.h           |  3 +--
 sequencer.c      | 46 +++++++++++++++++++++-------------------------
 7 files changed, 66 insertions(+), 51 deletions(-)

diff --git a/branch.c b/branch.c
index 6b31df539a5..f506f56de09 100644
--- a/branch.c
+++ b/branch.c
@@ -637,7 +637,7 @@ void remove_merge_branch_state(struct repository *r)
 	unlink(git_path_merge_msg(r));
 	unlink(git_path_merge_mode(r));
 	unlink(git_path_auto_merge(r));
-	save_autostash(git_path_merge_autostash(r));
+	save_autostash(MERGE_AUTOSTASH);
 }
 
 void remove_branch_state(struct repository *r, int verbose)
diff --git a/builtin/commit.c b/builtin/commit.c
index 33ca9e99c80..ef05ecf39df 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1855,7 +1855,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 				     &oid, flags);
 	}
 
-	apply_autostash(git_path_merge_autostash(the_repository));
+	apply_autostash(MERGE_AUTOSTASH);
 
 	UNLEAK(err);
 	UNLEAK(sb);
diff --git a/builtin/merge.c b/builtin/merge.c
index a94a03384ae..81f4fa83c24 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -492,7 +492,7 @@ static void finish(struct commit *head_commit,
 	/* Run a post-merge hook */
 	run_hooks_l("post-merge", squash ? "1" : "0", NULL);
 
-	apply_autostash(git_path_merge_autostash(the_repository));
+	apply_autostash(MERGE_AUTOSTASH);
 	strbuf_release(&reflog_message);
 }
 
@@ -1318,8 +1318,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 	if (abort_current_merge) {
 		int nargc = 2;
 		const char *nargv[] = {"reset", "--merge", NULL};
-		struct strbuf stash_oid = STRBUF_INIT;
-
+		struct object_id stash_oid;
+		char hex[GIT_MAX_HEXSZ + 1] = { 0 };
 		if (orig_argc != 2)
 			usage_msg_opt(_("--abort expects no arguments"),
 			      builtin_merge_usage, builtin_merge_options);
@@ -1327,17 +1327,17 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		if (!file_exists(git_path_merge_head(the_repository)))
 			die(_("There is no merge to abort (MERGE_HEAD missing)."));
 
-		if (read_oneliner(&stash_oid, git_path_merge_autostash(the_repository),
-		    READ_ONELINER_SKIP_IF_EMPTY))
-			unlink(git_path_merge_autostash(the_repository));
+		if (!read_ref(MERGE_AUTOSTASH, &stash_oid)) {
+			oid_to_hex_r(hex, &stash_oid);
+			delete_ref("merge --abort", MERGE_AUTOSTASH, NULL, 0);
+		}
 
 		/* Invoke 'git reset --merge' */
 		ret = cmd_reset(nargc, nargv, prefix);
 
-		if (stash_oid.len)
-			apply_autostash_oid(stash_oid.buf);
+		if (hex[0])
+			apply_autostash_oid(hex);
 
-		strbuf_release(&stash_oid);
 		goto done;
 	}
 
@@ -1567,13 +1567,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		}
 
 		if (autostash)
-			create_autostash(the_repository,
-					 git_path_merge_autostash(the_repository));
+			create_autostash(the_repository, MERGE_AUTOSTASH);
 		if (checkout_fast_forward(the_repository,
 					  &head_commit->object.oid,
 					  &commit->object.oid,
 					  overwrite_ignore)) {
-			apply_autostash(git_path_merge_autostash(the_repository));
+			apply_autostash(MERGE_AUTOSTASH);
+
 			ret = 1;
 			goto done;
 		}
@@ -1638,8 +1638,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		die_ff_impossible();
 
 	if (autostash)
-		create_autostash(the_repository,
-				 git_path_merge_autostash(the_repository));
+		create_autostash(the_repository, MERGE_AUTOSTASH);
 
 	/* We are going to make a new commit. */
 	git_committer_info(IDENT_STRICT);
@@ -1722,7 +1721,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		else
 			fprintf(stderr, _("Merge with strategy %s failed.\n"),
 				use_strategies[0]->name);
-		apply_autostash(git_path_merge_autostash(the_repository));
+		apply_autostash(MERGE_AUTOSTASH);
 		ret = 2;
 		goto done;
 	} else if (best_strategy == wt_strategy)
diff --git a/builtin/rebase.c b/builtin/rebase.c
index b29ad2b65e7..e84c21ab8fc 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -414,6 +414,17 @@ static const char *state_dir_path(const char *filename, struct rebase_options *o
 	return path.buf;
 }
 
+static const char *state_pseudoref(const char *suffix,
+				   struct rebase_options *opts)
+{
+	static struct strbuf pseudo_ref = STRBUF_INIT;
+	strbuf_reset(&pseudo_ref);
+	strbuf_addstr(&pseudo_ref, strrchr(opts->state_dir, '/') + 1);
+	strbuf_addstr(&pseudo_ref, "/");
+	strbuf_addstr(&pseudo_ref, suffix);
+	return pseudo_ref.buf;
+}
+
 /* Initialize the rebase options from the state directory. */
 static int read_basic_state(struct rebase_options *opts)
 {
@@ -544,10 +555,11 @@ static int finish_rebase(struct rebase_options *opts)
 {
 	struct strbuf dir = STRBUF_INIT;
 	int ret = 0;
+	const char *autostash_ref = state_pseudoref("autostash", opts);
 
 	delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
 	unlink(git_path_auto_merge(the_repository));
-	apply_autostash(state_dir_path("autostash", opts));
+	apply_autostash(autostash_ref);
 	/*
 	 * We ignore errors in 'git maintenance run --auto', since the
 	 * user should see them.
@@ -559,6 +571,9 @@ static int finish_rebase(struct rebase_options *opts)
 		replay.action = REPLAY_INTERACTIVE_REBASE;
 		ret = sequencer_remove_state(&replay);
 	} else {
+		if (delete_ref("cleanup autostash", autostash_ref, NULL,
+			       REF_SKIP_REFNAME_VERIFICATION))
+			die("failed cleaning up autostash ref");
 		strbuf_addstr(&dir, opts->state_dir);
 		if (remove_dir_recursively(&dir, 0))
 			ret = error(_("could not remove '%s'"),
@@ -760,8 +775,11 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action)
 			finish_rebase(opts);
 	} else if (status == 2) {
 		struct strbuf dir = STRBUF_INIT;
-
-		apply_autostash(state_dir_path("autostash", opts));
+		const char *autostash_ref = state_pseudoref("autostash", opts);
+		apply_autostash(autostash_ref);
+		if (delete_ref("cleanup autostash", autostash_ref, NULL,
+			       REF_SKIP_REFNAME_VERIFICATION))
+			die("failed cleaning up autostash ref");
 		strbuf_addstr(&dir, opts->state_dir);
 		remove_dir_recursively(&dir, 0);
 		strbuf_release(&dir);
@@ -1310,13 +1328,18 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		goto cleanup;
 	}
 	case ACTION_QUIT: {
-		save_autostash(state_dir_path("autostash", &options));
+		const char *autostash_ref =
+			state_pseudoref("autostash", &options);
+		save_autostash(autostash_ref);
 		if (options.type == REBASE_MERGE) {
 			struct replay_opts replay = REPLAY_OPTS_INIT;
 
 			replay.action = REPLAY_INTERACTIVE_REBASE;
 			ret = sequencer_remove_state(&replay);
 		} else {
+			if (delete_ref("deleted autostash_ref", autostash_ref,
+				       NULL, REF_SKIP_REFNAME_VERIFICATION))
+				die("failed to cleanup autostash ref");
 			strbuf_reset(&buf);
 			strbuf_addstr(&buf, options.state_dir);
 			ret = remove_dir_recursively(&buf, 0);
@@ -1670,8 +1693,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 
 	if (options.autostash)
 		create_autostash(the_repository,
-				 state_dir_path("autostash", &options));
-
+				 state_pseudoref("autostash", &options));
 
 	if (require_clean_work_tree(the_repository, "rebase",
 				    _("Please commit or stash them."), 1, 1)) {
diff --git a/path.c b/path.c
index 2c895471d90..f69a912a279 100644
--- a/path.c
+++ b/path.c
@@ -1552,7 +1552,6 @@ REPO_GIT_PATH_FUNC(merge_msg, "MERGE_MSG")
 REPO_GIT_PATH_FUNC(merge_rr, "MERGE_RR")
 REPO_GIT_PATH_FUNC(merge_mode, "MERGE_MODE")
 REPO_GIT_PATH_FUNC(merge_head, "MERGE_HEAD")
-REPO_GIT_PATH_FUNC(merge_autostash, "MERGE_AUTOSTASH")
 REPO_GIT_PATH_FUNC(auto_merge, "AUTO_MERGE")
 REPO_GIT_PATH_FUNC(fetch_head, "FETCH_HEAD")
 REPO_GIT_PATH_FUNC(shallow, "shallow")
diff --git a/path.h b/path.h
index b68691a86b8..e1cf1db98ba 100644
--- a/path.h
+++ b/path.h
@@ -175,7 +175,6 @@ struct path_cache {
 	const char *merge_rr;
 	const char *merge_mode;
 	const char *merge_head;
-	const char *merge_autostash;
 	const char *auto_merge;
 	const char *fetch_head;
 	const char *shallow;
@@ -188,11 +187,11 @@ const char *git_path_merge_msg(struct repository *r);
 const char *git_path_merge_rr(struct repository *r);
 const char *git_path_merge_mode(struct repository *r);
 const char *git_path_merge_head(struct repository *r);
-const char *git_path_merge_autostash(struct repository *r);
 const char *git_path_auto_merge(struct repository *r);
 const char *git_path_fetch_head(struct repository *r);
 const char *git_path_shallow(struct repository *r);
 
+#define MERGE_AUTOSTASH "MERGE_AUTOSTASH"
 
 int ends_with_path_components(const char *path, const char *components);
 
diff --git a/sequencer.c b/sequencer.c
index 35006c0cea6..d61ad1e215d 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -160,7 +160,6 @@ static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
 static GIT_PATH_FUNC(rebase_path_signoff, "rebase-merge/signoff")
 static GIT_PATH_FUNC(rebase_path_head_name, "rebase-merge/head-name")
 static GIT_PATH_FUNC(rebase_path_onto, "rebase-merge/onto")
-static GIT_PATH_FUNC(rebase_path_autostash, "rebase-merge/autostash")
 static GIT_PATH_FUNC(rebase_path_strategy, "rebase-merge/strategy")
 static GIT_PATH_FUNC(rebase_path_strategy_opts, "rebase-merge/strategy_opts")
 static GIT_PATH_FUNC(rebase_path_allow_rerere_autoupdate, "rebase-merge/allow_rerere_autoupdate")
@@ -4085,7 +4084,7 @@ static enum todo_command peek_command(struct todo_list *todo_list, int offset)
 	return -1;
 }
 
-void create_autostash(struct repository *r, const char *path)
+void create_autostash(struct repository *r, const char *pseudoref)
 {
 	struct strbuf buf = STRBUF_INIT;
 	struct lock_file lock_file = LOCK_INIT;
@@ -4117,10 +4116,10 @@ void create_autostash(struct repository *r, const char *path)
 		strbuf_reset(&buf);
 		strbuf_add_unique_abbrev(&buf, &oid, DEFAULT_ABBREV);
 
-		if (safe_create_leading_directories_const(path))
-			die(_("Could not create directory for '%s'"),
-			    path);
-		write_file(path, "%s", oid_to_hex(&oid));
+		refs_update_ref(get_main_ref_store(r), "create_autostash",
+				pseudoref, &oid, null_oid(), 0,
+				UPDATE_REFS_DIE_ON_ERR);
+
 		printf(_("Created autostash: %s\n"), buf.buf);
 		if (reset_head(r, &ropts) < 0)
 			die(_("could not reset --hard"));
@@ -4174,33 +4173,30 @@ static int apply_save_autostash_oid(const char *stash_oid, int attempt_apply)
 	return ret;
 }
 
-static int apply_save_autostash(const char *path, int attempt_apply)
+static int apply_save_autostash(const char *pseudoref, int attempt_apply)
 {
-	struct strbuf stash_oid = STRBUF_INIT;
+	struct object_id oid;
+	char hex[GIT_MAX_HEXSZ + 1] = { 0 };
 	int ret = 0;
 
-	if (!read_oneliner(&stash_oid, path,
-			   READ_ONELINER_SKIP_IF_EMPTY)) {
-		strbuf_release(&stash_oid);
+	if (read_ref(pseudoref, &oid))
 		return 0;
-	}
-	strbuf_trim(&stash_oid);
 
-	ret = apply_save_autostash_oid(stash_oid.buf, attempt_apply);
+	ret = apply_save_autostash_oid(oid_to_hex_r(hex, &oid), attempt_apply);
 
-	unlink(path);
-	strbuf_release(&stash_oid);
+	delete_ref("save autostash", pseudoref, NULL,
+		   REF_SKIP_REFNAME_VERIFICATION);
 	return ret;
 }
 
-int save_autostash(const char *path)
+int save_autostash(const char *pseudoref)
 {
-	return apply_save_autostash(path, 0);
+	return apply_save_autostash(pseudoref, 0);
 }
 
-int apply_autostash(const char *path)
+int apply_autostash(const char *pseudoref)
 {
-	return apply_save_autostash(path, 1);
+	return apply_save_autostash(pseudoref, 1);
 }
 
 int apply_autostash_oid(const char *stash_oid)
@@ -4222,7 +4218,7 @@ static int checkout_onto(struct repository *r, struct replay_opts *opts,
 		.default_reflog_action = "rebase"
 	};
 	if (reset_head(r, &ropts)) {
-		apply_autostash(rebase_path_autostash());
+		apply_autostash("rebase-merge/autostash");
 		sequencer_remove_state(opts);
 		return error(_("could not detach HEAD"));
 	}
@@ -4556,7 +4552,7 @@ cleanup_head_ref:
 				run_command(&hook);
 			}
 		}
-		apply_autostash(rebase_path_autostash());
+		apply_autostash("rebase-merge/autostash");
 
 		if (!opts->quiet) {
 			if (!opts->verbose)
@@ -5635,7 +5631,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
 		todo_list_add_exec_commands(todo_list, commands);
 
 	if (count_commands(todo_list) == 0) {
-		apply_autostash(rebase_path_autostash());
+		apply_autostash("rebase-merge/autostash");
 		sequencer_remove_state(opts);
 
 		return error(_("nothing to do"));
@@ -5646,12 +5642,12 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
 	if (res == -1)
 		return -1;
 	else if (res == -2) {
-		apply_autostash(rebase_path_autostash());
+		apply_autostash("rebase-merge/autostash");
 		sequencer_remove_state(opts);
 
 		return -1;
 	} else if (res == -3) {
-		apply_autostash(rebase_path_autostash());
+		apply_autostash("rebase-merge/autostash");
 		sequencer_remove_state(opts);
 		todo_list_release(&new_todo);
 
-- 
gitgitgadget



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux