diff --git a/.gitignore b/.gitignore index 52ac3d2117..a371024425 100644 --- a/.gitignore +++ b/.gitignore @@ -79,6 +79,8 @@ /git-interpret-trailers /git-instaweb /git-legacy-rebase +/git-legacy-rebase--interactive +/git-legacy-stash /git-log /git-ls-files /git-ls-remote diff --git a/Makefile b/Makefile index 3ca69336a1..221410e7ba 100644 --- a/Makefile +++ b/Makefile @@ -615,11 +615,13 @@ SCRIPT_SH += git-merge-resolve.sh SCRIPT_SH += git-mergetool.sh SCRIPT_SH += git-quiltimport.sh SCRIPT_SH += git-legacy-rebase.sh +SCRIPT_SH += git-legacy-stash.sh SCRIPT_SH += git-remote-testgit.sh SCRIPT_SH += git-request-pull.sh SCRIPT_SH += git-submodule.sh SCRIPT_SH += git-web--browse.sh +SCRIPT_LIB += git-legacy-rebase--interactive SCRIPT_LIB += git-mergetool--lib SCRIPT_LIB += git-parse-remote SCRIPT_LIB += git-rebase--am diff --git a/builtin/rebase--interactive.c b/builtin/rebase--interactive.c index a2ab68ed06..4b9d2a07cb 100644 --- a/builtin/rebase--interactive.c +++ b/builtin/rebase--interactive.c @@ -141,7 +141,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix) char *raw_strategies = NULL; enum { NONE = 0, CONTINUE, SKIP, EDIT_TODO, SHOW_CURRENT_PATCH, - SHORTEN_OIDS, EXPAND_OIDS, CHECK_TODO_LIST, REARRANGE_SQUASH, ADD_EXEC + SHORTEN_OIDS, EXPAND_OIDS, CHECK_TODO_LIST, REARRANGE_SQUASH, ADD_EXEC, + MAKE_SCRIPT, SKIP_UNNECESSARY_PICKS, } command = 0; struct option options[] = { OPT_BOOL(0, "ff", &opts.allow_ff, N_("allow fast-forward")), @@ -192,6 +193,10 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix) OPT_STRING(0, "onto-name", &onto_name, N_("onto-name"), N_("onto name")), OPT_STRING(0, "cmd", &cmd, N_("cmd"), N_("the command to run")), OPT_RERERE_AUTOUPDATE(&opts.allow_rerere_auto), + OPT_CMDMODE(0, "make-script", &command, + N_("make rebase script"), MAKE_SCRIPT), + OPT_CMDMODE(0, "skip-unnecessary-picks", &command, + N_("skip unnecessary picks"), SKIP_UNNECESSARY_PICKS), OPT_END() }; @@ -263,6 +268,17 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix) case ADD_EXEC: ret = sequencer_add_exec_commands(cmd); break; + case MAKE_SCRIPT: + ret = sequencer_make_script(stdout, argc, argv, flags); + break; + case SKIP_UNNECESSARY_PICKS: { + struct object_id oid; + + ret = skip_unnecessary_picks(&oid); + if (!ret) + printf("%s\n", oid_to_hex(&oid)); + break; + } default: BUG("invalid command '%d'", command); } diff --git a/builtin/rebase.c b/builtin/rebase.c index a20bcd6d6d..0b47846443 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -54,7 +54,7 @@ static int use_builtin_rebase(void) cp.git_cmd = 1; if (capture_command(&cp, &out, 6)) { strbuf_release(&out); - return 1; + return 0; } strbuf_trim(&out); diff --git a/builtin/stash.c b/builtin/stash.c index 571bac329f..965e938ebd 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -13,6 +13,7 @@ #include "revision.h" #include "log-tree.h" #include "diffcore.h" +#include "exec-cmd.h" static const char * const git_stash_usage[] = { N_("git stash list []"), @@ -1477,6 +1478,26 @@ static int save_stash(int argc, const char **argv, const char *prefix) return ret; } +static int use_builtin_stash(void) +{ + struct child_process cp = CHILD_PROCESS_INIT; + struct strbuf out = STRBUF_INIT; + int ret; + + argv_array_pushl(&cp.args, + "config", "--bool", "stash.usebuiltin", NULL); + cp.git_cmd = 1; + if (capture_command(&cp, &out, 6)) { + strbuf_release(&out); + return 0; + } + + strbuf_trim(&out); + ret = !strcmp("true", out.buf); + strbuf_release(&out); + return ret; +} + int cmd_stash(int argc, const char **argv, const char *prefix) { int i = -1; @@ -1488,6 +1509,20 @@ int cmd_stash(int argc, const char **argv, const char *prefix) OPT_END() }; + if (!use_builtin_stash()) { + const char *path = mkpath("%s/git-legacy-stash", + git_exec_path()); + + if (sane_execvp(path, (char **)argv) < 0) + die_errno(_("could not exec %s"), path); + else + BUG("sane_execvp() returned???"); + } + + prefix = setup_git_directory(); + trace_repo_setup(prefix); + setup_work_tree(); + git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, options, git_stash_usage, diff --git a/git-legacy-rebase--interactive.sh b/git-legacy-rebase--interactive.sh new file mode 100644 index 0000000000..9740875ad5 --- /dev/null +++ b/git-legacy-rebase--interactive.sh @@ -0,0 +1,283 @@ +# This shell script fragment is sourced by git-rebase to implement +# its interactive mode. "git rebase --interactive" makes it easy +# to fix up commits in the middle of a series and rearrange commits. +# +# Copyright (c) 2006 Johannes E. Schindelin +# +# The original idea comes from Eric W. Biederman, in +# https://public-inbox.org/git/m1odwkyuf5.fsf_-_@ebiederm.dsl.xmission.com/ +# +# The file containing rebase commands, comments, and empty lines. +# This file is created by "git rebase -i" then edited by the user. As +# the lines are processed, they are removed from the front of this +# file and written to the tail of $done. +todo="$state_dir"/git-rebase-todo + +GIT_CHERRY_PICK_HELP="$resolvemsg" +export GIT_CHERRY_PICK_HELP + +comment_char=$(git config --get core.commentchar 2>/dev/null) +case "$comment_char" in +'' | auto) + comment_char="#" + ;; +?) + ;; +*) + comment_char=$(echo "$comment_char" | cut -c1) + ;; +esac + +orig_reflog_action="$GIT_REFLOG_ACTION" + +comment_for_reflog () { + case "$orig_reflog_action" in + ''|rebase*) + GIT_REFLOG_ACTION="rebase -i ($1)" + export GIT_REFLOG_ACTION + ;; + esac +} + +append_todo_help () { + gettext " +Commands: +p, pick = use commit +r, reword = use commit, but edit the commit message +e, edit = use commit, but stop for amending +s, squash = use commit, but meld into previous commit +f, fixup = like \"squash\", but discard this commit's log message +x, exec = run command (the rest of the line) using shell +d, drop = remove commit +l, label