Skip to content

Commit c0485dc

Browse files
committed
Merge branch 'test-requires-fixes' of github.com:czoido/examples2 into test-requires-fixes
2 parents a33b2ae + 16672f7 commit c0485dc

File tree

2 files changed

+104
-86
lines changed

2 files changed

+104
-86
lines changed
Lines changed: 79 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,79 @@
1-
# FIXME: uncomment and fix once the Conan API is refactored in Conan 2.21
2-
3-
# import os
4-
5-
# from test.examples_tools import run, tmp_dir
6-
7-
8-
# non_deterministic_conanfile = """\
9-
# from datetime import datetime
10-
11-
# from conan import ConanFile
12-
# from conan.tools.files import copy
13-
14-
15-
# class HelloConan(ConanFile):
16-
# name = "{name}"
17-
# version = "1.0"
18-
# {comment}
19-
20-
# def build(self):
21-
# with open("random.txt", "w") as f:
22-
# f.write(str(datetime.now()))
23-
24-
# def package(self):
25-
# # Packaging a random content, the package revision will be different every time
26-
# copy(self, "random.txt", self.source_folder, self.package_folder)
27-
# """
28-
29-
30-
# def install_clean_command():
31-
# clean_command = os.path.join(os.path.dirname(os.path.realpath(__file__)), "clean")
32-
# commands_folder = os.path.join("extensions", "commands")
33-
# run(f"conan config install {clean_command} -tf {commands_folder}")
34-
35-
36-
# # At first, copy the commands into the ${CONAN_HOME}/extensions/commands folder
37-
# install_clean_command()
38-
39-
# # 1. Check the custom command is appearing in conan help
40-
# output = run("conan -h")
41-
# assert "commands\nclean" in output.replace("\r\n", "\n")
42-
# # 2. Create several packages
43-
# with tmp_dir("clean_hello"):
44-
# # Library (changing PREV each time)
45-
# with open(os.path.join("conanfile.py"), "w") as f:
46-
# f.write(non_deterministic_conanfile.format(name="clean_hello", comment=""))
47-
# run("conan create .")
48-
# run("conan create .") # different PREV (this is the latest one)
49-
50-
# with tmp_dir("clean_other"):
51-
# with open(os.path.join("conanfile.py"), "w") as f:
52-
# f.write(non_deterministic_conanfile.format(name="clean_other", comment=""))
53-
# run("conan create .")
54-
# # Changing RREV
55-
# with open(os.path.join("conanfile.py"), "w") as f:
56-
# f.write(non_deterministic_conanfile.format(name="clean_other", comment="# Changing RREV"))
57-
# run("conan create .") # different RREV (this is the latest one)
58-
59-
# # 3. Run "conan clean" command: Cleaning all the non-latest RREVs (and its packages) and PREVs
60-
# output = run("conan clean --force")
61-
# assert "Removed package revision: clean_hello/1.0#" in output # removing earlier PREV from clean_hello
62-
# assert "Removed recipe revision: clean_other/1.0#" in output # removing earlier RREV from clean_other
63-
# # Now, it should have removed nothing
64-
# output = run("conan clean --force")
65-
# assert "Removed recipe revision: clean_other/1.0#" not in output
66-
# assert "Removed package revision: clean_hello/1.0#" not in output
1+
import os
2+
import warnings
3+
import json
4+
5+
from test.examples_tools import run, tmp_dir
6+
from conan import conan_version
7+
8+
non_deterministic_conanfile = """\
9+
from datetime import datetime
10+
11+
from conan import ConanFile
12+
from conan.tools.files import copy
13+
14+
15+
class HelloConan(ConanFile):
16+
name = "{name}"
17+
version = "1.0"
18+
{comment}
19+
20+
def build(self):
21+
with open("random.txt", "w") as f:
22+
f.write(str(datetime.now()))
23+
24+
def package(self):
25+
# Packaging a random content, the package revision will be different every time
26+
copy(self, "random.txt", self.source_folder, self.package_folder)
27+
"""
28+
29+
30+
def install_clean_command():
31+
clean_command = os.path.join(os.path.dirname(os.path.realpath(__file__)), "clean")
32+
commands_folder = os.path.join("extensions", "commands")
33+
run(f"conan config install {clean_command} -tf {commands_folder}")
34+
35+
36+
# At first, copy the commands into the ${CONAN_HOME}/extensions/commands folder
37+
install_clean_command()
38+
39+
# 1. Check the custom command is appearing in conan help
40+
output = run("conan -h")
41+
assert "commands\nclean" in output.replace("\r\n", "\n")
42+
# 2. Create several packages
43+
with tmp_dir("clean_hello"):
44+
# Library (changing PREV each time)
45+
with open(os.path.join("conanfile.py"), "w") as f:
46+
f.write(non_deterministic_conanfile.format(name="clean_hello", comment=""))
47+
run("conan create .")
48+
run("conan create .") # different PREV (this is the latest one)
49+
50+
with tmp_dir("clean_other"):
51+
with open(os.path.join("conanfile.py"), "w") as f:
52+
f.write(non_deterministic_conanfile.format(name="clean_other", comment=""))
53+
run("conan create .")
54+
# Changing RREV
55+
with open(os.path.join("conanfile.py"), "w") as f:
56+
f.write(non_deterministic_conanfile.format(name="clean_other", comment="# Changing RREV"))
57+
run("conan create .") # different RREV (this is the latest one)
58+
59+
if conan_version >= "2.21.0-dev":
60+
output = run("conan list '*/*#*:*#*' --format=json ")
61+
all_packages = json.loads("\n".join(output.splitlines()[1:]))
62+
output = run("conan list '*/*#latest:*#latest' --format=json")
63+
latest_packages = json.loads("\n".join(output.splitlines()[1:]))
64+
if all_packages == latest_packages:
65+
warnings.warn("Skipping 'conan clean' test because there are no old revisions to clean.")
66+
# 3. Run "conan clean" command: Cleaning all the non-latest RREVs (and its packages) and PREVs
67+
output = run("conan clean --force")
68+
assert "Removed package revision: clean_hello/1.0#" in output # removing earlier PREV from clean_hello
69+
assert "Removed recipe revision: clean_other/1.0#" in output # removing earlier RREV from clean_other
70+
# Now, it should have removed nothing
71+
output = run("conan clean --force")
72+
assert "Removed recipe revision: clean_other/1.0#" not in output
73+
assert "Removed package revision: clean_hello/1.0#" not in output
74+
# Make sure latest revisions are still there
75+
output = run("conan list '*/*#*:*#*' --format=json")
76+
listed_after = json.loads("\n".join(output.splitlines()[1:]))
77+
assert latest_packages == listed_after
78+
else:
79+
warnings.warn("Skipping 'conan clean' test because it requires Conan 2.21 due new API list.")

examples/extensions/commands/clean/cmd_clean.py

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from conan.api.conan_api import ConanAPI
2+
from conan.api.model import PackagesList, ListPattern
23
from conan.api.input import UserInput
34
from conan.api.output import ConanOutput, Color
45
from conan.cli.command import OnceArgument, conan_command
@@ -27,26 +28,30 @@ def confirmation(message):
2728
remote = conan_api.remotes.get(args.remote) if args.remote else None
2829
output_remote = remote or "Local cache"
2930

30-
# Getting all the recipes
31-
recipes = conan_api.search.recipes("*/*", remote=remote)
32-
if recipes and not confirmation("Do you want to remove all the recipes revisions and their packages ones, "
31+
# List all recipes revisions and all their packages revisions as well
32+
pkg_list = conan_api.list.select(ListPattern("*/*#*:*#*", rrev=None, prev=None), remote=remote)
33+
if pkg_list and not confirmation("Do you want to remove all the recipes revisions and their packages ones, "
3334
"except the latest package revision from the latest recipe one?"):
35+
out.writeln("Aborted")
3436
return
35-
for recipe in recipes:
36-
out.writeln(f"{str(recipe)}", fg=recipe_color)
37-
all_rrevs = conan_api.list.recipe_revisions(recipe, remote=remote)
38-
latest_rrev = all_rrevs[0] if all_rrevs else None
39-
for rrev in all_rrevs:
40-
if rrev != latest_rrev:
41-
conan_api.remove.recipe(rrev, remote=remote)
42-
out.writeln(f"Removed recipe revision: {rrev.repr_notime()} "
43-
f"and all its package revisions [{output_remote}]", fg=removed_color)
37+
38+
# Split the package list into based on their recipe reference
39+
for sub_pkg_list in pkg_list.split():
40+
latest = max(sub_pkg_list.items(), key=lambda item: item[0])[0]
41+
out.writeln(f"Keeping recipe revision: {latest.repr_notime()} "
42+
f"and its latest package revisions [{output_remote}]", fg=recipe_color)
43+
for rref, packages in sub_pkg_list.items():
44+
# For the latest recipe revision, keep the latest package revision only
45+
if latest == rref:
46+
# Get the latest package timestamp for each package_id
47+
latest_pref_list = [max([p for p in packages if p.package_id == pkg_id], key=lambda p: p.timestamp)
48+
for pkg_id in {p.package_id for p in packages}]
49+
for pref in packages:
50+
if pref not in latest_pref_list:
51+
conan_api.remove.package(pref, remote=remote)
52+
out.writeln(f"Removed package revision: {pref.repr_notime()} [{output_remote}]", fg=removed_color)
4453
else:
45-
packages = conan_api.list.packages_configurations(rrev, remote=remote)
46-
for package_ref in packages:
47-
all_prevs = conan_api.list.package_revisions(package_ref, remote=remote)
48-
latest_prev = all_prevs[0] if all_prevs else None
49-
for prev in all_prevs:
50-
if prev != latest_prev:
51-
conan_api.remove.package(prev, remote=remote)
52-
out.writeln(f"Removed package revision: {prev.repr_notime()} [{output_remote}]", fg=removed_color)
54+
# Otherwise, remove all outdated recipe revisions and their packages
55+
conan_api.remove.recipe(rref, remote=remote)
56+
out.writeln(f"Removed recipe revision: {rref.repr_notime()} "
57+
f"and all its package revisions [{output_remote}]", fg=removed_color)

0 commit comments

Comments
 (0)