# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Common steps for recipes that use repo for source control."""

import re

from recipe_engine import recipe_api

class RepoApi(recipe_api.RecipeApi):
  """Provides methods to encapsulate repo operations."""

  _REPO_LIST_RE = re.compile(r'^(.+) : (.+)$')

  # WARNING: The version of repo checked into depot_tools doesn't support
  # switching between branches correctly due to
  # https://code.google.com/p/git-repo/issues/detail?id=46

  def __init__(self, **kwargs):
    super(RepoApi, self).__init__(**kwargs)
    self._repo_path = None

  @property
  def repo_path(self):
    if not self._repo_path:
      self._repo_path = self.m.depot_tools.package_repo_resource('repo')
    return self._repo_path

  def __call__(self, args, name=None, **kwargs):
    """Executes 'repo' with the supplied arguments.

    Args:
      args: (list): A list of arguments to supply to 'repo'.
      name (str): The name of the step. If None, generate a name from the args.
      kwargs: Keyword arguments to pass to the 'step' call.
    Returns:
      See 'step.__call__'.
    """
    name = name or ' '.join(args)
    return self.m.step(name, [self.repo_path] + args, **kwargs)

  def init(self, url, *args, **kwargs):
    """Perform a 'repo init' step with the given manifest url."""
    kwargs.setdefault('infra_step', True)
    kwargs.setdefault('name', 'repo init')
    return self(['init', '-u', url] + list(args), **kwargs)

  def sync(self, *args, **kwargs):
    """Sync an already-init'd repo."""
    # NOTE: This does not set self.m.path['checkout']
    kwargs.setdefault('infra_step', True)
    if not 'name' in kwargs:
      name = 'repo sync'
      kwargs['name'] = name
    return self(['sync'] + list(args), **kwargs)

  def clean(self, *args, **kwargs):
    """Clean an already-init'd repo."""
    kwargs.setdefault('infra_step', True)
    kwargs.setdefault('name', 'repo forall git clean')
    return self(['forall', '-c', 'git', 'clean', '-f', '-d'] + list(args),
                **kwargs)

  def reset(self, **kwargs):
    """Reset to HEAD an already-init'd repo."""
    kwargs.setdefault('name', 'repo forall git reset')
    return self(['forall', '-c', 'git', 'reset', '--hard', 'HEAD'], **kwargs)

  def list(self, **kwargs):
    """Return (list): A list of (path, name) project tuples.
        path (str): The relative path to the project's checkout.
        name (str): The name of the project in the manifst.
    """
    kwargs['stdout'] = self.m.raw_io.output_text()
    kwargs.setdefault('name', 'repo list')
    step_result = self(['list'], **kwargs)

    result = []
    for line in step_result.stdout.splitlines():
      match = self._REPO_LIST_RE.match(line)
      if match:
        result.append(match.groups())

    # Display the result in the step text.
    if result:
      step_result.presentation.step_text = '</br></br>'
      step_result.presentation.step_text += '</br>'.join(
          '%s : %s' % (path, name) for path, name in result)
    return result
