自定义命令:清理旧的 recipe 和 package 版本¶
注意
这主要是一个示例命令。内置的 conan remove *#!latest
语法,意思是“除最新版本之外的所有版本”,对于此用例来说可能已足够,而无需此自定义命令。
请首先克隆源代码以重新创建此项目。你可以在 GitHub 上的 examples2 仓库中找到它们
$ git clone https://github.com/conan-io/examples2.git
$ cd examples2/examples/extensions/commands/clean
在本例中,我们将演示如何创建/使用自定义命令:conan clean。它会删除本地缓存或远端中的所有 recipe 及其 package 版本,但保留最新 recipe 的最新 package 版本。
注意
为了更好地理解本例,强烈建议您先阅读 自定义命令参考。
定位命令¶
将命令文件 cmd_clean.py
复制到您的 [YOUR_CONAN_HOME]/extensions/commands/
文件夹中(如果不存在则创建)。如果您不知道 [YOUR_CONAN_HOME]
的位置,可以运行 conan config home 来查看。
运行它¶
现在,您应该能够在命令提示符中看到新命令
$ conan -h
...
Custom commands
clean Deletes (from local cache or remotes) all recipe and package revisions but the
latest package revision from the latest recipe revision.
$ conan clean -h
usage: conan clean [-h] [-r REMOTE] [--force]
Deletes (from local cache or remotes) all recipe and package revisions but
the latest package revision from the latest recipe revision.
optional arguments:
-h, --help show this help message and exit
-r REMOTE, --remote REMOTE
Will remove from the specified remote
--force Remove without requesting a confirmation
最后,如果您执行 conan clean
$ conan clean
Do you want to remove all the recipes revisions and their packages ones, except the latest package revision from the latest recipe one? (yes/no): yes
other/1.0
Removed package revision: other/1.0#31da245c3399e4124e39bd4f77b5261f:da39a3ee5e6b4b0d3255bfef95601890afd80709#a16985deb2e1aa73a8480faad22b722c [Local cache]
Removed recipe revision: other/1.0#721995a35b1a8d840ce634ea1ac71161 and all its package revisions [Local cache]
hello/1.0
Removed package revision: hello/1.0#9a77cdcff3a539b5b077dd811b2ae3b0:da39a3ee5e6b4b0d3255bfef95601890afd80709#cee90a74944125e7e9b4f74210bfec3f [Local cache]
Removed package revision: hello/1.0#9a77cdcff3a539b5b077dd811b2ae3b0:da39a3ee5e6b4b0d3255bfef95601890afd80709#7cddd50952de9935d6c3b5b676a34c48 [Local cache]
libcxx/0.1
如果您再次运行它,应该不会发生任何事情
$ conan clean
Do you want to remove all the recipes revisions and their packages ones, except the latest package revision from the latest recipe one? (yes/no): yes
other/1.0
hello/1.0
libcxx/0.1
代码导览¶
conan clean
命令的代码如下
from conan.api.conan_api import ConanAPI
from conan.api.output import ConanOutput, Color
from conan.cli.command import OnceArgument, conan_command
recipe_color = Color.BRIGHT_BLUE
removed_color = Color.BRIGHT_YELLOW
@conan_command(group="Custom commands")
def clean(conan_api: ConanAPI, parser, *args):
"""
Deletes (from local cache or remotes) all recipe and package revisions but
the latest package revision from the latest recipe revision.
"""
parser.add_argument('-r', '--remote', action=OnceArgument,
help='Will remove from the specified remote')
args = parser.parse_args(*args)
out = ConanOutput()
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)
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)
让我们分析最重要的部分。
parser¶
parser
参数是 Python 命令行解析库 argparse.ArgumentParser
的一个实例,因此如果您想了解更多关于其 API 的信息,请访问 其官方网站。
用户输出¶
ConanOutput()
: 用于管理用户输出的类。在本例中,我们仅使用 out.writeln(message, fg=None, bg=None)
,其中 fg
是字体前景色,bg
是字体背景色。除此之外,您还有一些预定义的方法,如 out.info()
、out.success()
、out.error()
等。
Conan 公共 API¶
警告
此特性是实验性的,可能会发生破坏性变更。有关详细信息,请参阅 Conan 稳定性 部分。
本例中最重要的部分是通过 conan_api
参数使用 Conan API。以下是此自定义命令中使用的一些示例
conan_api.remotes.get(args.remote)
conan_api.search.recipes("*/*", remote=remote)
conan_api.list.recipe_revisions(recipe, remote=remote)
conan_api.remove.recipe(rrev, remote=remote)
conan_api.list.packages_configurations(rrev, remote=remote)
conan_api.list.package_revisions(package_ref, remote=remote)
conan_api.remove.package(prev, remote=remote)
conan_api.remotes.get(...)
:[RemotesAPI]
根据远程名称返回一个 RemoteRegistry。conan_api.search.recipes(...)
:[SearchAPI]
返回匹配给定模式的所有 recipes 列表。conan_api.list.recipe_revisions(...)
:[ListAPI]
根据 recipe 引用返回所有 recipe 版本的列表。conan_api.list.packages_configurations(...)
:[ListAPI]
返回某个 recipe 版本的不同配置(package_id)列表。conan_api.list.package_revisions(...)
:[ListAPI]
返回给定 recipe 版本的 package 版本列表。conan_api.remove.recipe(...)
:[RemoveAPI]
删除给定的 recipe 版本。conan_api.remove.package(...)
:[RemoveAPI]
删除给定的 package 版本。
除此之外,这些行也值得特别关注
all_rrevs = conan_api.list.recipe_revisions(recipe, remote=remote)
latest_rrev = all_rrevs[0] if all_rrevs else None
...
packages = conan_api.list.packages_configurations(rrev, remote=remote)
...
all_prevs = conan_api.list.package_revisions(package_ref, remote=remote)
latest_prev = all_prevs[0] if all_prevs else None
基本上,这些 API 调用分别返回 recipe 版本和 package 版本的列表,但我们将第一个元素保存为最新版本,因为这些调用始终获取的是有序列表。
如果您想了解更多关于 Conan API 的信息,请访问 ConanAPI 部分