📄 svnmerge.sh
字号:
# Subroutine to get copyfrom info for a given target# NOTE: repo root has no copyfrom info. In this case null is returned.get_copyfrom(){ target_to_url "$1" url_to_rlpath "${RETURN_VALUE}" TEMP=`"${SVN_MERGE_SVN}" log -v --xml --stop-on-copy "$1" | tr '\n' ' '` TEMP2=`echo "${TEMP}" | sed -e 's#^.*\(<path .*action="A".*>'"${RETURN_VALUE}"'</path>\).*$#\1#'` if [ "${TEMP}" = "${TEMP2}" ]; then RETURN_VALUE="" else RETURN_VALUE=`echo "${TEMP2}" | sed -e 's/^.* copyfrom-path="\([^"]*\)".*$/\1/'` RETURN_VALUE="${RETURN_VALUE}:"`echo "${TEMP2}" | sed -e 's/^.* copyfrom-rev="\([^"]*\)".*$/\1/'` fi}# The "init" actioninit(){ # Check branch directory check_branch_dir # Get initial revision list if not explicitly specified if [ "${REVS}" = "" ]; then REVS="1-${HEAD_REVISION}" fi # Normalize and beautify ${REVS} normalize_list "${REVS}" beautify_list "${RETURN_VALUE}" REVS="${RETURN_VALUE}" report marking "${BRANCH_DIR}" as already containing \ revisions "${REVS}" of "${HEAD_URL}". # Set properties set_integrated_revs "${HEAD_PATH}" "${REVS}" "${BRANCH_DIR}" # Write out commit message if desired if [ "${SVN_MERGE_COMMIT_FILE}" != "" ]; then echo Initialized merge tracking via "${NAME}" with revisions \ "${REVS}" from > "${SVN_MERGE_COMMIT_FILE}" echo "${HEAD_URL}" >> "${SVN_MERGE_COMMIT_FILE}" report wrote commit message to "${SVN_MERGE_COMMIT_FILE}" fi}# "avail" actionavail(){ # Default --avail display type is "revisions" [ "${AVAIL_DISPLAY}" != "" ] || AVAIL_DISPLAY="revisions" # Calculate outstanding revisions list_subtract "1-${HEAD_REVISION}" "${MERGED_REVS}" AVAIL_REVS="${RETURN_VALUE}" # Limit to revisions specified by -r (if any) if [ "${REVS}" != "" ]; then normalize_list "${REVS}" list_subtract "1-${HEAD_REVISION}" "${RETURN_VALUE}" list_subtract "${AVAIL_REVS}" "${RETURN_VALUE}" AVAIL_REVS="${RETURN_VALUE}" fi # Show them, either numerically, in log format, or as diffs case "${AVAIL_DISPLAY}" in revisions) beautify_list "${AVAIL_REVS}" echo "${RETURN_VALUE}" ;; logs) for RNG in `echo "${AVAIL_REVS}" | tr ',' ' ' | tr '-' ':'`; do svn_command log --incremental -v -r "${RNG}" "${HEAD_URL}" done ;; diffs) for RNG in `echo "${AVAIL_REVS}" | tr ',' ' '`; do get_start_end "${RNG}" echo '' echo "${NAME}: changes in revisions ${RNG} follow" echo '' # Note: the starting revision number to 'svn diff' is # NOT inclusive so we have to subtract one from ${START}. svn_command diff -r `expr ${START} - 1`:${END} "${HEAD_URL}" done ;; *) error internal error esac}# "merge" actionmerge(){ # Check branch directory check_branch_dir # Default to merging all outstanding revisions if [ "${REVS}" = "" ]; then REVS="1-${HEAD_REVISION}" fi # Parse desired merge revisions normalize_list "${REVS}" REVS="${RETURN_VALUE}" # Calculate subset of REVS which is not in MERGED_REVS list_subtract "${REVS}" "${MERGED_REVS}" REVS="${RETURN_VALUE}" beautify_list "${REVS}" BREVS="${RETURN_VALUE}" # Save "svnmerge-integrated" property value from before the merge get_all_integrated_revs OLDREVS="${RETURN_VALUE}" # Show what we're doing beautify_list "${MERGED_REVS}" report "\"${BRANCH_DIR}\" already contains revisions ${RETURN_VALUE}" report merging in 'revision(s)' "${BREVS}" from "${HEAD_URL}" # Do the merge(s). Note: the starting revision number to 'svn merge' # is NOT inclusive so we have to subtract one from ${START}. for RNG in `echo "${REVS}" | tr ',' ' '`; do get_start_end "${RNG}" svn_command merge -r `expr ${START} - 1`:${END} \ "${HEAD_URL}" "${BRANCH_DIR}" done # Revert any merged-in changes to the "svnmerge-integrated" property. # We only want updates to this property to happen via explicit action. svn_command propset -q "${SVN_MERGE_PROP}" "${OLDREVS}" "${BRANCH_DIR}" # Write out commit message if desired if [ "${SVN_MERGE_COMMIT_FILE}" != "" ]; then echo "Merged revisions ${BREVS} via ${NAME} from" \ > "${SVN_MERGE_COMMIT_FILE}" echo "${HEAD_PATH}" >> "${SVN_MERGE_COMMIT_FILE}" report wrote commit message to "${SVN_MERGE_COMMIT_FILE}" fi # Update list of merged revisions normalize_list "${MERGED_REVS},${REVS}" beautify_list "${RETURN_VALUE}" set_integrated_revs "${HEAD_PATH}" "${RETURN_VALUE}" "${BRANCH_DIR}"}# Get the desired action, compute getopt flags, and apply defaults[ $# -ge 1 ] || usage_error no action specifiedcase "$1" in init) FLAGS="svnr:f:" BRANCH_DIR="." ;; avail) FLAGS="svldr:S:" BRANCH_DIR="." AVAIL_DISPLAY="revisions" ;; merge) FLAGS="svnr:f:S:" BRANCH_DIR="." ;; help) usage ;; -*) usage_error "no action specified" ;; *) usage_error "unknown action \"$1\"" ;;esacACTION="$1"shift# Unset variables we don't want to inherit from the environmentunset REVS# Parse remaining command lineARGS=`getopt "${FLAGS}" $*`[ $? = 0 ] || usageset -- ${ARGS}for i in "$@"; do case "$i" in -f) SVN_MERGE_COMMIT_FILE="$2" shift; shift ;; -r) REVS="$2" shift; shift ;; -d) AVAIL_DISPLAY="diffs" shift ;; -l) AVAIL_DISPLAY="logs" shift ;; -v) SVN_MERGE_VERBOSE="true" shift ;; -n) SVN_MERGE_PRETEND="true" SVN_MERGE_SHOW_CMDS="true" shift ;; -s) SVN_MERGE_SHOW_CMDS="true" shift ;; -S) HEAD="$2" shift shift ;; --) shift break ;; esacdone# Now parse the non-flag command line parameterscase "${ACTION}" in init) case $# in 1) HEAD="$1" ;; 0) ;; *) usage_error wrong number of parameters esac ;; avail) case $# in 1) BRANCH_DIR="$1" ;; 0) ;; *) usage_error wrong number of parameters esac ;; merge) case $# in 1) BRANCH_DIR="$1" ;; 0) ;; *) usage_error wrong number of parameters esac ;;esac# Validate branch-dir[ -d "${BRANCH_DIR}" -a -d "${BRANCH_DIR}/.svn" ] || \ error \"${BRANCH_DIR}\" is not a subversion working directory# Normalize ${BRANCH_DIR}normalize_url "${BRANCH_DIR}"BRANCH_DIR="${RETURN_VALUE}"# See if we need to upgrade revision metadata from previous schemes:# * revision and head data were stored individually in# svnmerge-[LABEL-]{head,revs} properties# * head used URL's instead of repo-local pathsif TEMP=`"${SVN_MERGE_SVN}" proplist "${BRANCH_DIR}" | grep -Ew "svnmerge-(.+-)?head"`; then echo "${NAME}: old property names detected; an upgrade is required." echo '' echo 'Please execute and commit these changes to upgrade:' echo '' INTEGRATED="" for OLD_PROP in ${TEMP}; do OLD_PROP=${OLD_PROP%-head} echo " svn propdel ${OLD_PROP}-head ${BRANCH_DIR}" echo " svn propdel ${OLD_PROP}-revs ${BRANCH_DIR}" HEAD=`"${SVN_MERGE_SVN}" propget "${OLD_PROP}-head" "${BRANCH_DIR}"` REVS=`"${SVN_MERGE_SVN}" propget "${OLD_PROP}-revs" "${BRANCH_DIR}"` if echo "${HEAD}" | grep -qE '^[[:alpha:]][-+.[:alnum:]]*://'; then url_to_rlpath "${HEAD}" HEAD="${RETURN_VALUE}" fi INTEGRATED="${INTEGRATED} ${HEAD}:${REVS}" done INTEGRATED=`echo "${INTEGRATED}" | xargs -n 1 | sort` echo " svn propset ${SVN_MERGE_PROP} \"${INTEGRATED}\" ${BRANCH_DIR}" echo '' exit 1fi# Previous svnmerge versions allowed trailing /'s in the repository# local path. Newer versions of svnmerge will trim trailing /'s# appearing in the command line, so if there are any properties with# trailing /'s, they will not be properly matched later on, so require# the user to change them now.if TEMP=`"${SVN_MERGE_SVN}" propget "${SVN_MERGE_PROP}" "${BRANCH_DIR}" | grep -E '/+:[-,0-9]+$'`; then echo "${NAME}: old property values detected; an upgrade is required." echo '' echo 'Please execute and commit these changes to upgrade:' echo '' echo "svn propget ${SVN_MERGE_PROP} ${BRANCH_DIR} > svnmerge1.txt" echo "sed -e 's/\/*\(:[-,0-9]*\)/\1/g' < svnmerge1.txt > svnmerge2.txt" echo "svn propset ${SVN_MERGE_PROP} ${BRANCH_DIR} -F svnmerge2.txt" echo "rm svnmerge1.txt svnmerge2.txt" exit 1fi# Calculate ${HEAD_URL} and ${HEAD_PATH}if [ -z "${HEAD}" ]; then if [ "${ACTION}" = "init" ]; then get_copyfrom "${BRANCH_DIR}" [ -z "${RETURN_VALUE}" ] && \ error no copyfrom info available. Explicit \"src\" argument required. HEAD_PATH=`echo "${RETURN_VALUE}" | cut -d: -f 1` [ -z "${REVS}" ] && REVS="1-"`echo "${RETURN_VALUE}" | cut -d: -f 2` else get_default_head "${BRANCH_DIR}" HEAD_PATH="${RETURN_VALUE}" fi get_repo_root "${BRANCH_DIR}" HEAD_URL="${RETURN_VALUE}/${HEAD_PATH}"else # The source was given as a command line argument and is stored in # HEAD. Ensure that the specified source does not end in a /, # otherwise it's easy to have the same source path listed more # than once in the integrated version properties, with and without # trailing /'s. HEAD=`echo ${HEAD} | sed -e 's/\/*$//'` target_to_url "${HEAD}" HEAD_URL="${RETURN_VALUE}" url_to_rlpath "${HEAD_URL}" HEAD_PATH="${RETURN_VALUE}"fi# Sanity check ${HEAD_URL}echo "${HEAD_URL}" | grep -qE '^[[:alpha:]][-+.[:alnum:]]*://' || error "\"${HEAD_URL}\" is not a valid URL or working directory"# Normalize head URLnormalize_url "${HEAD_URL}"HEAD_URL="${RETURN_VALUE}"# Get previously merged revisions (except when --init)if [ "${ACTION}" != "init" ]; then get_integrated_revs "${HEAD_PATH}" "${BRANCH_DIR}" normalize_list "${RETURN_VALUE}" MERGED_REVS="${RETURN_VALUE}"fi# Get latest revision of headreport checking latest revision of "${HEAD_URL}"HEAD_REVISION=`"${SVN_MERGE_SVN}" proplist --revprop -r HEAD "${HEAD_URL}" \ | sed -e 's/.* \([0-9]\{1,\}\).*$/\1/g' -e 1q`if ! expr "${HEAD_REVISION}" : '[0-9]\{1,\}$' >/dev/null; then error "can't get head revision of \"${HEAD_URL}\" (got \"${REVISION}\")"fireport latest revision of "${HEAD_URL}" is "${HEAD_REVISION}"# Perform action${ACTION}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -