#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2020 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.

"""Tool to automatically generate a new Rust uprev CL.

This tool is intended to automatically generate a CL to uprev Rust to a
newer version in Chrome OS, including creating a new Rust version or
removing an old version. It's based on
src/third_party/chromiumos-overlay/dev-lang/rust/UPGRADE.md. When using
the tool, the progress can be saved to a JSON file, so the user can resume
the process after a failing step is fixed. Example usage to create a new
version:

1. (inside chroot) $ ./rust_tools/rust_uprev.py
                     --state_file /tmp/state-file.json
                     create --rust_version 1.45.0
2. Step "compile rust" failed due to the patches can't apply to new version
3. Manually fix the patches
4. Execute the command in step 1 again.
5. Iterate 1-4 for each failed step until the tool passes.

Replace `create --rust_version 1.45.0` with `remove --rust_version 1.43.0`
if you want to remove all 1.43.0 related stuff in the same CL. Remember to
use a different state file if you choose to run different subcommands.

If you want a hammer that can do everything for you, use the subcommand
`roll`. It can create a Rust uprev CL with `create` and `remove` and upload
the CL to chromium code review.

See `--help` for all available options.
"""

# pylint: disable=cros-logging-import

import argparse
import pathlib
import json
import logging
import os
import re
import shutil
import subprocess
import sys
from pathlib import Path
from typing import Any, Callable, Dict, List, NamedTuple, Optional, T, Tuple

from llvm_tools import chroot, git
RUST_PATH = Path(
    '/mnt/host/source/src/third_party/chromiumos-overlay/dev-lang/rust')


def get_command_output(command: List[str], *args, **kwargs) -> str:
  return subprocess.check_output(
      command, encoding='utf-8', *args, **kwargs).strip()


class RustVersion(NamedTuple):
  """NamedTuple represents a Rust version"""
  major: int
  minor: int
  patch: int

  def __str__(self):
    return f'{self.major}.{self.minor}.{self.patch}'

  @staticmethod
  def parse_from_ebuild(ebuild_name: str) -> 'RustVersion':
    input_re = re.compile(r'^rust-'
                          r'(?P<major>\d+)\.'
                          r'(?P<minor>\d+)\.'
                          r'(?P<patch>\d+)'
                          r'(:?-r\d+)?'
                          r'\.ebuild$')
    m = input_re.match(ebuild_name)
    assert m, f'failed to parse {ebuild_name!r}'
    return RustVersion(
        int(m.group('major')), int(m.group('minor')), int(m.group('patch')))

  @staticmethod
  def parse(x: str) -> 'RustVersion':
    input_re = re.compile(r'^(?:rust-)?'
                          r'(?P<major>\d+)\.'
                          r'(?P<minor>\d+)\.'
                          r'(?P<patch>\d+)'
                          r'(?:.ebuild)?$')
    m = input_re.match(x)
    assert m, f'failed to parse {x!r}'
    return RustVersion(
        int(m.group('major')), int(m.group('minor')), int(m.group('patch')))


def find_ebuild_path(directory: Path,
                     name: str,
                     version: Optional[RustVersion] = None) -> Path:
  """Finds an ebuild in a directory.

  Returns the path to the ebuild file. Asserts if there is not
  exactly one match. The match is constrained by name and optionally
  by version, but can match any patch level. E.g. "rust" version
  1.3.4 can match rust-1.3.4.ebuild but also rust-1.3.4-r6.ebuild.
  """
  if version:
    pattern = '%s-%s*.ebuild' % (name, version)
  else:
    pattern = '%s-*.ebuild' % (name,)
  matches = list(Path(directory).glob(pattern))
  assert len(matches) == 1, matches
  return matches[0]


def get_rust_bootstrap_version():
  """Get the version of the current rust-bootstrap package."""
  bootstrap_ebuild = find_ebuild_path(rust_bootstrap_path(), 'rust-bootstrap')
  m = re.match(r'^rust-bootstrap-(\d+).(\d+).(\d+)', bootstrap_ebuild.name)
  assert m, bootstrap_ebuild.name
  return RustVersion(int(m.group(1)), int(m.group(2)), int(m.group(3)))


def parse_commandline_args() -> argparse.Namespace:
  parser = argparse.ArgumentParser(
      description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
  parser.add_argument(
      '--state_file',
      required=True,
      help='A state file to hold previous completed steps. If the file '
      'exists, it needs to be used together with --continue or --restart. '
      'If not exist (do not use --continue in this case), we will create a '
      'file for you.',
  )
  parser.add_argument(
      '--restart',
      action='store_true',
      help='Restart from the first step. Ignore the completed steps in '
      'the state file',
  )
  parser.add_argument(
      '--continue',
      dest='cont',
      action='store_true',
      help='Continue the steps from the state file',
  )

  create_parser_template = argparse.ArgumentParser(add_help=False)
  create_parser_template.add_argument(
      '--template',
      type=RustVersion.parse,
      default=None,
      help='A template to use for creating a Rust uprev from, in the form '
      'a.b.c The ebuild has to exist in the chroot. If not specified, the '
      'tool will use the current Rust version in the chroot as template.',
  )
  create_parser_template.add_argument(
      '--skip_compile',
      action='store_true',
      help='Skip compiling rust to test the tool. Only for testing',
  )

  subparsers = parser.add_subparsers(dest='subparser_name')
  subparser_names = []
  subparser_names.append('create')
  create_parser = subparsers.add_parser(
      'create',
      parents=[create_parser_template],
      help='Create changes uprevs Rust to a new version',
  )
  create_parser.add_argument(
      '--rust_version',
      type=RustVersion.parse,
      required=True,
      help='Rust version to uprev to, in the form a.b.c',
  )

  subparser_names.append('remove')
  remove_parser = subparsers.add_parser(
      'remove',
      help='Clean up old Rust version from chroot',
  )
  remove_parser.add_argument(
      '--rust_version',
      type=RustVersion.parse,
      default=None,
      help='Rust version to remove, in the form a.b.c If not '
      'specified, the tool will remove the oldest version in the chroot',
  )

  subparser_names.append('remove-bootstrap')
  remove_bootstrap_parser = subparsers.add_parser(
      'remove-bootstrap',
      help='Remove an old rust-bootstrap version',
  )
  remove_bootstrap_parser.add_argument(
      '--version',
      type=RustVersion.parse,
      required=True,
      help='rust-bootstrap version to remove',
  )

  subparser_names.append('roll')
  roll_parser = subparsers.add_parser(
      'roll',
      parents=[create_parser_template],
      help='A command can create and upload a Rust uprev CL, including '
      'preparing the repo, creating new Rust uprev, deleting old uprev, '
      'and upload a CL to crrev.',
  )
  roll_parser.add_argument(
      '--uprev',
      type=RustVersion.parse,
      required=True,
      help='Rust version to uprev to, in the form a.b.c',
  )
  roll_parser.add_argument(
      '--remove',
      type=RustVersion.parse,
      default=None,
      help='Rust version to remove, in the form a.b.c If not '
      'specified, the tool will remove the oldest version in the chroot',
  )
  roll_parser.add_argument(
      '--skip_cross_compiler',
      action='store_true',
      help='Skip updating cross-compiler in the chroot',
  )
  roll_parser.add_argument(
      '--no_upload',
      action='store_true',
      help='If specified, the tool will not upload the CL for review',
  )

  args = parser.parse_args()
  if args.subparser_name not in subparser_names:
    parser.error('one of %s must be specified' % subparser_names)

  if args.cont and args.restart:
    parser.error('Please select either --continue or --restart')

  if os.path.exists(args.state_file):
    if not args.cont and not args.restart:
      parser.error('State file exists, so you should either --continue '
                   'or --restart')
  if args.cont and not os.path.exists(args.state_file):
    parser.error('Indicate --continue but the state file does not exist')

  if args.restart and os.path.exists(args.state_file):
    os.remove(args.state_file)

  return args


def prepare_uprev(rust_version: RustVersion, template: Optional[RustVersion]
                 ) -> Optional[Tuple[RustVersion, str, RustVersion]]:
  if template is None:
    ebuild_path = get_command_output(['equery', 'w', 'rust'])
    ebuild_name = os.path.basename(ebuild_path)
    template_version = RustVersion.parse_from_ebuild(ebuild_name)
  else:
    ebuild_path = find_ebuild_for_rust_version(template)
    template_version = template

  bootstrap_version = get_rust_bootstrap_version()

  if rust_version <= template_version:
    logging.info(
        'Requested version %s is not newer than the template version %s.',
        rust_version, template_version)
    return None

  logging.info('Template Rust version is %s (ebuild: %r)', template_version,
               ebuild_path)
  logging.info('rust-bootstrap version is %s', bootstrap_version)

  return template_version, ebuild_path, bootstrap_version


def copy_patches(directory: Path, template_version: RustVersion,
                 new_version: RustVersion) -> None:
  patch_path = directory.joinpath('files')
  prefix = '%s-%s-' % (directory.name, template_version)
  new_prefix = '%s-%s-' % (directory.name, new_version)
  for f in os.listdir(patch_path):
    if not f.startswith(prefix):
      continue
    logging.info('Copy patch %s to new version', f)
    new_name = f.replace(str(template_version), str(new_version))
    shutil.copyfile(
        os.path.join(patch_path, f),
        os.path.join(patch_path, new_name),
    )

  subprocess.check_call(['git', 'add', f'{new_prefix}*.patch'], cwd=patch_path)


def create_ebuild(template_ebuild: str, new_version: RustVersion) -> str:
  shutil.copyfile(template_ebuild,
                  RUST_PATH.joinpath(f'rust-{new_version}.ebuild'))
  subprocess.check_call(['git', 'add', f'rust-{new_version}.ebuild'],
                        cwd=RUST_PATH)
  return os.path.join(RUST_PATH, f'rust-{new_version}.ebuild')


def update_bootstrap_ebuild(new_bootstrap_version: RustVersion) -> None:
  old_ebuild = find_ebuild_path(rust_bootstrap_path(), 'rust-bootstrap')
  m = re.match(r'^rust-bootstrap-(\d+).(\d+).(\d+)', old_ebuild.name)
  assert m, old_ebuild.name
  old_version = RustVersion(m.group(1), m.group(2), m.group(3))
  new_ebuild = old_ebuild.parent.joinpath(
      f'rust-bootstrap-{new_bootstrap_version}.ebuild')
  old_text = old_ebuild.read_text(encoding='utf-8')
  new_text, changes = re.subn(
      r'(RUSTC_FULL_BOOTSTRAP_SEQUENCE=\([^)]*)',
      f'\\1\t{old_version}\n',
      old_text,
      flags=re.MULTILINE)
  assert changes == 1, 'Failed to update RUSTC_FULL_BOOTSTRAP_SEQUENCE'
  new_ebuild.write_text(new_text, encoding='utf-8')


def update_ebuild(ebuild_file: str, new_bootstrap_version: RustVersion) -> None:
  contents = open(ebuild_file, encoding='utf-8').read()
  contents, subs = re.subn(
      r'^BOOTSTRAP_VERSION=.*$',
      'BOOTSTRAP_VERSION="%s"' % (new_bootstrap_version,),
      contents,
      flags=re.MULTILINE)
  if not subs:
    raise RuntimeError('BOOTSTRAP_VERSION not found in rust ebuild')
  open(ebuild_file, 'w', encoding='utf-8').write(contents)
  logging.info('Rust ebuild file has BOOTSTRAP_VERSION updated to %s',
               new_bootstrap_version)


def flip_mirror_in_ebuild(ebuild_file: Path, add: bool) -> None:
  restrict_re = re.compile(
      r'(?P<before>RESTRICT=")(?P<values>"[^"]*"|.*)(?P<after>")')
  with open(ebuild_file, encoding='utf-8') as f:
    contents = f.read()
  m = restrict_re.search(contents)
  assert m, 'failed to find RESTRICT variable in Rust ebuild'
  values = m.group('values')
  if add:
    if 'mirror' in values:
      return
    values += ' mirror'
  else:
    if 'mirror' not in values:
      return
    values = values.replace(' mirror', '')
  new_contents = restrict_re.sub(r'\g<before>%s\g<after>' % values, contents)
  with open(ebuild_file, 'w', encoding='utf-8') as f:
    f.write(new_contents)


def ebuild_actions(package: str, actions: List[str],
                   sudo: bool = False) -> None:
  ebuild_path_inchroot = get_command_output(['equery', 'w', package])
  cmd = ['ebuild', ebuild_path_inchroot] + actions
  if sudo:
    cmd = ['sudo'] + cmd
  subprocess.check_call(cmd)


def update_manifest(ebuild_file: os.PathLike) -> None:
  ebuild = Path(ebuild_file)
  logging.info('Added "mirror" to RESTRICT to %s', ebuild.name)
  flip_mirror_in_ebuild(ebuild, add=True)
  ebuild_actions(ebuild.parent.name, ['manifest'])
  logging.info('Removed "mirror" to RESTRICT from %s', ebuild.name)
  flip_mirror_in_ebuild(ebuild, add=False)


def update_rust_packages(rust_version: RustVersion, add: bool) -> None:
  package_file = RUST_PATH.joinpath(
      '../../profiles/targets/chromeos/package.provided')
  with open(package_file, encoding='utf-8') as f:
    contents = f.read()
  if add:
    rust_packages_re = re.compile(r'dev-lang/rust-(\d+\.\d+\.\d+)')
    rust_packages = rust_packages_re.findall(contents)
    # Assume all the rust packages are in alphabetical order, so insert the new
    # version to the place after the last rust_packages
    new_str = f'dev-lang/rust-{rust_version}'
    new_contents = contents.replace(rust_packages[-1],
                                    f'{rust_packages[-1]}\n{new_str}')
    logging.info('%s has been inserted into package.provided', new_str)
  else:
    old_str = f'dev-lang/rust-{rust_version}\n'
    assert old_str in contents, f'{old_str!r} not found in package.provided'
    new_contents = contents.replace(old_str, '')
    logging.info('%s has been removed from package.provided', old_str)

  with open(package_file, 'w', encoding='utf-8') as f:
    f.write(new_contents)


def update_virtual_rust(template_version: RustVersion,
                        new_version: RustVersion) -> None:
  template_ebuild = find_ebuild_path(
      RUST_PATH.joinpath('../../virtual/rust'), 'rust', template_version)
  virtual_rust_dir = template_ebuild.parent
  new_name = f'rust-{new_version}.ebuild'
  new_ebuild = virtual_rust_dir.joinpath(new_name)
  shutil.copyfile(template_ebuild, new_ebuild)
  subprocess.check_call(['git', 'add', new_name], cwd=virtual_rust_dir)


def perform_step(state_file: pathlib.Path,
                 tmp_state_file: pathlib.Path,
                 completed_steps: Dict[str, Any],
                 step_name: str,
                 step_fn: Callable[[], T],
                 result_from_json: Optional[Callable[[Any], T]] = None,
                 result_to_json: Optional[Callable[[T], Any]] = None) -> T:
  if step_name in completed_steps:
    logging.info('Skipping previously completed step %s', step_name)
    if result_from_json:
      return result_from_json(completed_steps[step_name])
    return completed_steps[step_name]

  logging.info('Running step %s', step_name)
  val = step_fn()
  logging.info('Step %s complete', step_name)
  if result_to_json:
    completed_steps[step_name] = result_to_json(val)
  else:
    completed_steps[step_name] = val

  with tmp_state_file.open('w', encoding='utf-8') as f:
    json.dump(completed_steps, f, indent=4)
  tmp_state_file.rename(state_file)
  return val


def prepare_uprev_from_json(obj: Any
                           ) -> Optional[Tuple[RustVersion, str, RustVersion]]:
  if not obj:
    return None
  version, ebuild_path, bootstrap_version = obj
  return RustVersion(*version), ebuild_path, RustVersion(*bootstrap_version)


def create_rust_uprev(rust_version: RustVersion,
                      maybe_template_version: Optional[RustVersion],
                      skip_compile: bool, run_step: Callable[[], T]) -> None:
  template_version, template_ebuild, old_bootstrap_version = run_step(
      'prepare uprev',
      lambda: prepare_uprev(rust_version, maybe_template_version),
      result_from_json=prepare_uprev_from_json,
  )
  if template_ebuild is None:
    return

  run_step(
      'copy bootstrap patches', lambda: copy_patches(rust_bootstrap_path(
      ), old_bootstrap_version, template_version))
  run_step('update bootstrap ebuild', lambda: update_bootstrap_ebuild(
      template_version))
  run_step(
      'update bootstrap manifest', lambda: update_manifest(rust_bootstrap_path(
      ).joinpath(f'rust-bootstrap-{template_version}.ebuild')))
  run_step('copy patches', lambda: copy_patches(RUST_PATH, template_version,
                                                rust_version))
  ebuild_file = run_step(
      'create ebuild', lambda: create_ebuild(template_ebuild, rust_version))
  run_step(
      'update ebuild', lambda: update_ebuild(ebuild_file, template_version))
  run_step('update manifest to add new version', lambda: update_manifest(
      Path(ebuild_file)))
  if not skip_compile:
    run_step('emerge rust', lambda: subprocess.check_call(
        ['sudo', 'emerge', 'dev-lang/rust']))
  run_step('insert version into rust packages', lambda: update_rust_packages(
      rust_version, add=True))
  run_step('upgrade virtual/rust', lambda: update_virtual_rust(
      template_version, rust_version))


def find_rust_versions_in_chroot() -> List[Tuple[RustVersion, str]]:
  return [(RustVersion.parse_from_ebuild(x), os.path.join(RUST_PATH, x))
          for x in os.listdir(RUST_PATH)
          if x.endswith('.ebuild')]


def find_oldest_rust_version_in_chroot() -> Tuple[RustVersion, str]:
  rust_versions = find_rust_versions_in_chroot()
  if len(rust_versions) <= 1:
    raise RuntimeError('Expect to find more than one Rust versions')
  return min(rust_versions)


def find_ebuild_for_rust_version(version: RustVersion) -> str:
  rust_ebuilds = [
      ebuild for x, ebuild in find_rust_versions_in_chroot() if x == version
  ]
  if not rust_ebuilds:
    raise ValueError(f'No Rust ebuilds found matching {version}')
  if len(rust_ebuilds) > 1:
    raise ValueError(f'Multiple Rust ebuilds found matching {version}: '
                     f'{rust_ebuilds}')
  return rust_ebuilds[0]


def remove_files(filename: str, path: str) -> None:
  subprocess.check_call(['git', 'rm', filename], cwd=path)


def remove_rust_bootstrap_version(version: RustVersion,
                                  run_step: Callable[[], T]) -> None:
  prefix = f'rust-bootstrap-{version}'
  run_step(
      'remove old bootstrap patches', lambda: remove_files(
          f'files/{prefix}-*.patch', rust_bootstrap_path()))
  run_step('remove old bootstrap ebuild', lambda: remove_files(
      f'{prefix}*.ebuild', rust_bootstrap_path()))
  ebuild_file = get_command_output(['equery', 'w', 'rust-bootstrap'])
  run_step('update bootstrap manifest to delete old version', lambda:
           update_manifest(ebuild_file))


def remove_rust_uprev(rust_version: Optional[RustVersion],
                      run_step: Callable[[], T]) -> None:

  def find_desired_rust_version():
    if rust_version:
      return rust_version, find_ebuild_for_rust_version(rust_version)
    return find_oldest_rust_version_in_chroot()

  def find_desired_rust_version_from_json(obj: Any) -> Tuple[RustVersion, str]:
    version, ebuild_path = obj
    return RustVersion(*version), ebuild_path

  delete_version, delete_ebuild = run_step(
      'find rust version to delete',
      find_desired_rust_version,
      result_from_json=find_desired_rust_version_from_json,
  )
  run_step(
      'remove patches', lambda: remove_files(
          f'files/rust-{delete_version}-*.patch', RUST_PATH))
  run_step('remove ebuild', lambda: remove_files(delete_ebuild, RUST_PATH))
  ebuild_file = get_command_output(['equery', 'w', 'rust'])
  run_step('update manifest to delete old version', lambda: update_manifest(
      ebuild_file))
  run_step('remove version from rust packages', lambda: update_rust_packages(
      delete_version, add=False))
  run_step('remove virtual/rust', lambda: remove_virtual_rust(delete_version))


def remove_virtual_rust(delete_version: RustVersion) -> None:
  ebuild = find_ebuild_path(
      RUST_PATH.joinpath('../../virtual/rust'), 'rust', delete_version)
  subprocess.check_call(['git', 'rm', str(ebuild.name)], cwd=ebuild.parent)


def rust_bootstrap_path() -> Path:
  return RUST_PATH.joinpath('../rust-bootstrap')


def create_new_repo(rust_version: RustVersion) -> None:
  output = get_command_output(['git', 'status', '--porcelain'], cwd=RUST_PATH)
  if output:
    raise RuntimeError(
        f'{RUST_PATH} has uncommitted changes, please either discard them '
        'or commit them.')
  git.CreateBranch(RUST_PATH, f'rust-to-{rust_version}')


def build_cross_compiler() -> None:
  # Get target triples in ebuild
  rust_ebuild = get_command_output(['equery', 'w', 'rust'])
  with open(rust_ebuild, encoding='utf-8') as f:
    contents = f.read()

  target_triples_re = re.compile(r'RUSTC_TARGET_TRIPLES=\(([^)]+)\)')
  m = target_triples_re.search(contents)
  assert m, 'RUST_TARGET_TRIPLES not found in rust ebuild'
  target_triples = m.group(1).strip().split('\n')

  compiler_targets_to_install = [
      target.strip() for target in target_triples if 'cros-' in target
  ]
  for target in target_triples:
    if 'cros-' not in target:
      continue
    target = target.strip()

  # We also always need arm-none-eabi, though it's not mentioned in
  # RUSTC_TARGET_TRIPLES.
  compiler_targets_to_install.append('arm-none-eabi')

  logging.info('Emerging cross compilers %s', compiler_targets_to_install)
  subprocess.check_call(
      ['sudo', 'emerge', '-j', '-G'] +
      [f'cross-{target}/gcc' for target in compiler_targets_to_install])


def create_new_commit(rust_version: RustVersion) -> None:
  subprocess.check_call(['git', 'add', '-A'], cwd=RUST_PATH)
  messages = [
      f'[DO NOT SUBMIT] dev-lang/rust: upgrade to Rust {rust_version}',
      '',
      'This CL is created by rust_uprev tool automatically.'
      '',
      'BUG=None',
      'TEST=Use CQ to test the new Rust version',
  ]
  git.UploadChanges(RUST_PATH, f'rust-to-{rust_version}', messages)


def main() -> None:
  if not chroot.InChroot():
    raise RuntimeError('This script must be executed inside chroot')

  logging.basicConfig(level=logging.INFO)

  args = parse_commandline_args()

  state_file = pathlib.Path(args.state_file)
  tmp_state_file = state_file.with_suffix('.tmp')

  try:
    with state_file.open(encoding='utf-8') as f:
      completed_steps = json.load(f)
  except FileNotFoundError:
    completed_steps = {}

  def run_step(
      step_name: str,
      step_fn: Callable[[], T],
      result_from_json: Optional[Callable[[Any], T]] = None,
      result_to_json: Optional[Callable[[T], Any]] = None,
  ) -> T:
    return perform_step(state_file, tmp_state_file, completed_steps, step_name,
                        step_fn, result_from_json, result_to_json)

  if args.subparser_name == 'create':
    create_rust_uprev(args.rust_version, args.template, args.skip_compile,
                      run_step)
  elif args.subparser_name == 'remove':
    remove_rust_uprev(args.rust_version, run_step)
  elif args.subparser_name == 'remove-bootstrap':
    remove_rust_bootstrap_version(args.version, run_step)
  else:
    # If you have added more subparser_name, please also add the handlers above
    assert args.subparser_name == 'roll'
    run_step('create new repo', lambda: create_new_repo(args.uprev))
    if not args.skip_cross_compiler:
      run_step('build cross compiler', build_cross_compiler)
    create_rust_uprev(args.uprev, args.template, args.skip_compile, run_step)
    remove_rust_uprev(args.remove, run_step)
    bootstrap_version = prepare_uprev_from_json(
        completed_steps['prepare uprev'])[2]
    remove_rust_bootstrap_version(bootstrap_version, run_step)
    if not args.no_upload:
      run_step('create rust uprev CL', lambda: create_new_commit(args.uprev))


if __name__ == '__main__':
  sys.exit(main())
