Merge branch 'jc/maint-mergetool-style-fix'

* jc/maint-mergetool-style-fix:
  mergetool: style fixes
This commit is contained in:
Junio C Hamano
2012-09-03 15:54:25 -07:00

View File

@ -18,270 +18,301 @@ require_work_tree
# Returns true if the mode reflects a symlink # Returns true if the mode reflects a symlink
is_symlink () { is_symlink () {
test "$1" = 120000 test "$1" = 120000
} }
is_submodule () { is_submodule () {
test "$1" = 160000 test "$1" = 160000
} }
local_present () { local_present () {
test -n "$local_mode" test -n "$local_mode"
} }
remote_present () { remote_present () {
test -n "$remote_mode" test -n "$remote_mode"
} }
base_present () { base_present () {
test -n "$base_mode" test -n "$base_mode"
} }
cleanup_temp_files () { cleanup_temp_files () {
if test "$1" = --save-backup ; then if test "$1" = --save-backup
rm -rf -- "$MERGED.orig" then
test -e "$BACKUP" && mv -- "$BACKUP" "$MERGED.orig" rm -rf -- "$MERGED.orig"
rm -f -- "$LOCAL" "$REMOTE" "$BASE" test -e "$BACKUP" && mv -- "$BACKUP" "$MERGED.orig"
else rm -f -- "$LOCAL" "$REMOTE" "$BASE"
rm -f -- "$LOCAL" "$REMOTE" "$BASE" "$BACKUP" else
fi rm -f -- "$LOCAL" "$REMOTE" "$BASE" "$BACKUP"
fi
} }
describe_file () { describe_file () {
mode="$1" mode="$1"
branch="$2" branch="$2"
file="$3" file="$3"
printf " {%s}: " "$branch" printf " {%s}: " "$branch"
if test -z "$mode"; then if test -z "$mode"
echo "deleted" then
elif is_symlink "$mode" ; then echo "deleted"
echo "a symbolic link -> '$(cat "$file")'" elif is_symlink "$mode"
elif is_submodule "$mode" ; then then
echo "submodule commit $file" echo "a symbolic link -> '$(cat "$file")'"
else elif is_submodule "$mode"
if base_present; then then
echo "modified file" echo "submodule commit $file"
elif base_present
then
echo "modified file"
else else
echo "created file" echo "created file"
fi fi
fi
} }
resolve_symlink_merge () { resolve_symlink_merge () {
while true; do while true
printf "Use (l)ocal or (r)emote, or (a)bort? " do
read ans || return 1 printf "Use (l)ocal or (r)emote, or (a)bort? "
case "$ans" in read ans || return 1
[lL]*) case "$ans" in
git checkout-index -f --stage=2 -- "$MERGED" [lL]*)
git add -- "$MERGED" git checkout-index -f --stage=2 -- "$MERGED"
cleanup_temp_files --save-backup git add -- "$MERGED"
return 0 cleanup_temp_files --save-backup
;; return 0
[rR]*) ;;
git checkout-index -f --stage=3 -- "$MERGED" [rR]*)
git add -- "$MERGED" git checkout-index -f --stage=3 -- "$MERGED"
cleanup_temp_files --save-backup git add -- "$MERGED"
return 0 cleanup_temp_files --save-backup
;; return 0
[aA]*) ;;
return 1 [aA]*)
;; return 1
esac ;;
esac
done done
} }
resolve_deleted_merge () { resolve_deleted_merge () {
while true; do while true
if base_present; then do
printf "Use (m)odified or (d)eleted file, or (a)bort? " if base_present
else then
printf "Use (c)reated or (d)eleted file, or (a)bort? " printf "Use (m)odified or (d)eleted file, or (a)bort? "
fi else
read ans || return 1 printf "Use (c)reated or (d)eleted file, or (a)bort? "
case "$ans" in fi
[mMcC]*) read ans || return 1
git add -- "$MERGED" case "$ans" in
cleanup_temp_files --save-backup [mMcC]*)
return 0 git add -- "$MERGED"
;; cleanup_temp_files --save-backup
[dD]*) return 0
git rm -- "$MERGED" > /dev/null ;;
cleanup_temp_files [dD]*)
return 0 git rm -- "$MERGED" > /dev/null
;; cleanup_temp_files
[aA]*) return 0
return 1 ;;
;; [aA]*)
esac return 1
;;
esac
done done
} }
resolve_submodule_merge () { resolve_submodule_merge () {
while true; do while true
printf "Use (l)ocal or (r)emote, or (a)bort? " do
read ans || return 1 printf "Use (l)ocal or (r)emote, or (a)bort? "
case "$ans" in read ans || return 1
[lL]*) case "$ans" in
if ! local_present; then [lL]*)
if test -n "$(git ls-tree HEAD -- "$MERGED")"; then if ! local_present
# Local isn't present, but it's a subdirectory then
git ls-tree --full-name -r HEAD -- "$MERGED" | git update-index --index-info || exit $? if test -n "$(git ls-tree HEAD -- "$MERGED")"
else then
test -e "$MERGED" && mv -- "$MERGED" "$BACKUP" # Local isn't present, but it's a subdirectory
git update-index --force-remove "$MERGED" git ls-tree --full-name -r HEAD -- "$MERGED" |
git update-index --index-info || exit $?
else
test -e "$MERGED" && mv -- "$MERGED" "$BACKUP"
git update-index --force-remove "$MERGED"
cleanup_temp_files --save-backup
fi
elif is_submodule "$local_mode"
then
stage_submodule "$MERGED" "$local_sha1"
else
git checkout-index -f --stage=2 -- "$MERGED"
git add -- "$MERGED"
fi
return 0
;;
[rR]*)
if ! remote_present
then
if test -n "$(git ls-tree MERGE_HEAD -- "$MERGED")"
then
# Remote isn't present, but it's a subdirectory
git ls-tree --full-name -r MERGE_HEAD -- "$MERGED" |
git update-index --index-info || exit $?
else
test -e "$MERGED" && mv -- "$MERGED" "$BACKUP"
git update-index --force-remove "$MERGED"
fi
elif is_submodule "$remote_mode"
then
! is_submodule "$local_mode" &&
test -e "$MERGED" &&
mv -- "$MERGED" "$BACKUP"
stage_submodule "$MERGED" "$remote_sha1"
else
test -e "$MERGED" && mv -- "$MERGED" "$BACKUP"
git checkout-index -f --stage=3 -- "$MERGED"
git add -- "$MERGED"
fi
cleanup_temp_files --save-backup cleanup_temp_files --save-backup
fi return 0
elif is_submodule "$local_mode"; then ;;
stage_submodule "$MERGED" "$local_sha1" [aA]*)
else return 1
git checkout-index -f --stage=2 -- "$MERGED" ;;
git add -- "$MERGED" esac
fi
return 0
;;
[rR]*)
if ! remote_present; then
if test -n "$(git ls-tree MERGE_HEAD -- "$MERGED")"; then
# Remote isn't present, but it's a subdirectory
git ls-tree --full-name -r MERGE_HEAD -- "$MERGED" | git update-index --index-info || exit $?
else
test -e "$MERGED" && mv -- "$MERGED" "$BACKUP"
git update-index --force-remove "$MERGED"
fi
elif is_submodule "$remote_mode"; then
! is_submodule "$local_mode" && test -e "$MERGED" && mv -- "$MERGED" "$BACKUP"
stage_submodule "$MERGED" "$remote_sha1"
else
test -e "$MERGED" && mv -- "$MERGED" "$BACKUP"
git checkout-index -f --stage=3 -- "$MERGED"
git add -- "$MERGED"
fi
cleanup_temp_files --save-backup
return 0
;;
[aA]*)
return 1
;;
esac
done done
} }
stage_submodule () { stage_submodule () {
path="$1" path="$1"
submodule_sha1="$2" submodule_sha1="$2"
mkdir -p "$path" || die "fatal: unable to create directory for module at $path" mkdir -p "$path" ||
# Find $path relative to work tree die "fatal: unable to create directory for module at $path"
work_tree_root=$(cd_to_toplevel && pwd) # Find $path relative to work tree
work_rel_path=$(cd "$path" && GIT_WORK_TREE="${work_tree_root}" git rev-parse --show-prefix) work_tree_root=$(cd_to_toplevel && pwd)
test -n "$work_rel_path" || die "fatal: unable to get path of module $path relative to work tree" work_rel_path=$(cd "$path" &&
git update-index --add --replace --cacheinfo 160000 "$submodule_sha1" "${work_rel_path%/}" || die GIT_WORK_TREE="${work_tree_root}" git rev-parse --show-prefix
)
test -n "$work_rel_path" ||
die "fatal: unable to get path of module $path relative to work tree"
git update-index --add --replace --cacheinfo 160000 "$submodule_sha1" "${work_rel_path%/}" || die
} }
checkout_staged_file () { checkout_staged_file () {
tmpfile=$(expr \ tmpfile=$(expr \
"$(git checkout-index --temp --stage="$1" "$2" 2>/dev/null)" \ "$(git checkout-index --temp --stage="$1" "$2" 2>/dev/null)" \
: '\([^ ]*\) ') : '\([^ ]*\) ')
if test $? -eq 0 -a -n "$tmpfile" ; then if test $? -eq 0 -a -n "$tmpfile"
mv -- "$(git rev-parse --show-cdup)$tmpfile" "$3" then
else mv -- "$(git rev-parse --show-cdup)$tmpfile" "$3"
>"$3" else
fi >"$3"
fi
} }
merge_file () { merge_file () {
MERGED="$1" MERGED="$1"
f=$(git ls-files -u -- "$MERGED") f=$(git ls-files -u -- "$MERGED")
if test -z "$f" ; then if test -z "$f"
if test ! -f "$MERGED" ; then then
echo "$MERGED: file not found" if test ! -f "$MERGED"
then
echo "$MERGED: file not found"
else
echo "$MERGED: file does not need merging"
fi
return 1
fi
ext="$$$(expr "$MERGED" : '.*\(\.[^/]*\)$')"
BACKUP="./$MERGED.BACKUP.$ext"
LOCAL="./$MERGED.LOCAL.$ext"
REMOTE="./$MERGED.REMOTE.$ext"
BASE="./$MERGED.BASE.$ext"
base_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==1) print $1;}')
local_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $1;}')
remote_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $1;}')
if is_submodule "$local_mode" || is_submodule "$remote_mode"
then
echo "Submodule merge conflict for '$MERGED':"
local_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $2;}')
remote_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $2;}')
describe_file "$local_mode" "local" "$local_sha1"
describe_file "$remote_mode" "remote" "$remote_sha1"
resolve_submodule_merge
return
fi
mv -- "$MERGED" "$BACKUP"
cp -- "$BACKUP" "$MERGED"
checkout_staged_file 1 "$MERGED" "$BASE"
checkout_staged_file 2 "$MERGED" "$LOCAL"
checkout_staged_file 3 "$MERGED" "$REMOTE"
if test -z "$local_mode" -o -z "$remote_mode"
then
echo "Deleted merge conflict for '$MERGED':"
describe_file "$local_mode" "local" "$LOCAL"
describe_file "$remote_mode" "remote" "$REMOTE"
resolve_deleted_merge
return
fi
if is_symlink "$local_mode" || is_symlink "$remote_mode"
then
echo "Symbolic link merge conflict for '$MERGED':"
describe_file "$local_mode" "local" "$LOCAL"
describe_file "$remote_mode" "remote" "$REMOTE"
resolve_symlink_merge
return
fi
echo "Normal merge conflict for '$MERGED':"
describe_file "$local_mode" "local" "$LOCAL"
describe_file "$remote_mode" "remote" "$REMOTE"
if "$prompt" = true
then
printf "Hit return to start merge resolution tool (%s): " "$merge_tool"
read ans || return 1
fi
if base_present
then
present=true
else else
echo "$MERGED: file does not need merging" present=false
fi
return 1
fi
ext="$$$(expr "$MERGED" : '.*\(\.[^/]*\)$')"
BACKUP="./$MERGED.BACKUP.$ext"
LOCAL="./$MERGED.LOCAL.$ext"
REMOTE="./$MERGED.REMOTE.$ext"
BASE="./$MERGED.BASE.$ext"
base_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==1) print $1;}')
local_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $1;}')
remote_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $1;}')
if is_submodule "$local_mode" || is_submodule "$remote_mode"; then
echo "Submodule merge conflict for '$MERGED':"
local_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $2;}')
remote_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $2;}')
describe_file "$local_mode" "local" "$local_sha1"
describe_file "$remote_mode" "remote" "$remote_sha1"
resolve_submodule_merge
return
fi
mv -- "$MERGED" "$BACKUP"
cp -- "$BACKUP" "$MERGED"
checkout_staged_file 1 "$MERGED" "$BASE"
checkout_staged_file 2 "$MERGED" "$LOCAL"
checkout_staged_file 3 "$MERGED" "$REMOTE"
if test -z "$local_mode" -o -z "$remote_mode"; then
echo "Deleted merge conflict for '$MERGED':"
describe_file "$local_mode" "local" "$LOCAL"
describe_file "$remote_mode" "remote" "$REMOTE"
resolve_deleted_merge
return
fi
if is_symlink "$local_mode" || is_symlink "$remote_mode"; then
echo "Symbolic link merge conflict for '$MERGED':"
describe_file "$local_mode" "local" "$LOCAL"
describe_file "$remote_mode" "remote" "$REMOTE"
resolve_symlink_merge
return
fi
echo "Normal merge conflict for '$MERGED':"
describe_file "$local_mode" "local" "$LOCAL"
describe_file "$remote_mode" "remote" "$REMOTE"
if "$prompt" = true; then
printf "Hit return to start merge resolution tool (%s): " "$merge_tool"
read ans || return 1
fi
if base_present; then
present=true
else
present=false
fi
if ! run_merge_tool "$merge_tool" "$present"; then
echo "merge of $MERGED failed" 1>&2
mv -- "$BACKUP" "$MERGED"
if test "$merge_keep_temporaries" = "false"; then
cleanup_temp_files
fi fi
return 1 if ! run_merge_tool "$merge_tool" "$present"
fi then
echo "merge of $MERGED failed" 1>&2
mv -- "$BACKUP" "$MERGED"
if test "$merge_keep_backup" = "true"; then if test "$merge_keep_temporaries" = "false"
mv -- "$BACKUP" "$MERGED.orig" then
else cleanup_temp_files
rm -- "$BACKUP" fi
fi
git add -- "$MERGED" return 1
cleanup_temp_files fi
return 0
if test "$merge_keep_backup" = "true"
then
mv -- "$BACKUP" "$MERGED.orig"
else
rm -- "$BACKUP"
fi
git add -- "$MERGED"
cleanup_temp_files
return 0
} }
show_tool_help () { show_tool_help () {
@ -325,61 +356,61 @@ prompt=$(git config --bool mergetool.prompt || echo true)
while test $# != 0 while test $# != 0
do do
case "$1" in case "$1" in
--tool-help) --tool-help)
show_tool_help show_tool_help
;; ;;
-t|--tool*) -t|--tool*)
case "$#,$1" in case "$#,$1" in
*,*=*) *,*=*)
merge_tool=$(expr "z$1" : 'z-[^=]*=\(.*\)') merge_tool=$(expr "z$1" : 'z-[^=]*=\(.*\)')
;; ;;
1,*) 1,*)
usage ;; usage ;;
*) *)
merge_tool="$2" merge_tool="$2"
shift ;; shift ;;
esac esac
;;
-y|--no-prompt)
prompt=false
;;
--prompt)
prompt=true
;;
--)
shift
break
;;
-*)
usage
;;
*)
break
;;
esac
shift
done
prompt_after_failed_merge() {
while true; do
printf "Continue merging other unresolved paths (y/n) ? "
read ans || return 1
case "$ans" in
[yY]*)
return 0
;; ;;
-y|--no-prompt)
[nN]*) prompt=false
return 1 ;;
--prompt)
prompt=true
;;
--)
shift
break
;;
-*)
usage
;;
*)
break
;; ;;
esac esac
done shift
done
prompt_after_failed_merge () {
while true
do
printf "Continue merging other unresolved paths (y/n) ? "
read ans || return 1
case "$ans" in
[yY]*)
return 0
;;
[nN]*)
return 1
;;
esac
done
} }
if test -z "$merge_tool"; then if test -z "$merge_tool"
merge_tool=$(get_merge_tool "$merge_tool") || exit then
merge_tool=$(get_merge_tool "$merge_tool") || exit
fi fi
merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)" merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)"
merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)" merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)"
@ -388,22 +419,24 @@ last_status=0
rollup_status=0 rollup_status=0
files= files=
if test $# -eq 0 ; then if test $# -eq 0
cd_to_toplevel then
cd_to_toplevel
if test -e "$GIT_DIR/MERGE_RR" if test -e "$GIT_DIR/MERGE_RR"
then then
files=$(git rerere remaining) files=$(git rerere remaining)
else else
files=$(git ls-files -u | sed -e 's/^[^ ]* //' | sort -u) files=$(git ls-files -u | sed -e 's/^[^ ]* //' | sort -u)
fi fi
else else
files=$(git ls-files -u -- "$@" | sed -e 's/^[^ ]* //' | sort -u) files=$(git ls-files -u -- "$@" | sed -e 's/^[^ ]* //' | sort -u)
fi fi
if test -z "$files" ; then if test -z "$files"
echo "No files need merging" then
exit 0 echo "No files need merging"
exit 0
fi fi
printf "Merging:\n" printf "Merging:\n"
@ -413,15 +446,17 @@ IFS='
' '
for i in $files for i in $files
do do
if test $last_status -ne 0; then if test $last_status -ne 0
prompt_after_failed_merge || exit 1 then
fi prompt_after_failed_merge || exit 1
printf "\n" fi
merge_file "$i" printf "\n"
last_status=$? merge_file "$i"
if test $last_status -ne 0; then last_status=$?
rollup_status=1 if test $last_status -ne 0
fi then
rollup_status=1
fi
done done
exit $rollup_status exit $rollup_status