Index: Tools/scripts/mfh =================================================================== --- Tools/scripts/mfh +++ Tools/scripts/mfh @@ -39,16 +39,18 @@ LF=${LF%X} IFS="${LF}" +# defaults from here --------------------------- + +: ${svnserver:="svn+ssh://repo.FreeBSD.org"} +: ${EDITOR:=vi} + +# implementation from here --------------------- + err() { echo "$@" >&2 exit 1 } -clean() { - rm -rf "${dir}" - exit 1 -} - ask() { question=${1} @@ -62,7 +64,7 @@ return 1 } -: "${svnserver:="svn+ssh://repo.FreeBSD.org"}" +# -- find svn command -- if [ -n "$(command -v svn 2>/dev/null)" ]; then svn=svn @@ -87,6 +89,8 @@ branch=${latest_branch} fi +## -- parse revisions -- + for rev in "$@" do rev=${rev##r} # remove a leading "r" @@ -95,12 +99,15 @@ esac done +## -- set up tmpdir and auto-clean -- +dir=$(mktemp -d /tmp/merge.XXXXXX) trap "rc=\$? ; rm -rf \"\${dir}\" ; exit \$rc" EXIT -dir=$(mktemp -d /tmp/merge.XXXXXX) cd "${dir}" + +## -- check out, merge, generate commit log -- + "${svn}" co --depth=empty ${svnserver}/ports/branches/"${branch}" -filelist="" printf "MFH:" > commit.txt for rev in "$@" @@ -109,24 +116,35 @@ printf " r%s" "${rev}" >> commit.txt done echo >> commit.txt + +dirlist="" for rev in "$@" do rev=${rev##r} for f in $("${svn}" diff --summarize -c "r${rev}" "${svnserver}/ports/head"); do + # ignore top-level filenames without slash case ${f} in */*) ;; - *)continue;; + *) continue ;; esac f=${f#*/ports/head/} - f=${f%/*} - filelist="${filelist}${LF}${f}" + # strip down f to the first two components (CATEGORY/PORTNAME), + # so that if the MFH only addresses files/, we still get the + # full port to review, and, for instance, bump PORTREVISION + # separately if the patch was broken out from a larger lump. + while :; do + case ${f} in + */*/*) f=${f%/*} ;; + *) break ;; + esac + done + dirlist="${dirlist}${f}${LF}" done "${svn}" log "-r${rev##-}" ${svnserver}/ports/head | sed '1,2d;$d;/^MFH:/d' \ | sed '$d' >> commit.txt done -filelist=$(printf '%s\n' "${filelist}" | sort -u) -"${svn}" up --parents $(printf '%s\n' $filelist \ - | sed "s}^}${branch}/}") +dirlist=$(printf '%s' "${dirlist}" | sort -u | sed "s}^}${branch}/}") +"${svn}" up --parents $dirlist "${svn}" up --quiet "${branch}" for rev in "$@" do @@ -134,19 +152,23 @@ "${svn}" merge -c "r${rev}" ^/head/ "${branch}" done "${svn}" up --quiet "${branch}" + +## -- present final result to user -- "${svn}" status "${branch}" "${svn}" diff "${branch}" -echo "All the merge work was done in ${dir}/${branch}" +printf '\nSee the status above: all the merge work was done on %s.\n' "${dir}/${branch}" ask "Do you want to commit? (no = start a shell)" || ( echo "Dropping you to a shell so you can investigate. Exit the shell to resume this script." cd "${branch}" pwd su -m $(id -un) || : - ask "Do you want to commit now? (no = clean up and abort)" || clean + ask "Do you want to commit now? (no = clean up and abort)" || err "User-requested abort." 1 ) echo >> commit.txt -echo "Approved by: " >> commit.txt -${EDITOR:-vi} commit.txt +echo "Approved by: " >> commit.txt + +## -- edit pre-assembled log message and commit -- +${EDITOR} commit.txt while ! "${svn}" ci -F commit.txt "${branch}"; do if ! ask "Commit failed. Re-edit message and try again?"; then save_log="$(mktemp -t mfh)" @@ -154,7 +176,8 @@ echo "Saving commit log to ${save_log}" break fi - ${EDITOR:-vi} commit.txt + ${EDITOR} commit.txt done -rm -rf "${dir}" -trap - 0 + +# the trap will clean up for us +exit 0