Commit 3feff049 by Sébastien Eustace

Fix support for VCS dependencies

parent 4dd15ebc
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
- Fixed installation of directory dependencies. - Fixed installation of directory dependencies.
- Fixed handling of dependencies with a `not in` marker operator. - Fixed handling of dependencies with a `not in` marker operator.
- Fixed support for VCS dependencies.
## [0.12.5] - 2018-10-26 ## [0.12.5] - 2018-10-26
......
...@@ -24,12 +24,8 @@ lists all packages available.""" ...@@ -24,12 +24,8 @@ lists all packages available."""
colors = ["green", "yellow", "cyan", "magenta", "blue"] colors = ["green", "yellow", "cyan", "magenta", "blue"]
def handle(self): def handle(self):
from poetry.packages.constraints import (
parse_constraint as parse_generic_constraint,
)
from poetry.repositories.installed_repository import InstalledRepository from poetry.repositories.installed_repository import InstalledRepository
from poetry.semver import Version from poetry.semver import Version
from poetry.semver import parse_constraint
package = self.argument("package") package = self.argument("package")
...@@ -172,7 +168,7 @@ lists all packages available.""" ...@@ -172,7 +168,7 @@ lists all packages available."""
color = "yellow" color = "yellow"
line += " <fg={}>{:{}}</>".format( line += " <fg={}>{:{}}</>".format(
color, latest.pretty_version, latest_length color, latest.full_pretty_version, latest_length
) )
if self.option("outdated") and update_status == "up-to-date": if self.option("outdated") and update_status == "up-to-date":
continue continue
...@@ -291,11 +287,17 @@ lists all packages available.""" ...@@ -291,11 +287,17 @@ lists all packages available."""
self.set_style(color, color) self.set_style(color, color)
def find_latest_package(self, package): def find_latest_package(self, package):
from poetry.io import NullIO
from poetry.puzzle.provider import Provider
from poetry.version.version_selector import VersionSelector from poetry.version.version_selector import VersionSelector
# find the latest version allowed in this pool # find the latest version allowed in this pool
if package.source_type == "git": if package.source_type == "git":
return for dep in self.poetry.package.requires:
if dep.name == package.name and dep.is_vcs():
return Provider(
self.poetry.package, self.poetry.pool, NullIO()
).search_for_vcs(dep)[0]
name = package.name name = package.name
selector = VersionSelector(self.poetry.pool) selector = VersionSelector(self.poetry.pool)
......
import os import os
import shutil
import tempfile import tempfile
from subprocess import CalledProcessError from subprocess import CalledProcessError
...@@ -92,6 +93,12 @@ class PipInstaller(BaseInstaller): ...@@ -92,6 +93,12 @@ class PipInstaller(BaseInstaller):
self.install(target, update=True) self.install(target, update=True)
def remove(self, package): def remove(self, package):
# If we have a VCS package, remove its source directory
if package.source_type == "git":
src_dir = self._env.path / "src" / package.name
if src_dir.exists():
shutil.rmtree(str(src_dir))
try: try:
self.run("uninstall", package.name, "-y") self.run("uninstall", package.name, "-y")
except CalledProcessError as e: except CalledProcessError as e:
...@@ -197,21 +204,22 @@ class PipInstaller(BaseInstaller): ...@@ -197,21 +204,22 @@ class PipInstaller(BaseInstaller):
def install_git(self, package): def install_git(self, package):
from poetry.packages import Package from poetry.packages import Package
from poetry.utils._compat import Path
from poetry.utils.helpers import temporary_directory
from poetry.vcs import Git from poetry.vcs import Git
with temporary_directory() as tmp_dir: src_dir = self._env.path / "src" / package.name
tmp_dir = Path(tmp_dir) if src_dir.exists():
shutil.rmtree(str(src_dir))
src_dir.parent.mkdir(exist_ok=True)
git = Git() git = Git()
git.clone(package.source_url, tmp_dir) git.clone(package.source_url, src_dir)
git.checkout(package.source_reference, tmp_dir) git.checkout(package.source_reference, src_dir)
# Now we just need to install from the temporary directory # Now we just need to install from the source directory
pkg = Package(package.name, package.version) pkg = Package(package.name, package.version)
pkg.source_type = "directory" pkg.source_type = "directory"
pkg.source_url = str(tmp_dir) pkg.source_url = str(src_dir)
pkg.develop = False pkg.develop = True
self.install_directory(pkg) self.install_directory(pkg)
...@@ -7,6 +7,7 @@ from typing import List ...@@ -7,6 +7,7 @@ from typing import List
from poetry.mixology import resolve_version from poetry.mixology import resolve_version
from poetry.mixology.failure import SolveFailure from poetry.mixology.failure import SolveFailure
from poetry.packages import DependencyPackage from poetry.packages import DependencyPackage
from poetry.packages import Package
from poetry.semver import parse_constraint from poetry.semver import parse_constraint
from poetry.version.markers import AnyMarker from poetry.version.markers import AnyMarker
...@@ -55,8 +56,33 @@ class Solver: ...@@ -55,8 +56,33 @@ class Solver:
for pkg in self._installed.packages: for pkg in self._installed.packages:
if package.name == pkg.name: if package.name == pkg.name:
installed = True installed = True
if pkg.source_type == "git" and package.source_type == "git":
# Trying to find the currently installed version
for locked in self._locked.packages:
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
):
operations.append(Update(pkg, package))
else:
operations.append(
Install(package).skip("Already installed")
)
elif package.version != pkg.version:
# Checking version # Checking version
if package.version != pkg.version:
operations.append(Update(pkg, package)) operations.append(Update(pkg, package))
else: else:
operations.append(Install(package).skip("Already installed")) operations.append(Install(package).skip("Already installed"))
......
...@@ -19,5 +19,24 @@ class InstalledRepository(Repository): ...@@ -19,5 +19,24 @@ class InstalledRepository(Repository):
if "==" in line: if "==" in line:
name, version = line.split("==") name, version = line.split("==")
repo.add_package(Package(name, version, version)) repo.add_package(Package(name, version, version))
elif line.startswith("-e "):
line = line[3:].strip()
if line.startswith("git+"):
url = line.lstrip("git+")
if "@" in url:
url, rev = url.rsplit("@", 1)
else:
rev = "master"
name = url.split("/")[-1].rstrip(".git")
if "#egg=" in rev:
rev, name = rev.split("#egg=")
package = Package(name, "0.0.0")
package.source_type = "git"
package.source_url = url
package.source_reference = rev
repo.add_package(package)
return repo return repo
...@@ -1224,3 +1224,69 @@ def test_solver_ignores_dependencies_with_incompatible_python_full_version_marke ...@@ -1224,3 +1224,69 @@ def test_solver_ignores_dependencies_with_incompatible_python_full_version_marke
{"job": "install", "package": package_b200}, {"job": "install", "package": package_b200},
], ],
) )
def test_solver_git_dependencies_update(solver, repo, package, installed):
pendulum = get_package("pendulum", "2.0.3")
cleo = get_package("cleo", "1.0.0")
repo.add_package(pendulum)
repo.add_package(cleo)
demo = get_package("demo", "0.1.2")
demo.source_type = "git"
demo.source_url = "https://github.com/demo/demo.git"
demo.source_reference = "123456"
installed.add_package(demo)
package.add_dependency("demo", {"git": "https://github.com/demo/demo.git"})
ops = solver.solve()
check_solver_result(
ops,
[
{"job": "install", "package": pendulum},
{"job": "install", "package": cleo},
{
"job": "update",
"from": get_package("demo", "0.1.2"),
"to": get_package("demo", "0.1.2"),
},
],
)
op = ops[2]
assert op.job_type == "update"
assert op.package.source_reference.startswith("9cf87a2")
assert op.initial_package.source_reference == "123456"
def test_solver_git_dependencies_update_skipped(solver, repo, package, installed):
pendulum = get_package("pendulum", "2.0.3")
cleo = get_package("cleo", "1.0.0")
repo.add_package(pendulum)
repo.add_package(cleo)
demo = get_package("demo", "0.1.2")
demo.source_type = "git"
demo.source_url = "https://github.com/demo/demo.git"
demo.source_reference = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24"
installed.add_package(demo)
package.add_dependency("demo", {"git": "https://github.com/demo/demo.git"})
ops = solver.solve()
check_solver_result(
ops,
[
{"job": "install", "package": pendulum},
{"job": "install", "package": cleo},
{
"job": "install",
"package": get_package("demo", "0.1.2"),
"skipped": True,
},
],
)
from poetry.repositories.installed_repository import InstalledRepository
from poetry.utils.env import MockEnv as BaseMockEnv
FREEZE_RESULTS = """cleo==0.6.8
-e git+https://github.com/sdispater/pendulum.git@bb058f6b78b2d28ef5d9a5e759cfa179a1a713d6#egg=pendulum
"""
class MockEnv(BaseMockEnv):
def run(self, bin, *args):
if bin == "pip" and args[0] == "freeze":
return FREEZE_RESULTS
super(MockEnv, self).run(bin, *args)
def test_load():
repository = InstalledRepository.load(MockEnv())
assert len(repository.packages) == 2
cleo = repository.packages[0]
assert cleo.name == "cleo"
assert cleo.version.text == "0.6.8"
pendulum = repository.packages[1]
assert pendulum.name == "pendulum"
assert pendulum.version.text == "0.0.0"
assert pendulum.source_type == "git"
assert pendulum.source_url == "https://github.com/sdispater/pendulum.git"
assert pendulum.source_reference == "bb058f6b78b2d28ef5d9a5e759cfa179a1a713d6"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment