# -*- coding:utf-8 -*-
#
# Copyright (C) 2010 The Android Open Source Project
#
# Licensed 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.

from __future__ import print_function
import sys

from color import Coloring
from command import Command
from git_command import GitCommand


class RebaseColoring(Coloring):
  def __init__(self, config):
    Coloring.__init__(self, config, 'rebase')
    self.project = self.printer('project', attr='bold')
    self.fail = self.printer('fail', fg='red')


class Rebase(Command):
  common = True
  helpSummary = "Rebase local branches on upstream branch"
  helpUsage = """
%prog {[<project>...] | -i <project>...}
"""
  helpDescription = """
'%prog' uses git rebase to move local changes in the current topic branch to
the HEAD of the upstream history, useful when you have made commits in a topic
branch but need to incorporate new upstream changes "underneath" them.
"""

  def _Options(self, p):
    p.add_option('-i', '--interactive',
                 dest="interactive", action="store_true",
                 help="interactive rebase (single project only)")

    p.add_option('--fail-fast',
                 dest='fail_fast', action='store_true',
                 help='Stop rebasing after first error is hit')
    p.add_option('-f', '--force-rebase',
                 dest='force_rebase', action='store_true',
                 help='Pass --force-rebase to git rebase')
    p.add_option('--no-ff',
                 dest='no_ff', action='store_true',
                 help='Pass --no-ff to git rebase')
    p.add_option('-q', '--quiet',
                 dest='quiet', action='store_true',
                 help='Pass --quiet to git rebase')
    p.add_option('--autosquash',
                 dest='autosquash', action='store_true',
                 help='Pass --autosquash to git rebase')
    p.add_option('--whitespace',
                 dest='whitespace', action='store', metavar='WS',
                 help='Pass --whitespace to git rebase')
    p.add_option('--auto-stash',
                 dest='auto_stash', action='store_true',
                 help='Stash local modifications before starting')
    p.add_option('-m', '--onto-manifest',
                 dest='onto_manifest', action='store_true',
                 help='Rebase onto the manifest version instead of upstream '
                      'HEAD.  This helps to make sure the local tree stays '
                      'consistent if you previously synced to a manifest.')

  def Execute(self, opt, args):
    all_projects = self.GetProjects(args)
    one_project = len(all_projects) == 1

    if opt.interactive and not one_project:
      print('error: interactive rebase not supported with multiple projects',
            file=sys.stderr)
      if len(args) == 1:
        print('note: project %s is mapped to more than one path' % (args[0],),
              file=sys.stderr)
      return 1

    # Setup the common git rebase args that we use for all projects.
    common_args = ['rebase']
    if opt.whitespace:
      common_args.append('--whitespace=%s' % opt.whitespace)
    if opt.quiet:
      common_args.append('--quiet')
    if opt.force_rebase:
      common_args.append('--force-rebase')
    if opt.no_ff:
      common_args.append('--no-ff')
    if opt.autosquash:
      common_args.append('--autosquash')
    if opt.interactive:
      common_args.append('-i')

    config = self.manifest.manifestProject.config
    out = RebaseColoring(config)
    out.redirect(sys.stdout)

    ret = 0
    for project in all_projects:
      if ret and opt.fail_fast:
        break

      cb = project.CurrentBranch
      if not cb:
        if one_project:
          print("error: project %s has a detached HEAD" % project.relpath,
                file=sys.stderr)
          return 1
        # ignore branches with detatched HEADs
        continue

      upbranch = project.GetBranch(cb)
      if not upbranch.LocalMerge:
        if one_project:
          print("error: project %s does not track any remote branches"
                % project.relpath, file=sys.stderr)
          return 1
        # ignore branches without remotes
        continue

      args = common_args[:]
      if opt.onto_manifest:
        args.append('--onto')
        args.append(project.revisionExpr)

      args.append(upbranch.LocalMerge)

      out.project('project %s: rebasing %s -> %s',
                  project.relpath, cb, upbranch.LocalMerge)
      out.nl()
      out.flush()

      needs_stash = False
      if opt.auto_stash:
        stash_args = ["update-index", "--refresh", "-q"]

        if GitCommand(project, stash_args).Wait() != 0:
          needs_stash = True
          # Dirty index, requires stash...
          stash_args = ["stash"]

          if GitCommand(project, stash_args).Wait() != 0:
            ret += 1
            continue

      if GitCommand(project, args).Wait() != 0:
        ret += 1
        continue

      if needs_stash:
        stash_args.append('pop')
        stash_args.append('--quiet')
        if GitCommand(project, stash_args).Wait() != 0:
          ret += 1

    if ret:
      out.fail('%i projects had errors', ret)
      out.nl()

    return ret
