Skip to content

Instantly share code, notes, and snippets.

@Lekensteyn
Created September 5, 2017 11:54
Show Gist options
  • Save Lekensteyn/de31b459e2d0230cfde780171d7c1839 to your computer and use it in GitHub Desktop.
Save Lekensteyn/de31b459e2d0230cfde780171d7c1839 to your computer and use it in GitHub Desktop.
Extracts commits from the src/crypto/tls/ directory (from Go upstream) in a reproducible way, preserving all metadata (including committer info).
#!/bin/bash
# Extracts commits from the src/crypto/tls/ directory (from Go upstream) in a
# reproducible way, preserving all metadata (including committer info).
#
# Strategy:
# 0. Create a new temporary working repo.
# 1. Fetch go branch/commit that should be pulled from.
# 2. Rewrite history of go branch, extracting just the src/crypto/tls/ commits.
# 3. Push the updated branch back to tls-tris.
# Check for version
if [ $# -lt 1 ] || [[ $1 != [1-9]* ]]; then
cat <<USAGE
Usage: $0 <go-version> [<tris-remote> [<tris-new-branch>]]
Extracts a crypto/tls copy for <go-version> (e.g. '1.9') and push it to
repository URL <tris-remote> at branch <tris-new-branch>.
<tris-remote> defaults to '~/repos/tls-tris'
<tris-new-branch> defaults to 'pwu/go-update/go<go-version>'
USAGE
exit 1
fi
set -e # -x
### BEGIN OF CONFIG ###
# Go repo (local or remote URLs), use upstream URL if there is no local copy.
go_repo=~/repos/go
[ -e "$go_repo/.git" ] || go_repo=https://go.googlesource.com/go
# Upstream go branch/tag/commit that must be synced.
go_branch=refs/tags/go$1
# Destination repo and branch
tris_repo=${2:-~/repos/tls-tris}
tris_branch_push=${3:-pwu/go-update/go$1}
### END OF CONFIG ###
# Create a temporary repo, it will be littered due to rewriting, that is why it
# is not done in an existing Go repository.
tmprepo=$(mktemp -d); trap '[ -z "$tmprepo" ] || rm -rf "$tmprepo"' EXIT
cd "$tmprepo"
git init
# Obtain upstream go changes and jump into it (fetches about 133 MiB).
time git fetch "$go_repo" --no-tags "$go_branch"
git checkout -b "$tris_branch_push" FETCH_HEAD
# Move src/{pkg => }/crypto/tls/ (takes ~80 seconds).
# (use printf because macOS bash 3.2 and BSD sed do not support other methods).
time git filter-branch --prune-empty --index-filter \
'git ls-files -s | sed "s-\('"$(printf '\t')"'src/\)pkg/-\1-" |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info &&
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD -- \
src/pkg/crypto/tls/ src/crypto/tls/
# Extract src/crypto/tls/ repo (takes ~42 seconds).
time git filter-branch -f --prune-empty --subdirectory-filter src/crypto/tls HEAD
# At this point, the resulting history should always be the same (reproducible),
# so we can directly push to the tris repo.
# Try to push it, if it fails, do not clean up.
if ! git push "$tris_repo" "HEAD:$tris_branch_push"; then
tmprepo=
echo "Push failed, please fetch manually from the tris repo:"
echo " git fetch $tmprepo $tris_branch_push"
exit 2
fi
cat <<EOF
Pushed. Now check if the branch is sane with:
git log --graph --oneline master..$tris_branch_push
where 'master' should be replaced by an existing branch with common commits.
EOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment