#!/bin/bash
# Copyright 2011 The Native Client Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

set -Ceu


GiveUp() {
  echo -n "*** "

  if [[ -n "$1" ]]; then
    # Print repo, do not output the trailing newline.
    echo -n "$1: "
  fi

  if [[ -n "$2" ]]; then
    # Print reason, do not output the trailing newline.
    echo -n "$2 "
  fi

  echo "Please update manually! ***"
  exit 0
}


# Go to repository.

my_repo="$@"

if [[ -n "$my_repo" ]]; then
  cd "$my_repo"
fi


# Determine working branch.
# We can't use 'git symbolic-ref HEAD' as it fails in detached HEAD state.

status=`git status --branch --short --untracked-files=no`

if [[ "$status" != "## HEAD (no branch)" ]]; then

  my_branch_ref=`git symbolic-ref HEAD`
  my_branch="${my_branch_ref#refs/heads/}"
  my_commit=`git rev-parse $my_branch_ref`

else

  # Detached HEAD state - checkout branch that fits best.
  # In general, we can walk all suitable branches and pick one that is closer
  # to the commit we are at, or give up if ambiguity.
  # However, what we actually need most of the times is to change from the
  # pinned revision to master - try it.

  my_branch_ref="refs/heads/master"
  my_branch="master"
  my_commit=`git rev-parse $my_branch_ref`

  if [[ -z "$my_commit" ]]; then
    # No branch master?
    GiveUp "$my_repo" "Failed to pick a branch to change from detached HEAD."
  fi

  prev_commit=`git rev-parse HEAD`
  merge_base=`git merge-base $prev_commit $my_commit`

  if [[ "$merge_base" != "$prev_commit" ]]; then
    # HEAD and master have diverged?
    GiveUp "$my_repo" "Failed to pick a branch to change from detached HEAD."
  fi

  # Branch seems to fit, check it out.
  git checkout "$my_branch"

fi


# Now determine upstream branch and check tracking.

upstream_branch_ref=`git for-each-ref --format='%(upstream)' $my_branch_ref`

if [[ -z "$upstream_branch_ref" ]]; then
  GiveUp "$my_repo" "Failed to determine upstream branch."
fi

upstream_branch="${upstream_branch_ref#refs/remotes/}"
upstream_commit=`git rev-parse $upstream_branch_ref`
merge_base=`git merge-base $my_commit $upstream_commit`

if [[ "$merge_base" = "$upstream_commit" ]]; then
  # We are on the tip of the remote branch already.
  exit 0
fi

if [[ "$merge_base" = "$my_commit" ]]; then
  # We can fast-forward - do it.
  git rebase "$upstream_branch" "$my_branch"
  exit 0
fi

# Need to resolve manually.
GiveUp "$my_repo" "Working branch and upstream branch have diverged."