Exemple #1
0
def get_fetcher_from_repository(package_name, package_root, python_settings):
    package_json = os.path.join(package_root, PACKAGE_JSON)

    with open(package_json, 'r') as fin:
        js = json.loads(fin.read())

    short_name = js.get('name').split('/')[-1]

    if 'repository' not in js:
        raise BuckitException(
            "The repository section is missing in {}", package_json)

    repository = js.get('repository')
    repo_type = repository.get("type", "")
    if 'pip_info' in repository:
        pip_info = repository.get('pip_info')
        dest_dir = os.path.join(
            package_root, pip_info.get("install_subdir", short_name)
        )
        return (
            PipFetcher(
                package_name,
                package_json,
                pip_info.get("pip2_package", ""),
                pip_info.get("pip2_version", ""),
                pip_info.get("pip3_package", ""),
                pip_info.get("pip3_version", ""),
                pip_info.get("main_rule", ""),
                pip_info.get("buck_deps", []),
                python_settings,
            ), dest_dir
        )
    elif repo_type == "git":
        dest_dir = os.path.join(package_root, short_name)
        return (
            GitFetcher(
                package_name,
                package_json,
                repository.get("url", ""),
                repository.get("commit", None),
                repository.get("tag", None),
            ), dest_dir
        )
    elif repo_type == "tarball":
        dest_dir = os.path.join(package_root, short_name)
        return (
            HttpTarballFetcher(
                package_name,
                package_json,
                repository.get("url", ""),
                repository.get("sha256", ""),
            ), dest_dir
        )
    else:
        raise BuckitException(
            "repository.type in {} must be either 'git', 'tarball', or 'pip'",
            package_json)
Exemple #2
0
    def __init__(
        self, package_name, json_file, pip2_package, pip2_version, pip3_package,
        pip3_version, main_rule, buck_deps, python_settings
    ):
        self.package_name = package_name
        self.main_rule = main_rule
        self.buck_deps = buck_deps
        self.python2 = None
        self.python3 = None
        if pip2_package and python_settings.use_python2:
            self.python2 = PipPythonSettings(
                python_settings.python2_virtualenv_command,
                python_settings.python2_virtualenv_root,
                pip2_package,
                pip2_version,
                'py2',
            )
        if pip3_package and python_settings.use_python3:
            self.python3 = PipPythonSettings(
                python_settings.python3_virtualenv_command,
                python_settings.python3_virtualenv_root,
                pip3_package,
                pip3_version,
                'py3',
            )
        self.python2_files = {"srcs": {}, "bins": {}}
        self.python3_files = {"srcs": {}, "bins": {}}

        if not main_rule:
            raise BuckitException(
                'A main_rule attribute must be set in {}', json_file)
Exemple #3
0
def parse_package_info(package_path):
    """
    Try to get the package info from the package.json inside of package_path

    Arguments:
        package_path - The path to the package root that contains package.json

    Returns:
        PackageInfo object with properties from the package.json
    """

    package_path = os.path.abspath(package_path)
    json_path = os.path.join(package_path, PACKAGE_JSON)
    try:
        with open(json_path, 'r') as fin:
            js = json.loads(fin.read())
            buckit = js.get('buckit', {})
            cell_name = buckit.get('cell_name', js['name'])
            includes = buckit.get('includes', None)
            if includes:
                includes_info = IncludesInfo(
                    includes.get('path', None),
                    includes.get('whitelist_functions', [])
                )
                if not isinstance(includes_info.path, str):
                    raise BuckitException(
                        "buckit.includes in {} should be a string", json_path)
                if not isinstance(includes_info.whitelist_functions, list):
                    raise BuckitException(
                        "buckit.whitelist_functions in {} should be a list",
                        json_path)
            else:
                includes_info = None

            return PackageInfo(
                js["name"],
                cell_name.split('/')[-1],
                'yarn|{}'.format(js["name"]), package_path, includes_info
            )
    except Exception as e:
        raise BuckitException(
            "Could not read property 'buckit.name' or 'name' from "
            "json file at {}: {}", json_path, e)
Exemple #4
0
    def __init__(self, package_name, json_file, url, commit, tag):
        if bool(commit) == bool(tag):
            raise BuckitException(
                "{}: Either the commit, or the tag must be specified",
                json_file)

        self.package_name = package_name
        self.url = url
        self.commit = commit
        self.tag = tag
Exemple #5
0
def find_project_root(start_path, node_modules=None):
    """
    Starting at start_path, going up, try to find the first directory with
    a package.json or .buckconfig, and call that the root of the project

    Args:
        start_path: The directory to start looking in
        node_modules: If provided, the name of the directory that yarn installs
                      packages to. This can be used if .buckconfig or
                      package.json do not exist yet
    Returns:
        The absolute path to the project root
    Raises:
        Exception: No parent project could be found
    """
    terminal = os.path.splitdrive(start_path)[0] or '/'
    path = os.path.abspath(start_path)
    while path != terminal:
        logging.debug("Checking %s for package.json or .buckconfig", path)

        package_json = os.path.join(path, PACKAGE_JSON)
        package_buckconfig = os.path.join(path, BUCKCONFIG)
        package_node_modules = None
        if node_modules:
            package_node_modules = os.path.join(path, node_modules)
        package_path = path
        path = os.path.split(path)[0]

        if os.path.exists(package_buckconfig):
            break
        elif os.path.exists(package_json):
            try:
                package_info = parse_package_info(package_path)
                logging.debug(
                    "Found project %s at %s", package_info.name, package_json
                )
                break
            except Exception:
                # If we couldn't parse it, it wasn't meant to be
                logging.debug("Could not parse json in %s", package_json)
                continue
        elif package_node_modules and os.path.exists(package_node_modules):
            logging.debug(
                "Found node modules directory at %s", package_node_modules)
            break
        else:
            continue
    else:
        raise BuckitException(
            "Could not find a .buckconfig or package.json above {}. Stopped "
            "at {}", start_path, path)

    logging.debug("{bold}Found project root at %s{clear}", package_path)
    return package_path
