diff --git a/examples/extensions/commands/clean/cmd_clean.py b/examples/extensions/commands/clean/cmd_clean.py index fb22e14a..3e5b4b87 100644 --- a/examples/extensions/commands/clean/cmd_clean.py +++ b/examples/extensions/commands/clean/cmd_clean.py @@ -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 @@ -27,26 +28,31 @@ 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, " + # List all recipes revisions and all their packages revisions as well + pkg_list = conan_api.list.select(ListPattern("*/*#*:*#*", rrev=None, prev=None), remote=remote) + 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) + + # Split the package list into recipe bundles based on their recipe reference + for ref_bundle in pkg_list.split(): + latest = max(ref_bundle.refs(), key=lambda r: r.revision) + out.writeln(f"Keeping recipe revision: {latest.repr_notime()} " + f"and its latest package revisions [{output_remote}]", fg=recipe_color) + for pkg_ref, pkg_bundle in ref_bundle.refs().items(): + # For the latest recipe revision, keep the latest package revision only + if latest == pkg_ref: + prefs = PackagesList.prefs(latest, pkg_bundle) + if prefs: + latest_pref = max(prefs.keys(), key=lambda p: p.revision) + out.writeln(f"Keeping package revision: {latest_pref.repr_notime()} [{output_remote}]", fg=recipe_color) + for pref in prefs.keys(): + if latest_pref != pref: + conan_api.remove.package(pref, remote=remote) + out.writeln(f"Removed package revision: {pref.repr_notime()} [{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) + # Otherwise, remove all outdated recipe revisions and their packages + conan_api.remove.recipe(pkg_ref, remote=remote) + out.writeln(f"Removed recipe revision: {pkg_ref.repr_notime()} " + f"and all its package revisions [{output_remote}]", fg=removed_color)