# -*- coding: utf-8 -*-
# Copyright 2015 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# TODO: Support cleaning /tmp and /build/*/tmp.
# TODO: Support running `eclean -q packages` on / and the sysroots.
# TODO: Support cleaning sysroots as a destructive option.

"""Clean up working files in a Chromium OS checkout.

If unsure, just use the --safe flag to clean out various objects.
"""

from __future__ import print_function

import glob
import os

from chromite.lib import constants
from chromite.cli import command
from chromite.cli import flash
from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging
from chromite.lib import osutils


@command.CommandDecorator('clean')
class CleanCommand(command.CliCommand):
  """Clean up working files from the build."""

  @classmethod
  def AddParser(cls, parser):
    """Add parser arguments."""
    super(CleanCommand, cls).AddParser(parser)

    parser.add_argument(
        '--safe', default=False, action='store_true',
        help='Clean up files that are automatically created.')
    parser.add_argument(
        '-n', '--dry-run', default=False, action='store_true',
        help='Show which paths would be cleaned up.')

    group = parser.add_argument_group(
        'Cache Selection (Advanced)',
        description='Clean out specific caches (--safe does all of these).')
    group.add_argument(
        '--cache', default=False, action='store_true',
        help='Clean up our shared cache dir.')
    group.add_argument(
        '--chromite', default=False, action='store_true',
        help='Clean up chromite working directories.')
    group.add_argument(
        '--deploy', default=False, action='store_true',
        help='Clean files cached by cros deploy.')
    group.add_argument(
        '--flash', default=False, action='store_true',
        help='Clean files cached by cros flash.')
    group.add_argument(
        '--images', default=False, action='store_true',
        help='Clean up locally generated images.')
    group.add_argument(
        '--incrementals', default=False, action='store_true',
        help='Clean up incremental package objects.')
    group.add_argument(
        '--logs', default=False, action='store_true',
        help='Clean up various build log files.')
    group.add_argument(
        '--workdirs', default=False, action='store_true',
        help='Clean up build various package build directories.')

    group = parser.add_argument_group(
        'Unrecoverable Options (Dangerous)',
        description='Clean out objects that cannot be recovered easily.')
    group.add_argument(
        '--clobber', default=False, action='store_true',
        help='Delete all non-source objects.')
    group.add_argument(
        '--chroot', default=False, action='store_true',
        help='Delete build chroot (affects all boards).')
    group.add_argument(
        '--board', action='append', help='Delete board(s) build root(s).')
    group.add_argument(
        '--autotest', default=False, action='store_true',
        help='Delete build_externals packages.')

  def __init__(self, options):
    """Initializes cros clean."""
    command.CliCommand.__init__(self, options)

  def Run(self):
    """Perfrom the cros clean command."""

    # If no option is set, default to "--safe"
    if not (self.options.safe or
            self.options.clobber or
            self.options.board or
            self.options.chroot or
            self.options.cache or
            self.options.deploy or
            self.options.flash or
            self.options.images or
            self.options.autotest or
            self.options.incrementals):
      self.options.safe = True

    if self.options.clobber:
      self.options.chroot = True
      self.options.autotest = True
      self.options.safe = True

    if self.options.safe:
      self.options.cache = True
      self.options.chromite = True
      self.options.deploy = True
      self.options.flash = True
      self.options.images = True
      self.options.incrementals = True
      self.options.logs = True
      self.options.workdirs = True

    self.options.Freeze()

    chroot_dir = os.path.join(constants.SOURCE_ROOT,
                              constants.DEFAULT_CHROOT_DIR)

    cros_build_lib.AssertOutsideChroot()

    def Clean(path):
      """Helper wrapper for the dry-run checks"""
      if self.options.dry_run:
        logging.notice('would have cleaned: %s', path)
      else:
        osutils.RmDir(path, ignore_missing=True, sudo=True)

    def CleanNoBindMount(path):
      # This test is a convenience for developers that bind mount these dirs.
      if not os.path.ismount(path):
        Clean(path)
      else:
        logging.debug('Ignoring bind mounted dir: %s', path)

    # Delete this first since many of the caches below live in the chroot.
    if self.options.chroot:
      logging.debug('Remove the chroot.')
      if self.options.dry_run:
        logging.notice('would have cleaned: %s', chroot_dir)
      else:
        cros_build_lib.run(['cros_sdk', '--delete'])

    if self.options.board:
      for b in self.options.board:
        logging.debug('Clean up the %s build root.', b)
        Clean(os.path.join(chroot_dir, 'build', b))

    if self.options.cache:
      logging.debug('Clean the common cache')
      CleanNoBindMount(self.options.cache_dir)

      # Recreate dirs that cros_sdk does when entering.
      # TODO: When sdk_lib/enter_chroot.sh is moved to chromite, we should unify
      # with those code paths.
      if not self.options.dry_run:
        for subdir in ('ccache', 'host', 'target'):
          osutils.SafeMakedirs(
              os.path.join(self.options.cache_dir, 'distfiles', subdir))
        os.chmod(os.path.join(self.options.cache_dir, 'distfiles', 'ccache'),
                 0o2775)

    if self.options.chromite:
      logging.debug('Clean chromite workdirs')
      Clean(os.path.join(constants.CHROMITE_DIR, 'venv', 'venv'))
      Clean(os.path.join(constants.CHROMITE_DIR, 'venv', '.venv_lock'))

    if self.options.deploy:
      logging.debug('Clean up the cros deploy cache.')
      for subdir in ('custom-packages', 'gmerge-packages'):
        for d in glob.glob(os.path.join(chroot_dir, 'build', '*', subdir)):
          Clean(d)

    if self.options.flash:
      logging.debug('Clean up the cros flash cache.')
      Clean(flash.DEVSERVER_STATIC_DIR)

    if self.options.images:
      logging.debug('Clean the images cache.')
      cache_dir = os.path.join(constants.SOURCE_ROOT, 'src', 'build')
      CleanNoBindMount(cache_dir)

    if self.options.incrementals:
      logging.debug('Clean package incremental objects')
      Clean(os.path.join(chroot_dir, 'var', 'cache', 'portage'))
      for d in glob.glob(os.path.join(chroot_dir, 'build', '*', 'var', 'cache',
                                      'portage')):
        Clean(d)

    if self.options.logs:
      logging.debug('Clean log files')
      Clean(os.path.join(chroot_dir, 'var', 'log'))
      for d in glob.glob(os.path.join(chroot_dir, 'build', '*', 'tmp',
                                      'portage', 'logs')):
        Clean(d)

    if self.options.workdirs:
      logging.debug('Clean package workdirs')
      Clean(os.path.join(chroot_dir, 'var', 'tmp', 'portage'))
      Clean(os.path.join(constants.CHROMITE_DIR, 'venv', 'venv'))
      for d in glob.glob(os.path.join(chroot_dir, 'build', '*', 'tmp',
                                      'portage')):
        Clean(d)

    if self.options.autotest:
      logging.debug('Clean build_externals')
      packages_dir = os.path.join(
          constants.SOURCE_ROOT, 'src', 'third_party', 'autotest', 'files',
          'site-packages')
      Clean(packages_dir)
