# 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.

import atexit
import collections
import copy
import datetime
import hashlib
import os
import shutil
# Do not use subprocess2 as we won't be able to test encoding failures
import subprocess
import sys
import tempfile
import unittest

import gclient_utils


DEFAULT_BRANCH = 'master'

if sys.version_info.major == 3:
  # pylint: disable=redefined-builtin
  basestring = (str,)


def git_hash_data(data, typ='blob'):
  """Calculate the git-style SHA1 for some data.

  Only supports 'blob' type data at the moment.
  """
  assert typ == 'blob', 'Only support blobs for now'
  return hashlib.sha1(b'blob %d\0%s' % (len(data), data)).hexdigest()


class OrderedSet(collections.MutableSet):
  # from http://code.activestate.com/recipes/576694/
  def __init__(self, iterable=None):
    self.end = end = []
    end += [None, end, end]         # sentinel node for doubly linked list
    self.data = {}                  # key --> [key, prev, next]
    if iterable is not None:
      self |= iterable

  def __contains__(self, key):
    return key in self.data

  def __eq__(self, other):
    if isinstance(other, OrderedSet):
      return len(self) == len(other) and list(self) == list(other)
    return set(self) == set(other)

  def __ne__(self, other):
    if isinstance(other, OrderedSet):
      return len(self) != len(other) or list(self) != list(other)
    return set(self) != set(other)

  def __len__(self):
    return len(self.data)

  def __iter__(self):
    end = self.end
    curr = end[2]
    while curr is not end:
      yield curr[0]
      curr = curr[2]

  def __repr__(self):
    if not self:
      return '%s()' % (self.__class__.__name__,)
    return '%s(%r)' % (self.__class__.__name__, list(self))

  def __reversed__(self):
    end = self.end
    curr = end[1]
    while curr is not end:
      yield curr[0]
      curr = curr[1]

  def add(self, key):
    if key not in self.data:
      end = self.end
      curr = end[1]
      curr[2] = end[1] = self.data[key] = [key, curr, end]

  def difference_update(self, *others):
    for other in others:
      for i in other:
        self.discard(i)

  def discard(self, key):
    if key in self.data:
      key, prev, nxt = self.data.pop(key)
      prev[2] = nxt
      nxt[1] = prev

  def pop(self, last=True):  # pylint: disable=arguments-differ
    if not self:
      raise KeyError('set is empty')
    key = self.end[1][0] if last else self.end[2][0]
    self.discard(key)
    return key


class UTC(datetime.tzinfo):
  """UTC time zone.

  from https://docs.python.org/2/library/datetime.html#tzinfo-objects
  """
  def utcoffset(self, dt):
    return datetime.timedelta(0)

  def tzname(self, dt):
    return "UTC"

  def dst(self, dt):
    return datetime.timedelta(0)


UTC = UTC()


