Skip to content

Instantly share code, notes, and snippets.

@sneppy
Last active December 20, 2019 16:05
Show Gist options
  • Save sneppy/94a3cf95b7cebd9602e368c73e8e3a38 to your computer and use it in GitHub Desktop.
Save sneppy/94a3cf95b7cebd9602e368c73e8e3a38 to your computer and use it in GitHub Desktop.
A simple shell script based on splitsh-lite to sync split repos with the parent monorepo
#!/bin/bash
#================================
# A git subtree util to split
# a packagist monorepo in multiple
# manyrepos and sync version (tags)
#
# Usage:
# Download the script and call it
# inside the root folder of your
# master repo
#
# You must specify the folder in
# which to find the modules with
# -P <path>
#
# By default, the master branch
# is used as the target. To change
# this use -b <target_branch>. Tag
# and changes are pulled from the
# current local active branch
#================================
#--------------------------------
# Variables
# Parse arguments
while getopts ":s:P:b:" o; do
case "$o" in
P) PREFIX=$OPTARG;;
b) TARGET_BRANCH=$OPTARG;;
*) exit 0
esac
done
# Remove redundant slash from prefix
PREFIX="${PREFIX%/}"
# Currently active local branch
LOCAL_ACTIVE_BRANCH=$(git rev-parse --abbrev-ref HEAD)
# Default active branch
: "${TARGET_BRANCH:=master}"
#--------------------------------
# Functions
# Log message
#
# $1 content to log
# $2 file to log to
log () {
file="$2"
if [ -n "$file" -a -e "$file" ]; then
echo "$1" >> "$file"
else
echo "$1"
fi
}
# Notify error and exit
#
# $1 error message
# $2 file to write to
err () {
file="$2"
if [ -n "$file" -a -e "$file" ]; then
echo "$1" >> "$file"
else
echo "$1" >&2
fi
# Exit with code 1
exit 1
}
# Convert input to lower case
#
# $1 content
lc () {
if [ -n "$1" ]; then
echo "$1" | tr "[:upper:]" "[:lower:]"
fi
}
# Split module
# Push changes and tags
#
# $1 folder path
# $2 module name (also branch and remote name)
split () {
path="$1"
module="$2"
log "\n"
log "=== $module ==="
log "\n"
# Run splitsh-lite
splitsh-lite --prefix="${path}" --target=refs/heads/"${module}" \
|| err "fatal: could not split ${path} as ${module}"
log "✓ split ${path} as ${module}"
# Push changes
git push -f "$module" "${module}:${TARGET_BRANCH}" \
|| err "fatal: could not push to ${module}/${TARGET_BRANCH}"
log "✓ pushed ${module} to ${module}/${TARGET_BRANCH}"
# If tag exists
if [ -n "$TAG" ]; then
# Push tag
git tag -f "$TAG" "$module" \
|| err "fatal: could not tag to ${module} with tag ${TAG}"
log "✓ tagged ${module} with tag ${TAG}"
git push -f "$module" "$TAG" \
|| err "fatal: could not push tag ${TAG} to ${module}/${TARGET_BRANCH}"
log "✓ pushed tag ${TAG} to ${module}/${TARGET_BRANCH}"
# Reset tag
git tag -f "$TAG" "$LOCAL_ACTIVE_BRANCH"
fi
}
# Iterate over prefixes
map () {
# Find all modules
for i in "${PREFIX}"/* ; do
path="$i"
# If path is directory
if [[ -d "$path" ]]; then
folder=$(basename "$i")
module=$(lc "$folder")
# Split
split "$path" "$module"
fi
done
}
#--------------------------------
# Run
# Retrieve current tag
TAG=$(git describe --tags --abbrev=0)
# Iterate
map
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment