From 1cc7eea683044c0c295a6fdb05e848cc6554e361 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Mon, 30 May 2016 11:29:26 +0900 Subject: Add tool/sync-with-trunk Add a helper script to merge changes from Ruby trunk. --- tool/sync-with-trunk | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100755 tool/sync-with-trunk (limited to 'tool') diff --git a/tool/sync-with-trunk b/tool/sync-with-trunk new file mode 100755 index 00000000..c4fcf1f7 --- /dev/null +++ b/tool/sync-with-trunk @@ -0,0 +1,102 @@ +#!/bin/sh +set -e + +# Pick changes from Ruby trunk and apply on this repository. +# Note that Git >= 2.5 is required. + +sha1_to_rev() { git show -s --format=format:%B $1 | tail -n1 | grep -Po '(?<=@)[0-9]+'; } +rev_to_sha1() { git log --format=format:%H -n1 --grep '^git-svn-id: .*@'$2' ' $1; } + +MERGE_INTO=$(git rev-parse --abbrev-ref HEAD) + +echo "#### Step 0. Fetch Ruby trunk" +git remote | grep '^ruby$' >/dev/null || git remote add ruby https://github.com/ruby/ruby.git +git fetch ruby + +BRANCH_EXTRACT=sync/extract +echo "#### Step 1. Sync '$BRANCH_EXTRACT' with 'ruby/trunk'" +[ "$(git branch --list $BRANCH_EXTRACT)" ] || git branch $BRANCH_EXTRACT ruby/trunk +[ ! -d tmp/sync-extract ] && git worktree add tmp/sync-extract $BRANCH_EXTRACT +( + cd tmp/sync-extract + git checkout $BRANCH_EXTRACT + + if [ $(git rev-parse HEAD) = $(git rev-parse ruby/trunk) ]; then + filter_range= + else + old_head=$(git rev-parse HEAD) + echo "Updating '$BRANCH_EXTRACT'... HEAD was $old_head." + graftpoint="$(rev_to_sha1 ruby/trunk $(sha1_to_rev $old_head)) $old_head" + grep "^$graftpoint$" $(git rev-parse --git-common-dir)/info/grafts >/dev/null 2>&1 || + echo "$graftpoint" >> $(git rev-parse --git-common-dir)/info/grafts + git reset -q --hard ruby/trunk + filter_range=$old_head..$BRANCH_EXTRACT + fi + + echo "## Remove unrelated commits" + git filter-branch -f --prune-empty --index-filter ' + git rm --cached -qr --ignore-unmatch . && + git reset -q $GIT_COMMIT -- ext/openssl test/openssl sample/openssl && + git rm --cached -q --ignore-unmatch ext/openssl/depend + ' -- $filter_range ||: + + echo "## Adjust path" + git filter-branch -f --prune-empty --index-filter ' + git ls-files --stage | \ + sed "s:\ttest/openssl:\ttest:" | \ + sed "s:\text/openssl/lib:\tlib:" | \ + sed "s:\text/openssl/sample:\tsample/openssl:" | \ + sed "s:\tsample/openssl:\tsample:" | \ + GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && + mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE" + : + ' -- $filter_range ||: + + echo "## Fix author/committer email" + git filter-branch -f --env-filter ' + export GIT_AUTHOR_EMAIL=${GIT_AUTHOR_EMAIL/b2dd03c8-39d4-4d8f-98ff-823fe69b080e/ruby-lang.org} + export GIT_COMMITTER_EMAIL=${GIT_COMMITTER_EMAIL/b2dd03c8-39d4-4d8f-98ff-823fe69b080e/ruby-lang.org} + ' -- $filter_range ||: + + [ "$graftpoint" ] && + sed -ie "/^$graftpoint$/d" $(git rev-parse --git-common-dir)/info/grafts +) + +LAST_SYNC_REV=$(git log --format=format:%B -n1 --grep '^Sync-with-trunk: r' | grep -Po '(?<=^Sync-with-trunk: r)[0-9]+$' | tail -n1) +NEXT_SYNC_REV=$(sha1_to_rev $BRANCH_EXTRACT) + +[ "$LAST_SYNC_REV" = "$NEXT_SYNC_REV" ] && ( + echo "No changes since last sync; aborting." + exit 1 +) + +BRANCH_MERGE=sync/merge-r$NEXT_SYNC_REV +echo "#### Step 2. Rebase '$BRANCH_EXTRACT' to apply to '$MERGE_INTO'" +[ "$(git branch --list $BRANCH_MERGE)" ] || git branch $BRANCH_MERGE $BRANCH_EXTRACT +[ ! -d tmp/sync-merge ] && git worktree add tmp/sync-merge $BRANCH_MERGE +( + cd tmp/sync-merge + git checkout $BRANCH_MERGE + git reset -q --hard $BRANCH_EXTRACT + git rebase --onto $MERGE_INTO $(rev_to_sha1 $BRANCH_EXTRACT $LAST_SYNC_REV) $BRANCH_MERGE || ( + echo "Automerge failed. Resolve conflicts and continue merge in tmp/sync-merge." + echo -n "Press a key to continue." + read _tmp + ) +) + +echo "#### Step 3. Merge '$BRANCH_MERGE' into '$MERGE_INTO'" +git merge --no-ff --no-commit $BRANCH_MERGE +( + echo "Merge changes from Ruby trunk r$LAST_SYNC_REV..r$NEXT_SYNC_REV" + echo "" + echo "* ruby-trunk r$LAST_SYNC_REV..r$NEXT_SYNC_REV: ($(git rev-list --count HEAD..$BRANCH_MERGE) commits)" + git log --oneline --format='%H %<(61,trunc)%s' HEAD..$BRANCH_MERGE | while read line; do + sha1=$(echo "$line" | cut -f1 -d' ') + cmsg=$(echo "$line" | cut -f2- -d' ') + echo " (r$(sha1_to_rev $sha1)) $cmsg" + done + + echo "" + echo "Sync-with-trunk: r$NEXT_SYNC_REV" +) | git commit -F- -- cgit v1.2.3