#!/bin/sh

###
### This script has been moved to the git-scripts repository:
### https://github.com/plume-lib/git-scripts
###
echo "Please use $(basename "$0") from https://github.com/plume-lib/git-scripts ."
echo "You are using $0,"
echo "which is an obsolete version from https://github.com/plume-lib/plume-scripts ."

# git-clone-related:  clones a repository that is related to this one,
#   or pulls it if it has already been cloned.
#
# Sometimes, two repositories are related:  you need clones of both of them.
# When run from a clone of one (possibly in a fork and/or on a branch), this
# clones the other, attempting to find a matching fork and branch.
# This script also works in an Azure Pipelines, CircleCI, GitHub Actions, or
# Travis CI job; in a CI job, it uses (for example) the pull request's branch
# name even if the CI system uses a different branch name for its local clone.
# (On CircleCI, it depends on environment variable CIRCLE_COMPARE_URL;
# see documentation of `ci-info` script for details.)
#
# Usage:  git-clone-related [ARGS] UPSTREAM_ORG REPO_NAME [DESTINATION] [GIT_CLONE_ARGS...]
#   ARGS are:
#     --upstream-branch FALLBACK_BRANCH
#           the branch name to use if there is no branch matching this clone's
#           branch name.  If not specified (or if no branch of the given name
#           exists), uses the default branch name (often "master" or "main").
#     --debug                     print logging information
#   UPSTREAM_ORG is, if this is a fork, the parent organization.
#   REPO_NAME is the repository name without the organization.
#   DESTINATION is the new clone (not its parent), by default ../REPO_NAME .
#     If it exists, it is updated via "git pull", without changing its fork
#     or branch.  No error is issued if the pull fails.
#   GIT_CLONE_ARGS is extra arguments to git clone.  It defaults to
#     "-q --single-branch --depth 1" (without the quotes).
#     It is not used if the destination already exists.
#
# When invoked from within a clone of MYORG/MYREPO, at branch MYBRANCH,
# this script chooses the first of these that exists:
#   branch ${MYBRANCH} of https://github.com/${MYORG}/${REPO_NAME}.git
#   branch ${MYBRANCH} of https://github.com/${UPSTREAM_ORG}/${REPO_NAME}.git
#   branch ${FALLBACK_BRANCH} of https://github.com/${UPSTREAM_ORG}/${REPO_NAME}.git
#
# Requires the `jq` program to be installed, when used in Azure Pipelines jobs.

# Do not attempt to add "--filter=blob:none" to the git command, as older git
# clients (apparently including GitHub, as of 2024-01-27) do not support it.

# Fail if any command fails.
set +e

if [ "$1" = "--debug" ]; then
  DEBUG=1
  shift
  set -x
fi

# FALLBACK_BRANCH may be unset.
if [ "$1" = "--upstream-branch" ]; then
  shift
  FALLBACK_BRANCH=$1
  shift
fi

if [ "$#" -lt 2 ]; then
  echo "Usage: $0 UPSTREAM_ORG REPO [DESTINATION] [GIT_CLONE_ARGS...]" >&2
  exit 1
fi

beginswith() { case $2 in "$1"*) true ;; *) false ;; esac }

UPSTREAM_ORG=$1
shift
REPO_NAME=$1
shift
if [ "$#" -ne 0 ] && ! beginswith "-" "$1"; then
  DESTINATION=$1
  shift
  if [ -d "$DESTINATION" ] && [ "$(pwd -P)" = "$(
    cd "$DESTINATION"
    pwd -P
  )" ]; then
    echo "git-clone-related: destination is same as current directory"
    exit 1
  fi
else
  if [ "${REPO_NAME}" = "${PWD##*/}" ]; then
    echo "git-clone-related: provide a destination argument"
    exit 1
  fi
  DESTINATION=../${REPO_NAME}
fi
if [ "$#" -eq 0 ]; then
  set -- -q --single-branch --depth 1
fi

if [ -n "$DEBUG" ]; then
  echo "Entering git-clone-related $UPSTREAM_ORG $REPO_NAME $DESTINATION $*"
fi

