Esempio n. 1
0
def test_git_clone_fails_for_non_existent_branch(source_url: str):
    branch = uuid.uuid4().hex

    with pytest.raises(PoetrySimpleConsoleException) as e:
        Git.clone(url=source_url, branch=branch)

    assert f"Failed to clone {source_url} at '{branch}'" in str(e.value)
Esempio n. 2
0
def test_git_clone_fails_for_non_existent_revision(source_url: str):
    revision = sha1(uuid.uuid4().bytes).hexdigest()

    with pytest.raises(PoetrySimpleConsoleException) as e:
        Git.clone(url=source_url, revision=revision)

    assert f"Failed to clone {source_url} at '{revision}'" in str(e.value)
Esempio n. 3
0
def test_git_local_info(source_url: str, remote_refs: FetchPackResult,
                        remote_default_ref: bytes) -> None:
    with Git.clone(url=source_url) as repo:
        info = Git.info(repo=repo)
        assert info.origin == source_url
        assert info.revision == remote_refs.refs[remote_default_ref].decode(
            "utf-8")
Esempio n. 4
0
def _get_package_from_git(
    url: str,
    branch: str | None = None,
    tag: str | None = None,
    rev: str | None = None,
    subdirectory: str | None = None,
    source_root: Path | None = None,
) -> Package:
    source = Git.clone(
        url=url,
        source_root=source_root,
        branch=branch,
        tag=tag,
        revision=rev,
        clean=False,
    )
    revision = Git.get_revision(source)

    path = Path(source.path)
    if subdirectory:
        path = path.joinpath(subdirectory)

    package = Provider.get_package_from_directory(path)
    package._source_type = "git"
    package._source_url = url
    package._source_reference = rev or tag or branch or "HEAD"
    package._source_resolved_reference = revision
    package._source_subdirectory = subdirectory

    return package
Esempio n. 5
0
    def load(cls, env):  # type: (Env) -> InstalledRepository
        """
        Load installed packages.

        For now, it uses the pip "freeze" command.
        """
        repo = cls()
        seen = set()

        for entry in env.sys_path:
            for distribution in sorted(
                    metadata.distributions(path=[entry]),
                    key=lambda d: str(d._path),
            ):
                name = distribution.metadata["name"]
                version = distribution.metadata["version"]
                package = Package(name, version, version)
                package.description = distribution.metadata.get("summary", "")

                if package.name in seen:
                    continue

                seen.add(package.name)

                repo.add_package(package)

                path = Path(str(distribution._path))
                is_standard_package = True
                try:
                    path.relative_to(env.site_packages)
                except ValueError:
                    is_standard_package = False

                if is_standard_package:
                    continue

                src_path = env.path / "src"

                # A VCS dependency should have been installed
                # in the src directory. If not, it's a path dependency
                try:
                    path.relative_to(src_path)

                    from poetry.vcs.git import Git

                    git = Git()
                    revision = git.rev_parse("HEAD",
                                             src_path / package.name).strip()
                    url = git.remote_url(src_path / package.name)

                    package.source_type = "git"
                    package.source_url = url
                    package.source_reference = revision
                except ValueError:
                    package.source_type = "directory"
                    package.source_url = str(path.parent)

        return repo
Esempio n. 6
0
    def _install_git(self, operation: Install | Update) -> int:
        from poetry.vcs.git import Git

        package = operation.package
        operation_message = self.get_operation_message(operation)

        message = (
            f"  <fg=blue;options=bold>•</> {operation_message}: <info>Cloning...</info>"
        )
        self._write(operation, message)

        source = Git.clone(
            url=package.source_url,
            source_root=self._env.path / "src",
            revision=package.source_resolved_reference
            or package.source_reference,
        )

        # Now we just need to install from the source directory
        original_url = package.source_url
        package._source_url = str(source.path)

        status_code = self._install_directory(operation)

        package._source_url = original_url

        return status_code
