#!/bin/bash ########################################################################### # reverts changesets for a set of tickets from a branch ########################################################################### # $1 = name of branch # $2 = ticket prefix # $3 = message suffix # $4... = ticket ids whose changesets are to be moved ########################################################################### # the mapping of branch names to file system paths is done in # ~/.fli4l/repo-info ########################################################################### rootdir=${0%/*} allowed_options="-q --no-merge-details" # if non-empty, a clean target branch is required clean_before_merge=1 # by default, provide details for merge commits mergedetails=1 if [ "$(type -t usage)" != "function" ] then usage() { echo "Usage: $(basename $0) [-q] +" exit 1 } fi . "$rootdir/include/config.inc" . "$rootdir/include/options.inc" . "$rootdir/include/display.inc" . "$rootdir/include/utility.inc" . "$rootdir/include/cleanup.inc" . "$rootdir/include/svn.inc" . "$rootdir/include/repo-info.inc" . "$rootdir/include/branching.inc" . "$rootdir/include/ticket.inc" case $1 in -*) warning "Unknown option: $1" usage ;; esac has_option "--continue-merge" && clean_before_merge= has_option "--no-merge-details" && mergedetails= if [ $# -lt 4 ] then usage fi [ -n "$1" ] || error "Branch name is missing" [ -n "$2" ] || error "Ticket prefix is missing" branch="$1" prefix="$2" msgsfx="$3" shift 3 message "Loading repository information" standout load_repo_info message "Initializing local branch" standout init_local_branch "$branch" $clean_before_merge allrevs=$(get_revs "$branch") revmin=$(($(echo "$allrevs" | tail -n 1)+1)) [ -n "$revmin" ] || error "Computing minimum revision of $branch failed" revmax=$(get_head_rev "$branch") [ -n "$revmax" ] || error "Computing maximum revision of $branch failed" round=1 revs= tickets="$(prepend_prefix "$(mask_for_regex "$@")" "$prefix")" old_tickets="" while [ -n "$tickets" -a "$(sort_list "$old_tickets")" != "$(sort_list "$tickets")" ] do message "Determining changesets to be unmerged (round $round)" standout old_tickets="$tickets" stop_tickets="$tickets" tickets="" while [ -n "$stop_tickets" ] && read rev do msg=$(get_log_message "$branch" $rev | head -n 1) ok= for ticket in $stop_tickets do if echo "$msg" | grep -q "^MERGE .*\<$ticket\>" then for t in $(extract_tickets "$msg" "$prefix") do echo "$tickets" | grep -q "\<$t\>" || tickets+="$t " done ok=1 break elif echo "$msg" | grep -q "^UNMERGE .*\<$ticket\>" then for t in $(extract_tickets "$msg" "$prefix") do stop_tickets=$(remove_ticket "$stop_tickets" $t) done break fi done if [ -n "$ok" ] then if ! echo "$revs" | grep -q "\<$rev\>" then revs+="$rev " print_log_messages "$branch" $rev $mergedetails fi fi done <<< "$allrevs" round=$((round+1)) tickets="${tickets% }" done revs=$(echo "-$revs" | $SED -e 's/[[:space:]]*$//;s/[[:space:]]\+/,-/g') if [ -n "$tickets" ] then message "Tickets to be considered:" standout for t in $tickets do message " $t: " -n message "$(get_ticket_title "$t")" yellow done message "Please review and press Ctrl+C to abort or RETURN to continue..." -n standout read message "Unmerging changesets for $tickets from $branch" standout push_cleanup clean_branch_if_enabled "$branch" if ! do_svn_quiet merge --diff3-cmd /usr/bin/diff3 -c $revs --accept postpone \ "$remote_root/$branch" "$local_root/$branch" then error "Error encountered while unmerging${part_message} -- possibly a text/binary diff conflict!" fi conflicts=$(get_merge_conflicts "$branch") if [ -n "$conflicts" ] then analyse_conflicts "$branch" "$branch" "$conflicts" "$allrevs" "$(echo "$revs" | $SED 's/[-,]/ /g')" min_rev -lt "$prefix" error "Conflict(s) encountered while merging" fi message "Building commit message" standout msg="UNMERGE $tickets${msgsfx:+ $msgsfx} (from /$branch)" for rev in ${revs//,/ } do msg+=" $(print_log_messages "$branch" ${rev#-} 1 nocolor)" done message "Committing unmerge result into $branch" standout do_svn_quiet commit -m "$msg" "$local_root/$branch" || svn_error "Committing unmerge result into $branch failed" do_message "Success: $tickets unmerged from $branch, commit [$(_get_head_rev "$remote_root/$branch")]" green pop_cleanup else error "No changesets for specified tickets found" fi