# 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.path['depot_tools'].join('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()
    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

# 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.path['depot_tools'].join('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()
    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

# 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. Provides methods to encapsulate repo operations. # 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 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__'. Perform a 'repo init' step with the given manifest url. Sync an already-init'd repo. # NOTE: This does not set self.m.path['checkout'] Clean an already-init'd repo. Reset to HEAD an already-init'd repo. 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. # Display the result in the step text.