xref: /aosp_15_r20/development/tools/mergetool/remerge3.sh (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
1*90c8c64dSAndroid Build Coastguard Worker#!/bin/bash
2*90c8c64dSAndroid Build Coastguard Worker
3*90c8c64dSAndroid Build Coastguard Workerusage() {
4*90c8c64dSAndroid Build Coastguard Worker  cat <<EOF
5*90c8c64dSAndroid Build Coastguard WorkerUsage:
6*90c8c64dSAndroid Build Coastguard Worker  ${0}                  Remerge all files with conflict markers in the git working tree
7*90c8c64dSAndroid Build Coastguard Worker  ${0} [FILE...]        Remerge the given files
8*90c8c64dSAndroid Build Coastguard Worker
9*90c8c64dSAndroid Build Coastguard WorkerOptions:
10*90c8c64dSAndroid Build Coastguard Worker  -t, --tool {bcompare,meld,vimdiff}
11*90c8c64dSAndroid Build Coastguard Worker    Use the specified merge tool.
12*90c8c64dSAndroid Build Coastguard WorkerEOF
13*90c8c64dSAndroid Build Coastguard Worker}
14*90c8c64dSAndroid Build Coastguard Worker
15*90c8c64dSAndroid Build Coastguard Worker# shellcheck disable=SC2155
16*90c8c64dSAndroid Build Coastguard Workerreadonly BIN_DIR=$(dirname "${BASH_SOURCE[0]}")
17*90c8c64dSAndroid Build Coastguard Workerreadonly SPLIT3="${BIN_DIR}/split3.awk"
18*90c8c64dSAndroid Build Coastguard Workerreadonly CONFLICT_MARKER_BEGIN='^<{7}( .+)?$'
19*90c8c64dSAndroid Build Coastguard Workerreadonly CONFLICT_MARKER_BASE='^\|{7}( .+)?$'
20*90c8c64dSAndroid Build Coastguard Worker
21*90c8c64dSAndroid Build Coastguard WorkerTEMP_FILES=()
22*90c8c64dSAndroid Build Coastguard Workercleanup() {
23*90c8c64dSAndroid Build Coastguard Worker  rm -rf "${TEMP_FILES[@]}"
24*90c8c64dSAndroid Build Coastguard Worker}
25*90c8c64dSAndroid Build Coastguard Workertrap cleanup EXIT
26*90c8c64dSAndroid Build Coastguard Worker
27*90c8c64dSAndroid Build Coastguard Workerxtrace() {
28*90c8c64dSAndroid Build Coastguard Worker  (
29*90c8c64dSAndroid Build Coastguard Worker    set -x
30*90c8c64dSAndroid Build Coastguard Worker    "${@}"
31*90c8c64dSAndroid Build Coastguard Worker  )
32*90c8c64dSAndroid Build Coastguard Worker}
33*90c8c64dSAndroid Build Coastguard Worker
34*90c8c64dSAndroid Build Coastguard Workermergetool() {
35*90c8c64dSAndroid Build Coastguard Worker  local file="${1}"
36*90c8c64dSAndroid Build Coastguard Worker  local MERGED="$file"
37*90c8c64dSAndroid Build Coastguard Worker  local BASE="${file}:BASE"
38*90c8c64dSAndroid Build Coastguard Worker  local LOCAL="${file}:LOCAL"
39*90c8c64dSAndroid Build Coastguard Worker  local REMOTE="${file}:REMOTE"
40*90c8c64dSAndroid Build Coastguard Worker  TEMP_FILES+=("$BASE" "$LOCAL" "$REMOTE")
41*90c8c64dSAndroid Build Coastguard Worker
42*90c8c64dSAndroid Build Coastguard Worker  local has_base=false
43*90c8c64dSAndroid Build Coastguard Worker  if grep -qE "${CONFLICT_MARKER_BASE}" "$file"; then
44*90c8c64dSAndroid Build Coastguard Worker    has_base=true
45*90c8c64dSAndroid Build Coastguard Worker  fi
46*90c8c64dSAndroid Build Coastguard Worker
47*90c8c64dSAndroid Build Coastguard Worker  $has_base && awk -f "$SPLIT3" -v TARGET=BASE <"$file" >"$BASE"
48*90c8c64dSAndroid Build Coastguard Worker  awk -f "$SPLIT3" -v TARGET=LOCAL <"$file" >"$LOCAL"
49*90c8c64dSAndroid Build Coastguard Worker  awk -f "$SPLIT3" -v TARGET=REMOTE <"$file" >"$REMOTE"
50*90c8c64dSAndroid Build Coastguard Worker
51*90c8c64dSAndroid Build Coastguard Worker  case "$MERGETOOL" in
52*90c8c64dSAndroid Build Coastguard Worker    bc*)
53*90c8c64dSAndroid Build Coastguard Worker      if $has_base; then
54*90c8c64dSAndroid Build Coastguard Worker        xtrace bcompare "$LOCAL" "$REMOTE" "$BASE" -mergeoutput="$MERGED"
55*90c8c64dSAndroid Build Coastguard Worker      else
56*90c8c64dSAndroid Build Coastguard Worker        xtrace bcompare "$LOCAL" "$REMOTE" -mergeoutput="$MERGED"
57*90c8c64dSAndroid Build Coastguard Worker      fi
58*90c8c64dSAndroid Build Coastguard Worker      ;;
59*90c8c64dSAndroid Build Coastguard Worker    meld)
60*90c8c64dSAndroid Build Coastguard Worker      if $has_base; then
61*90c8c64dSAndroid Build Coastguard Worker        xtrace meld "$LOCAL" "$BASE" "$REMOTE" -o "$MERGED"
62*90c8c64dSAndroid Build Coastguard Worker      else
63*90c8c64dSAndroid Build Coastguard Worker        xtrace meld "$LOCAL" "$MERGED" "$REMOTE"
64*90c8c64dSAndroid Build Coastguard Worker      fi
65*90c8c64dSAndroid Build Coastguard Worker      ;;
66*90c8c64dSAndroid Build Coastguard Worker    vim*)
67*90c8c64dSAndroid Build Coastguard Worker      if $has_base; then
68*90c8c64dSAndroid Build Coastguard Worker        xtrace vimdiff -c '4wincmd w | wincmd J' "$LOCAL" "$BASE" "$REMOTE" "$MERGED"
69*90c8c64dSAndroid Build Coastguard Worker      else
70*90c8c64dSAndroid Build Coastguard Worker        xtrace vimdiff -c 'wincmd l' "$LOCAL" "$MERGED" "$REMOTE"
71*90c8c64dSAndroid Build Coastguard Worker      fi
72*90c8c64dSAndroid Build Coastguard Worker      ;;
73*90c8c64dSAndroid Build Coastguard Worker  esac
74*90c8c64dSAndroid Build Coastguard Worker}
75*90c8c64dSAndroid Build Coastguard Worker
76*90c8c64dSAndroid Build Coastguard Worker#
77*90c8c64dSAndroid Build Coastguard Worker# BEGIN
78*90c8c64dSAndroid Build Coastguard Worker#
79*90c8c64dSAndroid Build Coastguard Worker
80*90c8c64dSAndroid Build Coastguard WorkerMERGETOOL=vimdiff
81*90c8c64dSAndroid Build Coastguard Workerif [[ -n "$DISPLAY" ]]; then
82*90c8c64dSAndroid Build Coastguard Worker  if command -v bcompare; then
83*90c8c64dSAndroid Build Coastguard Worker    MERGETOOL=bcompare
84*90c8c64dSAndroid Build Coastguard Worker  elif command -v meld; then
85*90c8c64dSAndroid Build Coastguard Worker    MERGETOOL=meld
86*90c8c64dSAndroid Build Coastguard Worker  fi
87*90c8c64dSAndroid Build Coastguard Workerfi >/dev/null
88*90c8c64dSAndroid Build Coastguard Worker
89*90c8c64dSAndroid Build Coastguard Workerwhile [[ "$1" =~ ^- ]]; do
90*90c8c64dSAndroid Build Coastguard Worker  arg="${1}"
91*90c8c64dSAndroid Build Coastguard Worker  shift
92*90c8c64dSAndroid Build Coastguard Worker  case "$arg" in
93*90c8c64dSAndroid Build Coastguard Worker    --) break ;;
94*90c8c64dSAndroid Build Coastguard Worker    -t | --tool)
95*90c8c64dSAndroid Build Coastguard Worker      MERGETOOL="${1}"
96*90c8c64dSAndroid Build Coastguard Worker      shift
97*90c8c64dSAndroid Build Coastguard Worker      ;;
98*90c8c64dSAndroid Build Coastguard Worker    -h | --help | --usage)
99*90c8c64dSAndroid Build Coastguard Worker      usage
100*90c8c64dSAndroid Build Coastguard Worker      exit 0
101*90c8c64dSAndroid Build Coastguard Worker      ;;
102*90c8c64dSAndroid Build Coastguard Worker    *)
103*90c8c64dSAndroid Build Coastguard Worker      usage
104*90c8c64dSAndroid Build Coastguard Worker      exit 1
105*90c8c64dSAndroid Build Coastguard Worker      ;;
106*90c8c64dSAndroid Build Coastguard Worker  esac
107*90c8c64dSAndroid Build Coastguard Workerdone
108*90c8c64dSAndroid Build Coastguard Worker
109*90c8c64dSAndroid Build Coastguard WorkerTRUST_EXIT_CODE=false
110*90c8c64dSAndroid Build Coastguard Workerif git rev-parse >/dev/null 2>/dev/null; then
111*90c8c64dSAndroid Build Coastguard Worker  case "$MERGETOOL" in
112*90c8c64dSAndroid Build Coastguard Worker    bc* | vim*)
113*90c8c64dSAndroid Build Coastguard Worker      TRUST_EXIT_CODE=true
114*90c8c64dSAndroid Build Coastguard Worker      ;;
115*90c8c64dSAndroid Build Coastguard Worker  esac
116*90c8c64dSAndroid Build Coastguard Workerfi
117*90c8c64dSAndroid Build Coastguard Worker
118*90c8c64dSAndroid Build Coastguard Workerreadonly MERGETOOL
119*90c8c64dSAndroid Build Coastguard Workerreadonly TRUST_EXIT_CODE
120*90c8c64dSAndroid Build Coastguard Worker
121*90c8c64dSAndroid Build Coastguard WorkerFILES_UNFILTERED=()
122*90c8c64dSAndroid Build Coastguard Workerif [[ "${#}" -eq 0 ]]; then
123*90c8c64dSAndroid Build Coastguard Worker  while IFS= read -r -d '' ARG; do
124*90c8c64dSAndroid Build Coastguard Worker    FILES_UNFILTERED+=("$ARG")
125*90c8c64dSAndroid Build Coastguard Worker  done < <(git -c grep.fallbackToNoIndex=true grep -zlE "$CONFLICT_MARKER_BEGIN" 2>/dev/null)
126*90c8c64dSAndroid Build Coastguard Workerelse
127*90c8c64dSAndroid Build Coastguard Worker  FILES_UNFILTERED+=("${@}")
128*90c8c64dSAndroid Build Coastguard Workerfi
129*90c8c64dSAndroid Build Coastguard Worker
130*90c8c64dSAndroid Build Coastguard WorkerFILES=()
131*90c8c64dSAndroid Build Coastguard Workerfor file in "${FILES_UNFILTERED[@]}"; do
132*90c8c64dSAndroid Build Coastguard Worker  if ! [[ -f "$file" ]] || [[ -L "$file" ]]; then
133*90c8c64dSAndroid Build Coastguard Worker    echo "[SKIPPED] ${file}: not a regular file"
134*90c8c64dSAndroid Build Coastguard Worker  elif ! grep -qE "$CONFLICT_MARKER_BEGIN" "$file"; then
135*90c8c64dSAndroid Build Coastguard Worker    echo "[SKIPPED] ${file}: no conflict markers found"
136*90c8c64dSAndroid Build Coastguard Worker  else
137*90c8c64dSAndroid Build Coastguard Worker    FILES+=("$file")
138*90c8c64dSAndroid Build Coastguard Worker  fi
139*90c8c64dSAndroid Build Coastguard Workerdone
140*90c8c64dSAndroid Build Coastguard Worker
141*90c8c64dSAndroid Build Coastguard Workerecho "Found files with conflict markers:"
142*90c8c64dSAndroid Build Coastguard Workerprintf '    %s\n' "${FILES[@]}"
143*90c8c64dSAndroid Build Coastguard Worker
144*90c8c64dSAndroid Build Coastguard Workerfor file in "${FILES[@]}"; do
145*90c8c64dSAndroid Build Coastguard Worker  echo
146*90c8c64dSAndroid Build Coastguard Worker  echo "Merging '${file}'"
147*90c8c64dSAndroid Build Coastguard Worker
148*90c8c64dSAndroid Build Coastguard Worker  mergetool "$file"
149*90c8c64dSAndroid Build Coastguard Worker  exit_code="$?"
150*90c8c64dSAndroid Build Coastguard Worker  if [[ "$exit_code" -ne 0 ]]; then
151*90c8c64dSAndroid Build Coastguard Worker    echo "Failed to merge '${file}'"
152*90c8c64dSAndroid Build Coastguard Worker  fi
153*90c8c64dSAndroid Build Coastguard Worker
154*90c8c64dSAndroid Build Coastguard Worker  if $TRUST_EXIT_CODE && [[ "$exit_code" -eq 0 ]]; then
155*90c8c64dSAndroid Build Coastguard Worker    if [[ -n "$(git ls-files "$file")" ]]; then
156*90c8c64dSAndroid Build Coastguard Worker      xtrace git add "$file"
157*90c8c64dSAndroid Build Coastguard Worker    fi
158*90c8c64dSAndroid Build Coastguard Worker    continue
159*90c8c64dSAndroid Build Coastguard Worker  fi
160*90c8c64dSAndroid Build Coastguard Worker  read -r -p "Continue merging other files? [Y/n]" -n 1 yn || exit
161*90c8c64dSAndroid Build Coastguard Worker  echo
162*90c8c64dSAndroid Build Coastguard Worker  [[ "$yn" == [nNqQ] ]] && exit "$exit_code"
163*90c8c64dSAndroid Build Coastguard Workerdone
164*90c8c64dSAndroid Build Coastguard Worker
165*90c8c64dSAndroid Build Coastguard Workerexit 0
166