Пример #1
0
    def get_package_vcs_properties_from_path(cls, src: Path) -> tuple[str, str, str]:
        from poetry.core.vcs.git import Git

        git = Git()
        revision = git.rev_parse("HEAD", src).strip()
        url = git.remote_url(src)

        return "git", url, revision
Пример #2
0
    def set_package_vcs_properties_from_path(cls, src: Path,
                                             package: Package) -> None:
        from poetry.core.vcs.git import Git

        git = Git()
        revision = git.rev_parse("HEAD", src).strip()
        url = git.remote_url(src)

        package._source_type = "git"
        package._source_url = url
        package._source_reference = revision
Пример #3
0
def _parse_dependency_specification_git_url(requirement: str,
                                            env: Env | None = None
                                            ) -> DependencySpec | None:
    from poetry.core.vcs.git import Git
    from poetry.core.vcs.git import ParsedUrl

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

    pair = {"name": parsed.name, "git": url.url}

    if parsed.rev:
        pair["rev"] = url.revision

    if parsed.subdirectory:
        pair["subdirectory"] = parsed.subdirectory

    source_root = env.path.joinpath("src") if env else None
    package = Provider.get_package_from_vcs(
        "git",
        url=url.url,
        rev=pair.get("rev"),
        subdirectory=parsed.subdirectory,
        source_root=source_root,
    )
    pair["name"] = package.name
    return pair
Пример #4
0
    def get_package_from_vcs(
        cls, vcs, url, branch=None, tag=None, rev=None, name=None
    ):  # type: (str, str, Optional[str], Optional[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)
            reference = branch or tag or rev
            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 = reference
            package._source_resolved_reference = revision
        except Exception:
            raise
        finally:
            safe_rmtree(str(tmp_dir))

        return package
Пример #5
0
def test_ensure_existing_git_executable_is_found(mocker):
    mock = mocker.patch.object(subprocess, "check_output", return_value=b"")

    Git().run("config")

    cmd = Path(mock.call_args_list[-1][0][0][0])

    assert cmd.is_absolute()
    assert cmd.name == "git.exe"
Пример #6
0
    def install_git(self, package: Package) -> None:
        from poetry.core.packages.package import Package
        from poetry.core.vcs.git import Git

        src_dir = self._env.path / "src" / package.name
        if src_dir.exists():
            safe_rmtree(str(src_dir))

        src_dir.parent.mkdir(exist_ok=True)

        git = Git()
        git.clone(package.source_url, src_dir)

        reference = package.source_resolved_reference
        if not reference:
            reference = package.source_reference

        git.checkout(reference, src_dir)

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

        self.install_directory(pkg)
Пример #7
0
def test_ensure_absolute_path_to_git(mocker):
    _reset_executable()

    def checkout_output(cmd, *args, **kwargs):
        if Path(cmd[0]).name == "where.exe":
            return "\n".join(
                [str(Path.cwd().joinpath("git.exe")), "C:\\Git\\cmd\\git.exe"])

        return b""

    mock = mocker.patch.object(subprocess,
                               "check_output",
                               side_effect=checkout_output)

    Git().run("config")

    assert mock.call_args_list[-1][0][0] == [
        "C:\\Git\\cmd\\git.exe",
        "config",
    ]
Пример #8
0
def get_vcs(directory: Path) -> Git | None:
    working_dir = Path.cwd()
    os.chdir(str(directory.resolve()))

    vcs: Git | None

    try:
        from poetry.core.vcs.git import executable

        git_dir = (subprocess.check_output(
            [executable(), "rev-parse", "--show-toplevel"],
            stderr=subprocess.STDOUT).decode().strip())

        vcs = Git(Path(git_dir))

    except (subprocess.CalledProcessError, OSError, RuntimeError):
        vcs = None
    finally:
        os.chdir(str(working_dir))

    return vcs
