blob: c514af1d56526d076dd86276ca4de466ebf0deb5 [file]
#!/usr/bin/env sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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
#
# http://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.
# Syntax: ./setup-worktree-plugins.sh [plugins-branch]
#
# plugins/ is listed in .gitignore and is itself an independent git
# repository (see pullPluginSource.sh / pullAllPluginsSource.sh). Because
# it's gitignored, `git worktree add` for this repo does not populate it --
# a freshly created linked worktree gets no plugins/ directory at all, which
# later fails the build (missing-plugins-dir builds silently skip all plugin
# subprojects; a wrong-branch plugins/ instead fails with a misleading
# Groovy-version dependency conflict).
#
# Run this script from inside a linked worktree of *this* repo (i.e. after
# `git worktree add ../some-path -b some-branch`) to give that worktree a
# plugins/ checkout on a matching branch, without re-cloning: it adds a
# linked worktree of the *existing* plugins/ git repository found via the
# main checkout.
#
# The matching plugins/ branch is found by name first, then (for a
# feature/ticket branch with no plugins/ branch of the same name) by
# walking this repo's actual branch ancestry to find the branch it was cut
# from -- no assumption is made about branch-naming conventions.
set -e
if [ -e "plugins" ]; then
echo "ERROR: plugins/ already exists here ($(pwd)/plugins) -- refusing to overwrite it. Remove it first if you want this script to (re)create it." >&2
exit 1
fi
git_common_dir=$(git rev-parse --git-common-dir 2>/dev/null) || {
echo "ERROR: not inside a git repository." >&2
exit 1
}
main_worktree=$(cd "$(dirname "$git_common_dir")" && pwd)
plugins_repo="$main_worktree/plugins"
if [ ! -e "$plugins_repo/.git" ]; then
echo "ERROR: no plugins/ git repository found at $plugins_repo -- expected the main ofbiz checkout to have a working plugins/ git checkout to branch off of." >&2
exit 1
fi
branch_exists() {
git -C "$plugins_repo" show-ref --verify --quiet "refs/heads/$1" ||
git -C "$plugins_repo" show-ref --verify --quiet "refs/remotes/origin/$1"
}
ofbiz_branch=$(git branch --show-current)
plugins_branch=""
if [ -n "$1" ]; then
plugins_branch=$1
if ! branch_exists "$plugins_branch"; then
echo "ERROR: plugins branch '$plugins_branch' not found (checked refs/heads and refs/remotes/origin in $plugins_repo)." >&2
exit 1
fi
elif [ -z "$ofbiz_branch" ]; then
echo "ERROR: this worktree is in detached HEAD state, so the matching plugins branch can't be inferred. Pass it explicitly: ./setup-worktree-plugins.sh <branch>" >&2
exit 1
elif branch_exists "$ofbiz_branch"; then
plugins_branch=$ofbiz_branch
else
# No plugins branch shares this worktree's exact branch name -- it's
# presumably a feature/ticket branch. Rather than guess from naming
# conventions (which vary per team/fork), walk this repo's own branch
# ancestry, nearest first, to find the branch it was actually cut from,
# and use that name in plugins/ instead. Keep walking further back
# (e.g. past an intermediate release branch to trunk) until one of
# them has a matching plugins branch.
candidates=$(
for ref in $(git for-each-ref --format='%(refname:short)' refs/heads refs/remotes/origin); do
if [ "$ref" = "$ofbiz_branch" ] || [ "$ref" = "origin/$ofbiz_branch" ] || [ "$ref" = "origin/HEAD" ]; then
continue
fi
if git merge-base --is-ancestor "$ref" HEAD 2>/dev/null; then
distance=$(git rev-list --count "$ref"..HEAD 2>/dev/null) && echo "$distance $ref"
fi
done | sort -n
)
old_ifs=$IFS
IFS='
'
for line in $candidates; do
ref=${line#* }
candidate=${ref#origin/}
if branch_exists "$candidate"; then
plugins_branch=$candidate
break
fi
done
IFS=$old_ifs
fi
if [ -z "$plugins_branch" ]; then
echo "ERROR: could not determine a plugins/ branch matching ofbiz branch '$ofbiz_branch'." >&2
echo "Pass one explicitly: ./setup-worktree-plugins.sh <branch>" >&2
echo "Branches available in $plugins_repo:" >&2
git -C "$plugins_repo" branch -a --format=' %(refname:short)' >&2
exit 1
fi
echo "Setting up plugins/ as a linked worktree of $plugins_repo on branch '$plugins_branch'..."
# If that branch is already checked out elsewhere (e.g. in the main
# checkout this was branched from), git refuses a second worktree on the
# same branch -- fall back to a detached checkout of the same commit,
# which is fine for building since we only need matching source, not to
# commit from inside this worktree's plugins/.
if worktree_add_output=$(git -C "$plugins_repo" worktree add "$(pwd)/plugins" "$plugins_branch" 2>&1); then
echo "$worktree_add_output"
elif echo "$worktree_add_output" | grep -q "already checked out"; then
echo "Branch '$plugins_branch' is already checked out elsewhere; using a detached checkout of the same commit instead."
git -C "$plugins_repo" worktree add --detach "$(pwd)/plugins" "$plugins_branch"
else
echo "$worktree_add_output" >&2
exit 1
fi
echo "Done: plugins/ is ready on '$plugins_branch'."