# Copyright 2013 The Flutter 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 python script uses `pub get --offline` to fill in
# .dart_tool/package_config.json files for Dart packages in the tree whose
# dependencies should be entirely resolved without requesting data from pub.dev.
# This allows us to be certain that the Dart code we are pulling for these
# packages is explicitly fetched by `gclient sync` rather than implicitly
# fetched by pub version solving, and pub fetching transitive dependencies.

import json
import os
import subprocess
import sys

ALL_PACKAGES = [
  os.path.join("src", "flutter", "ci"),
  os.path.join("src", "flutter", "flutter_frontend_server"),
  os.path.join("src", "flutter", "shell", "vmservice"),
  os.path.join("src", "flutter", "testing", "benchmark"),
  os.path.join("src", "flutter", "testing", "dart"),
  os.path.join("src", "flutter", "testing", "litetest"),
  os.path.join("src", "flutter", "testing", "android_background_image"),
  os.path.join("src", "flutter", "testing", "scenario_app"),
  os.path.join("src", "flutter", "testing", "smoke_test_failure"),
  os.path.join("src", "flutter", "testing", "symbols"),
  os.path.join("src", "flutter", "tools", "api_check"),
  os.path.join("src", "flutter", "tools", "android_lint"),
  os.path.join("src", "flutter", "tools", "clang_tidy"),
  os.path.join("src", "flutter", "tools", "const_finder"),
  os.path.join("src", "flutter", "tools", "githooks"),
  os.path.join("src", "flutter", "tools", "licenses"),
]


def FetchPackage(pub, package):
  try:
    subprocess.check_output(pub, cwd=package, stderr=subprocess.STDOUT)
  except subprocess.CalledProcessError as err:
    print("'%s' failed in '%s' with status %d:\n%s" %
          (' '.join(pub), package, err.returncode, err.output))
    return 1
  return 0


def CheckPackage(package):
  package_config = os.path.join(package, ".dart_tool", "package_config.json")
  pub_count = 0
  with open(package_config) as f:
    data_dict = json.load(f)
    packages_data = data_dict["packages"]
    for package_data in packages_data:
      package_uri = package_data["rootUri"]
      package_name = package_data["name"]
      if ".pub-cache" in package_uri and "pub.dartlang.org" in package_uri:
        print("Error: package '%s' was fetched from pub" % package_name)
        pub_count = pub_count + 1
  if pub_count > 0:
    print("Error: %d packages were fetched from pub for %s" % (pub_count, package))
    print("Please fix the pubspec.yaml for %s "
          "so that all dependencies are path dependencies" % package)
  return pub_count


def Main():
  leading = os.path.join("src", "third_party", "dart", "tools", "sdks", "dart-sdk", "bin")
  dart = "dart"
  if os.name == "nt":
    dart = "dart.exe"
  pubcmd = [os.path.abspath(os.path.join(leading, dart)), "pub", "get", "--offline"]

  pub_count = 0
  for package in ALL_PACKAGES:
    if FetchPackage(pubcmd, package) != 0:
      return 1
    pub_count = pub_count + CheckPackage(package)

  if pub_count > 0:
    return 1

  return 0


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