#!/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; } 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 ext/openssl/openssl.gemspec ' -- $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:" | \ sed "s:\text/openssl/History.md:\tHistory.md:" | \ 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_COMMIT=$(git log --format=format:%H -n1 --grep '^Sync-with-trunk: r') LAST_SYNC_REV=$(git show --format=format:%B $LAST_SYNC_COMMIT | 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' on the last sync commit" [ "$(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 $LAST_SYNC_COMMIT $(rev_to_sha1 $BRANCH_EXTRACT $LAST_SYNC_REV) $BRANCH_MERGE ) echo "#### Step 3. Merge '$BRANCH_MERGE' into '$(git rev-parse --abbrev-ref HEAD)'" commit_message=$( commits=$(git log --oneline --format='%H %<(61,trunc)%s' $LAST_SYNC_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: ($(echo "$commits" | wc -l) commits)" echo "$commits" | 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" ) if git merge --no-ff --no-commit $BRANCH_MERGE; then git commit -m "$commit_message" else echo "Merge failed; fix conflict and commit with message:" echo "" echo "$commit_message" exit 1 fi