Release: merge release notes with previous

This change does a three way merge with previous release notes if it exists.

--
Change-Id: Idac7905e1550a8e00f96c7034b61603678ff59a6
Reviewed-on: https://cr.bazel.build/7355
PiperOrigin-RevId: 141031870
MOS_MIGRATED_REVID=141031870
diff --git a/scripts/release/BUILD b/scripts/release/BUILD
index 832b98e..d14dd24 100644
--- a/scripts/release/BUILD
+++ b/scripts/release/BUILD
@@ -46,6 +46,7 @@
         "//:git",
         "//src/test/shell:bashunit",
     ],
+    shard_count = 2,
     tags = ["need_git"],
     deps = [":release"],
 )
diff --git a/scripts/release/common.sh b/scripts/release/common.sh
index 2f0bc0d..de3ccd0 100755
--- a/scripts/release/common.sh
+++ b/scripts/release/common.sh
@@ -190,3 +190,39 @@
     git_commit_msg "$@"
   fi
 }
+
+# Merge three release notes using branch $1 as a base
+# Args:
+#   $1 the branch name to use to play on
+#   $2 the new generated release notes
+#   $3 the last generated release notes
+#   $4 the last edited release notes
+function merge_release_notes() {
+  local branch_name="$1"
+  local relnotes="$2"
+  local last_relnotes="$3"
+  local last_savedrelnotes="$4"
+  if [ "${last_relnotes}" == "${last_savedrelnotes}" ]; then
+    echo "${relnotes}"
+  else
+    # Merge the three release notes, use git merge for it
+    git checkout -q -b "${branch_name}-merge-notes-1"
+    echo "${last_relnotes}" >.relnotes
+    git add .relnotes
+    git commit -q -m "last_relnotes" --allow-empty
+    echo "${last_savedrelnotes}" >.relnotes
+    git add .relnotes
+    git commit -q -m "last_savedrelnotes" --allow-empty
+    git checkout -q -b "${branch_name}-merge-notes-2" HEAD~
+    echo "${relnotes}" >.relnotes
+    git add .relnotes
+    git commit -q -m "relnotes" --allow-empty
+    git merge -q --no-commit "${branch_name}-merge-notes-1" &>/dev/null || true
+    cat .relnotes
+
+    # Clean-up
+    git merge --abort || true &>/dev/null
+    git checkout -q "${branch_name}"
+    git branch -D ${branch_name}-merge-notes-{1,2} >/dev/null
+  fi
+}
diff --git a/scripts/release/release.sh b/scripts/release/release.sh
index fc2942a..7e92c76 100755
--- a/scripts/release/release.sh
+++ b/scripts/release/release.sh
@@ -222,26 +222,41 @@
 
   # Edit the release notes
   local tmpfile=$(mktemp ${TMPDIR:-/tmp}/relnotes-XXXXXXXX)
-  local tmpfile2=$(mktemp ${TMPDIR:-/tmp}/relnotes-XXXXXXXX)
-  trap 'rm -f ${tmpfile} ${tmpfile2}' EXIT
-
-  # Save the changelog so we compute the relnotes against HEAD.
-  git show master:CHANGELOG.md >${tmpfile2} 2>/dev/null || echo >${tmpfile2}
+  trap "rm -f ${tmpfile}" EXIT
 
   echo "Creating release notes"
+
+  # Save the changelog so we compute the relnotes against HEAD.
+  git show master:CHANGELOG.md >${tmpfile} 2>/dev/null || echo >${tmpfile}
+  # Compute the new release notes
+  local relnotes="$(create_release_notes "${tmpfile}" "${baseline}" ${cherrypicks})"
+
+  # Try to merge the release notes if there was a previous release
+  if [ -n "${last_release}" ]; then
+    # Compute the previous release notes
+    local last_baseline="$(get_release_baseline "${last_release}")"
+    local last_cherrypicks="$(get_cherrypicks "${last_release}" \
+      "${last_baseline}")"
+    git checkout -q "${last_release}"
+    local last_relnotes="$(create_release_notes "${tmpfile}")"
+    git checkout -q "${branch_name}"
+    local last_savedrelnotes="$(get_release_notes "${last_release}")"
+    relnotes="$(merge_release_notes "${branch_name}" "${relnotes}" \
+      "${last_relnotes}" "${last_savedrelnotes}")"
+  fi
   echo "${RELEASE_NOTE_MESSAGE}" > ${tmpfile}
   echo "# $(get_release_title "${release_name}rc${rc}")" >> ${tmpfile}
   echo >> ${tmpfile}
-  create_release_notes "${tmpfile2}" "${baseline}" ${cherrypicks} >> ${tmpfile}
+  echo "${relnotes}" >>"${tmpfile}"
   release_note_editor ${tmpfile} "${branch_name}" || return 1
-  local relnotes="$(cat ${tmpfile})"
+  relnotes="$(cat ${tmpfile})"
 
   # Add the git notes
   set_release_name "${release_name}" "${rc}"
   git notes --ref=release-notes add -f -m "${relnotes}"
 
   # Clean-up
-  rm -f ${tmpfile} ${tmpfile2}
+  rm -f ${tmpfile}
   trap - EXIT
 }
 
diff --git a/scripts/release/release_test.sh b/scripts/release/release_test.sh
index 8df6edd..9ead3e2 100755
--- a/scripts/release/release_test.sh
+++ b/scripts/release/release_test.sh
@@ -145,6 +145,50 @@
 
 }
 
+function test_merge_release_notes() {
+  local RELNOTES='Incompatible changes:
+
+  - Remove deprecated "make var" INCDIR
+
+Important changes:
+
+  - Use a default implementation of a progress message, rather than
+    defaulting to null for all SpawnActions.'
+  local NEW_RELNOTES="${RELNOTES}"'
+  - Attribute error messages related to Android resources are easier
+    to understand now.'
+  local REPLACEMENT="Test replacement."
+
+  assert_equals '<<<<<<< HEAD
+Incompatible changes:
+
+  - Remove deprecated "make var" INCDIR
+
+Important changes:
+
+  - Use a default implementation of a progress message, rather than
+    defaulting to null for all SpawnActions.
+  - Attribute error messages related to Android resources are easier
+    to understand now.
+=======
+Test replacement.
+>>>>>>> master-merge-notes-1' "$(merge_release_notes master "${NEW_RELNOTES}" "${RELNOTES}" "${REPLACEMENT}")"
+
+  assert_equals "${NEW_RELNOTES}" \
+    "$(merge_release_notes master "${NEW_RELNOTES}" "${RELNOTES}" "${RELNOTES}")"
+
+  assert_equals "${RELNOTES}"'
+<<<<<<< HEAD
+  - Attribute error messages related to Android resources are easier
+    to understand now.
+=======
+  - Merge conflict.
+>>>>>>> master-merge-notes-1' "$(merge_release_notes master "${NEW_RELNOTES}" "${RELNOTES}" "${RELNOTES}
+  - Merge conflict.")"
+
+}
+
+
 function test_release_workflow() {
   export EDITOR=true
   # Initial release
@@ -215,7 +259,27 @@
   push v1
 
   # Test creating a second candidate
-  echo "#!$(which true)" >${EDITOR}
+  RELNOTES="${RELNOTES}"'
+  - Attribute error messages related to Android resources are easier
+    to understand now.'
+
+  # There should be a merge conflict
+  cat >${TEST_TMPDIR}/expected.log <<EOF
+# Editing release notes
+# Modify the release notes to make them suitable for the release.
+# Every line starting with a # will be removed as well as every
+# empty line at the start and at the end.
+
+# Release v1rc2 ($(date +%Y-%m-%d))
+
+<<<<<<< HEAD
+${RELNOTES}
+=======
+Test replacement
+>>>>>>> release-v1-merge-notes-1
+EOF
+  echo "${RELNOTES}" >${TEST_TMPDIR}/replacement.log
+
   create v1 1170dc6 0540fde cef25c4
   header='Release v1rc2 ('$(date +%Y-%m-%d)')
 
@@ -228,9 +292,6 @@
               resources are easier to understand now.
 
 '
-  RELNOTES="${RELNOTES}"'
-  - Attribute error messages related to Android resources are easier
-    to understand now.'
   assert_equals "${header}${RELNOTES}" "$(cat ${TEST_log})"
   assert_equals "${RELNOTES}" "$(get_release_notes release-v1)"
   assert_equals 2 "$(get_release_candidate release-v1)"