Esempio n. 7
0
def test_git_clone_clones_submodules(source_url: str) -> None:
    with Git.clone(url=source_url) as repo:
        submodule_package_directory = (Path(repo.path) / "submodules" /
                                       "sample-namespace-packages")

    assert submodule_package_directory.exists()
    assert submodule_package_directory.joinpath("README.md").exists()
    assert len(list(submodule_package_directory.glob("*"))) > 1
Esempio n. 8
0
    def get_package_from_vcs(
        cls,
        vcs,
        url,
        reference=None,
        name=None
    ):  # type: (str, str, Optional[str], Optional[str]) -> Package
        if vcs != "git":
            raise ValueError("Unsupported VCS dependency {}".format(vcs))

        tmp_dir = Path(
            mkdtemp(prefix="pypoetry-git-{}".format(
                url.split("/")[-1].rstrip(".git"))))

        try:
            git = Git()
            git.clone(url, tmp_dir)
            if reference is not None:
                git.checkout(reference, tmp_dir)
            else:
                reference = "HEAD"

            revision = git.rev_parse(reference, tmp_dir).strip()

            package = cls.get_package_from_directory(tmp_dir, name=name)

            package.source_type = "git"
            package.source_url = url
            package.source_reference = revision
        except Exception:
            raise
        finally:
            safe_rmtree(str(tmp_dir))

        return package
Esempio n. 9
0
def assert_version(repo: Repo, expected_revision: str) -> None:
    version = PyProjectTOML(path=Path(repo.path).joinpath(
        "pyproject.toml")).poetry_config["version"]

    revision = Git.get_revision(repo=repo)

    assert revision == expected_revision
    assert revision in REVISION_TO_VERSION_MAP
    assert version == REVISION_TO_VERSION_MAP[revision]
Esempio n. 10
0
def test_git_clone_default_branch_head(
    source_url: str,
    remote_refs: FetchPackResult,
    remote_default_ref: bytes,
    mocker: MockerFixture,
):
    spy = mocker.spy(Git, "_clone")
    spy_legacy = mocker.spy(Git, "_clone_legacy")

    with Git.clone(url=source_url) as repo:
        assert remote_refs.refs[remote_default_ref] == repo.head()

    spy_legacy.assert_not_called()
    spy.assert_called()
Esempio n. 11
0
def test_username_password_parameter_is_not_passed_to_dulwich(
        mocker: MockerFixture, source_url: str, config: Config) -> None:
    from poetry.vcs.git import backend

    spy_clone = mocker.spy(Git, "_clone")
    spy_get_transport_and_path = mocker.spy(backend, "get_transport_and_path")

    with Git.clone(url=source_url, branch="0.1") as repo:
        assert_version(repo, BRANCH_TO_REVISION_MAP["0.1"])

    spy_clone.assert_called_once()

    spy_get_transport_and_path.assert_called_with(location=source_url, )
    spy_get_transport_and_path.assert_called_once()
Esempio n. 12
0
def test_system_git_fallback_on_http_401(
    mocker: MockerFixture,
    source_url: str,
) -> None:
    spy = mocker.spy(Git, "_clone_legacy")
    mocker.patch.object(Git, "_clone", side_effect=HTTPUnauthorized(None, None))

    with Git.clone(url=source_url, branch="0.1") as repo:
        path = Path(repo.path)
        assert_version(repo, BRANCH_TO_REVISION_MAP["0.1"])

    spy.assert_called_with(
        url="https://github.com/python-poetry/test-fixture-vcs-repository.git",
        target=path,
        refspec=GitRefSpec(branch="0.1", revision=None, tag=None, ref=b"HEAD"),
    )
    spy.assert_called_once()
Esempio n. 13
0
def test_system_git_called_when_configured(
        mocker: MockerFixture, source_url: str,
        use_system_git_client: None) -> None:
    spy_legacy = mocker.spy(Git, "_clone_legacy")
    spy = mocker.spy(Git, "_clone")

    with Git.clone(url=source_url, branch="0.1") as repo:
        path = Path(repo.path)
        assert_version(repo, BRANCH_TO_REVISION_MAP["0.1"])

    spy.assert_not_called()

    spy_legacy.assert_called_once()
    spy_legacy.assert_called_with(
        url=source_url,
        target=path,
        refspec=GitRefSpec(branch="0.1", revision=None, tag=None, ref=b"HEAD"),
    )
