Skip to content

Commit

Permalink
Improve package operations management
Browse files Browse the repository at this point in the history
  • Loading branch information
sdispater committed Jul 31, 2021
1 parent df77c80 commit 6dce09c
Show file tree
Hide file tree
Showing 13 changed files with 777 additions and 365 deletions.
22 changes: 16 additions & 6 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,19 @@ The `--dev-only` option is now deprecated. You should use the `--only dev` notat
See [Dependency groups]({{< relref "managing-dependencies#dependency-groups" >}}) for more information
about dependency groups.

If you want to remove old dependencies no longer present in the lock file, use the
`--remove-untracked` option.
If you want to synchronize your environment – and ensure it matches the lock file use the
`--sync` option.

```bash
poetry install --remove-untracked
poetry install --sync
```

The `--sync` can be combined with group-related options:

```bash
poetry install --without dev --sync
poetry install --with docs --sync
poetry install --only dev
```

You can also specify the extras you want installed
Expand Down Expand Up @@ -204,12 +212,14 @@ option is used.
* `--with`: The optional dependency groups to include for installation.
* `--only`: The only dependency groups to install.
* `--default`: Only install the default dependencies.
* `--no-dev`: Do not install dev dependencies. (**Deprecated**)
* `--dev-only`: Only install dev dependencies. (**Deprecated**)
* `--sync`: Synchronize the environment with the locked packages and the specified groups.
* `--no-root`: Do not install the root package (your project).
* `--dry-run`: Output the operations but do not execute anything (implicitly enables --verbose).
* `--remove-untracked`: Remove dependencies not presented in the lock file
* `--extras (-E)`: Features to install (multiple values allowed).
* `--no-dev`: Do not install dev dependencies. (**Deprecated**)
* `--dev-only`: Only install dev dependencies. (**Deprecated**)
* `--remove-untracked`: Remove dependencies not presented in the lock file. (**Deprecated**)


## update

Expand Down
26 changes: 26 additions & 0 deletions docs/managing-dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,29 @@ to remove packages from a specific group:
```bash
poetry remove mkdocs --group docs
```


## Synchronizing dependencies

Poetry supports what's called dependency synchronization. What this does is ensuring
that the locked dependencies in the `poetry.lock` file are the only ones present
in the environment, removing anything that's not necessary.

This is done by using the `--sync` option of the `install` command:

```bash
poetry install --sync
```

The `--sync` option can be combined with any [dependency groups]({{< relref "dependency-groups" >}}) related options
to synchronize the environment with specific groups.

```bash
poetry install --without dev --sync
poetry install --with docs --sync
poetry install --only dev
```

{{% note %}}
The `--sync` option replaces the `--remove-untracked` option which is now deprecated.
{{% /note %}}
4 changes: 2 additions & 2 deletions poetry/console/commands/debug/resolve.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def handle(self) -> Optional[int]:

solver = Solver(package, pool, Repository(), Repository(), self._io)

ops = solver.solve()
ops = solver.solve().calculate_operations()

self.line("")
self.line("Resolution results:")
Expand Down Expand Up @@ -123,7 +123,7 @@ def handle(self) -> Optional[int]:

solver = Solver(package, pool, Repository(), Repository(), NullIO())
with solver.use_environment(env):
ops = solver.solve()
ops = solver.solve().calculate_operations()

for op in ops:
if self.option("install") and op.skipped:
Expand Down
16 changes: 15 additions & 1 deletion poetry/console/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ class InstallCommand(InstallerCommand):
None,
"Only install the development dependencies. (<warning>Deprecated</warning>)",
),
option(
"sync",
None,
"Synchronize the environment with the locked packages and the specified groups.",
),
option(
"no-root", None, "Do not install the root package (the current project)."
),
Expand Down Expand Up @@ -138,11 +143,20 @@ def handle(self) -> int:
if self.option("default"):
only_groups.append("default")

