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

"""This script moves ebuilds between 'stable' and 'live' states.

By default 'stable' ebuilds point at and build from source at the
last known good commit. Moving an ebuild to 'live' (via cros_workon start)
is intended to support development. The current source tip is fetched,
source modified and built using the unstable 'live' (9999) ebuild.
"""

from __future__ import print_function

from chromite.lib import brick_lib
from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import terminal
from chromite.lib import workon_helper


def main(argv):
  shared = commandline.SharedParser()
  shared.add_argument('--board', default=cros_build_lib.GetDefaultBoard(),
                      help='The board to set package keywords for.')
  shared.add_argument('--brick', help='The brick to set package keywords for.')
  shared.add_argument('--host', default=False, action='store_true',
                      help='Uses the host instead of board')
  shared.add_argument('--remote', default='',
                      help='For non-workon projects, the git remote to use.')
  shared.add_argument('--revision', default='',
                      help='Use to override the manifest defined default '
                           'revision used for a project')
  shared.add_argument('--command', default='git status', dest='iterate_command',
                      help='The command to be run by forall.')
  shared.add_argument('--workon_only', default=False, action='store_true',
                      help='Apply to packages that have a workon ebuild only')
  shared.add_argument('--all', default=False, action='store_true',
                      help='Apply to all possible packages for the '
                           'given command (overrides workon_only)')

  parser = commandline.ArgumentParser(description=__doc__, parents=[shared,])

  # Add the shared 'packages' argument after creating the main parser so that
  # it is only bound/shared with the subcommands and doesn't confuse argparse.
  shared.add_argument('packages', nargs='*',
                      help='The packages to run command against.')

  commands = [
      ('start', 'Moves an ebuild to live (intended to support development)'),
      ('stop', 'Moves an ebuild to stable (use last known good)'),
      ('info', 'Print package name, repo name, and source directory.'),
      ('list', 'List of live ebuilds (workon ebuilds if --all)'),
      ('list-all', 'List all of the live ebuilds for all setup boards'),
      ('iterate', 'For each ebuild, cd to the source dir and run a command'),
  ]
  command_parsers = parser.add_subparsers(dest='command', title='commands')
  for command, description in commands:
    command_parsers.add_parser(command, parents=(shared,), help=description,
                               description=description)

  options = parser.parse_args(argv)
  options.Freeze()

  if options.command == 'list-all':
    board_to_packages = workon_helper.ListAllWorkedOnAtoms()
    color = terminal.Color()
    for board in sorted(board_to_packages):
      print(color.Start(color.GREEN) + board + ':' + color.Stop())
      for package in board_to_packages[board]:
        print('    ' + package)
      print('')
    return 0

  # TODO(wiley): Assert that we're not running as root.
  cros_build_lib.AssertInsideChroot()

  if options.host:
    friendly_name = 'host'
    sysroot = '/'
  elif options.board:
    friendly_name = options.board
    sysroot = cros_build_lib.GetSysroot(board=options.board)
  elif options.brick:
    brick = brick_lib.Brick(options.brick)
    friendly_name = brick.FriendlyName()
    # TODO(wiley) This is a hack.  It doesn't really make sense to calculate
    #             the sysroot from a brick alone, since bricks are installed
    #             into sysroots.  Revisit this when blueprints are working.
    sysroot = cros_build_lib.GetSysroot(friendly_name)
  else:
    cros_build_lib.Die('You must specify either --host, --board or --brick')

  helper = workon_helper.WorkonHelper(sysroot, friendly_name)
  try:
    if options.command == 'start':
      helper.StartWorkingOnPackages(options.packages, use_all=options.all,
                                    use_workon_only=options.workon_only)
    elif options.command == 'stop':
      helper.StopWorkingOnPackages(options.packages, use_all=options.all,
                                   use_workon_only=options.workon_only)
    elif options.command == 'info':
      triples = helper.GetPackageInfo(options.packages, use_all=options.all,
                                      use_workon_only=options.workon_only)
      for package, repos, paths in triples:
        print(package, ','.join(repos), ','.join(paths))
    elif options.command == 'list':
      packages = helper.ListAtoms(
          use_all=options.all, use_workon_only=options.workon_only)
      if packages:
        print('\n'.join(packages))
    elif options.command == 'iterate':
      helper.RunCommandInPackages(options.packages, options.iterate_command,
                                  use_all=options.all,
                                  use_workon_only=options.workon_only)
  except workon_helper.WorkonError as e:
    cros_build_lib.Die(e.message)

  return 0
