# Copyright 2014 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 module uprevs Mojo for cbuildbot.

If a new version of Mojo is found, a stable ebuild for the new version
is created and older stable ebuilds will be deleted. The changes will be
contained in a single commit on the "stabilizing_branch" branch which
will be created if it does not already exist. Additionally, the program
will print out

 MOJO_VERSION_ATOM="version atom string"

This can be used with emerge to build the newly uprevved version:

 $ cros_mark_mojo_as_stable
 MOJO_VERSION_ATOM=dev-libs/mojo-0.20141202.181307-r1
 $ emerge-lumpy =dev-libs/mojo-0.20141202.181307-r1

If no new version of Mojo is found, the program will not print anything.
"""

from __future__ import print_function

import os

from chromite.lib import constants
from chromite.lib import commandline
from chromite.lib import git
from chromite.lib import gob_util
from chromite.lib import portage_util
from chromite.scripts import cros_mark_as_stable


MOJO_CATEGORY = 'dev-libs'
MOJO_PN = 'mojo'
MOJO_CP = MOJO_CATEGORY + '/' + MOJO_PN
MOJO_EBUILD_PATH = 'third_party/chromiumos-overlay/' + MOJO_CP
MOJO_REPO_URL = 'https://chromium.googlesource.com/external/mojo'


def GetStableEBuilds(ebuild_dir):
  """Gets all stable ebuilds from the given directory.

  Args:
    ebuild_dir: Path to the directory to look in.

  Returns:
    An array of ebuilds in the given directory.
  """
  return [x for x in os.listdir(ebuild_dir)
          if x.endswith('.ebuild') and not
          x.endswith(portage_util.WORKON_EBUILD_SUFFIX)]


def UprevStableEBuild(ebuild_dir, commit_to_use, date_of_commit,
                      tracking_branch='cros/master'):
  """Checks if there already if a stable Mojo ebuild for the given commit.

  If there already is a stable Mojo ebuild for the given commit, this
  function does nothing and returns None. Otherwise creates a stabilization
  branch with a single commit that creates a new stable ebuild and deletes
  all other stable ebuilds.

  Args:
    ebuild_dir: Path to the directory holding Mojo ebuilds.
    commit_to_use: The upstream Mojo commit id.
    date_of_commit: The date of the commit.
    tracking_branch: The branch that the stabilization branch should track.

  Returns:
    None or a version atom describing the newly created ebuild.
  """
  # There is no version number or other monotonically increasing value
  # that is suitable to use as a version number except for the point
  # in time that a commit was added to the repository. So we use that
  # for now.
  pvr = date_of_commit.strftime('0.%Y%m%d.%H%M%S-r1')
  mojo_stable_pn = '%s-%s.ebuild' % (MOJO_PN, pvr)

  # Find existing stable ebuilds and only add a new one if there's a
  # newer commit.
  existing_ebuilds = GetStableEBuilds(ebuild_dir)
  if mojo_stable_pn in existing_ebuilds:
    return None

  # OK. First create a stablizing branch.
  tracking_branch_full = 'remotes/m/%s' % os.path.basename(tracking_branch)
  existing_branch = git.GetCurrentBranch(ebuild_dir)
  work_branch = cros_mark_as_stable.GitBranch(constants.STABLE_EBUILD_BRANCH,
                                              tracking_branch_full,
                                              ebuild_dir)
  work_branch.CreateBranch()

  # In the case of uprevving overlays that have patches applied to them,
  # include the patched changes in the stabilizing branch.
  if existing_branch:
    git.RunGit(ebuild_dir, ['rebase', existing_branch])

  # Create a new ebuild.
  unstable_ebuild_path = os.path.join(ebuild_dir, MOJO_PN +
                                      portage_util.WORKON_EBUILD_SUFFIX)
  new_stable_ebuild_path = os.path.join(ebuild_dir, mojo_stable_pn)
  variables = {'MOJO_REVISION': commit_to_use}
  portage_util.EBuild.MarkAsStable(unstable_ebuild_path,
                                   new_stable_ebuild_path,
                                   variables, make_stable=True)

  # Add it to the repo.
  git.RunGit(ebuild_dir, ['add', new_stable_ebuild_path])

  # Nuke the now stale older ebuilds.
  for f in existing_ebuilds:
    git.RunGit(ebuild_dir, ['rm', '-f', f])

  # ... and finally commit the change.
  portage_util.EBuild.CommitChange('Updated %s to upstream commit %s.' %
                                   (MOJO_CP, commit_to_use),
                                   ebuild_dir)
  # Return version atom for newly created ebuild.
  return MOJO_CP + '-' + pvr


def main(_argv):
  parser = commandline.ArgumentParser(usage=__doc__)
  parser.add_argument('--force_version', default=None,
                      help='git revision hash to use')
  parser.add_argument('--repo_url', default=MOJO_REPO_URL)
  parser.add_argument('--srcroot', type='path',
                      default=os.path.join(os.environ['HOME'], 'trunk', 'src'),
                      help='Path to the src directory')
  parser.add_argument('--tracking_branch', default='cros/master',
                      help='Branch we are tracking changes against')
  options = parser.parse_args()
  options.Freeze()

  mojo_version_atom = None
  ebuild_dir = os.path.join(options.srcroot, MOJO_EBUILD_PATH)

  # Figure out commit to use and its date.
  if options.force_version:
    commit_to_use = options.force_version
  else:
    commit_to_use = gob_util.GetTipOfTrunkRevision(options.repo_url)
  date_of_commit = gob_util.GetCommitDate(options.repo_url, commit_to_use)

  # Do the uprev and explicit print version to inform caller if we
  # made a change.
  mojo_version_atom = UprevStableEBuild(ebuild_dir, commit_to_use,
                                        date_of_commit, options.tracking_branch)
  if mojo_version_atom:
    print('MOJO_VERSION_ATOM=%s' % mojo_version_atom)