with_synchronization = self.option("sync")
if self.option("remove-untracked"):
self.line(
"<warning>The `<fg=yellow;options=bold>--remove-untracked</>` option is deprecated,"
"use the `<fg=yellow;options=bold>--sync</>` option instead.</warning>"
)

with_synchronization = True

self._installer.only_groups(only_groups)
self._installer.without_groups(excluded_groups)
self._installer.with_groups(included_groups)
self._installer.dry_run(self.option("dry-run"))
self._installer.remove_untracked(self.option("remove-untracked"))
self._installer.requires_synchronization(with_synchronization)
self._installer.verbose(self._io.is_verbose())

return_code = self._installer.run()
Expand Down
2 changes: 1 addition & 1 deletion poetry/console/commands/show.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def handle(self) -> Optional[int]:
)
solver.provider.load_deferred(False)
with solver.use_environment(self.env):
ops = solver.solve()
ops = solver.solve().calculate_operations()

required_locked_packages = set([op.package for op in ops if not op.skipped])

Expand Down
46 changes: 30 additions & 16 deletions poetry/installation/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def __init__(
self._pool = pool

self._dry_run = False
self._remove_untracked = False
self._requires_synchronization = False
self._update = False
self._verbose = False
self._write_lock = True
Expand Down Expand Up @@ -122,14 +122,13 @@ def dry_run(self, dry_run: bool = True) -> "Installer":
def is_dry_run(self) -> bool:
return self._dry_run

def remove_untracked(self, remove_untracked: bool = True) -> "Installer":
self._remove_untracked = remove_untracked
def requires_synchronization(
self, requires_synchronization: bool = True
) -> "Installer":
self._requires_synchronization = requires_synchronization

return self

def is_remove_untracked(self) -> bool:
return self._remove_untracked

def verbose(self, verbose: bool = True) -> "Installer":
self._verbose = verbose
self._executor.verbose(verbose)
Expand Down Expand Up @@ -212,7 +211,7 @@ def _do_refresh(self) -> int:
self._io,
)

ops = solver.solve(use_latest=[])
ops = solver.solve(use_latest=[]).calculate_operations()

local_repo = Repository()
self._populate_local_repo(local_repo, ops)
Expand Down Expand Up @@ -247,10 +246,9 @@ def _do_install(self, local_repo: Repository) -> int:
self._installed_repository,
locked_repository,
self._io,
remove_untracked=self._remove_untracked,
)

ops = solver.solve(use_latest=self._whitelist)
ops = solver.solve(use_latest=self._whitelist).calculate_operations()
else:
self._io.write_line("<info>Installing dependencies from lock file</>")

Expand Down Expand Up @@ -318,19 +316,35 @@ def _do_install(self, local_repo: Repository) -> int:
pool.add_repository(repo)

solver = Solver(
root,
pool,
self._installed_repository,
locked_repository,
NullIO(),
remove_untracked=self._remove_untracked,
root, pool, self._installed_repository, locked_repository, NullIO()
)
# Everything is resolved at this point, so we no longer need
# to load deferred dependencies (i.e. VCS, URL and path dependencies)
solver.provider.load_deferred(False)

with solver.use_environment(self._env):
ops = solver.solve(use_latest=self._whitelist)
ops = solver.solve(use_latest=self._whitelist).calculate_operations(
with_uninstalls=self._requires_synchronization,
synchronize=self._requires_synchronization,
)

if not self._requires_synchronization:
# If no packages synchronisation has been requested we need
# to calculate the uninstall operations
from poetry.puzzle.transaction import Transaction

transaction = Transaction(
locked_repository.packages,
[(package, 0) for package in local_repo.packages],
installed_packages=self._installed_repository.packages,
root_package=root,
)

ops = [
op
for op in transaction.calculate_operations(with_uninstalls=True)
if op.job_type == "uninstall"
] + ops

# We need to filter operations so that packages
# not compatible with the current system,
Expand Down
Loading

0 comments on commit 6dce09c

Please sign in to comment.