From 65c425a2ec815989994716c81a2307ae5b5645bc Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Fri, 3 Apr 2020 21:11:16 -0400 Subject: sequencer: stop leaking buf In read_populate_opts(), we call read_oneliner() _after_ calling strbuf_release(). This means that `buf` is leaked at the end of the function. Always clean up the strbuf by going to `done_rebase_i` whether or not we return an error. Signed-off-by: Denton Liu Signed-off-by: Junio C Hamano --- sequencer.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'sequencer.c') diff --git a/sequencer.c b/sequencer.c index e528225e78..faab0b13e8 100644 --- a/sequencer.c +++ b/sequencer.c @@ -2485,6 +2485,7 @@ static int read_populate_opts(struct replay_opts *opts) { if (is_rebase_i(opts)) { struct strbuf buf = STRBUF_INIT; + int ret = 0; if (read_oneliner(&buf, rebase_path_gpg_sign_opt(), 1)) { if (!starts_with(buf.buf, "-S")) @@ -2525,7 +2526,7 @@ static int read_populate_opts(struct replay_opts *opts) opts->keep_redundant_commits = 1; read_strategy_opts(opts, &buf); - strbuf_release(&buf); + strbuf_reset(&buf); if (read_oneliner(&opts->current_fixups, rebase_path_current_fixups(), 1)) { @@ -2538,12 +2539,16 @@ static int read_populate_opts(struct replay_opts *opts) } if (read_oneliner(&buf, rebase_path_squash_onto(), 0)) { - if (get_oid_hex(buf.buf, &opts->squash_onto) < 0) - return error(_("unusable squash-onto")); + if (get_oid_hex(buf.buf, &opts->squash_onto) < 0) { + ret = error(_("unusable squash-onto")); + goto done_rebase_i; + } opts->have_squash_onto = 1; } - return 0; +done_rebase_i: + strbuf_release(&buf); + return ret; } if (!file_exists(git_path_opts_file())) -- cgit v1.2.3 From 5b2f6d9cd50b1c8909326c7175aef288a9915f33 Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Tue, 7 Apr 2020 10:27:51 -0400 Subject: sequencer: make file exists check more efficient We currently check whether a file exists and return early before reading the file. Instead of accessing the file twice, always read the file and check `errno` to see if the file doesn't exist. Signed-off-by: Denton Liu Signed-off-by: Junio C Hamano --- sequencer.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sequencer.c') diff --git a/sequencer.c b/sequencer.c index faab0b13e8..a961cf5a9b 100644 --- a/sequencer.c +++ b/sequencer.c @@ -433,11 +433,9 @@ static int read_oneliner(struct strbuf *buf, { int orig_len = buf->len; - if (!file_exists(path)) - return 0; - if (strbuf_read_file(buf, path, 0) < 0) { - warning_errno(_("could not read '%s'"), path); + if (errno != ENOENT && errno != ENOTDIR) + warning_errno(_("could not read '%s'"), path); return 0; } -- cgit v1.2.3 From 3442c3d11df16d7cd3867b133a8ec6ddd21a8839 Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Tue, 7 Apr 2020 10:27:52 -0400 Subject: sequencer: make read_oneliner() accept flags In a future commit, we will need read_oneliner() to accept flags other than just `skip_if_empty`. Instead of having an argument for each flag, teach read_oneliner() to accept the bitfield `flags` instead. For now, only recognize the `READ_ONELINER_SKIP_IF_EMPTY` flag. More flags will be added in a future commit. The result of this is that parallel topics which introduce invocations of read_oneliner() will still be compatible with this new function signature since, instead of passing 1 or 0 for `skip_if_empty`, they'll be passing 1 or 0 to `flags`, which gives equivalent behavior. Mechanically fix up invocations of read_oneliner() with the following spatch @@ expression a, b; @@ read_oneliner(a, b, - 1 + READ_ONELINER_SKIP_IF_EMPTY ) and manually break up long lines in the result. Signed-off-by: Denton Liu Signed-off-by: Junio C Hamano --- sequencer.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'sequencer.c') diff --git a/sequencer.c b/sequencer.c index a961cf5a9b..6c4e8743ef 100644 --- a/sequencer.c +++ b/sequencer.c @@ -419,6 +419,8 @@ static int write_message(const void *buf, size_t len, const char *filename, return 0; } +#define READ_ONELINER_SKIP_IF_EMPTY (1 << 0) + /* * Reads a file that was presumably written by a shell script, i.e. with an * end-of-line marker that needs to be stripped. @@ -429,7 +431,7 @@ static int write_message(const void *buf, size_t len, const char *filename, * Returns 1 if the file was read, 0 if it could not be read or does not exist. */ static int read_oneliner(struct strbuf *buf, - const char *path, int skip_if_empty) + const char *path, unsigned flags) { int orig_len = buf->len; @@ -445,7 +447,7 @@ static int read_oneliner(struct strbuf *buf, buf->buf[buf->len] = '\0'; } - if (skip_if_empty && buf->len == orig_len) + if ((flags & READ_ONELINER_SKIP_IF_EMPTY) && buf->len == orig_len) return 0; return 1; @@ -2485,7 +2487,8 @@ static int read_populate_opts(struct replay_opts *opts) struct strbuf buf = STRBUF_INIT; int ret = 0; - if (read_oneliner(&buf, rebase_path_gpg_sign_opt(), 1)) { + if (read_oneliner(&buf, rebase_path_gpg_sign_opt(), + READ_ONELINER_SKIP_IF_EMPTY)) { if (!starts_with(buf.buf, "-S")) strbuf_reset(&buf); else { @@ -2495,7 +2498,8 @@ static int read_populate_opts(struct replay_opts *opts) strbuf_reset(&buf); } - if (read_oneliner(&buf, rebase_path_allow_rerere_autoupdate(), 1)) { + if (read_oneliner(&buf, rebase_path_allow_rerere_autoupdate(), + READ_ONELINER_SKIP_IF_EMPTY)) { if (!strcmp(buf.buf, "--rerere-autoupdate")) opts->allow_rerere_auto = RERERE_AUTOUPDATE; else if (!strcmp(buf.buf, "--no-rerere-autoupdate")) @@ -2527,7 +2531,8 @@ static int read_populate_opts(struct replay_opts *opts) strbuf_reset(&buf); if (read_oneliner(&opts->current_fixups, - rebase_path_current_fixups(), 1)) { + rebase_path_current_fixups(), + READ_ONELINER_SKIP_IF_EMPTY)) { const char *p = opts->current_fixups.buf; opts->current_fixup_count = 1; while ((p = strchr(p, '\n'))) { @@ -3668,7 +3673,8 @@ static int apply_autostash(struct replay_opts *opts) struct child_process child = CHILD_PROCESS_INIT; int ret = 0; - if (!read_oneliner(&stash_sha1, rebase_path_autostash(), 1)) { + if (!read_oneliner(&stash_sha1, rebase_path_autostash(), + READ_ONELINER_SKIP_IF_EMPTY)) { strbuf_release(&stash_sha1); return 0; } @@ -4292,7 +4298,8 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts) struct strbuf buf = STRBUF_INIT; struct object_id oid; - if (read_oneliner(&buf, rebase_path_stopped_sha(), 1) && + if (read_oneliner(&buf, rebase_path_stopped_sha(), + READ_ONELINER_SKIP_IF_EMPTY) && !get_oid_committish(buf.buf, &oid)) record_in_rewritten(&oid, peek_command(&todo_list, 0)); strbuf_release(&buf); -- cgit v1.2.3 From bfa50c2c7f0cb806af6d272a84c16f114e15ceee Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Tue, 7 Apr 2020 10:27:53 -0400 Subject: sequencer: configurably warn on non-existent files In the future, we plan on externing read_oneliner(). Future users of read_oneliner() will want the ability to output warnings in the event that the `path` doesn't exist. Introduce the `READ_ONELINER_WARN_MISSING` flag which, if active, would issue a warning when a file doesn't exist by always executing warning_errno() in the case where strbuf_read_file() fails. Signed-off-by: Denton Liu Signed-off-by: Junio C Hamano --- sequencer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sequencer.c') diff --git a/sequencer.c b/sequencer.c index 6c4e8743ef..32cc289da3 100644 --- a/sequencer.c +++ b/sequencer.c @@ -420,6 +420,7 @@ static int write_message(const void *buf, size_t len, const char *filename, } #define READ_ONELINER_SKIP_IF_EMPTY (1 << 0) +#define READ_ONELINER_WARN_MISSING (1 << 1) /* * Reads a file that was presumably written by a shell script, i.e. with an @@ -436,7 +437,8 @@ static int read_oneliner(struct strbuf *buf, int orig_len = buf->len; if (strbuf_read_file(buf, path, 0) < 0) { - if (errno != ENOENT && errno != ENOTDIR) + if ((flags & READ_ONELINER_WARN_MISSING) || + (errno != ENOENT && errno != ENOTDIR)) warning_errno(_("could not read '%s'"), path); return 0; } -- cgit v1.2.3 From c20de8bec6ba759c5e17ad8b8fd7105e8228e313 Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Tue, 7 Apr 2020 10:27:54 -0400 Subject: sequencer: make read_oneliner() extern The function read_oneliner() is a generally useful util function. Instead of hiding it as a static function within sequencer.c, extern it so that it can be reused by others. This patch is best viewed with --color-moved. Signed-off-by: Denton Liu Signed-off-by: Junio C Hamano --- sequencer.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'sequencer.c') diff --git a/sequencer.c b/sequencer.c index 32cc289da3..0d98ddc33c 100644 --- a/sequencer.c +++ b/sequencer.c @@ -419,19 +419,7 @@ static int write_message(const void *buf, size_t len, const char *filename, return 0; } -#define READ_ONELINER_SKIP_IF_EMPTY (1 << 0) -#define READ_ONELINER_WARN_MISSING (1 << 1) - -/* - * Reads a file that was presumably written by a shell script, i.e. with an - * end-of-line marker that needs to be stripped. - * - * Note that only the last end-of-line marker is stripped, consistent with the - * behavior of "$(cat path)" in a shell script. - * - * Returns 1 if the file was read, 0 if it could not be read or does not exist. - */ -static int read_oneliner(struct strbuf *buf, +int read_oneliner(struct strbuf *buf, const char *path, unsigned flags) { int orig_len = buf->len; -- cgit v1.2.3 From be1bb600da13523dd2d63ae93432d7f3b16ffb74 Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Tue, 7 Apr 2020 10:27:56 -0400 Subject: sequencer: make apply_autostash() accept a path In order to make apply_autostash() more generic for future extraction, make it accept a `path` argument so that the location from where to read the reference to the autostash commit can be customized. Remove the `opts` argument since it was unused before anyway. Signed-off-by: Denton Liu Signed-off-by: Junio C Hamano --- sequencer.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'sequencer.c') diff --git a/sequencer.c b/sequencer.c index 0d98ddc33c..4917c70a86 100644 --- a/sequencer.c +++ b/sequencer.c @@ -3657,13 +3657,13 @@ static enum todo_command peek_command(struct todo_list *todo_list, int offset) return -1; } -static int apply_autostash(struct replay_opts *opts) +static int apply_autostash(const char *path) { struct strbuf stash_sha1 = STRBUF_INIT; struct child_process child = CHILD_PROCESS_INIT; int ret = 0; - if (!read_oneliner(&stash_sha1, rebase_path_autostash(), + if (!read_oneliner(&stash_sha1, path, READ_ONELINER_SKIP_IF_EMPTY)) { strbuf_release(&stash_sha1); return 0; @@ -3756,7 +3756,7 @@ static int checkout_onto(struct repository *r, struct replay_opts *opts, return error(_("%s: not a valid OID"), orig_head); if (run_git_checkout(r, opts, oid_to_hex(onto), action)) { - apply_autostash(opts); + apply_autostash(rebase_path_autostash()); sequencer_remove_state(opts); return error(_("could not detach HEAD")); } @@ -4070,7 +4070,7 @@ cleanup_head_ref: run_command(&hook); } } - apply_autostash(opts); + apply_autostash(rebase_path_autostash()); if (!opts->quiet) { if (!opts->verbose) @@ -5079,7 +5079,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(opts); + apply_autostash(rebase_path_autostash()); sequencer_remove_state(opts); return error(_("nothing to do")); @@ -5090,12 +5090,12 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla if (res == -1) return -1; else if (res == -2) { - apply_autostash(opts); + apply_autostash(rebase_path_autostash()); sequencer_remove_state(opts); return -1; } else if (res == -3) { - apply_autostash(opts); + apply_autostash(rebase_path_autostash()); sequencer_remove_state(opts); todo_list_release(&new_todo); -- cgit v1.2.3 From facca7f06e7256bf15675657f59ef6f6c883aec3 Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Tue, 7 Apr 2020 10:27:57 -0400 Subject: sequencer: rename stash_sha1 to stash_oid The preferred terminology is to refer to object identifiers as "OIDs". Rename the `stash_sha1` variable to `stash_oid` in order to conform to this. Signed-off-by: Denton Liu Signed-off-by: Junio C Hamano --- sequencer.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'sequencer.c') diff --git a/sequencer.c b/sequencer.c index 4917c70a86..4a6812e90e 100644 --- a/sequencer.c +++ b/sequencer.c @@ -3659,23 +3659,23 @@ static enum todo_command peek_command(struct todo_list *todo_list, int offset) static int apply_autostash(const char *path) { - struct strbuf stash_sha1 = STRBUF_INIT; + struct strbuf stash_oid = STRBUF_INIT; struct child_process child = CHILD_PROCESS_INIT; int ret = 0; - if (!read_oneliner(&stash_sha1, path, + if (!read_oneliner(&stash_oid, path, READ_ONELINER_SKIP_IF_EMPTY)) { - strbuf_release(&stash_sha1); + strbuf_release(&stash_oid); return 0; } - strbuf_trim(&stash_sha1); + strbuf_trim(&stash_oid); child.git_cmd = 1; child.no_stdout = 1; child.no_stderr = 1; argv_array_push(&child.args, "stash"); argv_array_push(&child.args, "apply"); - argv_array_push(&child.args, stash_sha1.buf); + argv_array_push(&child.args, stash_oid.buf); if (!run_command(&child)) fprintf(stderr, _("Applied autostash.\n")); else { @@ -3687,9 +3687,9 @@ static int apply_autostash(const char *path) argv_array_push(&store.args, "-m"); argv_array_push(&store.args, "autostash"); argv_array_push(&store.args, "-q"); - argv_array_push(&store.args, stash_sha1.buf); + argv_array_push(&store.args, stash_oid.buf); if (run_command(&store)) - ret = error(_("cannot store %s"), stash_sha1.buf); + ret = error(_("cannot store %s"), stash_oid.buf); else fprintf(stderr, _("Applying autostash resulted in conflicts.\n" @@ -3698,7 +3698,7 @@ static int apply_autostash(const char *path) " \"git stash drop\" at any time.\n")); } - strbuf_release(&stash_sha1); + strbuf_release(&stash_oid); return ret; } -- cgit v1.2.3 From 86ed00aff4b86eed6ecc606e9d5f7828a1dca353 Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Tue, 7 Apr 2020 10:27:58 -0400 Subject: rebase: use apply_autostash() from sequencer.c The apply_autostash() function in builtin/rebase.c is similar enough to the apply_autostash() function in sequencer.c that they are almost interchangeable, except for the type of arg they accept. Make the sequencer.c version extern and use it in rebase. The rebase version was introduced in 6defce2b02 (builtin rebase: support `--autostash` option, 2018-09-04) as part of the shell to C conversion. It opted to duplicate the function because, at the time, there was another in-progress project converting interactive rebase from shell to C as well and they did not want to clash with them by refactoring sequencer.c version of apply_autostash(). Since both efforts are long done, we can freely combine them together now. Signed-off-by: Denton Liu Signed-off-by: Junio C Hamano --- sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sequencer.c') diff --git a/sequencer.c b/sequencer.c index 4a6812e90e..f5bb1cc1fb 100644 --- a/sequencer.c +++ b/sequencer.c @@ -3657,7 +3657,7 @@ static enum todo_command peek_command(struct todo_list *todo_list, int offset) return -1; } -static int apply_autostash(const char *path) +int apply_autostash(const char *path) { struct strbuf stash_oid = STRBUF_INIT; struct child_process child = CHILD_PROCESS_INIT; -- cgit v1.2.3 From 0816f1dff8715e80b5fa0b73b48dd36ef9e1e381 Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Tue, 7 Apr 2020 10:28:03 -0400 Subject: sequencer: extract perform_autostash() from rebase Lib-ify the autostash code by extracting perform_autostash() from rebase into sequencer. In a future commit, this will be used to implement `--autostash` in other builtins. This patch is best viewed with `--color-moved`. Signed-off-by: Denton Liu Signed-off-by: Junio C Hamano --- sequencer.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'sequencer.c') diff --git a/sequencer.c b/sequencer.c index f5bb1cc1fb..e0b8262521 100644 --- a/sequencer.c +++ b/sequencer.c @@ -32,6 +32,7 @@ #include "alias.h" #include "commit-reach.h" #include "rebase-interactive.h" +#include "reset.h" #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION" @@ -3657,6 +3658,55 @@ static enum todo_command peek_command(struct todo_list *todo_list, int offset) return -1; } +void create_autostash(struct repository *r, const char *path, + const char *default_reflog_action) +{ + struct strbuf buf = STRBUF_INIT; + struct lock_file lock_file = LOCK_INIT; + int fd; + + fd = repo_hold_locked_index(r, &lock_file, 0); + refresh_index(r->index, REFRESH_QUIET, NULL, NULL, NULL); + if (0 <= fd) + repo_update_index_if_able(r, &lock_file); + rollback_lock_file(&lock_file); + + if (has_unstaged_changes(r, 1) || + has_uncommitted_changes(r, 1)) { + struct child_process stash = CHILD_PROCESS_INIT; + struct object_id oid; + + argv_array_pushl(&stash.args, + "stash", "create", "autostash", NULL); + stash.git_cmd = 1; + stash.no_stdin = 1; + strbuf_reset(&buf); + if (capture_command(&stash, &buf, GIT_MAX_HEXSZ)) + die(_("Cannot autostash")); + strbuf_trim_trailing_newline(&buf); + if (get_oid(buf.buf, &oid)) + die(_("Unexpected stash response: '%s'"), + buf.buf); + 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)); + printf(_("Created autostash: %s\n"), buf.buf); + if (reset_head(r, NULL, "reset --hard", + NULL, RESET_HEAD_HARD, NULL, NULL, + default_reflog_action) < 0) + die(_("could not reset --hard")); + + if (discard_index(r->index) < 0 || + repo_read_index(r) < 0) + die(_("could not read index")); + } + strbuf_release(&buf); +} + int apply_autostash(const char *path) { struct strbuf stash_oid = STRBUF_INIT; -- cgit v1.2.3 From 0dd562e0f7c0bb9ca64f1a02265ff5d1be86df34 Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Tue, 7 Apr 2020 10:28:04 -0400 Subject: sequencer: unlink autostash in apply_autostash() Explicitly remove autostash file in apply_autostash() once it has been applied successfully. This is currently a no-op because the only users of this function will unlink the state (including the autostash file) after this function runs. However, in the future, we will introduce a user of the function that does not explicitly remove the state so we do it here. Signed-off-by: Denton Liu Signed-off-by: Junio C Hamano --- sequencer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sequencer.c') diff --git a/sequencer.c b/sequencer.c index e0b8262521..645bc47ce3 100644 --- a/sequencer.c +++ b/sequencer.c @@ -3748,6 +3748,7 @@ int apply_autostash(const char *path) " \"git stash drop\" at any time.\n")); } + unlink(path); strbuf_release(&stash_oid); return ret; } -- cgit v1.2.3 From 12b6e1367af429628dbaeaa0c7518cacc620d786 Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Tue, 7 Apr 2020 10:28:05 -0400 Subject: sequencer: implement save_autostash() Extract common functionality of apply_autostash() into apply_save_autostash() and use it to implement save_autostash(). This function will be used in a future commit. The difference between save_autostash() and apply_autostash() is that the former does not try to apply the stash. It skips that step and just stores the created entry in the stash reflog. This is useful in the case where we abort an operation when an autostash is present but we don't want to dirty the worktree with the application of the stash. For example, in a future commit, we will implement `git merge --autostash`. Since merges can be aborted using `git reset --hard`, we'd make use of save_autostash() to save the autostash entry instead of applying it to the worktree thus keeping the worktree undirtied. Signed-off-by: Denton Liu Signed-off-by: Junio C Hamano --- sequencer.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) (limited to 'sequencer.c') diff --git a/sequencer.c b/sequencer.c index 645bc47ce3..084ea4117e 100644 --- a/sequencer.c +++ b/sequencer.c @@ -3707,7 +3707,7 @@ void create_autostash(struct repository *r, const char *path, strbuf_release(&buf); } -int apply_autostash(const char *path) +static int apply_save_autostash(const char *path, int attempt_apply) { struct strbuf stash_oid = STRBUF_INIT; struct child_process child = CHILD_PROCESS_INIT; @@ -3720,13 +3720,17 @@ int apply_autostash(const char *path) } strbuf_trim(&stash_oid); - child.git_cmd = 1; - child.no_stdout = 1; - child.no_stderr = 1; - argv_array_push(&child.args, "stash"); - argv_array_push(&child.args, "apply"); - argv_array_push(&child.args, stash_oid.buf); - if (!run_command(&child)) + if (attempt_apply) { + child.git_cmd = 1; + child.no_stdout = 1; + child.no_stderr = 1; + argv_array_push(&child.args, "stash"); + argv_array_push(&child.args, "apply"); + argv_array_push(&child.args, stash_oid.buf); + ret = run_command(&child); + } + + if (attempt_apply && !ret) fprintf(stderr, _("Applied autostash.\n")); else { struct child_process store = CHILD_PROCESS_INIT; @@ -3742,10 +3746,13 @@ int apply_autostash(const char *path) ret = error(_("cannot store %s"), stash_oid.buf); else fprintf(stderr, - _("Applying autostash resulted in conflicts.\n" + _("%s\n" "Your changes are safe in the stash.\n" "You can run \"git stash pop\" or" - " \"git stash drop\" at any time.\n")); + " \"git stash drop\" at any time.\n"), + attempt_apply ? + _("Applying autostash resulted in conflicts.") : + _("Autostash exists; creating a new stash entry.")); } unlink(path); @@ -3753,6 +3760,16 @@ int apply_autostash(const char *path) return ret; } +int save_autostash(const char *path) +{ + return apply_save_autostash(path, 0); +} + +int apply_autostash(const char *path) +{ + return apply_save_autostash(path, 1); +} + static const char *reflog_message(struct replay_opts *opts, const char *sub_action, const char *fmt, ...) { -- cgit v1.2.3 From 804fe3155761e73c3dcc4e162ddb3ff560f16cd7 Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Tue, 7 Apr 2020 10:28:06 -0400 Subject: sequencer: implement apply_autostash_oid() Split apply_save_autostash() into apply_autostash_oid() and apply_save_autostash() where the former operates on an OID string and the latter reads the OID from a file before passing it into apply_save_autostash_oid(). This function is required for a future commmit which will rely on being able to apply an autostash whose OID is stored as a string. Signed-off-by: Denton Liu Signed-off-by: Junio C Hamano --- sequencer.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) (limited to 'sequencer.c') diff --git a/sequencer.c b/sequencer.c index 084ea4117e..f1eba4cb1f 100644 --- a/sequencer.c +++ b/sequencer.c @@ -3707,26 +3707,18 @@ void create_autostash(struct repository *r, const char *path, strbuf_release(&buf); } -static int apply_save_autostash(const char *path, int attempt_apply) +static int apply_save_autostash_oid(const char *stash_oid, int attempt_apply) { - struct strbuf stash_oid = STRBUF_INIT; struct child_process child = CHILD_PROCESS_INIT; int ret = 0; - if (!read_oneliner(&stash_oid, path, - READ_ONELINER_SKIP_IF_EMPTY)) { - strbuf_release(&stash_oid); - return 0; - } - strbuf_trim(&stash_oid); - if (attempt_apply) { child.git_cmd = 1; child.no_stdout = 1; child.no_stderr = 1; argv_array_push(&child.args, "stash"); argv_array_push(&child.args, "apply"); - argv_array_push(&child.args, stash_oid.buf); + argv_array_push(&child.args, stash_oid); ret = run_command(&child); } @@ -3741,9 +3733,9 @@ static int apply_save_autostash(const char *path, int attempt_apply) argv_array_push(&store.args, "-m"); argv_array_push(&store.args, "autostash"); argv_array_push(&store.args, "-q"); - argv_array_push(&store.args, stash_oid.buf); + argv_array_push(&store.args, stash_oid); if (run_command(&store)) - ret = error(_("cannot store %s"), stash_oid.buf); + ret = error(_("cannot store %s"), stash_oid); else fprintf(stderr, _("%s\n" @@ -3755,6 +3747,23 @@ static int apply_save_autostash(const char *path, int attempt_apply) _("Autostash exists; creating a new stash entry.")); } + return ret; +} + +static int apply_save_autostash(const char *path, int attempt_apply) +{ + struct strbuf stash_oid = STRBUF_INIT; + int ret = 0; + + if (!read_oneliner(&stash_oid, path, + READ_ONELINER_SKIP_IF_EMPTY)) { + strbuf_release(&stash_oid); + return 0; + } + strbuf_trim(&stash_oid); + + ret = apply_save_autostash_oid(stash_oid.buf, attempt_apply); + unlink(path); strbuf_release(&stash_oid); return ret; @@ -3770,6 +3779,11 @@ int apply_autostash(const char *path) return apply_save_autostash(path, 1); } +int apply_autostash_oid(const char *stash_oid) +{ + return apply_save_autostash_oid(stash_oid, 1); +} + static const char *reflog_message(struct replay_opts *opts, const char *sub_action, const char *fmt, ...) { -- cgit v1.2.3