echo "In directory $(pwd) :"
if [ -d "${DESTINATION}" ]; then
  echo "(cd ${DESTINATION} && git pull -q)"
  # Use "cd" because older versions of git (eg, CircleCI) don't support the -C command-line option.
  # In a Travis pull request, a repository can be in state "(HEAD detached at b475d58d)"
  # and "git pull" fails.
  (cd "${DESTINATION}" && (git pull -q || (git branch && true)))
else
  SCRIPT_DIR="$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd -P)"

  CI_INFO="$SCRIPT_DIR/../plume-scripts/ci-info"
  if [ ! -f "$CI_INFO" ]; then
    CI_INFO="$SCRIPT_DIR/../.plume-scripts/ci-info"
  fi
  if [ ! -f "$CI_INFO" ]; then
    CI_INFO="$SCRIPT_DIR/.plume-scripts/ci-info"
  fi
  if [ ! -f "$CI_INFO" ]; then
    (cd "$SCRIPT_DIR" && git clone --depth 1 https://github.com/plume-lib/plume-scripts .plume-scripts)
  fi
  if [ ! -f "$CI_INFO" ]; then
    echo "CI_INFO does not exist: $CI_INFO"
    exit 1
  fi

  if [ -n "$DEBUG" ]; then
    echo "About to run ci-info --debug"
    "${CI_INFO}" --debug "${UPSTREAM_ORG}"
    echo "Ran ci-info --debug"
    echo "About to run ci-info"
  fi

  eval "$("${CI_INFO}" "${UPSTREAM_ORG}")"
  if [ -n "$DEBUG" ]; then
    echo "Finished running ci-info"
  fi
  UPSTREAM_REPO_URL="https://github.com/${UPSTREAM_ORG}/${REPO_NAME}.git"

  if [ -n "$DEBUG" ]; then
    echo "About to run git-find-fork" "${CI_ORGANIZATION}" "${UPSTREAM_ORG}" "${REPO_NAME}"
  fi
  # REPO_URL is what will be cloned.  It might be the same as UPSTREAM_REPO_URL.
  REPO_URL=$("${SCRIPT_DIR}"/git-find-fork "${CI_ORGANIZATION}" "${UPSTREAM_ORG}" "${REPO_NAME}")
  if [ -n "$DEBUG" ]; then
    echo "git-find-fork ${CI_ORGANIZATION} ${UPSTREAM_ORG} ${REPO_NAME} => ${REPO_URL}"
  fi
  if [ -n "$DEBUG" ]; then
    echo "About to run git-find-branch" "${REPO_URL}" "${CI_BRANCH_NAME}" ${FALLBACK_BRANCH:+"$FALLBACK_BRANCH"}
  fi
  REPO_BRANCH=$("${SCRIPT_DIR}"/git-find-branch "${REPO_URL}" "${CI_BRANCH_NAME}" ${FALLBACK_BRANCH:+"$FALLBACK_BRANCH"})
  if [ -n "$DEBUG" ]; then
    echo "git-find-branch ${REPO_URL} ${CI_BRANCH_NAME} => ${REPO_BRANCH}"
  fi
  if [ "$UPSTREAM_REPO_URL" != "$REPO_URL" ] && [ "$REPO_BRANCH" != "$CI_BRANCH_NAME" ]; then
    ## Don't use the fallback branch (e.g., master) of the downstream repo
    REPO_URL="$UPSTREAM_REPO_URL"
    REPO_BRANCH=$("${SCRIPT_DIR}"/git-find-branch "${REPO_URL}" "${CI_BRANCH_NAME}" ${FALLBACK_BRANCH:+"$FALLBACK_BRANCH"})
  fi
  echo "git clone -b ${REPO_BRANCH} $* ${REPO_URL} ${DESTINATION}"
  # Try twice in case of network lossage.
  git clone --depth 1 -b "${REPO_BRANCH}" "$@" "${REPO_URL}" "${DESTINATION}" \
    || (sleep 60 && git clone --depth 1 -b "${REPO_BRANCH}" "$@" "${REPO_URL}" "${DESTINATION}")
fi
echo "Done in directory ${DESTINATION} : $(cd "${DESTINATION}" && git rev-parse HEAD)"
