#!/usr/bin/env python3
# Copyright 2026 The PDFium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import argparse
import os
import re
import sys

ALL_DEPS_ENTRIES = (
    'abseil_revision',
    'android_ndk_version',
    'brotli_revision',
    'build_revision',
    'buildtools_revision',
    'clang_format_revision',
    'clang_revision',
    'cpu_features_revision',
    'cpython3_version',
    'dragonbox_revision',
    'fast_float_revision',
    'fp16_revision',
    'freetype_revision',
    'gn_version',
    'gtest_revision',
    'harfbuzz_revision',
    'highway_revision',
    'icu_revision',
    'jpeg_turbo_revision',
    'libcxx_revision',
    'libcxxabi_revision',
    'libunwind_revision',
    'llvm_libc_revision',
    'nasm_source_revision',
    'ninja_version',
    'partition_allocator_revision',
    'reclient_version',
    'result_adapter_revision',
    'rust_revision',
    'siso_version',
    'skia_revision',
    'testing_rust_revision',
    'tools_rust_revision',
    'tools_win_revision',
    'v8_revision',
)

UNSUPPORTED_ENTRIES = ('pdfium_tests_revision', 'test_fonts_revision')


class DepsParser:

  def __init__(self, deps_content):
    self._deps_content = deps_content
    self.deps = {}
    self.vars = {}
    # self.Str and self.Var are used by exec() below.
    self.Str = lambda s: s
    self.Var = lambda v: self.vars.get(v, f"Var('{v}')")
    exec(self._deps_content, self.__dict__)


def find_path_for_revision_in_deps(deps_dict, revision):
  """Finds the deps path that corresponds to a given revision string."""
  for path, dep_info in deps_dict.items():
    if revision in str(dep_info):
      return path
  return None


def get_revision_from_dep_value(dep_value):
  url = dep_value
  if isinstance(dep_value, dict):
    # This is for CIPD packages.
    if 'packages' in dep_value:
      for package in dep_value['packages']:
        if 'version' in package:
          return package['version']
    url = dep_value.get('url')

  if not url or not isinstance(url, str):
    return None

  match = re.search(r'@(.+)', url)
  if match:
    return match.group(1)
  return None


def roll_dep_impl(chromium_deps_parser, pdfium_deps_parser, deps_entry):
  if deps_entry in UNSUPPORTED_ENTRIES:
    return (False, f'Rolling {deps_entry} is not supported.')

  # In PDFium DEPS, only search vars for the entry.
  if deps_entry not in pdfium_deps_parser.vars:
    return (False, f'Entry "{deps_entry}" not found in PDFium DEPS.')

  pdfium_revision = pdfium_deps_parser.vars.get(deps_entry)
  deps_path = find_path_for_revision_in_deps(pdfium_deps_parser.deps,
                                             pdfium_revision)
  if not deps_path:
    return (False,
            f'Could not find path for var "{deps_entry}" in PDFium DEPS file.')

  # Check if the dependency is a CIPD package, which is not supported.
  pdfium_dep_value = pdfium_deps_parser.deps.get(deps_path)
  is_cipd = (
      isinstance(pdfium_dep_value, dict) and
      pdfium_dep_value.get('dep_type') == 'cipd')

  # In Chromium DEPS, search vars and deps.
  chromium_revision = None
  chromium_revision = chromium_deps_parser.vars.get(deps_entry)

  if not chromium_revision:
    # Not in vars, try deps.
    if deps_path:
      chromium_path = 'src/' + deps_path
      chromium_dep_value = chromium_deps_parser.deps.get(chromium_path)
      if chromium_dep_value:
        chromium_revision = get_revision_from_dep_value(chromium_dep_value)

  if not chromium_revision:
    if is_cipd:
      return (False, f'CIPD entry "{deps_entry}" not found in Chromium DEPS.')

    # If chromium_revision is still None, it means it wasn't found in Chromium
    # DEPS. In which case, suggest rolling to ToT.
    return (True, f'roll-dep {deps_path} --ignore-dirty-tree --no-log')

  if chromium_revision == pdfium_revision:
    return (True, 'Revisions are the same.')

  if is_cipd:
    return (True, f"CIPD {deps_entry}: {chromium_revision}")

  if deps_entry == 'freetype_revision':
    return (True, 'third_party/freetype/roll-freetype.sh --roll-to '
            f'{chromium_revision} --ignore-dirty-tree --no-log')

  return (True, f'roll-dep {deps_path} --roll-to {chromium_revision} '
          '--ignore-dirty-tree --no-log')


def roll_dep(chromium_deps_content, pdfium_deps_content, deps_entry):
  chromium_deps_parser = DepsParser(chromium_deps_content)
  pdfium_deps_parser = DepsParser(pdfium_deps_content)
  return roll_dep_impl(chromium_deps_parser, pdfium_deps_parser, deps_entry)


def roll_all_deps(chromium_deps_content, pdfium_deps_content):
  chromium_deps_parser = DepsParser(chromium_deps_content)
  pdfium_deps_parser = DepsParser(pdfium_deps_content)
  messages = []
  for deps_entry in ALL_DEPS_ENTRIES:
    success, message = roll_dep_impl(chromium_deps_parser, pdfium_deps_parser,
                                     deps_entry)
    if not success:
      return (False, message)

    if message == 'Revisions are the same.':
      continue

    messages.append(message)

  return (True, messages)


def main():
  parser = argparse.ArgumentParser()
  parser.add_argument('chromium_deps_file', help='Path to Chromium DEPS file')
  parser.add_argument('pdfium_deps_file', help='Path to the PDFium DEPS file')
  parser.add_argument('deps_entry', help='DEPS entry to roll, can be "ALL"')
  args = parser.parse_args()

  if os.path.abspath(args.chromium_deps_file) == os.path.abspath(
      args.pdfium_deps_file):
    print('DEPS files must be different.', file=sys.stderr)
    return 1

  with open(args.chromium_deps_file, 'r') as f:
    chromium_deps_content = f.read()
  with open(args.pdfium_deps_file, 'r') as f:
    pdfium_deps_content = f.read()

  if args.deps_entry == 'ALL':
    success, maybe_messages = roll_all_deps(chromium_deps_content,
                                            pdfium_deps_content)
    if not success:
      print(maybe_messages, file=sys.stderr)
      return 1

    for message in maybe_messages:
      print(message)
    return 0

  success, message = roll_dep(chromium_deps_content, pdfium_deps_content,
                              args.deps_entry)
  if not success:
    print(message, file=sys.stderr)
    return 1

  print(message)
  return 0


if __name__ == '__main__':
  main()