class GitRepoSchema(object):
  """A declarative git testing repo.

  Pass a schema to __init__ in the form of:
     A B C D
       B E D

  This is the repo

     A - B -  C - D
           \\ E /

  Whitespace doesn't matter. Each line is a declaration of which commits come
  before which other commits.

  Every commit gets a tag 'tag_%(commit)s'
  Every unique terminal commit gets a branch 'branch_%(commit)s'
  Last commit in First line is the branch 'master'
  Root commits get a ref 'root_%(commit)s'

  Timestamps are in topo order, earlier commits (as indicated by their presence
  in the schema) get earlier timestamps. Stamps start at the Unix Epoch, and
  increment by 1 day each.
  """
  COMMIT = collections.namedtuple('COMMIT', 'name parents is_branch is_root')

  def __init__(self, repo_schema='',
               content_fn=lambda v: {v: {'data': v}}):
    """Builds a new GitRepoSchema.

    Args:
      repo_schema (str) - Initial schema for this repo. See class docstring for
        info on the schema format.
      content_fn ((commit_name) -> commit_data) - A function which will be
        lazily called to obtain data for each commit. The results of this
        function are cached (i.e. it will never be called twice for the same
        commit_name). See the docstring on the GitRepo class for the format of
        the data returned by this function.
    """
    self.master = None
    self.par_map = {}
    self.data_cache = {}
    self.content_fn = content_fn
    self.add_commits(repo_schema)

  def walk(self):
    """(Generator) Walks the repo schema from roots to tips.

    Generates GitRepoSchema.COMMIT objects for each commit.

    Throws an AssertionError if it detects a cycle.
    """
    is_root = True
    par_map = copy.deepcopy(self.par_map)
    while par_map:
      empty_keys = set(k for k, v in par_map.items() if not v)
      assert empty_keys, 'Cycle detected! %s' % par_map

      for k in sorted(empty_keys):
        yield self.COMMIT(k, self.par_map[k],
                          not any(k in v for v in self.par_map.values()),
                          is_root)
        del par_map[k]
      for v in par_map.values():
        v.difference_update(empty_keys)
      is_root = False

  def add_partial(self, commit, parent=None):
    if commit not in self.par_map:
      self.par_map[commit] = OrderedSet()
    if parent is not None:
      self.par_map[commit].add(parent)

  def add_commits(self, schema):
    """Adds more commits from a schema into the existing Schema.

    Args:
      schema (str) - See class docstring for info on schema format.

    Throws an AssertionError if it detects a cycle.
    """
    for commits in (l.split() for l in schema.splitlines() if l.strip()):
      parent = None
      for commit in commits:
        self.add_partial(commit, parent)
        parent = commit
      if parent and not self.master:
        self.master = parent
    for _ in self.walk():  # This will throw if there are any cycles.
      pass

  def reify(self):
    """Returns a real GitRepo for this GitRepoSchema"""
    return GitRepo(self)

  def data_for(self, commit):
    """Obtains the data for |commit|.

    See the docstring on the GitRepo class for the format of the returned data.

    Caches the result on this GitRepoSchema instance.
    """
    if commit not in self.data_cache:
      self.data_cache[commit] = self.content_fn(commit)
    return self.data_cache[commit]

  def simple_graph(self):
    """Returns a dictionary of {commit_subject: {parent commit_subjects}}

    This allows you to get a very simple connection graph over the whole repo
    for comparison purposes. Only commit subjects (not ids, not content/data)
    are considered
    """
    ret = {}
    for commit in self.walk():
      ret.setdefault(commit.name, set()).update(commit.parents)
    return ret


