# Copyright 2018 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
r"""A script that compares 2 CToolchains from proto format.

This script accepts two files in either a CROSSTOOL proto text format or a
CToolchain proto text format. It then locates the CToolchains with the given
toolchain_identifier and checks if the resulting CToolchain objects in Java
are the same.

Example usage:

bazel run \
@rules_cc//tools/migration:ctoolchain_comparator -- \
--before=/path/to/CROSSTOOL1 \
--after=/path/to/CROSSTOOL2 \
--toolchain_identifier=id
"""

import os
from absl import app
from absl import flags
from google.protobuf import text_format
from third_party.com.github.bazelbuild.bazel.src.main.protobuf import crosstool_config_pb2
from tools.migration.ctoolchain_comparator_lib import compare_ctoolchains

flags.DEFINE_string(
    "before", None,
    ("A text proto file containing the relevant CTooclchain before the change, "
     "either a CROSSTOOL file or a single CToolchain proto text"))
flags.DEFINE_string(
    "after", None,
    ("A text proto file containing the relevant CToolchain after the change, "
     "either a CROSSTOOL file or a single CToolchain proto text"))
flags.DEFINE_string("toolchain_identifier", None,
                    "The identifier of the CToolchain that is being compared.")
flags.mark_flag_as_required("before")
flags.mark_flag_as_required("after")
flags.mark_flag_as_required("toolchain_identifier")


def _to_absolute_path(path):
  path = os.path.expanduser(path)
  if os.path.isabs(path):
    return path
  else:
    if "BUILD_WORKING_DIRECTORY" in os.environ:
      return os.path.join(os.environ["BUILD_WORKING_DIRECTORY"], path)
    else:
      return path


def _find_toolchain(crosstool, toolchain_identifier):
  for toolchain in crosstool.toolchain:
    if toolchain.toolchain_identifier == toolchain_identifier:
      return toolchain
  return None


def _read_crosstool_or_ctoolchain_proto(input_file, toolchain_identifier):
  """Reads a proto file and finds the CToolchain with the given identifier."""
  with open(input_file, "r") as f:
    text = f.read()
  crosstool_release = crosstool_config_pb2.CrosstoolRelease()
  c_toolchain = crosstool_config_pb2.CToolchain()
  try:
    text_format.Merge(text, crosstool_release)
    toolchain = _find_toolchain(crosstool_release, toolchain_identifier)
    if toolchain is None:
      print(("Cannot find a CToolchain with an identifier '%s' in CROSSTOOL "
             "file") % toolchain_identifier)
      return None
    return toolchain
  except text_format.ParseError as crosstool_error:
    try:
      text_format.Merge(text, c_toolchain)
      if c_toolchain.toolchain_identifier != toolchain_identifier:
        print(("Expected CToolchain with identifier '%s', got CToolchain with "
               "identifier '%s'" % (toolchain_identifier,
                                    c_toolchain.toolchain_identifier)))
        return None
      return c_toolchain
    except text_format.ParseError as toolchain_error:
      print(("Error parsing file '%s':" % input_file))  # pylint: disable=superfluous-parens
      print("Attempt to parse it as a CROSSTOOL proto:")  # pylint: disable=superfluous-parens
      print(crosstool_error)  # pylint: disable=superfluous-parens
      print("Attempt to parse it as a CToolchain proto:")  # pylint: disable=superfluous-parens
      print(toolchain_error)  # pylint: disable=superfluous-parens
      return None


def main(unused_argv):

  before_file = _to_absolute_path(flags.FLAGS.before)
  after_file = _to_absolute_path(flags.FLAGS.after)
  toolchain_identifier = flags.FLAGS.toolchain_identifier

  toolchain_before = _read_crosstool_or_ctoolchain_proto(
      before_file, toolchain_identifier)
  toolchain_after = _read_crosstool_or_ctoolchain_proto(after_file,
                                                        toolchain_identifier)

  if not toolchain_before or not toolchain_after:
    print("There was an error getting the required toolchains.")
    exit(1)

  found_difference = compare_ctoolchains(toolchain_before, toolchain_after)
  if found_difference:
    exit(1)


if __name__ == "__main__":
  app.run(main)
