Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adds script for git migration. #10882

Merged
merged 12 commits into from
Apr 20, 2023
156 changes: 156 additions & 0 deletions scripts/split_repo_migration/git-migrate-history.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#!/bin/bash
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -ex

[[ "${BASH_SOURCE[0]}" != "${0}" ]] && EXIT=return || EXIT=exit

if [ $# -lt 4 ]
vchudnov-g marked this conversation as resolved.
Show resolved Hide resolved
then
echo "Usage: $0 <source-repo> <target-repo> <source-path> <target-path> [folders,to,skip] [files,to,keep] [branch-name]"
atulep marked this conversation as resolved.
Show resolved Hide resolved
$EXIT 1
fi

# source GitHub repository. format: <owner>/<repo>
SOURCE_REPO=$1

# destination GitHub repository. format: <owner>/<repo>
TARGET_REPO=$2

# path in the source repo to copy code from. Defaults to the root directory
SOURCE_PATH=$3

# path in the target repo to put the copied code
TARGET_PATH=$4

# comma-separated list of files/folders to skip
IGNORE_FOLDERS=$5
# keep these specific files that would otherwise be deleted by IGNORE_FOLDERS
KEEP_FILES=$6

# override the HEAD branch name for the migration PR
BRANCH=$7


atulep marked this conversation as resolved.
Show resolved Hide resolved
if [[ -z "${BRANCH}" ]]
then
# default the branch name to be generated from the source repo name
BRANCH=$(basename ${SOURCE_REPO})-migration
fi
export FILTER_BRANCH_SQUELCH_WARNING=1

# create a working directory
WORKDIR="$(mktemp -d -t code-migration-XXXXXXXXXX)"
echo "Created working directory: ${WORKDIR}"

pushd "${WORKDIR}" # cd into workdir

echo "Cloning source repository: ${SOURCE_REPO}"
git clone "git@github.com:${SOURCE_REPO}.git" source-repo

pushd source-repo
git remote remove origin

# prune only files within the specified directory
if [[ ! -z "${SOURCE_PATH}" ]]
then
echo "Pruning commits only including path: ${SOURCE_PATH}"
git filter-branch \ # rewrites history... unsafe
--prune-empty \
--subdirectory-filter "${SOURCE_PATH}"
fi

if [[ ! -z "${IGNORE_FOLDERS}" ]]
then
echo "Ignoring folder: ${IGNORE_FOLDERS}"
mkdir -p "${WORKDIR}/filtered-source"
FOLDERS=$(echo ${IGNORE_FOLDERS} | tr "," " ")
# remove files/folders we don't want
FILTER="(rm -rf ${FOLDERS} || true)"
if [[ ! -z "${KEEP_FILES}" ]]
then
KEEP_FILES_SPACES=($(echo ${KEEP_FILES} | tr "," " "))
atulep marked this conversation as resolved.
Show resolved Hide resolved
LAST_ELEMENT=$(( ${#KEEP_FILES_SPACES[@]} - 1 ))
KEEP_FILE_COMMANDS=""
for file in "${KEEP_FILES_SPACES[@]}"
do
if [[ $file == "${KEEP_FILES_SPACES[$LAST_ELEMENT]}" ]]
then
KEEP_FILE_COMMANDS+="git checkout -- ${file} 2>/dev/null || true"
else
KEEP_FILE_COMMANDS+="git checkout -- ${file} 2>/dev/null || true; "
fi
done
atulep marked this conversation as resolved.
Show resolved Hide resolved
# restore files to keep, silence errors if the file doesn't exist
FILTER="${FILTER}; ${KEEP_FILE_COMMANDS}"
fi
git filter-branch \
--force \
--prune-empty \
--tree-filter "${FILTER}"
fi

# reorganize the filtered code into the desired target locations
if [[ ! -z "${TARGET_PATH}" ]]
atulep marked this conversation as resolved.
Show resolved Hide resolved
then
echo "Moving files to destination path: ${TARGET_PATH}"
git filter-branch \
--force \
--prune-empty \
--tree-filter \
"shopt -s dotglob; mkdir -p ${WORKDIR}/migrated-source; mv * ${WORKDIR}/migrated-source; mkdir -p ${TARGET_PATH}; mv ${WORKDIR}/migrated-source/* ${TARGET_PATH}"
atulep marked this conversation as resolved.
Show resolved Hide resolved
fi

# back to workdir
popd

# merge histories
echo "Cloning target repository: ${SOURCE_REPO}"
git clone "git@github.com:${TARGET_REPO}.git" target-repo
atulep marked this conversation as resolved.
Show resolved Hide resolved
pushd target-repo

git remote add --fetch migration ../source-repo
git checkout -b "${BRANCH}"
atulep marked this conversation as resolved.
Show resolved Hide resolved
git merge --allow-unrelated-histories migration/main --no-edit

echo "Success"

popd # back to workdir

# Do a diff between source code split repo and migrated code.
git clone "git@github.com:${SOURCE_REPO}.git" source-repo-validation # Not ideal to clone again.
rm -rf source-repo-validation/.git # That folder is not needed for validation.

if diff -r target-repo/"${TARGET_PATH}" source-repo-validation; then
echo "No diff"
else
diff -r target-repo/"${TARGET_PATH}" source-repo-validation > "diff.txt"
echo "Diff non-empty. See ${WORKDIR}/diff.txt"
$EXIT 1
fi
atulep marked this conversation as resolved.
Show resolved Hide resolved

pushd target-repo # To target repo

git push -u origin "${BRANCH}" --force

# create pull request
if gh --help > /dev/null
then
gh pr create --title "migrate code from ${SOURCE_REPO}"
else
hub pull-request -m "migrate code from ${SOURCE_REPO}"
fi

popd
56 changes: 56 additions & 0 deletions scripts/split_repo_migration/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/bin/bash
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -e

[[ "${BASH_SOURCE[0]}" != "${0}" ]] && EXIT=return || EXIT=exit

if [ $# -lt 2 ]
then
echo "Usage: $0 <split-repo-name> <target-path>"
$EXIT 1
fi

# repo name (e.g. nodejs-asset)
SPLIT_REPO=$1
# destination directory (e.g. google-cloud-asset)
ARTIFACT_NAME=$2
atulep marked this conversation as resolved.
Show resolved Hide resolved

## Get the directory of the build script
SCRIPT_DIR=$(realpath $(dirname "${BASH_SOURCE[0]}"))

export PACKAGE_PATH="packages/${ARTIFACT_NAME}"

# Args to migrate git
# 1. source GitHub repository. format: <owner>/<repo>
# 2. destination GitHub repository. format: <owner>/<repo>
# 3. path in the source repo to copy code from. Defaults to the root directory
# 4. path in the target repo to put the copied code
# 5. comma-separated list of files/folders to skip
# 6. keep these specific files that would otherwise be deleted by IGNORE_FOLDERS
# 7. override the HEAD branch name for the migration PR
# 8. path for update script.

echo ${PACKAGE_PATH}

# run the migrate script, remove .kokoro and .github folders
# keep the .github/.OwlBot.yaml config
${SCRIPT_DIR}/git-migrate-history.sh \
atulep marked this conversation as resolved.
Show resolved Hide resolved
"googleapis/${SPLIT_REPO}" \
atulep marked this conversation as resolved.
Show resolved Hide resolved
"googleapis/google-cloud-python" \
"" \
"${PACKAGE_PATH}" \
"" \
".github/.OwlBot.yaml"