class GitRepo(object):
  """Creates a real git repo for a GitRepoSchema.

  Obtains schema and content information from the GitRepoSchema.

  The format for the commit data supplied by GitRepoSchema.data_for is:
    {
      SPECIAL_KEY: special_value,
      ...
      "path/to/some/file": { 'data': "some data content for this file",
                              'mode': 0o755 },
      ...
    }

  The SPECIAL_KEYs are the following attributes of the GitRepo class:
    * AUTHOR_NAME
    * AUTHOR_EMAIL
    * AUTHOR_DATE - must be a datetime.datetime instance
    * COMMITTER_NAME
    * COMMITTER_EMAIL
    * COMMITTER_DATE - must be a datetime.datetime instance

  For file content, if 'data' is None, then this commit will `git rm` that file.
  """
  BASE_TEMP_DIR = tempfile.mkdtemp(suffix='base', prefix='git_repo')
  atexit.register(gclient_utils.rmtree, BASE_TEMP_DIR)

  # Singleton objects to specify specific data in a commit dictionary.
  AUTHOR_NAME = object()
  AUTHOR_EMAIL = object()
  AUTHOR_DATE = object()
  COMMITTER_NAME = object()
  COMMITTER_EMAIL = object()
  COMMITTER_DATE = object()

  DEFAULT_AUTHOR_NAME = 'Author McAuthorly'
  DEFAULT_AUTHOR_EMAIL = 'author@example.com'
  DEFAULT_COMMITTER_NAME = 'Charles Committish'
  DEFAULT_COMMITTER_EMAIL = 'commitish@example.com'

  COMMAND_OUTPUT = collections.namedtuple('COMMAND_OUTPUT', 'retcode stdout')

  def __init__(self, schema):
    """Makes new GitRepo.

    Automatically creates a temp folder under GitRepo.BASE_TEMP_DIR. It's
    recommended that you clean this repo up by calling nuke() on it, but if not,
    GitRepo will automatically clean up all allocated repos at the exit of the
    program (assuming a normal exit like with sys.exit)

    Args:
      schema - An instance of GitRepoSchema
    """
    self.repo_path = os.path.realpath(tempfile.mkdtemp(dir=self.BASE_TEMP_DIR))
    self.commit_map = {}
    self._date = datetime.datetime(1970, 1, 1, tzinfo=UTC)

    self.to_schema_refs = ['--branches']

    # TODO(crbug.com/114712) use git.init -b and remove 'checkout' once git is
    # upgraded to 2.28 on all builders.
    self.git('init')
    self.git('config', 'user.name', 'testcase')
    self.git('config', 'user.email', 'testcase@example.com')
    self.git('checkout', '-b', DEFAULT_BRANCH)
    for commit in schema.walk():
      self._add_schema_commit(commit, schema.data_for(commit.name))
      self.last_commit = self[commit.name]
    if schema.master:
      self.git('update-ref', 'refs/heads/master', self[schema.master])

  def __getitem__(self, commit_name):
    """Gets the hash of a commit by its schema name.

    >>> r = GitRepo(GitRepoSchema('A B C'))
    >>> r['B']
    '7381febe1da03b09da47f009963ab7998a974935'
    """
    return self.commit_map[commit_name]

  def _add_schema_commit(self, commit, commit_data):
    commit_data = commit_data or {}

    if commit.parents:
      parents = list(commit.parents)
      self.git('checkout', '--detach', '-q', self[parents[0]])
      if len(parents) > 1:
        self.git('merge', '--no-commit', '-q', *[self[x] for x in parents[1:]])
    else:
      self.git('checkout', '--orphan', 'root_%s' % commit.name)
      self.git('rm', '-rf', '.')

    env = self.get_git_commit_env(commit_data)

    for fname, file_data in commit_data.items():
      # If it isn't a string, it's one of the special keys.
      if not isinstance(fname, basestring):
        continue

      deleted = False
      if 'data' in file_data:
        data = file_data.get('data')
        if data is None:
          deleted = True
          self.git('rm', fname)
        else:
          path = os.path.join(self.repo_path, fname)
          pardir = os.path.dirname(path)
          if not os.path.exists(pardir):
            os.makedirs(pardir)
          with open(path, 'wb') as f:
            f.write(data)

      mode = file_data.get('mode')
      if mode and not deleted:
        os.chmod(path, mode)

      self.git('add', fname)

    rslt = self.git('commit', '--allow-empty', '-m', commit.name, env=env)
    assert rslt.retcode == 0, 'Failed to commit %s' % str(commit)
    self.commit_map[commit.name] = self.git('rev-parse', 'HEAD').stdout.strip()
    self.git('tag', 'tag_%s' % commit.name, self[commit.name])
    if commit.is_branch:
      self.git('branch', '-f', 'branch_%s' % commit.name, self[commit.name])

  def get_git_commit_env(self, commit_data=None):
    commit_data = commit_data or {}
    env = os.environ.copy()
    for prefix in ('AUTHOR', 'COMMITTER'):
      for suffix in ('NAME', 'EMAIL', 'DATE'):
        singleton = '%s_%s' % (prefix, suffix)
        key = getattr(self, singleton)
        if key in commit_data:
          val = commit_data[key]
        elif suffix == 'DATE':
          val = self._date
          self._date += datetime.timedelta(days=1)
        else:
          val = getattr(self, 'DEFAULT_%s' % singleton)
        if not isinstance(val, str) and not isinstance(val, bytes):
          val = str(val)
        env['GIT_%s' % singleton] = val
    return env

  def git(self, *args, **kwargs):
    """Runs a git command specified by |args| in this repo."""
    assert self.repo_path is not None
    try:
      with open(os.devnull, 'wb') as devnull:
        shell = sys.platform == 'win32'
        output = subprocess.check_output(
            ('git', ) + args,
            shell=shell,
            cwd=self.repo_path,
            stderr=devnull,
            **kwargs)
        output = output.decode('utf-8')
      return self.COMMAND_OUTPUT(0, output)
    except subprocess.CalledProcessError as e:
      return self.COMMAND_OUTPUT(e.returncode, e.output)

  def show_commit(self, commit_name, format_string):
    """Shows a commit (by its schema name) with a given format string."""
    return self.git('show', '-q', '--pretty=format:%s' % format_string,
                    self[commit_name]).stdout

  def git_commit(self, message):
    return self.git('commit', '-am', message, env=self.get_git_commit_env())

  def nuke(self):
    """Obliterates the git repo on disk.

    Causes this GitRepo to be unusable.
    """
    gclient_utils.rmtree(self.repo_path)
    self.repo_path = None

  def run(self, fn, *args, **kwargs):
    """Run a python function with the given args and kwargs with the cwd set to
    the git repo."""
    assert self.repo_path is not None
    curdir = os.getcwd()
    try:
      os.chdir(self.repo_path)
      return fn(*args, **kwargs)
    finally:
      os.chdir(curdir)

  def capture_stdio(self, fn, *args, **kwargs):
    """Run a python function with the given args and kwargs with the cwd set to
    the git repo.

    Returns the (stdout, stderr) of whatever ran, instead of the what |fn|
    returned.
    """
    stdout = sys.stdout
    stderr = sys.stderr
    try:
      with tempfile.TemporaryFile('w+') as out:
        with tempfile.TemporaryFile('w+') as err:
          sys.stdout = out
          sys.stderr = err
          try:
            self.run(fn, *args, **kwargs)
          except SystemExit:
            pass
          out.seek(0)
          err.seek(0)
          return out.read(), err.read()
    finally:
      sys.stdout = stdout
      sys.stderr = stderr

  def open(self, path, mode='rb'):
    return open(os.path.join(self.repo_path, path), mode)

  def to_schema(self):
    lines = self.git('rev-list', '--parents', '--reverse', '--topo-order',
                     '--format=%s', *self.to_schema_refs).stdout.splitlines()
    hash_to_msg = {}
    ret = GitRepoSchema()
    current = None
    parents = []
    for line in lines:
      if line.startswith('commit'):
        assert current is None
        tokens = line.split()
        current, parents = tokens[1], tokens[2:]
        assert all(p in hash_to_msg for p in parents)
      else:
        assert current is not None
        hash_to_msg[current] = line
        ret.add_partial(line)
        for parent in parents:
          ret.add_partial(line, hash_to_msg[parent])
        current = None
        parents = []
    assert current is None
    return ret