Esempio n. 14
0
def test_configured_repository_http_auth(
    mocker: MockerFixture, source_url: str, config: Config
) -> None:
    from poetry.vcs.git import backend

    spy_clone_legacy = mocker.spy(Git, "_clone_legacy")
    spy_get_transport_and_path = mocker.spy(backend, "get_transport_and_path")

    config.merge(
        {
            "repositories": {"git-repo": {"url": source_url}},
            "http-basic": {
                "git-repo": {
                    "username": GIT_USERNAME,
                    "password": GIT_PASSWORD,
                }
            },
        }
    )

    dummy_git_config = ConfigFile()
    mocker.patch(
        "poetry.vcs.git.backend.Repo.get_config_stack",
        return_value=dummy_git_config,
    )

    mocker.patch(
        "poetry.vcs.git.backend.get_default_authenticator",
        return_value=Authenticator(config=config),
    )

    with Git.clone(url=source_url, branch="0.1") as repo:
        assert_version(repo, BRANCH_TO_REVISION_MAP["0.1"])

    spy_clone_legacy.assert_not_called()

    spy_get_transport_and_path.assert_called_with(
        location=source_url,
        config=dummy_git_config,
        username=GIT_USERNAME,
        password=GIT_PASSWORD,
    )
    spy_get_transport_and_path.assert_called_once()
Esempio n. 15
0
    def install_git(self, package: Package) -> None:
        from poetry.core.packages.package import Package

        from poetry.vcs.git import Git

        source = Git.clone(
            url=package.source_url,
            source_root=self._env.path / "src",
            revision=package.source_resolved_reference
            or package.source_reference,
        )

        # Now we just need to install from the source directory
        pkg = Package(package.name, package.version)
        pkg._source_type = "directory"
        pkg._source_url = str(source.path)
        pkg.develop = package.develop

        self.install_directory(pkg)
Esempio n. 16
0
    def search_for_vcs(self,
                       dependency):  # type: (VCSDependency) -> List[Package]
        """
        Search for the specifications that match the given VCS dependency.

        Basically, we clone the repository in a temporary directory
        and get the information we need by checking out the specified reference.
        """
        if dependency.vcs != "git":
            raise ValueError("Unsupported VCS dependency {}".format(
                dependency.vcs))

        tmp_dir = Path(
            mkdtemp(prefix="pypoetry-git-{}".format(dependency.name)))

        try:
            git = Git()
            git.clone(dependency.source, tmp_dir)
            git.checkout(dependency.reference, tmp_dir)
            revision = git.rev_parse(dependency.reference, tmp_dir).strip()

            if dependency.tag or dependency.rev:
                revision = dependency.reference

            directory_dependency = DirectoryDependency(
                dependency.name,
                tmp_dir,
                category=dependency.category,
                optional=dependency.is_optional(),
            )
            for extra in dependency.extras:
                directory_dependency.extras.append(extra)

            package = self.search_for_directory(directory_dependency)[0]

            package.source_type = "git"
            package.source_url = dependency.source
            package.source_reference = revision
        except Exception:
            raise
        finally:
            safe_rmtree(str(tmp_dir))

        return [package]
Esempio n. 17
0
    def __init__(self,
                 project,
                 version='0.1.0',
                 readme_format='md',
                 author=None):
        self._project = project
        self._package_name = module_name(project)
        self._version = version
        self._readme_format = readme_format
        self._dependencies = {}
        self._dev_dependencies = {}
        self._include = []

        self._git = Git()
        git_config = self._git.config
        if not author:
            if (git_config.get('user.name') and git_config.get('user.email')):
                author = u'{} <{}>'.format(git_config['user.name'],
                                           git_config['user.email'])
            else:
                author = 'Your Name <*****@*****.**>'

        self._author = author
