# 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.

# This script is used to migrate modules from SVN to Git
#!/bin/sh -e

# prefixes to strip from module paths. trailing slash is mandatory
prefixes='bundles/extensions/ bundles/ contrib/bundles contrib/extensions/ contrib/ karaf/ tooling/maven/'
git_repo_location='../sling-modules'
git_src_location='../sling-modules-src'

function usage  {
    echo "Usage: $0 [-p|-c] < repo-list.txt"
    echo ""
    echo "   -r : provision the Remote repositories"
    echo "   -c : Convert the Repositories locally"
    echo "   -p : Push local repositories to remote"
    echo ""
    echo "The repo-list.txt file can be generated using the "
    echo "$(dirname $0)/gen-repo-candidates.sh script"
}

if [ ! -f check_staged_release.sh ]; then
    echo "Please run this script from the root of the Sling SVN repository"
    exit 1
fi

if [ ! -d ${git_src_location} ]; then
    # generate a git-svn checkout
    echo "Creating source git-svn checkout ..."
    git clone https://github.com/apache/sling.git ${git_src_location}
    #  ensure we don't accidentally overwrite the source repository
    chmod ugo-w ${git_src_location}
    echo "Done!"
fi

# validate CLI
if [ $# -ne 1 ]; then
    usage
    exit -1
fi

case "$1" in 
    "-r") echo "Provisioning remote repositories" ;;
    "-c") echo "Converting local repositories";;
    "-p") echo "Pushing local repositories to remote";;
    *)
        usage
        exit -1
esac

while read -r module; do

    module_orig=$module

    for prefix in $prefixes; do
        module=${module#${prefix}}
    done

    if [ -e ${module_orig}/pom.xml ]; then

        artifactId=$(xmllint --xpath "/*[local-name()='project']/*[local-name()='artifactId']/text()" ${module_orig}/pom.xml)
        short_desc=$(xmllint --xpath "/*[local-name()='project']/*[local-name()='name']/text()" ${module_orig}/pom.xml)
        if [ -z "${short_desc}" ]; then
            echo "No name for ${module_orig}, aborting"
            exit 3
        fi

        # some overrides where it does not make sense to switch the artifact id
        case $artifactId in
            "sling-samples-builder") artifactId="sling-samples";;
            "org.apache.sling.performance.reactor" ) artifactId="org.apache.sling.performance";;
            "sling") artifactId="parent";;
        esac

        # add TLP prefix _if needed_
        if [[ $artifactId == sling-* ]]; then
            repo_name=${artifactId}
        else
            repo_name="sling-${artifactId}"
        fi
    else
        repo_name="sling-$(echo ${module} | tr '/' '-')"
        case ${module} in
            "tooling/scm") short_desc="Apache Sling SCM Tooling";;
            "tooling/jenkins") short_desc="Apache Sling Jenkins Tooling";;
            *) echo "Unknown non-Maven module ${module}, unable to set description"; exit 1;;
        esac
    fi

    # ASF infra does not permit dots in repository names
    repo_name=${repo_name//./-}
    
    echo "---- Preparing to process $module_orig as $repo_name ---"

    if [ $1 == "-c" ]; then
   
        if [ ! -d ${git_repo_location}/${repo_name}/.git ]; then
            echo "Converting from SVN to Git..."

            # create the initial repo
            git clone --no-hardlinks ${git_src_location} ${git_repo_location}/${repo_name}
            pushd ${git_repo_location}/${repo_name}

            # make sure we don't push to the incorrect repo and also remove make sure
            # we don't keep references to the remote repo
            git remote rm origin

            # rename trunk to master
            git branch -m trunk master

            # Remove everything except the path belonging to the module
            git filter-branch --subdirectory-filter ${module_orig}

            # remove unrelated tags
            for tag in $(git tag); do
                if [[ $tag != ${artifactId}* ]]; then
                    git tag -d ${tag} > /dev/null
                fi
            done

            # cleanup and compaction
            git for-each-ref --format="%(refname)" refs/original/ | xargs -n1 git update-ref -d
            git reflog expire --expire=now --all
            git repack -Ad
            git gc --aggressive --prune=now
            popd
            echo "Complete!"
        else
            echo "Already converted"
        fi

    elif [ $1 == "-r" ]; then
        status=$(curl -s -o /dev/null -I  -w "%{http_code}" https://github.com/apache/${repo_name})

        if [ $status = "404" ]; then
            echo "Repository not found, will create";
        elif [ $status = "200" ] ;then
            echo "Repository exists, skipping";
            continue
        else
            echo "Unhandled HTTP status code ${status}, aborting"
            exit 1
        fi

        echo "Creating GIT repository ..."
     
        ./tooling/scm/scripts/create-gitbox-repo.sh ${repo_name} "${short_desc}"

    else # -p
        pushd ${git_repo_location}/${repo_name}
        if [ $(git remote show | grep origin | wc -l) -eq 0 ]; then
            git remote add origin https://github.com/apache/${repo_name}.git
            git push -u origin master
        else
            echo "Remote origin already exists, skipping"
        fi
        popd
    fi
done
