#!/bin/sh
#/ Usage: script/vendor-gem [-r <rev>] [-n <gem>] [-d <directory>] <git-url>
#/ Build a gem for the given git repository and stick it in vendor/cache. With -r, build
#/ the gem at the branch, tag, or SHA1 given. With no -r, build the default HEAD.
#/ With -d, build the gem at the given directory within the repository.
#/
#/ This command is used in situations where you'd typically use a :git bundler
#/ source which should not be used in the main github app (even for development gems).
set -e
[[ $TRACE ]] && set -x

# write out compare url for review
[ $# -eq 0 ] && set -- --help

# parse args
rev=main
directory="."
local_dir=""
while [ $# -gt 0 ]; do
        case "$1" in
                -d)
                       directory=$2
                       shift 2
                       ;;
                -l)
                       local_dir=$2
                       shift 2
                       ;;
                -r)
                        rev=$2
                        shift 2
                        ;;
                -n)
                        gem=$2
                        shift 2
                        ;;
                -h|--help)
                        grep ^#/ <"$0" |cut -c4-
                        exit
                        ;;
                *)
                        url="$1"
                        shift
                        ;;
        esac
done

if [ -z "$url" ]; then
    echo "error: no git url given. see $0 --help for usage." 1>&2
    exit 1
fi

repo=$(echo "$url" | sed 's@^\(https://github\.com.*\)\.git$@\1@')

if [ -z "$gem" ]; then
    gem=$(basename "$url" .git)
fi

# the RAILS_ROOT directory
root=$(cd $(dirname "$0")/.. && pwd)
cd "$root"

gem_directory="$root/tmp/gems/$gem/$directory"

# clone the repo under tmp, clean up on exit
echo "Cloning $url for gem build"
mkdir -p "tmp/gems/$gem"

# go in and build the gem using the HEAD version, clean up this tmp dir on exit
echo "Building $gem"
(
    cd "tmp/gems/$gem"
    if [ -n "$local_dir" ]; then
      thisdir=$(pwd)
      cd "$local_dir" && tar -cf - . | ( cd "$thisdir" && tar -xf - )
      cd "$thisdir"
    else
      git init -q
      git fetch -q -fu "$url" "+refs/*:refs/*"
      git reset --hard HEAD
      git clean -df
      git checkout "$rev"
      git submodule update --init
      git --no-pager log -n 1
    fi

    cd "$gem_directory"
    gemspec=$(ls -1 *.gemspec | head -1)
    echo "Building $gemspec"

    gemname=$(basename "$gemspec" .gemspec)
    echo $gemname > vendor-gem-name

    # tag name + number of commits on top of tag + tree sha
    GEM_VERSION=""

    # No tags
    if [ -z "${GEM_VERSION}" ]
    then
      gem_version=$(ruby -e "require 'rubygems'; spec=eval(File.read('$gemspec')); print spec.version.to_s")
      tree_sha=$(git show --quiet --format=format:%t $rev)
      GEM_VERSION="${gem_version}.g${tree_sha}"
    fi

    if [ -z "${GEM_VERSION}" ]
    then
      echo "couldn't determine the gem version from \"$gemspec\""
      exit 1
    fi

    export GEM_VERSION

    # build a wrapping gemspec that adds the sha1 version to the gem version
    # unless the gemspec references the GEM_VERSION environment variable
    # in which case we assume this is handled explicitly in the gemspec itself
    if ! grep -q "GEM_VERSION" < $gemspec
    then
      cat <<-RUBY > vendor.gemspec
  require 'rubygems'
  spec = eval(File.read("$gemspec"))
  spec.version = "$GEM_VERSION"
  spec
RUBY
      gem build vendor.gemspec
    else
      gem build $gemspec
    fi

    cd "$root/tmp/gems/$gem"
    # Bump gem version in Gemfile (and deal with OS X sed differences)
    sed -i -e "s/^gem ['\"]$gemname['\"],\( *\)['\"]\([^'\"]*\)['\"]/gem \"$gemname\",\\1\"$GEM_VERSION\"/" ../../../Gemfile
    if [ `uname` = 'Darwin' ]; then
      rm -f "../../../Gemfile-e"
    fi
)
[ $? -eq 0 ] || exit 1

# get the gem name determined in the subprocess
gemname=$(cat "$gem_directory/vendor-gem-name")

# record old gem ref before deleting
oldref=$(ls vendor/cache/$gemname-*.gem | grep -o -E -e "g[0-9a-f]{7}" | cut -c 2-)

# remove any existing gems and add the newly built gem
if [ -n "$gemname" ]; then
    git rm -f vendor/cache/$gemname*.gem 2>/dev/null || true
    cp "$gem_directory/$gemname"*.gem vendor/cache
    git add vendor/cache/$gemname*
fi

# get new gem ref
newref=$(ls vendor/cache/$gemname-*.gem | grep -o -E -e "g[0-9a-f]{7}" | cut -c 2-)

# write out compare url for review
echo "$repo/compare/$oldref...$newref"

rm -rf "tmp"
bundle update --local $gemname
git add Gemfile Gemfile.lock