Esempio n. 18
0
    def solve(self, use_latest=None):  # type: (...) -> List[Operation]
        with self._provider.progress():
            start = time.time()
            packages, depths = self._solve(use_latest=use_latest)
            end = time.time()

            if len(self._branches) > 1:
                self._provider.debug(
                    "Complete version solving took {:.3f} seconds for {} branches"
                    .format(end - start, len(self._branches[1:])))
                self._provider.debug("Resolved for branches: {}".format(
                    ", ".join("({})".format(b) for b in self._branches[1:])))

        operations = []
        for package in packages:
            installed = False
            for pkg in self._installed.packages:
                if package.name == pkg.name:
                    installed = True

                    if pkg.source_type == "git" and package.source_type == "git":
                        from poetry.vcs.git import Git

                        # Trying to find the currently installed version
                        pkg_source_url = Git.normalize_url(pkg.source_url)
                        package_source_url = Git.normalize_url(
                            package.source_url)
                        for locked in self._locked.packages:
                            locked_source_url = Git.normalize_url(
                                locked.source_url)
                            if (locked.name == pkg.name
                                    and locked.source_type == pkg.source_type
                                    and locked_source_url == pkg_source_url
                                    and locked.source_reference
                                    == pkg.source_reference):
                                pkg = Package(pkg.name, locked.version)
                                pkg.source_type = "git"
                                pkg.source_url = locked.source_url
                                pkg.source_reference = locked.source_reference
                                break

                        if pkg_source_url != package_source_url or (
                                pkg.source_reference !=
                                package.source_reference
                                and not pkg.source_reference.startswith(
                                    package.source_reference)):
                            operations.append(Update(pkg, package))
                        else:
                            operations.append(
                                Install(package).skip("Already installed"))
                    elif package.version != pkg.version:
                        # Checking version
                        operations.append(Update(pkg, package))
                    elif package.source_type != pkg.source_type:
                        operations.append(Update(pkg, package))
                    else:
                        operations.append(
                            Install(package).skip("Already installed"))

                    break

            if not installed:
                operations.append(Install(package))

        # Checking for removals
        for pkg in self._locked.packages:
            remove = True
            for package in packages:
                if pkg.name == package.name:
                    remove = False
                    break

            if remove:
                skip = True
                for installed in self._installed.packages:
                    if installed.name == pkg.name:
                        skip = False
                        break

                op = Uninstall(pkg)
                if skip:
                    op.skip("Not currently installed")

                operations.append(op)

        return sorted(
            operations,
            key=lambda o: (
                o.job_type == "uninstall",
                # Packages to be uninstalled have no depth so we default to 0
                # since it actually doesn't matter since removals are always on top.
                -depths[packages.index(o.package)]
                if o.job_type != "uninstall" else 0,
                o.package.name,
                o.package.version,
            ),
        )
