#!/bin/sh # # mfh - Merge from head to a given branch # Copyright 2013 Baptiste Daroussin # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # MAINTAINER= portmgr@FreeBSD.org set -eu ########################################## # Init and Validation ######################################### if [ $# -ne 3 ] then echo "$(basename $0) requires 3 arguments: {ports|base} " echo "e.g. $0 base stable/10 r245453" exit 1 fi LF=$(printf '\nX') LF=${LF%X} IFS="${LF}" case ${1} in base) tree=base branchprefix= ;; ports) tree=ports branchprefix=/branches ;; *) echo "need a tree to work in: $0 " echo "e.g. $0 base stable/10 r345453" exit 1 ;; esac shift branch=$1 # what branches do we support and how? case "${branch}" in stable/[89]) echo "only sure this works on 10 for now)" # maybe we could set something here to support them?? exit 1 ;; stable/1[01]) echo "using source tree root as base of merge" ;; esac : ${svnserver:="repo.FreeBSD.org"} if [ -n "$(type svn 2>/dev/null)" ] then svn=svn elif [ -n "$(type svnlite 2>/dev/null)" ] then svn=svnlite else err "Neither svn(1) nor svnlite(1) found. Please install devel/subversion." fi workdir=$(mktemp -d /tmp/merge.XXXXXX) cd "${workdir}" echo > ${workdir}/commit.txt trap " cd - ; rc=\$? ; rm -rf \"\${workdir}\" ; exit \$rc" EXIT err() { echo "$@" >&2 exit 1 } clean() { rm -rf "${workdir}" exit 1 } ask() { question=${1} answer=x while [ "${answer}" != "y" -a "${answer}" != "n" ] ; do read -p "${question} [y/n] " answer done [ "${answer}" = "y" ] && return 0 return 1 } ######################################################### # mergebranch branch rev # e.g. mergebranch stable/10 243545 # # we compile filelist though we don't use it.. # We COULD just check out the files we need for a super-sparse # checkout but I have no idea if it would work so stick with # using dirlist in the 'svn up' for now even though it checks # out stuff we don't touch ######################################################### mergechange() { filelist="" dirlist="" # svn:// is faster than svn+ssh://. Use it wherever it's possible. for f in $("${svn}" diff --summarize -c ${rev} svn://${svnserver}/${tree}/head); do case ${f} in */*) ;; *)continue;; esac file=${f##*/${tree}/head/} filelist="${filelist}${LF}${file}" dir=${file%/*} dirlist="${dirlist}${LF}${dir}" done filelist=$(printf '%s\n' "${filelist}" | sort -u) dirlist=$(printf '%s\n' "${dirlist}" | sort -u) echo "MFH: r${rev}" >> ${workdir}/commit.txt "${svn}" log -r${rev} svn://${svnserver}/${tree}/head | sed '1,2d;$d;/^MFH:/d' \ | sed '$d' >> ${workdir}/commit.txt "${svn}" up --parents $(printf '%s\n' $dirlist \ | sed "s}^}${branch}/}") "${svn}" up --quiet "${branch}" "${svn}" merge -c r${rev} ^/head/ "${branch}" "${svn}" up --quiet "${branch}" "${svn}" status "${branch}" "${svn}" diff "${branch}" } ##################################################### # main code ##################################################### rev=${2##r} # remove a leading "r" case ${rev} in ''|*[!0-9]*) err "revision should be a number" ;; esac "${svn}" co --depth=empty svn+ssh://${svnserver}/${tree}${branchprefix}/"${branch}" ${branch} while : do mergechange ${branch} ${rev} read -p "Do you want to integrate another change number? (CR for no) : " VAL JUNK echo "VAL=$VAL" rev=${VAL##r} # remove a leading "r" case "${rev}" in "") break ;; [1-9]*) rev=$(($rev)) # normalise if [ "${rev}" = "0" ] then echo "really?" break fi ;; *) break ;; esac done 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 ) ${EDITOR:-vi} ${workdir}/commit.txt "${svn}" ci -F ${workdir}/commit.txt "${branch}" rm -rf "${workdir}" trap - 0