class GitRepoSchemaTestBase(unittest.TestCase):
  """A TestCase with a built-in GitRepoSchema.

  Expects a class variable REPO_SCHEMA to be a GitRepoSchema string in the form
  described by that class.

  You may also set class variables in the form COMMIT_%(commit_name)s, which
  provide the content for the given commit_name commits.

  You probably will end up using either GitRepoReadOnlyTestBase or
  GitRepoReadWriteTestBase for real tests.
  """
  REPO_SCHEMA = None

  @classmethod
  def getRepoContent(cls, commit):
    commit = 'COMMIT_%s' % commit
    if sys.version_info.major == 2:
      commit = commit.encode('utf-8')
    return getattr(cls, commit, None)

  @classmethod
  def setUpClass(cls):
    super(GitRepoSchemaTestBase, cls).setUpClass()
    assert cls.REPO_SCHEMA is not None
    cls.r_schema = GitRepoSchema(cls.REPO_SCHEMA, cls.getRepoContent)


class GitRepoReadOnlyTestBase(GitRepoSchemaTestBase):
  """Injects a GitRepo object given the schema and content from
  GitRepoSchemaTestBase into TestCase classes which subclass this.

  This GitRepo will appear as self.repo, and will be deleted and recreated once
  for the duration of all the tests in the subclass.
  """
  REPO_SCHEMA = None

  @classmethod
  def setUpClass(cls):
    super(GitRepoReadOnlyTestBase, cls).setUpClass()
    assert cls.REPO_SCHEMA is not None
    cls.repo = cls.r_schema.reify()

  def setUp(self):
    self.repo.git('checkout', '-f', self.repo.last_commit)

  @classmethod
  def tearDownClass(cls):
    cls.repo.nuke()
    super(GitRepoReadOnlyTestBase, cls).tearDownClass()


class GitRepoReadWriteTestBase(GitRepoSchemaTestBase):
  """Injects a GitRepo object given the schema and content from
  GitRepoSchemaTestBase into TestCase classes which subclass this.

  This GitRepo will appear as self.repo, and will be deleted and recreated for
  each test function in the subclass.
  """
  REPO_SCHEMA = None

  def setUp(self):
    super(GitRepoReadWriteTestBase, self).setUp()
    self.repo = self.r_schema.reify()

  def tearDown(self):
    self.repo.nuke()
    super(GitRepoReadWriteTestBase, self).tearDown()

  def assertSchema(self, schema_string):
    self.assertEqual(GitRepoSchema(schema_string).simple_graph(),
                     self.repo.to_schema().simple_graph())