Esempio n. 19
0
    def search_for_vcs(self, dependency):  # type: (VCSDependency) -> List[Package]
        """
        Search for the specifications that match the given VCS dependency.

        Basically, we clone the repository in a temporary directory
        and get the information we need by checking out the specified reference.
        """
        if dependency.vcs != "git":
            raise ValueError("Unsupported VCS dependency {}".format(dependency.vcs))

        tmp_dir = Path(mkdtemp(prefix="pypoetry-git-{}".format(dependency.name)))

        try:
            git = Git()
            git.clone(dependency.source, tmp_dir)
            git.checkout(dependency.reference, tmp_dir)
            revision = git.rev_parse(dependency.reference, tmp_dir).strip()

            if dependency.tag or dependency.rev:
                revision = dependency.reference

            pyproject = TomlFile(tmp_dir / "pyproject.toml")
            pyproject_content = None
            has_poetry = False
            if pyproject.exists():
                pyproject_content = pyproject.read()
                has_poetry = (
                    "tool" in pyproject_content
                    and "poetry" in pyproject_content["tool"]
                )

            if pyproject_content and has_poetry:
                # If a pyproject.toml file exists
                # We use it to get the information we need
                info = pyproject_content["tool"]["poetry"]

                name = info["name"]
                version = info["version"]
                package = Package(name, version, version)
                package.source_type = dependency.vcs
                package.source_url = dependency.source
                package.source_reference = dependency.reference
                for req_name, req_constraint in info["dependencies"].items():
                    if req_name == "python":
                        package.python_versions = req_constraint
                        continue

                    package.add_dependency(req_name, req_constraint)
            else:
                # We need to use setup.py here
                # to figure the information we need
                # We need to place ourselves in the proper
                # folder for it to work
                venv = Venv.create(self._io)

                current_dir = os.getcwd()
                os.chdir(tmp_dir.as_posix())

                try:
                    venv.run("python", "setup.py", "egg_info")

                    # Sometimes pathlib will fail on recursive
                    # symbolic links, so we need to workaround it
                    # and use the glob module instead.
                    # Note that this does not happen with pathlib2
                    # so it's safe to use it for Python < 3.4.
                    if PY35:
                        egg_info = next(
                            Path(p)
                            for p in glob.glob(
                                os.path.join(str(tmp_dir), "**", "*.egg-info"),
                                recursive=True,
                            )
                        )
                    else:
                        egg_info = next(tmp_dir.glob("**/*.egg-info"))

                    meta = pkginfo.UnpackedSDist(str(egg_info))

                    if meta.requires_dist:
                        reqs = list(meta.requires_dist)
                    else:
                        reqs = []
                        requires = egg_info / "requires.txt"
                        if requires.exists():
                            with requires.open() as f:
                                reqs = parse_requires(f.read())

                    package = Package(meta.name, meta.version)

                    for req in reqs:
                        dep = dependency_from_pep_508(req)
                        if dep.in_extras:
                            for extra in dep.in_extras:
                                if extra not in package.extras:
                                    package.extras[extra] = []

                                package.extras[extra].append(dep)

                        package.requires.append(dep)
                except Exception:
                    raise
                finally:
                    os.chdir(current_dir)

            package.source_type = "git"
            package.source_url = dependency.source
            package.source_reference = revision
        except Exception:
            raise
        finally:
            shutil.rmtree(tmp_dir.as_posix())

        if dependency.name != package.name:
            # For now, the dependency's name must match the actual package's name
            raise RuntimeError(
                "The dependency name for {} does not match the actual package's name: {}".format(
                    dependency.name, package.name
                )
            )

        if dependency.extras:
            for extra in dependency.extras:
                if extra in package.extras:
                    for dep in package.extras[extra]:
                        dep.activate()

        return [package]
