Commit e677299e by Sébastien Eustace

Add a remove command

parent 40569558
......@@ -10,6 +10,7 @@ from .commands import AddCommand
from .commands import InstallCommand
from .commands import LockCommand
from .commands import NewCommand
from .commands import RemoveCommand
from .commands import UpdateCommand
......@@ -46,6 +47,7 @@ class Application(BaseApplication):
InstallCommand(),
LockCommand(),
NewCommand(),
RemoveCommand(),
UpdateCommand(),
]
......
......@@ -3,4 +3,5 @@ from .add import AddCommand
from .install import InstallCommand
from .lock import LockCommand
from .new import NewCommand
from .remove import RemoveCommand
from .update import UpdateCommand
import toml
from poetry.installation import Installer
from .command import Command
class RemoveCommand(Command):
"""
Removes a package from the project dependencies.
remove
{ packages* : Packages that should be removed. }
{--D|dev : Removes a package from the development dependencies. }
{--dry-run : Outputs the operations but will not execute anything
(implicitly enables --verbose). }
"""
help = """The <info>remove</info> command removes a package from the current
list of installed packages
<info>poetry remove</info>"""
def handle(self):
packages = [p.lower() for p in self.argument('packages')]
is_dev = self.option('dev')
with self.poetry.locker.original.path.open() as fd:
content = fd.read().split('\n')
# Trying to figure out where are our dependencies
# If we find a toml library that keeps comments
# We could remove this whole section
section = '[dependencies]'
if is_dev:
section = '[dev-dependencies]'
# Searching for package in
in_section = False
indices = []
requirements = {}
for i, line in enumerate(content):
line = line.strip()
if line == section:
in_section = True
continue
if in_section:
if not line:
# End of section
break
requirement = toml.loads(line)
name = list(requirement.keys())[0].lower()
version = requirement[name]
if name in packages:
requirements[name] = version
indices.append(i)
break
if not indices or len(indices) != len(packages):
raise RuntimeError(
'Packages are not present in your poetry.toml file'
)
new_content = []
for i, line in enumerate(content):
if i in indices:
continue
new_content.append(line)
new_content = '\n'.join(new_content)
with self.poetry.locker.original.path.open('w') as fd:
fd.write(new_content)
# Update packages
self.reset_poetry()
installer = Installer(
self.output,
self.poetry.package,
self.poetry.locker,
self.poetry.repository
)
installer.dry_run(self.option('dry-run'))
installer.update(True)
installer.whitelist(requirements)
try:
status = installer.run()
except Exception:
with self.poetry.locker.original.path.open('w') as fd:
fd.write('\n'.join(content))
raise
if status != 0 or self.option('dry-run'):
# Revert changes
if not self.option('dry-run'):
self.error(
'\n'
'Removal failed, reverting poetry.toml '
'to its original content.'
)
with self.poetry.locker.original.path.open('w') as fd:
fd.write('\n'.join(content))
return status
......@@ -127,8 +127,7 @@ class Installer:
solver = Solver(locked_repository, self._io)
request = self._package.requires
if self.is_dev_mode():
request += self._package.dev_requires
request += self._package.dev_requires
ops = solver.solve(request, self._repository, fixed=fixed)
else:
......@@ -136,7 +135,19 @@ class Installer:
# If we are installing from lock
# Filter the operations by comparing it with what is
# currently installed
ops = self._get_operations_from_lock(locked_repository)
ops = []
for package in locked_repository.packages:
ops.append(Install(package))
for op in ops:
if op.job_type == 'install':
local_repo.add_package(op.package)
elif op.job_type == 'update':
local_repo.add_package(op.target_package)
elif op.job_type == 'uninstall':
local_repo.remove_package(op.package)
ops = self._filter_operations(ops)
self._io.new_line()
......@@ -174,24 +185,6 @@ class Installer:
)
self._io.new_line()
for op in ops:
if op.job_type == 'install':
local_repo.add_package(op.package)
elif op.job_type == 'update':
local_repo.add_package(op.target_package)
# Adding untouched locked package
# to local_repo
if self._update:
for locked in locked_repository.packages:
untouched = True
for local_pkg in local_repo.packages:
if locked.name == local_pkg.name:
untouched = False
if untouched:
local_repo.add_package(locked)
# Writing lock before installing
if self._update and self._write_lock:
updated_lock = self._locker.set_lock_data(
......@@ -254,28 +247,44 @@ class Installer:
self._installer.remove(operation.package)
def _get_operations_from_lock(self,
locked_repository: Repository
) -> List[Operation]:
def _filter_operations(self,
ops: List[Operation]
) -> List[Operation]:
installed_repo = InstalledRepository.load(self._io.venv)
ops = []
new_ops = []
for op in ops:
if isinstance(op, Update):
package = op.target_package
else:
package = op.package
for locked in locked_repository.packages:
is_installed = False
for installed in installed_repo.packages:
if locked.name == installed.name:
if package.name == installed.name:
is_installed = True
if locked.category == 'dev' and not self.is_dev_mode():
ops.append(Uninstall(locked))
elif locked.version != installed.version:
ops.append(Update(
installed, locked
))
if op.job_type == 'uninstall':
new_ops.append(op)
break
if package.version != installed.version:
new_ops.append(Update(installed, package))
elif package.category == 'dev' and not self.is_dev_mode():
if op.job_type == 'uninstall':
new_ops.append(op)
else:
new_ops.append(Uninstall(installed))
else:
# Nothing to do
break
if not is_installed:
ops.append(Install(locked))
if op.job_type in ['update', 'uninstall']:
continue
new_ops.append(op)
return ops
return new_ops
......@@ -46,17 +46,17 @@ class Solver:
operations = []
for package in packages:
installed = False
processed = False
for pkg in self._installed.packages:
if package.name == pkg.name:
installed = True
# Checking version
if package.version != pkg.version:
processed = True
operations.append(Update(pkg, package))
break
if not installed:
if not processed:
operations.append(Install(package))
# Checking for removals
......
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