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

from recipe_engine import recipe_api


class ArchiveApi(recipe_api.RecipeApi):
  """Provides steps to manipulate archive files (tar, zip, etc.)."""

  ARCHIVE_TYPES = ('tar', 'tgz', 'tbz', 'zip')

  def package(self, root):
    """Returns Package object that can be used to compress a set of files.

    Usage:

        # Archive root/file and root/directory/**
        (api.archive.package(root).
            with_file(root.join('file')).
            with_dir(root.join('directory')).
            archive('archive step', output, 'tbz'))

        # Archive root/**
        zip_path = (
          api.archive.package(root).
          archive('archive step', api.path['start_dir'].join('output.zip'))
        )

    Args:

      * root: a directory that would become root of a package, all files added
          to an archive must be Paths which are under this directory. If no
          files or directories are added with 'with_file' or 'with_dir', the
          entire root directory is packaged.

    Returns:
      Package object.
    """
    return Package(self._archive_impl, root)

  def extract(self, step_name, archive_file, output, mode='safe',
              include_files=()):
    """Step to uncompress |archive_file| into |output| directory.

    Archive will be unpacked to |output| so that root of an archive is in
    |output|, i.e. archive.tar/file.txt will become |output|/file.txt.

    Step will FAIL if |output| already exists.

    Args:

      * step_name (str): display name of a step.
      * archive_file (Path): path to an archive file to uncompress, MUST exist.
      * output (Path): path to a directory to unpack to, MUST NOT exist.
      * mode (str): Must be either 'safe' or 'unsafe'. In safe mode, if the
        archive attempts to extract files which would escape the extraction
        `output` location, the extraction will fail (raise StepException)
        which contains a member `StepException.archive_skipped_files` (all
        other files will be extracted normally). If 'unsafe', then tarfiles
        containing paths escaping `output` will be extracted as-is.
      * include_files (List[str]) - A list of globs matching files within the
        archive. Any files not matching any of these globs will be skipped.
        If omitted, all files are extracted (the default). Globs are matched
        with the `fnmatch` module. If a file "filename" in the archive exists,
        include_files with "file*" will match it. All paths for the matcher
        are converted to posix style (forward slash).
    """
    assert mode in ('safe', 'unsafe'), 'Unknown mode %r' % (mode,)

    step_result = self.m.python(
      step_name,
      self.resource('extract.py'),
      [
        '--json-input', self.m.json.input({
          'output': str(output),
          'archive_file': str(archive_file),
          'safe_mode': mode == 'safe',
          'include_files': list(include_files),
        }),
        '--json-output', self.m.json.output(),
      ],
      step_test_data=lambda: self.m.json.test_api.output({
        'extracted': {
          'filecount': 1337,
          'bytes': 0xbadc0ffee,
        },
      }))
    self.m.path.mock_add_paths(output)
    j = step_result.json.output
    if j.get('extracted', {}).get('filecount'):
      stat = j['extracted']
      step_result.presentation.step_text += (
        '<br/>extracted %s files - %.02f MB' % (
          stat['filecount'], stat['bytes'] / (1000.0**2)))
    if j.get('skipped', {}).get('filecount'):
      stat = j['skipped']
      step_result.presentation.step_text += (
        '<br/>SKIPPED %s files - %.02f MB' % (
          stat['filecount'], stat['bytes'] / (1000.0**2)))
      step_result.presentation.logs['skipped files'] = stat['names']
      step_result.presentation.status = self.m.step.FAILURE
      ex = self.m.step.StepFailure(step_name)
      ex.archive_skipped_files = stat['names']
      raise ex

  def _archive_impl(self, root, entries, step_name, output, archive_type):
    assert entries, 'entries is empty!'

    if archive_type is None:
      base, ext = self.m.path.splitext(output)
      if base.endswith('.tar'):
        ext = '.tar' + ext
      archive_type = {
        '.tbz': 'tbz',
        '.tbz2': 'tbz',
        '.tb2': 'tbz',
        '.tar.bz2': 'tbz',

        '.tgz': 'tgz',
        '.tar.gz': 'tgz',

        '.tar': 'tar',

        '.zip': 'zip',
      }.get(ext)
      assert archive_type is not None, (
        'Unable to infer archive_type from extension: %r' % (ext,))

    assert archive_type in self.ARCHIVE_TYPES, (
      'Unsupported archive_type %r' % (archive_type,))

    script_input = {
      'entries': entries,
      'output': str(output),
      'archive_type': archive_type,
      'root': str(root),
    }
    self.m.python(
        name=step_name,
        script=self.resource('archive.py'),
        stdin=self.m.json.input(script_input))
    self.m.path.mock_add_paths(output)


class Package(object):
  """Used to gather a list of files to archive.

  Construct this with api.archive.package().

  If no 'with_file' or 'with_dir' calls are made, this defaults to including
  the entire root in the archive.
  """

  def __init__(self, archive_callback, root):
    self._archive_callback = archive_callback
    self._root = root
    self._entries = []

  @property
  def root(self):
    return self._root

  def with_file(self, path):
    """Stages single file to be added to the package.

    Args:
      path: absolute path to a file, should be in |root| subdirectory.

    Returns:
      `self` to allow chaining.
    """
    assert self._root.is_parent_of(path), (
      '%r is not a parent of %r' % (self._root, path))
    self._entries.append({
      'type': 'file',
      'path': str(path),
    })
    return self

  def with_dir(self, path):
    """Stages a directory with all its content to be added to the package.

    Args:
      path: absolute path to a directory, should be in |root| subdirectory.

    Returns:
      `self` to allow chaining.
    """
    assert self._root.is_parent_of(path) or path == self._root, (
      '%r is not a parent of %r' % (self._root, path))
    self._entries.append({
      'type': 'dir',
      'path': str(path),
    })
    return self

  def archive(self, step_name, output, archive_type=None):
    """Archives all staged files to an archive file indicated by `output`.

    If no 'with_file' or 'with_dir' calls were made, this will zip the entire
    root by default.

    Args:
      output: path to an archive file to create.
      archive_type: The type of archive to create. This may be:
        tar, tgz, tbz, zip. If None, will be inferred from the extension of
        output.

    Returns:
      `output`, for convenience.
    """
    entries = self._entries or [
      {'type': 'dir', 'path': str(self._root)}
    ]
    self._archive_callback(self._root, entries, step_name, output,
                           archive_type)
    return output
