Skip to content
Merged
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 20 additions & 21 deletions examples/extensions/commands/clean/cmd_clean.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from conan.api.conan_api import ConanAPI
from conan.api.model import PackagesList, ListPattern
from conan.api.input import UserInput
from conan.api.output import ConanOutput, Color
from conan.cli.command import OnceArgument, conan_command
Expand Down Expand Up @@ -27,26 +28,24 @@ def confirmation(message):
remote = conan_api.remotes.get(args.remote) if args.remote else None
output_remote = remote or "Local cache"

# Getting all the recipes
recipes = conan_api.search.recipes("*/*", remote=remote)
if recipes and not confirmation("Do you want to remove all the recipes revisions and their packages ones, "
# Get all recipes and packages, where recipe revision is not the latest
pkg_list = conan_api.list.select(ListPattern("*/*#!latest:*#*", rrev=None, prev=None), remote=remote)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the whole command implementation sounds a bit too complicated.
For example, it is not necessary to select all binaries and all revisions here with :*#* as later only the recipe will be removed (and it will remove all the associated binaries automatically)

Then, it sounds very inefficient to list twice with the */* pattern. It sounds better to do a recipe revision list only pkg_list = conan_api.list.select(ListPattern("*/*", rrev=None, prev=None), then remove all but the latest revision, and for that latest revision list the specific package revisions to remove (!latest)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, I have a learn curve just to write this small piece, needing to understand the API class implementation around this example. Let me update according to your suggestion.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, check the commit 48c7135

if pkg_list and not confirmation("Do you want to remove all the recipes revisions and their packages ones, "
"except the latest package revision from the latest recipe one?"):
out.writeln("Aborted")
return
for recipe in recipes:
out.writeln(f"{str(recipe)}", fg=recipe_color)
all_rrevs = conan_api.list.recipe_revisions(recipe, remote=remote)
latest_rrev = all_rrevs[0] if all_rrevs else None
for rrev in all_rrevs:
if rrev != latest_rrev:
conan_api.remove.recipe(rrev, remote=remote)
out.writeln(f"Removed recipe revision: {rrev.repr_notime()} "
f"and all its package revisions [{output_remote}]", fg=removed_color)
else:
packages = conan_api.list.packages_configurations(rrev, remote=remote)
for package_ref in packages:
all_prevs = conan_api.list.package_revisions(package_ref, remote=remote)
latest_prev = all_prevs[0] if all_prevs else None
for prev in all_prevs:
if prev != latest_prev:
conan_api.remove.package(prev, remote=remote)
out.writeln(f"Removed package revision: {prev.repr_notime()} [{output_remote}]", fg=removed_color)

# Remove all packages for old recipe revisions
for recipe_ref, recipe_bundle in pkg_list.refs().items():
conan_api.remove.recipe(recipe_ref, remote=remote)
out.writeln(f"Removed recipe revision: {recipe_ref.repr_notime()} "
f"and all its package revisions [{output_remote}]", fg=removed_color)

# Get all package revisions from the latest recipe revision, except the latest package revision
pkg_list = conan_api.list.select(ListPattern("*/*#latest:*#!latest", rrev=None, prev=None), remote=remote)
for recipe_ref, recipe_bundle in pkg_list.refs().items():
pkg_list = PackagesList.prefs(recipe_ref, recipe_bundle)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Conan we usually would call this static method from the pkg_list object itself, but do note that this is still an undocumented method, maybe we need to take a look into it - I think getting the refs and prefs of a pkglist is a valid operation that users might want access to.

We also need to check if the remove api can be improved

for pkg_ref in pkg_list.keys():
# Remove all package revisions except the latest one
conan_api.remove.package(pkg_ref, remote=remote)
out.writeln(f"Removed package revision: {pkg_ref.repr_notime()} [{output_remote}]", fg=removed_color)