Skip to content

Commit 6defce2

Browse files
prertikgitster
authored andcommitted
builtin rebase: support --autostash option
To support `--autostash` we introduce a function `apply_autostash()` just like in `git-legacy-rebase.sh`. Rather than refactoring and using the same function that exists in `sequencer.c`, we go a different route here, to avoid clashes with the sister GSoC project that turns the interactive rebase into a builtin. Signed-off-by: Pratik Karki <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7998dbe commit 6defce2

File tree

1 file changed

+109
-8
lines changed

1 file changed

+109
-8
lines changed

builtin/rebase.c

Lines changed: 109 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,6 @@ static int use_builtin_rebase(void)
6363
return ret;
6464
}
6565

66-
static int apply_autostash(void)
67-
{
68-
warning("TODO");
69-
return 0;
70-
}
71-
7266
struct rebase_options {
7367
enum rebase_type type;
7468
const char *state_dir;
@@ -98,6 +92,7 @@ struct rebase_options {
9892
int keep_empty;
9993
int autosquash;
10094
char *gpg_sign_opt;
95+
int autostash;
10196
};
10297

10398
static int is_interactive(struct rebase_options *opts)
@@ -224,13 +219,56 @@ static int read_basic_state(struct rebase_options *opts)
224219
return 0;
225220
}
226221

222+
static int apply_autostash(struct rebase_options *opts)
223+
{
224+
const char *path = state_dir_path("autostash", opts);
225+
struct strbuf autostash = STRBUF_INIT;
226+
struct child_process stash_apply = CHILD_PROCESS_INIT;
227+
228+
if (!file_exists(path))
229+
return 0;
230+
231+
if (read_one(state_dir_path("autostash", opts), &autostash))
232+
return error(_("Could not read '%s'"), path);
233+
argv_array_pushl(&stash_apply.args,
234+
"stash", "apply", autostash.buf, NULL);
235+
stash_apply.git_cmd = 1;
236+
stash_apply.no_stderr = stash_apply.no_stdout =
237+
stash_apply.no_stdin = 1;
238+
if (!run_command(&stash_apply))
239+
printf(_("Applied autostash.\n"));
240+
else {
241+
struct argv_array args = ARGV_ARRAY_INIT;
242+
int res = 0;
243+
244+
argv_array_pushl(&args,
245+
"stash", "store", "-m", "autostash", "-q",
246+
autostash.buf, NULL);
247+
if (run_command_v_opt(args.argv, RUN_GIT_CMD))
248+
res = error(_("Cannot store %s"), autostash.buf);
249+
argv_array_clear(&args);
250+
strbuf_release(&autostash);
251+
if (res)
252+
return res;
253+
254+
fprintf(stderr,
255+
_("Applying autostash resulted in conflicts.\n"
256+
"Your changes are safe in the stash.\n"
257+
"You can run \"git stash pop\" or \"git stash drop\" "
258+
"at any time.\n"));
259+
}
260+
261+
strbuf_release(&autostash);
262+
return 0;
263+
}
264+
227265
static int finish_rebase(struct rebase_options *opts)
228266
{
229267
struct strbuf dir = STRBUF_INIT;
230268
const char *argv_gc_auto[] = { "gc", "--auto", NULL };
231269

232270
delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
233-
apply_autostash();
271+
apply_autostash(opts);
234272
close_all_packs(the_repository->objects);
235273
/*
236274
* We ignore errors in 'gc --auto', since the
@@ -345,7 +383,7 @@ static int run_specific_rebase(struct rebase_options *opts)
345383
} else if (status == 2) {
346384
struct strbuf dir = STRBUF_INIT;
347385

348-
apply_autostash();
386+
apply_autostash(opts);
349387
strbuf_addstr(&dir, opts->state_dir);
350388
remove_dir_recursively(&dir, 0);
351389
strbuf_release(&dir);
@@ -480,6 +518,11 @@ static int rebase_config(const char *var, const char *value, void *data)
480518
return 0;
481519
}
482520

521+
if (!strcmp(var, "rebase.autostash")) {
522+
opts->autostash = git_config_bool(var, value);
523+
return 0;
524+
}
525+
483526
return git_default_config(var, value, data);
484527
}
485528

@@ -647,6 +690,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
647690
N_("whitespace"), N_("passed to 'git apply'")),
648691
OPT_SET_INT('C', NULL, &opt_c, N_("passed to 'git apply'"),
649692
REBASE_AM),
693+
OPT_BOOL(0, "autostash", &options.autostash,
694+
N_("automatically stash/stash pop before and after")),
650695
OPT_END(),
651696
};
652697

@@ -976,6 +1021,62 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
9761021
if (read_index(the_repository->index) < 0)
9771022
die(_("could not read index"));
9781023

1024+
if (options.autostash) {
1025+
struct lock_file lock_file = LOCK_INIT;
1026+
int fd;
1027+
1028+
fd = hold_locked_index(&lock_file, 0);
1029+
refresh_cache(REFRESH_QUIET);
1030+
if (0 <= fd)
1031+
update_index_if_able(&the_index, &lock_file);
1032+
rollback_lock_file(&lock_file);
1033+
1034+
if (has_unstaged_changes(0) || has_uncommitted_changes(0)) {
1035+
const char *autostash =
1036+
state_dir_path("autostash", &options);
1037+
struct child_process stash = CHILD_PROCESS_INIT;
1038+
struct object_id oid;
1039+
struct commit *head =
1040+
lookup_commit_reference(the_repository,
1041+
&options.orig_head);
1042+
1043+
argv_array_pushl(&stash.args,
1044+
"stash", "create", "autostash", NULL);
1045+
stash.git_cmd = 1;
1046+
stash.no_stdin = 1;
1047+
strbuf_reset(&buf);
1048+
if (capture_command(&stash, &buf, GIT_MAX_HEXSZ))
1049+
die(_("Cannot autostash"));
1050+
strbuf_trim_trailing_newline(&buf);
1051+
if (get_oid(buf.buf, &oid))
1052+
die(_("Unexpected stash response: '%s'"),
1053+
buf.buf);
1054+
strbuf_reset(&buf);
1055+
strbuf_add_unique_abbrev(&buf, &oid, DEFAULT_ABBREV);
1056+
1057+
if (safe_create_leading_directories_const(autostash))
1058+
die(_("Could not create directory for '%s'"),
1059+
options.state_dir);
1060+
write_file(autostash, "%s", buf.buf);
1061+
printf(_("Created autostash: %s\n"), buf.buf);
1062+
if (reset_head(&head->object.oid, "reset --hard",
1063+
NULL, 0) < 0)
1064+
die(_("could not reset --hard"));
1065+
printf(_("HEAD is now at %s"),
1066+
find_unique_abbrev(&head->object.oid,
1067+
DEFAULT_ABBREV));
1068+
strbuf_reset(&buf);
1069+
pp_commit_easy(CMIT_FMT_ONELINE, head, &buf);
1070+
if (buf.len > 0)
1071+
printf(" %s", buf.buf);
1072+
putchar('\n');
1073+
1074+
if (discard_index(the_repository->index) < 0 ||
1075+
read_index(the_repository->index) < 0)
1076+
die(_("could not read index"));
1077+
}
1078+
}
1079+
9791080
if (require_clean_work_tree("rebase",
9801081
_("Please commit or stash them."), 1, 1)) {
9811082
ret = 1;

0 commit comments

Comments
 (0)