Пример #9
0
    def get_package_from_vcs(
        cls,
        vcs: str,
        url: str,
        branch: Optional[str] = None,
        tag: Optional[str] = None,
        rev: Optional[str] = None,
        name: Optional[str] = None,
    ) -> "Package":
        if vcs != "git":
            raise ValueError(f"Unsupported VCS dependency {vcs}")

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

        try:
            git = Git()
            git.clone(url, tmp_dir)
            reference = branch or tag or rev
            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 = reference
            package._source_resolved_reference = revision
        except Exception:
            raise
        finally:
            safe_rmtree(str(tmp_dir))

        return package
Пример #10
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._overrides) > 1:
                self._provider.debug(
                    "Complete version solving took {:.3f} seconds with {} overrides"
                    .format(end - start, len(self._overrides)))
                self._provider.debug("Resolved with overrides: {}".format(
                    ", ".join("({})".format(b) for b in self._overrides)))

        operations = []
        for i, package in enumerate(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.core.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:
                            if locked.name != pkg.name or locked.source_type != "git":
                                continue

                            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, priority=depths[i]))
                        else:
                            operations.append(
                                Install(package).skip("Already installed"))
                    elif package.version != pkg.version:
                        # Checking version
                        operations.append(
                            Update(pkg, package, priority=depths[i]))
                    elif pkg.source_type and package.source_type != pkg.source_type:
                        operations.append(
                            Update(pkg, package, priority=depths[i]))
                    else:
                        operations.append(
                            Install(
                                package,
                                priority=depths[i]).skip("Already installed"))

                    break

            if not installed:
                operations.append(Install(package, priority=depths[i]))

        # 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)

        if self._remove_untracked:
            locked_names = {locked.name for locked in self._locked.packages}

            for installed in self._installed.packages:
                if installed.name == self._package.name:
                    continue
                if installed.name in Provider.UNSAFE_PACKAGES:
                    # Never remove pip, setuptools etc.
                    continue
                if installed.name not in locked_names:
                    operations.append(Uninstall(installed))

        return sorted(
            operations,
            key=lambda o: (
                -o.priority,
                o.package.name,
                o.package.version,
            ),
        )
Пример #11
0
    def _parse_requirements(self, requirements: List[str]) -> List[Dict[str, str]]:
        from poetry.puzzle.provider import Provider

        result = []

        try:
            cwd = self.poetry.file.parent
        except (PyProjectException, 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 = urllib.parse.urlparse(requirement)
            if url_parsed.scheme and url_parsed.netloc:
                # Url
                if url_parsed.scheme in ["git+https", "git+ssh"]:
                    from poetry.core.vcs.git import Git
                    from poetry.core.vcs.git import ParsedUrl

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

                    pair = dict([("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, rev=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 = dict([("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(
                    dict(
                        [
                            ("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 = dict()
            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
Пример #12
0
    def load(cls, env):  # type: (Env) -> InstalledRepository
        """
        Load installed packages.
        """
        repo = cls()
        seen = set()

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

                if package.name in seen:
                    continue

                try:
                    path.relative_to(_VENDORS)
                except ValueError:
                    pass
                else:
                    continue

                seen.add(package.name)

                repo.add_package(package)

                is_standard_package = True
                try:
                    path.relative_to(env.site_packages)
                except ValueError:
                    is_standard_package = False

                if is_standard_package:
                    if path.name.endswith(".dist-info"):
                        paths = cls.get_package_paths(
                            sitedir=env.site_packages,
                            name=package.pretty_name)
                        if paths:
                            # TODO: handle multiple source directories?
                            package.source_type = "directory"
                            package.source_url = paths.pop().as_posix()

                    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.core.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
Пример #13
0
def test_git_rev_parse_raises_error_on_invalid_repository() -> None:
    with pytest.raises(GitError):
        Git().rev_parse("-u./payload")
Пример #14
0
def test_git_checkout_raises_error_on_invalid_repository() -> None:
    with pytest.raises(GitError):
        Git().checkout("-u./payload")
Пример #15
0
def test_git_clone_raises_error_on_invalid_repository() -> None:
    with pytest.raises(GitError):
        Git().clone("-u./payload", Path("foo"))
Пример #16
0
def test_normalize_url(url: str, normalized: GitUrl) -> None:
    assert normalized == Git.normalize_url(url)
Пример #17
0
def test_normalize_url(url, normalized):
    assert normalized == Git.normalize_url(url)