#!/bin/sh
# Fetching all remote pull/merge requests could be heavy.
# This script will fetch only wanted pull/merge request.
#
# For GitLab: Use `git mr 1` to fetch merge-request 1 into mr/1
# For GitHub: Use `git pr 1` to fetch pull-request 1 into pr/1

# Usage:
# die "error"
die() {
    echo >&2 "$1"
    exit 1
}

# find branch from $remote matching $commit
remote_branch_match() {
	local remote="$1"
	local commit="$2"

	git for-each-ref --format "%(refname:strip=3)" "refs/remotes/$remote" --points-at "$commit"
}

set_track_remote() {
	local remote_name="$1"
	local branch_name="$2"
	local remote_ref="$3"
	local commit tracking_branch ref_name

	# find matching commit
	commit=$(git rev-parse "$branch_name")
	# and branch
	tracking_branch=$(remote_branch_match "$remote_name" "$commit")
	# strip MR itself
	tracking_branch=$(echo "$tracking_branch" | grep -vF "$branch_name")

	# set upstream as such
	if [ -n "$tracking_branch" ]; then
		remote_ref="heads/$tracking_branch"
	fi

	git config "branch.$branch_name.remote" "$remote_name"
	git config "branch.$branch_name.merge" "refs/$remote_ref"
	# normal branch
	ref_name=${remote_ref#heads/}
	# pull/merge requests
	ref_name=${ref_name%/head}
	echo "Configured '$branch_name' branch to track '${ref_name}' from '$remote_name'"
}

fetch_request() {
	local request_number="$1"
	local remote_name="${2:-origin}"
	local branch_name="$local_namespace/$request_number"
	local remote_ref="$remote_namespace/$request_number/head"

	# fetch and checkout
	git fetch "$remote_name" "$remote_ref:$branch_name"
	git checkout "$branch_name"

	set_track_remote "$remote_name" "$branch_name" "$remote_ref"
}

case "$0" in
	*-mr)
		local_namespace=mr
		remote_namespace=merge-requests
		;;
	*-pr)
		local_namespace=pr
		remote_namespace=pull
		;;
esac

set -e

test -n "$1" || die "Usage: $0 <request_number> [<remote_name>]"

fetch_request "$@"