Esempio n. 20
0
    def _parse_requirements(
            self, requirements):  # type: (List[str]) -> List[Dict[str, str]]
        from poetry.puzzle.provider import Provider

        result = []

        try:
            cwd = self.poetry.file.parent
        except RuntimeError:
            cwd = Path.cwd()

        for requirement in requirements:
            requirement = requirement.strip()
            extras = []
            extras_m = re.search(r"\[([\w\d,-_]+)\]$", requirement)
            if extras_m:
                extras = [e.strip() for e in extras_m.group(1).split(",")]
                requirement, _ = requirement.split("[")

            url_parsed = urlparse.urlparse(requirement)
            if url_parsed.scheme and url_parsed.netloc:
                # Url
                if url_parsed.scheme in ["git+https", "git+ssh"]:
                    from poetry.vcs.git import Git
                    from poetry.vcs.git import ParsedUrl

                    parsed = ParsedUrl.parse(requirement)
                    url = Git.normalize_url(requirement)

                    pair = OrderedDict([("name", parsed.name),
                                        ("git", url.url)])
                    if parsed.rev:
                        pair["rev"] = url.revision

                    if extras:
                        pair["extras"] = extras

                    package = Provider.get_package_from_vcs(
                        "git", url.url, reference=pair.get("rev"))
                    pair["name"] = package.name
                    result.append(pair)

                    continue
                elif url_parsed.scheme in ["http", "https"]:
                    package = Provider.get_package_from_url(requirement)

                    pair = OrderedDict([("name", package.name),
                                        ("url", package.source_url)])
                    if extras:
                        pair["extras"] = extras

                    result.append(pair)
                    continue
            elif (os.path.sep in requirement or "/"
                  in requirement) and cwd.joinpath(requirement).exists():
                path = cwd.joinpath(requirement)
                if path.is_file():
                    package = Provider.get_package_from_file(path.resolve())
                else:
                    package = Provider.get_package_from_directory(path)

                result.append(
                    OrderedDict([
                        ("name", package.name),
                        ("path", path.relative_to(cwd).as_posix()),
                    ] + ([("extras", extras)] if extras else [])))

                continue

            pair = re.sub("^([^@=: ]+)(?:@|==|(?<![<>~!])=|:| )(.*)$",
                          "\\1 \\2", requirement)
            pair = pair.strip()

            require = OrderedDict()
            if " " in pair:
                name, version = pair.split(" ", 2)
                extras_m = re.search(r"\[([\w\d,-_]+)\]$", name)
                if extras_m:
                    extras = [e.strip() for e in extras_m.group(1).split(",")]
                    name, _ = name.split("[")

                require["name"] = name
                if version != "latest":
                    require["version"] = version
            else:
                m = re.match(r"^([^><=!: ]+)((?:>=|<=|>|<|!=|~=|~|\^).*)$",
                             requirement.strip())
                if m:
                    name, constraint = m.group(1), m.group(2)
                    extras_m = re.search(r"\[([\w\d,-_]+)\]$", name)
                    if extras_m:
                        extras = [
                            e.strip() for e in extras_m.group(1).split(",")
                        ]
                        name, _ = name.split("[")

                    require["name"] = name
                    require["version"] = constraint
                else:
                    extras_m = re.search(r"\[([\w\d,-_]+)\]$", pair)
                    if extras_m:
                        extras = [
                            e.strip() for e in extras_m.group(1).split(",")
                        ]
                        pair, _ = pair.split("[")

                    require["name"] = pair

            if extras:
                require["extras"] = extras

            result.append(require)

        return result
Esempio n. 21
0
def source_directory_name(source_url: str) -> str:
    return Git.get_name_from_source_url(url=source_url)
Esempio n. 22
0
    def search_for_vcs(self, dependency: VCSDependency) -> List[Package]:
        """
        Search for the specifications that match the given VCS dependency.

        Basically, we clone the repository in a temporary directory
        and get the information we need by checking out the specified reference.
        """
        if dependency.vcs != 'git':
            raise ValueError(f'Unsupported VCS dependency {dependency.vcs}')

        tmp_dir = Path(mkdtemp(prefix=f'pypoetry-git-{dependency.name}'))

        try:
            git = Git()
            git.clone(dependency.source, tmp_dir)
            git.checkout(dependency.reference, tmp_dir)
            revision = git.rev_parse(dependency.reference, tmp_dir).strip()

            if dependency.tag or dependency.rev:
                revision = dependency.reference

            poetry = TomlFile(tmp_dir / 'pyproject.toml')
            if poetry.exists():
                # If a pyproject.toml file exists
                # We use it to get the information we need
                info = poetry.read()

                name = info['package']['name']
                version = info['package']['version']
                package = Package(name, version, version)
                for req_name, req_constraint in info['dependencies'].items():
                    package.add_dependency(req_name, req_constraint)
            else:
                # We need to use setup.py here
                # to figure the information we need
                # We need to place ourselves in the proper
                # folder for it to work
                current_dir = os.getcwd()
                os.chdir(tmp_dir.as_posix())

                try:
                    venv = Venv.create()
                    output = venv.run('python', 'setup.py', '--name',
                                      '--version')
                    output = output.split('\n')
                    name = output[-3]
                    version = output[-2]
                    package = Package(name, version, version)
                    # Figure out a way to get requirements
                except Exception:
                    raise
                finally:
                    os.chdir(current_dir)

            package.source_type = 'git'
            package.source_url = dependency.source
            package.source_reference = revision
        except Exception:
            raise
        finally:
            shutil.rmtree(tmp_dir.as_posix())

        return [package]
