Skip to content

Instantly share code, notes, and snippets.

@3v1n0
Last active October 4, 2018 18:54
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 3v1n0/63ea0c9f08d10bee9e50 to your computer and use it in GitHub Desktop.
Save 3v1n0/63ea0c9f08d10bee9e50 to your computer and use it in GitHub Desktop.
A tool for cherry-picking revisions from bazaar repositories
#!/bin/bash
#
# Simply cherry picks a revision from a bazaar branch, cloning its metadata
#
# Usage:
# bzr-cherry-pick lp:unity 1234
if ! (bzr root &> /dev/null); then
echo "It seems you're not in a bazaar branch directory"
exit 1
fi
if [ -z "$1" ]; then
echo "$(basename $0) <branch location> <revision number> [--debchange] [--no-commit] [--use-merge]"
exit 1
fi
if ! [[ $2 =~ ^-?[0-9]+$ ]]; then
echo "You need to provide the revision number you want to pick"
exit 1
fi
if [ "$(bzr diff | head -n1 | wc -l)" -gt 0 ]; then
echo "Impossible to work in a branch which has uncommitted changes"
exit 1
fi
branch=$1
shift
rev=$1
shift
cmdline_args=$*
use_debchange=false
no_commit=false
use_merge=false
if (echo "$cmdline_args" | grep -q -w -- "--debchange"); then
cmdline_args="${cmdline_args//--debchange/}"
if [ -f debian/changelog ]; then
use_debchange=true
fi
fi
if (echo "$cmdline_args" | grep -q -w -- "--no-commit"); then
cmdline_args="${cmdline_args//--no-commit/}"
no_commit=true
fi
if (echo "$cmdline_args" | grep -q -w -- "--use-merge"); then
cmdline_args="${cmdline_args//--use-merge/}"
use_merge=true
fi
export LC_ALL=C.UTF-8
log="$(bzr log -n1 -r $rev $branch $cmdline_args)"
log_msg="$(echo "$log" | sed '0,/^message:$/d' | tail -n +1 | sed -e 's/^\s*//' | sed '/^Approved by: /d')"
log_author="$(echo "$log" | sed -n 's/^author: //p')"
log_time="$(echo "$log" | sed -n 's/^timestamp: \([A-Za-z]\+ \)\?//p')"
log_bugs="$(echo "$log" | sed -n 's/^fixes bugs\?: //p' | sed 's,https://launchpad.net/bugs/,,g')"
if [ -z "$log_author" ]; then
log_author="$(echo "$log" | sed -n 's/^committer: //p')"
fi
if [ -z "$log_author" ]; then log_author="$(bzr whoami)"; fi
if [ -z "$log_bugs" ]; then log_bugs="$(echo "$log_msg" | sed '/Fixes: #[0-9]\+/!d' | sed 's/.*Fixes: #\([0-9#, ]\+\).*/\1/m' | sed 's/[,#]//g')"; fi
if [ -z "$log_bugs" ]; then log_bugs="$(echo "$log_msg" | sed '/(LP: [^)]\+)/!d' | sed 's/.*(LP: \([^)]\+\)).*/\1/m' | sed 's/[,#]//g')"; fi
log_msg=$(echo "$log_msg" | sed 's/Fixes: #[0-9, #]\+//')
log_msg=$(echo "$log_msg" | sed 's/(LP: [^)]\+)//')
if [ "$log_author" == "Bileto Bot <ci-train-bot@canonical.com>" ]; then
echo "Ignoring release commit..."
exit 0
fi
echo "Author: $log_author"
echo "Time: $log_time"
for bug in $log_bugs; do echo "Bug: https://launchpad.net/bugs/$bug"; done;
echo -e "Message:\n$log_msg\n"
if [ "$use_merge" == true ]; then
bzr merge --no-remember -c $rev $branch $cmdline_args
merged=$?
else
bzr di -c $rev $branch $cmdline_args | patch -p0
merged=$?
for i in $(bzr di -c $rev $branch $cmdline_args | lsdiff); do
bzr add $i
done
fi
if [ "$merged" == 0 ] && [ "$(bzr di | head -n1 | wc -l)" == 0 ]; then
echo "Revision $rev has no changes to merge, ignoring it..."
exit 0
fi
# msg_file=$(mktemp /tmp/bzr-cherry-pick.XXXXXXX)
# echo "$log_msg" > $msg_file
args="--message=\"${log_msg//\"/\\\"}\" --author=\"${log_author//\"/\\\"}\" --commit-time=\"$log_time\""
for bug in $log_bugs; do args="$args --fixes=\"lp:$bug\""; done;
if [ $use_debchange == true ]; then
change="$(echo "$log_msg" | head -n1)"
if [ -n "$log_bugs" ]; then
read -r -a bugs_array <<< "$log_bugs"
change="$change ($(printf "LP: #%s, " "${bugs_array[@]}")"
change=${change%, }")"
fi
unset DEBFULLNAME DEBEMAIL NAME EMAIL
export DEBFULLNAME="$(echo "$log_author" | sed "s/\([^<]*\)<\([^>]\+\)>/\1/g" | sed -e 's/ *$//')"
export DEBEMAIL="$(echo "$log_author" | sed "s/[^<]*<\([^>]\+\)>/\1/g" | sed -e 's/ *$//')"
debchange --multimaint-merge --release-heuristic changelog -- $change
fi
if [ $no_commit == true ]; then
echo -e "No committing, you can do this manually by using\n bzr commit $args"
exit $merged
fi
if [ $merged == 0 ]; then
if [ "$(bzr di | head -n1 | wc -l)" -gt 0 ]; then
#echo bzr commit "$args"
eval "$(echo bzr commit "$args")"
fi
else
if [ "$(bzr conflicts -q | head -n1 | wc -l)" -gt 0 ]; then
echo -e "\nMerging of version $rev failed, impossible to commit. Please use 'bzr resolve' to fix the issues and then commit with\n bzr commit $args"
exit 1
fi
fi
# rm -f $msg_file
@Ede123
Copy link

Ede123 commented May 6, 2017

Minor suggestion: If you add --no-remember to the bzr merge command it will not add a submit_branch to branch.conf.
This for example makes Bazaar Explorer raise a red flag because the "Branch has changes not present in its submit branch." and makes it do additional (unnecessary) work...

Thanks for this really handy script! It made bzr bearable for me 😉

@3v1n0
Copy link
Author

3v1n0 commented Jun 27, 2017

Thanks @Ede123, I've added it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment