refspec: make hash size independent
[gitweb.git] / git-legacy-rebase.sh
index 797344764510e0a2b09bf91af08c528411a9025b..5c2c4e5276d17f257b255e85db112557d9d7fc61 100755 (executable)
@@ -48,6 +48,7 @@ skip!              skip current patch and continue
 edit-todo!         edit the todo list during an interactive rebase
 quit!              abort but keep HEAD where it is
 show-current-patch! show the patch file being applied or merged
+reschedule-failed-exec automatically reschedule failed exec commands
 "
 . git-sh-setup
 set_reflog_action rebase
@@ -57,12 +58,7 @@ cd_to_toplevel
 LF='
 '
 ok_to_skip_pre_rebase=
-resolvemsg="
-$(gettext 'Resolve all conflicts manually, mark them as resolved with
-"git add/rm <conflicted_files>", then run "git rebase --continue".
-You can instead skip this commit: run "git rebase --skip".
-To abort and get back to the state before "git rebase", run "git rebase --abort".')
-"
+
 squash_onto=
 unset onto
 unset restrict_revision
@@ -97,11 +93,15 @@ autosquash=
 keep_empty=
 allow_empty_message=--allow-empty-message
 signoff=
+reschedule_failed_exec=
 test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t
 case "$(git config --bool commit.gpgsign)" in
 true)  gpg_sign_opt=-S ;;
 *)     gpg_sign_opt= ;;
 esac
+test "$(git config --bool rebase.reschedulefailedexec)" = "true" &&
+reschedule_failed_exec=--reschedule-failed-exec
+. git-rebase--common
 
 read_basic_state () {
        test -f "$state_dir/head-name" &&
@@ -117,7 +117,7 @@ read_basic_state () {
        else
                orig_head=$(cat "$state_dir"/head)
        fi &&
-       GIT_QUIET=$(cat "$state_dir"/quiet) &&
+       test -f "$state_dir"/quiet && GIT_QUIET=t
        test -f "$state_dir"/verbose && verbose=t
        test -f "$state_dir"/strategy && strategy="$(cat "$state_dir"/strategy)"
        test -f "$state_dir"/strategy_opts &&
@@ -130,67 +130,8 @@ read_basic_state () {
                signoff="$(cat "$state_dir"/signoff)"
                force_rebase=t
        }
-}
-
-write_basic_state () {
-       echo "$head_name" > "$state_dir"/head-name &&
-       echo "$onto" > "$state_dir"/onto &&
-       echo "$orig_head" > "$state_dir"/orig-head &&
-       echo "$GIT_QUIET" > "$state_dir"/quiet &&
-       test t = "$verbose" && : > "$state_dir"/verbose
-       test -n "$strategy" && echo "$strategy" > "$state_dir"/strategy
-       test -n "$strategy_opts" && echo "$strategy_opts" > \
-               "$state_dir"/strategy_opts
-       test -n "$allow_rerere_autoupdate" && echo "$allow_rerere_autoupdate" > \
-               "$state_dir"/allow_rerere_autoupdate
-       test -n "$gpg_sign_opt" && echo "$gpg_sign_opt" > "$state_dir"/gpg_sign_opt
-       test -n "$signoff" && echo "$signoff" >"$state_dir"/signoff
-}
-
-output () {
-       case "$verbose" in
-       '')
-               output=$("$@" 2>&1 )
-               status=$?
-               test $status != 0 && printf "%s\n" "$output"
-               return $status
-               ;;
-       *)
-               "$@"
-               ;;
-       esac
-}
-
-move_to_original_branch () {
-       case "$head_name" in
-       refs/*)
-               message="rebase finished: $head_name onto $onto"
-               git update-ref -m "$message" \
-                       $head_name $(git rev-parse HEAD) $orig_head &&
-               git symbolic-ref \
-                       -m "rebase finished: returning to $head_name" \
-                       HEAD $head_name ||
-               die "$(eval_gettext "Could not move back to \$head_name")"
-               ;;
-       esac
-}
-
-apply_autostash () {
-       if test -f "$state_dir/autostash"
-       then
-               stash_sha1=$(cat "$state_dir/autostash")
-               if git stash apply $stash_sha1 >/dev/null 2>&1
-               then
-                       echo "$(gettext 'Applied autostash.')" >&2
-               else
-                       git stash store -m "autostash" -q $stash_sha1 ||
-                       die "$(eval_gettext "Cannot store \$stash_sha1")"
-                       gettext 'Applying autostash resulted in conflicts.
-Your changes are safe in the stash.
-You can run "git stash pop" or "git stash drop" at any time.
-' >&2
-               fi
-       fi
+       test -f "$state_dir"/reschedule-failed-exec &&
+               reschedule_failed_exec=t
 }
 
 finish_rebase () {
@@ -200,26 +141,64 @@ finish_rebase () {
        rm -rf "$state_dir"
 }
 
+run_interactive () {
+       GIT_CHERRY_PICK_HELP="$resolvemsg"
+       export GIT_CHERRY_PICK_HELP
+
+       test -n "$keep_empty" && keep_empty="--keep-empty"
+       test -n "$rebase_merges" && rebase_merges="--rebase-merges"
+       test -n "$rebase_cousins" && rebase_cousins="--rebase-cousins"
+       test -n "$autosquash" && autosquash="--autosquash"
+       test -n "$verbose" && verbose="--verbose"
+       test -n "$force_rebase" && force_rebase="--no-ff"
+       test -n "$restrict_revision" && \
+               restrict_revision="--restrict-revision=^$restrict_revision"
+       test -n "$upstream" && upstream="--upstream=$upstream"
+       test -n "$onto" && onto="--onto=$onto"
+       test -n "$squash_onto" && squash_onto="--squash-onto=$squash_onto"
+       test -n "$onto_name" && onto_name="--onto-name=$onto_name"
+       test -n "$head_name" && head_name="--head-name=$head_name"
+       test -n "$strategy" && strategy="--strategy=$strategy"
+       test -n "$strategy_opts" && strategy_opts="--strategy-opts=$strategy_opts"
+       test -n "$switch_to" && switch_to="--switch-to=$switch_to"
+       test -n "$cmd" && cmd="--cmd=$cmd"
+       test -n "$action" && action="--$action"
+
+       exec git rebase--interactive "$action" "$keep_empty" "$rebase_merges" "$rebase_cousins" \
+               "$upstream" "$onto" "$squash_onto" "$restrict_revision" \
+               "$allow_empty_message" "$autosquash" "$verbose" \
+               "$force_rebase" "$onto_name" "$head_name" "$strategy" \
+               "$strategy_opts" "$cmd" "$switch_to" \
+               "$allow_rerere_autoupdate" "$gpg_sign_opt" "$signoff" \
+               "$reschedule_failed_exec"
+}
+
 run_specific_rebase () {
        if [ "$interactive_rebase" = implied ]; then
-               GIT_EDITOR=:
-               export GIT_EDITOR
+               GIT_SEQUENCE_EDITOR=:
+               export GIT_SEQUENCE_EDITOR
                autosquash=
        fi
-       . git-rebase--$type
 
-       if test -z "$preserve_merges"
+       if test -n "$interactive_rebase" -a -z "$preserve_merges"
        then
-               git_rebase__$type
+               run_interactive
        else
-               git_rebase__preserve_merges
+               . git-rebase--$type
+
+               if test -z "$preserve_merges"
+               then
+                       git_rebase__$type
+               else
+                       git_rebase__preserve_merges
+               fi
        fi
 
        ret=$?
        if test $ret -eq 0
        then
                finish_rebase
-       elif test $ret -eq 2 # special exit status for rebase -i
+       elif test $ret -eq 2 # special exit status for rebase -p
        then
                apply_autostash &&
                rm -rf "$state_dir" &&
@@ -246,6 +225,7 @@ then
        state_dir="$apply_dir"
 elif test -d "$merge_dir"
 then
+       type=interactive
        if test -d "$merge_dir"/rewritten
        then
                type=preserve-merges
@@ -253,10 +233,7 @@ then
                preserve_merges=t
        elif test -f "$merge_dir"/interactive
        then
-               type=interactive
                interactive_rebase=explicit
-       else
-               type=merge
        fi
        state_dir="$merge_dir"
 fi
@@ -365,6 +342,11 @@ do
                fix|strip)
                        force_rebase=t
                        ;;
+               warn|nowarn|error|error-all)
+                       ;; # okay, known whitespace option
+               *)
+                       die "fatal: Invalid whitespace option: '${1#*=}'"
+                       ;;
                esac
                ;;
        --ignore-whitespace)
@@ -380,6 +362,9 @@ do
                git_am_opt="$git_am_opt $1"
                force_rebase=t
                ;;
+       -C*[!0-9]*)
+               die "fatal: switch \`C' expects a numerical value"
+               ;;
        -C*)
                git_am_opt="$git_am_opt $1"
                ;;
@@ -398,6 +383,12 @@ do
        --gpg-sign=*)
                gpg_sign_opt="-S${1#--gpg-sign=}"
                ;;
+       --reschedule-failed-exec)
+               reschedule_failed_exec=--reschedule-failed-exec
+               ;;
+       --no-reschedule-failed-exec)
+               reschedule_failed_exec=
+               ;;
        --)
                shift
                break
@@ -497,6 +488,7 @@ then
        test -z "$interactive_rebase" && interactive_rebase=implied
 fi
 
+actually_interactive=
 if test -n "$interactive_rebase"
 then
        if test -z "$preserve_merges"
@@ -505,11 +497,12 @@ then
        else
                type=preserve-merges
        fi
-
+       actually_interactive=t
        state_dir="$merge_dir"
 elif test -n "$do_merge"
 then
-       type=merge
+       interactive_rebase=implied
+       type=interactive
        state_dir="$merge_dir"
 else
        type=am
@@ -521,28 +514,20 @@ then
        git_format_patch_opt="$git_format_patch_opt --progress"
 fi
 
-if test -n "$git_am_opt"; then
-       incompatible_opts=$(echo " $git_am_opt " | \
-                           sed -e 's/ -q / /g' -e 's/^ \(.*\) $/\1/')
-       if test -n "$interactive_rebase"
+incompatible_opts=$(echo " $git_am_opt " | \
+                   sed -e 's/ -q / /g' -e 's/^ \(.*\) $/\1/')
+if test -n "$incompatible_opts"
+then
+       if test -n "$actually_interactive" || test "$do_merge"
        then
-               if test -n "$incompatible_opts"
-               then
-                       die "$(gettext "error: cannot combine interactive options (--interactive, --exec, --rebase-merges, --preserve-merges, --keep-empty, --root + --onto) with am options ($incompatible_opts)")"
-               fi
-       fi
-       if test -n "$do_merge"; then
-               if test -n "$incompatible_opts"
-               then
-                       die "$(gettext "error: cannot combine merge options (--merge, --strategy, --strategy-option) with am options ($incompatible_opts)")"
-               fi
+               die "$(gettext "fatal: cannot combine am options with either interactive or merge options")"
        fi
 fi
 
 if test -n "$signoff"
 then
        test -n "$preserve_merges" &&
-               die "$(gettext "error: cannot combine '--signoff' with '--preserve-merges'")"
+               die "$(gettext "fatal: cannot combine '--signoff' with '--preserve-merges'")"
        git_am_opt="$git_am_opt $signoff"
        force_rebase=t
 fi
@@ -553,15 +538,18 @@ then
        # Note: incompatibility with --interactive is just a strong warning;
        #       git-rebase.txt caveats with "unless you know what you are doing"
        test -n "$rebase_merges" &&
-               die "$(gettext "error: cannot combine '--preserve_merges' with '--rebase-merges'")"
+               die "$(gettext "fatal: cannot combine '--preserve-merges' with '--rebase-merges'")"
+
+       test -n "$reschedule_failed_exec" &&
+               die "$(gettext "error: cannot combine '--preserve-merges' with '--reschedule-failed-exec'")"
 fi
 
 if test -n "$rebase_merges"
 then
        test -n "$strategy_opts" &&
-               die "$(gettext "error: cannot combine '--rebase_merges' with '--strategy-option'")"
+               die "$(gettext "fatal: cannot combine '--rebase-merges' with '--strategy-option'")"
        test -n "$strategy" &&
-               die "$(gettext "error: cannot combine '--rebase_merges' with '--strategy'")"
+               die "$(gettext "fatal: cannot combine '--rebase-merges' with '--strategy'")"
 fi
 
 if test -z "$rebase_root"
@@ -700,7 +688,7 @@ require_clean_work_tree "rebase" "$(gettext "Please commit or stash them.")"
 # but this should be done only when upstream and onto are the same
 # and if this is not an interactive rebase.
 mb=$(git merge-base "$onto" "$orig_head")
-if test -z "$interactive_rebase" && test "$upstream" = "$onto" &&
+if test -z "$actually_interactive" && test "$upstream" = "$onto" &&
        test "$mb" = "$onto" && test -z "$restrict_revision" &&
        # linear history?
        ! (git rev-list --parents "$onto".."$orig_head" | sane_grep " .* ") > /dev/null
@@ -738,10 +726,29 @@ if test -n "$diffstat"
 then
        if test -n "$verbose"
        then
-               echo "$(eval_gettext "Changes from \$mb to \$onto:")"
+               if test -z "$mb"
+               then
+                       echo "$(eval_gettext "Changes to \$onto:")"
+               else
+                       echo "$(eval_gettext "Changes from \$mb to \$onto:")"
+               fi
        fi
+       mb_tree="${mb:-$(git hash-object -t tree /dev/null)}"
        # We want color (if set), but no pager
-       GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
+       GIT_PAGER='' git diff --stat --summary "$mb_tree" "$onto"
+fi
+
+if test -z "$actually_interactive" && test "$mb" = "$orig_head"
+then
+       say "$(eval_gettext "Fast-forwarded \$branch_name to \$onto_name.")"
+       GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name" \
+               git checkout -q "$onto^0" || die "could not detach HEAD"
+       # If the $onto is a proper descendant of the tip of the branch, then
+       # we just fast-forwarded.
+       git update-ref ORIG_HEAD $orig_head
+       move_to_original_branch
+       finish_rebase
+       exit 0
 fi
 
 test -n "$interactive_rebase" && run_specific_rebase
@@ -753,16 +760,6 @@ GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name" \
        git checkout -q "$onto^0" || die "could not detach HEAD"
 git update-ref ORIG_HEAD $orig_head
 
-# If the $onto is a proper descendant of the tip of the branch, then
-# we just fast-forwarded.
-if test "$mb" = "$orig_head"
-then
-       say "$(eval_gettext "Fast-forwarded \$branch_name to \$onto_name.")"
-       move_to_original_branch
-       finish_rebase
-       exit 0
-fi
-
 if test -n "$rebase_root"
 then
        revisions="$onto..$orig_head"