Esempio n. 23
0
    def search_for_vcs(self,
                       dependency):  # type: (VCSDependency) -> List[Package]
        """
        Search for the specifications that match the given VCS dependency.

        Basically, we clone the repository in a temporary directory
        and get the information we need by checking out the specified reference.
        """
        if dependency.vcs != 'git':
            raise ValueError('Unsupported VCS dependency {}'.format(
                dependency.vcs))

        tmp_dir = Path(
            mkdtemp(prefix='pypoetry-git-{}'.format(dependency.name)))

        try:
            git = Git()
            git.clone(dependency.source, tmp_dir)
            git.checkout(dependency.reference, tmp_dir)
            revision = git.rev_parse(dependency.reference, tmp_dir).strip()

            if dependency.tag or dependency.rev:
                revision = dependency.reference

            pyproject = TomlFile(tmp_dir / 'pyproject.toml')
            pyproject_content = None
            has_poetry = False
            if pyproject.exists():
                pyproject_content = pyproject.read(True)
                has_poetry = ('tool' in pyproject_content
                              and 'poetry' in pyproject_content['tool'])

            if pyproject_content and has_poetry:
                # If a pyproject.toml file exists
                # We use it to get the information we need
                info = pyproject_content['tool']['poetry']

                name = info['name']
                version = info['version']
                package = Package(name, version, version)
                package.source_type = dependency.vcs
                package.source_url = dependency.source
                package.source_reference = dependency.reference
                for req_name, req_constraint in info['dependencies'].items():
                    if req_name == 'python':
                        package.python_versions = req_constraint
                        continue

                    package.add_dependency(req_name, req_constraint)
            else:
                # We need to use setup.py here
                # to figure the information we need
                # We need to place ourselves in the proper
                # folder for it to work
                venv = Venv.create(self._io)

                current_dir = os.getcwd()
                os.chdir(tmp_dir.as_posix())

                try:
                    venv.run('python', 'setup.py', 'egg_info')

                    egg_info = list(tmp_dir.glob('*.egg-info'))[0]

                    meta = pkginfo.UnpackedSDist(str(egg_info))

                    if meta.requires_dist:
                        reqs = list(meta.requires_dist)
                    else:
                        reqs = []
                        requires = egg_info / 'requires.txt'
                        if requires.exists():
                            with requires.open() as f:
                                reqs = parse_requires(f.read())

                    package = Package(meta.name, meta.version)

                    for req in reqs:
                        package.requires.append(dependency_from_pep_508(req))
                except Exception:
                    raise
                finally:
                    os.chdir(current_dir)

            package.source_type = 'git'
            package.source_url = dependency.source
            package.source_reference = revision
        except Exception:
            raise
        finally:
            shutil.rmtree(tmp_dir.as_posix())

        return [package]
Esempio n. 24
0
def test_git_clone_revision_is_tag(source_url: str,
                                   remote_refs: FetchPackResult, revision: str,
                                   expected_revision: str) -> None:
    with Git.clone(url=source_url, revision=revision) as repo:
        assert_version(repo, expected_revision)
Esempio n. 25
0
def test_git_clone_revision_is_ref(source_url: str,
                                   remote_refs: FetchPackResult) -> None:
    with Git.clone(url=source_url, revision="refs/heads/0.1") as repo:
        assert_version(repo, BRANCH_TO_REVISION_MAP["0.1"])
Esempio n. 26
0
def test_git_clone_multiple_times(source_url: str,
                                  remote_refs: FetchPackResult) -> None:
    for revision in REVISION_TO_VERSION_MAP:
        with Git.clone(url=source_url, revision=revision) as repo:
            assert_version(repo, revision)
Esempio n. 27
0
def test_git_clone_tag(source_url: str, remote_refs: FetchPackResult,
                       tag: str) -> None:
    with Git.clone(url=source_url, tag=tag) as repo:
        assert_version(repo, TAG_TO_REVISION_MAP[tag])
Esempio n. 28
0
def test_normalize_url(url, normalized):
    assert normalized == Git.normalize_url(url)
Esempio n. 29
0
def test_git_clone_when_branch_is_ref(source_url: str) -> None:
    with Git.clone(url=source_url, branch="refs/heads/0.1") as repo:
        assert_version(repo, BRANCH_TO_REVISION_MAP["0.1"])