Exemple #6
0
    def install_and_get_files(self, python_settings, pip_command, env):
        # TODO: Windows
        activate_path = os.path.join(
            python_settings.virtualenv_root, 'bin', 'activate'
        )
        if (not os.path.exists(python_settings.virtualenv_root) or
                not os.path.exists(activate_path)):
            logging.info(
                "Virtualenv at %s does not exist, creating",
                python_settings.virtualenv_root
            )
            readable_check_call(
                python_settings.virtualenv_command +
                [python_settings.virtualenv_root],
                "installing python virtual env",
                env=env,
            )

        package = shlex.quote(
            python_settings.pip_package + (python_settings.pip_version or '')
        )
        command = (
            "source bin/activate && {pip} install -I {package} && "
            "{pip} show -f {package}"
        ).format(
            pip=pip_command, package=package
        )
        logging.info(
            "Installing %s via pip with %s in %s", package, command,
            python_settings.virtualenv_root
        )
        proc = subprocess.Popen(
            args=command,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            stdin=subprocess.PIPE,
            cwd=python_settings.virtualenv_root,
            shell=True,
            env=env,
        )
        stdout, stderr = proc.communicate()
        if proc.returncode != 0:
            logging.error(
                "{red}Error installing into virtualenv:{clear}\n"
                "stdout: %sstderr: %s\nReturn code %s\n", stdout, stderr,
                proc.returncode
            )
            raise BuckitException(
                "Could not install virtualenv at {}",
                python_settings.virtualenv_root)

        stdout = stdout.decode('utf-8')

        return self.parse_pip_output(python_settings, stdout)
Exemple #7
0
    def check_hash(self, filename):
        file_hash = hashlib.sha256()
        with open(filename, 'rb') as fin:
            while True:
                data = fin.read(self.HASH_BUFFER_SIZE)
                if not data:
                    break
                file_hash.update(data)

        if file_hash.hexdigest() != self.sha256:
            raise BuckitException(
                'SHA256 of downloaded file didn\'t match! Expected {}, got {}',
                self.sha256, file_hash.hexdigest())
Exemple #8
0
def find_package_paths(
    project_root,
    node_modules,
    package_name='',
    already_found=None
):
    """
    Find all the packages in a given project root, return information about
    each of those packages.

    Arguments:
        project_root - The root path of the main project
        node_modules - The name of the node_modules directory in project_root
        package_name - The name of the package underneath node_modules, or
                       empty if the root package.json should be examined
        already_found - A list of package names that have already been
                        investigated. Used for cycle detection

    Returns a tuple of (
        dictionary of package names to paths,
        set of all of root's direct dependencies,
        dictionary of package names to original parsed json
    )
    """
    already_found = already_found or []
    jsons = {}
    if package_name:
        # Look for cells that have compiled artifacts first
        package_root = os.path.join(project_root, node_modules, package_name)
        package_json = os.path.join(package_root, PACKAGE_JSON)
    else:
        package_json = os.path.join(project_root, PACKAGE_JSON)

    if os.path.exists(package_json):
        with open(package_json, 'r') as fin:
            js = json.loads(fin.read())
    elif package_name:
        logging.debug(
            "Could not find a json file at %s for package %s", package_json,
            package_name)
        return {}, set(), jsons
    else:
        js = {}

    paths = {}
    root_deps = set()

    # When a package is first added with yarn add, it will not be present
    # in package.json in the project root. It will, however, be mentioned in
    # environment variables. So, grab from there and make sure that we find
    # the package.json in node_modules if we haven't written to the file yet
    # If we are just running `buckit buckconfig`, though, make sure we still
    # look at all of the root dependencies. Also note that yarn run buckit X
    # will populate npm_package_name ,but with a blank string, so we do a
    # truthy check
    env_deps = {
        os.environ['npm_package_name']: os.environ.get('npm_package_version', '*')
    } if not package_name and os.environ.get('npm_package_name') else {}
    js_deps = js.get('dependencies', {}).copy()
    js_deps.update(env_deps)

    for dep in js_deps:
        if dep in already_found:
            raise BuckitException(
                'Found a cycle when finding dependencies: {}',
                ' -> '.join(already_found))
        already_found.append(dep)
        dep_paths, ignore, dep_jsons = find_package_paths(
            project_root, node_modules, dep, already_found
        )
        paths.update(dep_paths)
        jsons.update(dep_jsons)
        if not package_name:
            root_deps.add(dep)
        del already_found[-1]

    if package_name:
        paths[package_name] = package_root
        jsons[package_name] = js
    return paths, root_deps, jsons
Exemple #9
0
 def populate_cache(self, destination, use_proxy):
     raise BuckitException('Not implemented')