blob: 87110495fe28d77e22685af9ba099293cb05b953 [file] [log] [blame]
#!/bin/bash
#*******************************************************************************
# Copyright (c) 2019-2020 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0 which is available a
# thttp://www.eclipse.org/legal/epl-2.0.
#
# SPDX-License-Identifier: EPL-2.0
#*******************************************************************************
# This script is related to the openMDM requirement 560684 - https://bugs.eclipse.org/bugs/show_bug.cgi?id=560684
# Interesting articles about merging different git repositories into one
# https://medium.com/altcampus/how-to-merge-two-or-multiple-git-repositories-into-one-9f8a5209913f
# https://gist.github.com/msrose/2feacb303035d11d2d05
##### Configuration begin
# COMMIT_USER, COMMIT_MAIL will be used as User and Mail adress for the commits (merge) in the new repository
# COMMIT_PREFIX will be used as part of the commit message Matthias Koller <m.koller@peak-solution.de>
# Please change COMMIT_USER, COMMIT_MAIL and COMMIT_PREFIX if necessary
COMMIT_USER="Simon Skoczylas"
COMMIT_MAIL="simon.skoczylas@karakun.com"
COMMIT_PREFIX="561698 - "
# The name of the git remote for the new repository.
REMOTE_NAME=restructuring
# The sub directory which will be used to clone the necessary git repositories
SUBDIR=restructuring
# The name of the new git repository which will only be created on your local maschine
NEW_REPO_NAME="org.eclipse.mdm"
# The name of the new git bare repository which will only be created on your local maschine (should end with .git)
NEW_REPO_DIR="$NEW_REPO_NAME.git"
# Items for projects with name and location.
BASE=("org.eclipse.mdm.api.base" "git://git.eclipse.org/gitroot/mdmbl/org.eclipse.mdm.api.base.git")
DEFAULT=("org.eclipse.mdm.api.default" "git://git.eclipse.org/gitroot/mdmbl/org.eclipse.mdm.api.default.git")
ODSADAPTER=("org.eclipse.mdm.api.odsadapter" "git://git.eclipse.org/gitroot/mdmbl/org.eclipse.mdm.api.odsadapter.git")
NUCLEUS=("org.eclipse.mdm.nucleus" "git://git.eclipse.org/gitroot/mdmbl/org.eclipse.mdm.nucleus.git")
# List of the defined items
REPOS=(BASE DEFAULT ODSADAPTER NUCLEUS)
##### Configuration end!
echo "WELCOME! This script helps to merge the existing openMDM git repositories into one!"
echo "At the end you must add an git remote the the new created local repository and push it to the remote if everything is fine"
echo
echo "Will work with the following configuration:"
echo "-- Commiter name: '${COMMIT_USER}'"
echo "-- Commiter email adress: '${COMMIT_MAIL}'"
echo "-- Commit message prefix: '${COMMIT_PREFIX}'"
echo
# Output the list of repositories which will be cloned
echo "Will work with the following repositories:"
for repo in ${REPOS[*]}; do
temp="$repo[@]"
list=("${!temp}")
echo "-- ${list[0]} from ${list[1]}"
done
# Create the new directory where all the work will be done. If the directory already exists, it will be DELETED!
if [ -d "$SUBDIR" ]; then
echo
echo "WARNING: The directory '$SUBDIR' already exists and will be DELETED!"
echo
rm -rf $SUBDIR/
mkdir $SUBDIR
else
mkdir $SUBDIR
fi
cd $SUBDIR
read -p "Press Enter to continue"
echo "Working inside:"
pwd
echo
# Create a new directory for the git bare repository
REMOTE_DIR=$(pwd)/$NEW_REPO_DIR
echo "Remote directory is $REMOTE_DIR/"
if [ -d "$NEW_REPO_DIR" ]; then
echo "$NEW_REPO_DIR already exists"
else
mkdir $NEW_REPO_DIR
fi
# Initialize the new git bare repository
cd $NEW_REPO_DIR
if [ -d ".git" ]; then
echo
echo "WARNING: Already a git repository, this should not happen!"
echo
exit 1
else
git init --bare
fi
cd ..
# Clone the new repository to create a working copy where all the magic will happen!
git clone file://$REMOTE_DIR $NEW_REPO_NAME
cd $NEW_REPO_NAME
# Set the user and mail for the working repository
git config user.name "\"$COMMIT_USER\""
git config user.email "\"$COMMIT_MAIL\""
# Create a list with just the names of the projects
REPO_NAMES=()
for repo in ${REPOS[*]}; do
temp="$repo[@]"
list=("${!temp}")
REPO_NAMES+=(${list[0]})
done
echo
# Create a dummy commit+cleanup in the new repository to be able to merge into this repository
echo "Create initial commit"
touch initial_commit.md
git add initial_commit.md
git commit -s -q -m "\"$COMMIT_PREFIX Initial commit in the new repository\""
rm initial_commit.md
git add initial_commit.md
git commit -s -q -m "\"$COMMIT_PREFIX Cleanup the new repository\""
git checkout -b init/empty
git push -q --set-upstream origin init/empty
git checkout master
git push -q --set-upstream origin master
echo
# Add the existing projects as remotes to the working repository
echo "Add remotes"
for repo in ${REPOS[*]}; do
temp="$repo[@]"
list=("${!temp}")
echo "Add remote '${list[0]}' with '${list[1]}'"
git remote add ${list[0]} ${list[1]}
done
# Fetch data from remote without merging (don't pull here)
echo "Fetch from all"
git fetch -q --all --no-tags
echo
# Create all branches which were found in the projects
echo "Create branches"
for repo in ${REPOS[*]}; do
temp="$repo[@]"
list=("${!temp}")
BRANCHES=($(git branch -a --list "*${list[0]}*"))
echo "Branches for '${list[0]}'"
for branch in ${BRANCHES[*]}; do
BRANCH_REGEX="remotes/${list[0]}/"
CURRENT_BRANCH="${branch/$BRANCH_REGEX/}"
if [ $CURRENT_BRANCH != "master" ]; then
echo "Create branch '$CURRENT_BRANCH'"
git branch $CURRENT_BRANCH
fi
done
done
echo
# The magic will happen here!
# 1. Checkout every branch of every project into a temporary branch
# 2. Move (with git mv) all files into a separate directory which is named like the project
# 3. Checkout the relevant branch (which was created before)
# 4. Merge the temporary branch into the new branch and allow to merge unrelated histories
for repo in ${REPOS[*]}; do
temp="$repo[@]"
list=("${!temp}")
RECENT_COMMIT=''
BRANCHES=($(git branch -a --list "*${list[0]}*"))
for branch in ${BRANCHES[*]}; do
BRANCH_REGEX="remotes/${list[0]}/"
CURRENT_BRANCH="${branch/$BRANCH_REGEX/}"
echo "Working on branch '${list[0]}/$CURRENT_BRANCH'"
echo "Checkout '${list[0]}/$CURRENT_BRANCH' as 'temp/${list[0]}/$CURRENT_BRANCH'"
git checkout -q -b temp/${list[0]}/$CURRENT_BRANCH ${list[0]}/$CURRENT_BRANCH
echo "Collect files"
shopt -s dotglob
FILE_LIST=()
for entry in "."/*; do
#echo "Entry is $entry"
if [ $entry != "./.git" ]; then
ADD=true
for r in ${REPO_NAMES[*]}; do
if [ $entry = "./$r" ]; then
#echo "Omit repo $r"
ADD=false
break
fi
done
if [ $ADD = true ]; then
#echo "Add $entry"
FILE_LIST+=($entry)
fi
fi
done
shopt -u dotglob
echo "Move files for ${list[0]}/$CURRENT_BRANCH"
if [ ! -d ${list[0]} ]; then
echo "Creating folder for project ${list[0]}"
mkdir ${list[0]}
fi
for file in ${FILE_LIST[*]}; do
git mv $file ${list[0]}/$file
done
git commit -s -q -m "\"$COMMIT_PREFIX Move files into separate folder for '${list[0]}/$CURRENT_BRANCH'\""
echo "Back to $CURRENT_BRANCH"
git checkout -q $CURRENT_BRANCH
echo "Merge 'temp/${list[0]}/$CURRENT_BRANCH' into '$CURRENT_BRANCH'"
git merge --signoff -q --allow-unrelated-histories -m "\"$COMMIT_PREFIX Merge '${list[0]}/$CURRENT_BRANCH' into '$CURRENT_BRANCH'\"" temp/${list[0]}/$CURRENT_BRANCH
echo
done
done
# Get back to master
git checkout -q master
# Check wether all projects directories exits on every branch. Merge temporary master if the project directories does not exits on that branch
echo "Check branches"
BRANCHES=($(git --no-pager branch --list | sed -e "s/* master//" | sed -e "s/temp.*//"))
for branch in ${BRANCHES[*]}; do
if [ $branch != "master" ] && [ $branch != "init/empty" ]; then
git checkout -q $branch
for repo in ${REPOS[*]}; do
temp="$repo[@]"
list=("${!temp}")
if [ ! -d ${list[0]} ]; then
echo "Must create ${list[0]} on $branch"
git merge --signoff -q --allow-unrelated-histories -m "\"$COMMIT_PREFIX Merge '${list[0]}/master' into '$branch'\"" temp/${list[0]}/master
fi
done
fi
done
# Get back to master
git checkout -q master
echo
# Remove all temporary branches
echo "Clean up"
BRANCHES=($(git --no-pager branch --list "temp*"))
for branch in ${BRANCHES[*]}; do
echo "Delete temporary branch $branch"
git branch -q -D $branch
done
echo
# Remove the remotes from the working repository
echo "Remove remotes"
for repo in ${REPOS[*]}; do
temp="$repo[@]"
list=("${!temp}")
echo "Remove remote '${list[0]}' with '${list[1]}'"
git remote remove ${list[0]}
done
cd ..
echo
pwd
echo "Clone repositories to list available tags"
for repo in ${REPOS[*]}; do
temp="$repo[@]"
list=("${!temp}")
echo "Will now clone '${list[0]}' from '${list[1]}'"
git clone -q ${list[1]} ${list[0]}
cd ${list[0]}
TAGS=($(git --no-pager tag --list))
for tag in ${TAGS[*]}; do
COMMIT_HASH=$(git rev-list -n 1 ${tag})
echo "Found tag ${tag} in ${list[0]} as ${COMMIT_HASH}"
done
cd ..
rm -rf ${list[0]}/
done