Esempio n. 30
0
    def search_for_vcs(self,
                       dependency):  # type: (VCSDependency) -> List[Package]
        """
        Search for the specifications that match the given VCS dependency.

        Basically, we clone the repository in a temporary directory
        and get the information we need by checking out the specified reference.
        """
        if dependency.vcs != "git":
            raise ValueError("Unsupported VCS dependency {}".format(
                dependency.vcs))

        tmp_dir = Path(
            mkdtemp(prefix="pypoetry-git-{}".format(dependency.name)))

        try:
            git = Git()
            git.clone(dependency.source, tmp_dir)
            git.checkout(dependency.reference, tmp_dir)
            revision = git.rev_parse(dependency.reference, tmp_dir).strip()

            if dependency.tag or dependency.rev:
                revision = dependency.reference

            pyproject = TomlFile(tmp_dir / "pyproject.toml")
            pyproject_content = None
            has_poetry = False
            if pyproject.exists():
                pyproject_content = pyproject.read()
                has_poetry = ("tool" in pyproject_content
                              and "poetry" in pyproject_content["tool"])

            if pyproject_content and has_poetry:
                # If a pyproject.toml file exists
                # We use it to get the information we need
                info = pyproject_content["tool"]["poetry"]

                name = info["name"]
                version = info["version"]
                package = Package(name, version, version)
                package.source_type = dependency.vcs
                package.source_url = dependency.source
                package.source_reference = dependency.reference
                for req_name, req_constraint in info["dependencies"].items():
                    if req_name == "python":
                        package.python_versions = req_constraint
                        continue

                    package.add_dependency(req_name, req_constraint)
            else:
                # We need to use setup.py here
                # to figure the information we need
                # We need to place ourselves in the proper
                # folder for it to work
                venv = Venv.create(self._io)

                current_dir = os.getcwd()
                os.chdir(tmp_dir.as_posix())

                try:
                    venv.run("python", "setup.py", "egg_info")

                    # Sometimes pathlib will fail on recursive
                    # symbolic links, so we need to workaround it
                    # and use the glob module instead.
                    # Note that this does not happen with pathlib2
                    # so it's safe to use it for Python < 3.4.
                    if PY35:
                        egg_info = next(
                            Path(p) for p in glob.glob(
                                os.path.join(str(tmp_dir), "**", "*.egg-info"),
                                recursive=True,
                            ))
                    else:
                        egg_info = next(tmp_dir.glob("**/*.egg-info"))

                    meta = pkginfo.UnpackedSDist(str(egg_info))

                    if meta.requires_dist:
                        reqs = list(meta.requires_dist)
                    else:
                        reqs = []
                        requires = egg_info / "requires.txt"
                        if requires.exists():
                            with requires.open() as f:
                                reqs = parse_requires(f.read())

                    package = Package(meta.name, meta.version)

                    for req in reqs:
                        dep = dependency_from_pep_508(req)
                        if dep.in_extras:
                            for extra in dep.in_extras:
                                if extra not in package.extras:
                                    package.extras[extra] = []

                                package.extras[extra].append(dep)

                        package.requires.append(dep)
                except Exception:
                    raise
                finally:
                    os.chdir(current_dir)

            package.source_type = "git"
            package.source_url = dependency.source
            package.source_reference = revision
        except Exception:
            raise
        finally:
            shutil.rmtree(tmp_dir.as_posix())

        if dependency.name != package.name:
            # For now, the dependency's name must match the actual package's name
            raise RuntimeError(
                "The dependency name for {} does not match the actual package's name: {}"
                .format(dependency.name, package.name))

        if dependency.extras:
            for extra in dependency.extras:
                if extra in package.extras:
                    for dep in package.extras[extra]:
                        dep.activate()

        return [package]
Esempio n. 31
0
def test_git_clone_branch(source_url: str, remote_refs: FetchPackResult,
                          branch: str) -> None:
    with Git.clone(url=source_url, branch=branch) as repo:
        assert_version(repo, BRANCH_TO_REVISION_MAP[branch])