From 55323dca4993f3eb72a831097f6520fb34599e03 Mon Sep 17 00:00:00 2001 From: James Date: Mon, 29 Mar 2021 16:34:37 +0200 Subject: [PATCH] added new lock install command (#8021) * added new lock install command * merged * working * lock install --recipes for speed --- conans/client/command.py | 11 +++- conans/client/conan_api.py | 37 ++++++++++++++ conans/client/manager.py | 2 +- .../graph_lock/lock_install_test.py | 50 +++++++++++++++++++ 4 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 conans/test/functional/graph_lock/lock_install_test.py diff --git a/conans/client/command.py b/conans/client/command.py index 1d1bc365a6f..4e5f7b47745 100644 --- a/conans/client/command.py +++ b/conans/client/command.py @@ -1890,6 +1890,13 @@ def lock(self, *args): clean_modified_cmd = subparsers.add_parser('clean-modified', help='Clean modified flags') clean_modified_cmd.add_argument('lockfile', help='Path to the lockfile') + install_cmd = subparsers.add_parser('install', help='Install a lockfile') + install_cmd.add_argument('lockfile', help='Path to the lockfile') + install_cmd.add_argument("--recipes", action="store_true", + help="Install only recipes, not binaries") + install_cmd.add_argument("-g", "--generator", nargs=1, action=Extender, + help='Generators to use') + create_cmd = subparsers.add_parser('create', help='Create a lockfile from a conanfile or a reference') create_cmd.add_argument("path", nargs="?", help="Path to a conanfile, including filename, " @@ -1933,7 +1940,9 @@ def lock(self, *args): args = parser.parse_args(*args) self._warn_python_version() - if args.subcommand == "update": + if args.subcommand == "install": + self._conan.lock_install(args.lockfile, generators=args.generator, recipes=args.recipes) + elif args.subcommand == "update": self._conan.lock_update(args.old_lockfile, args.new_lockfile) elif args.subcommand == "bundle": if args.bundlecommand == "create": diff --git a/conans/client/conan_api.py b/conans/client/conan_api.py index 321c997e5a5..bc65362daef 100644 --- a/conans/client/conan_api.py +++ b/conans/client/conan_api.py @@ -1344,6 +1344,43 @@ def lock_clean_modified(self, lockfile, cwd=None): graph_lock.clean_modified() graph_lock_file.save(lockfile) + @api_method + def lock_install(self, lockfile, remote_name=None, build=None, + generators=None, install_folder=None, cwd=None, + lockfile_out=None, recipes=None): + lockfile = _make_abs_path(lockfile, cwd) if lockfile else None + graph_info = get_graph_info(None, None, cwd, None, + self.app.cache, self.app.out, lockfile=lockfile) + + if not generators: # We don't want the default txt + generators = False + + install_folder = _make_abs_path(install_folder, cwd) + + mkdir(install_folder) + remotes = self.app.load_remotes(remote_name=remote_name) + recorder = ActionRecorder() + graph_lock = graph_info.graph_lock + root_id = graph_lock.root_node_id() + reference = graph_lock.nodes[root_id].ref + if recipes: + graph = self.app.graph_manager.load_graph(reference, create_reference=None, + graph_info=graph_info, build_mode=None, + check_updates=False, update=None, + remotes=remotes, recorder=recorder, + lockfile_node_id=root_id) + print_graph(graph, self.app.out) + else: + deps_install(self.app, ref_or_path=reference, install_folder=install_folder, + remotes=remotes, graph_info=graph_info, build_modes=build, + generators=generators, recorder=recorder, lockfile_node_id=root_id) + + if lockfile_out: + lockfile_out = _make_abs_path(lockfile_out, cwd) + graph_lock_file = GraphLockFile(graph_info.profile_host, graph_info.profile_build, + graph_info.graph_lock) + graph_lock_file.save(lockfile_out) + @api_method def lock_bundle_create(self, lockfiles, lockfile_out, cwd=None): cwd = cwd or os.getcwd() diff --git a/conans/client/manager.py b/conans/client/manager.py index 7ff82470d53..558eb247665 100644 --- a/conans/client/manager.py +++ b/conans/client/manager.py @@ -35,8 +35,8 @@ def deps_install(app, ref_or_path, install_folder, graph_info, remotes=None, bui @param generators: List of generators from command line. If False, no generator will be written @param no_imports: Install specified packages but avoid running imports - """ + out, user_io, graph_manager, cache = app.out, app.user_io, app.graph_manager, app.cache remote_manager, hook_manager = app.remote_manager, app.hook_manager profile_host, profile_build = graph_info.profile_host, graph_info.profile_build diff --git a/conans/test/functional/graph_lock/lock_install_test.py b/conans/test/functional/graph_lock/lock_install_test.py new file mode 100644 index 00000000000..b7561387c39 --- /dev/null +++ b/conans/test/functional/graph_lock/lock_install_test.py @@ -0,0 +1,50 @@ +from conans.test.utils.tools import TestClient, GenConanfile + + +def test_install(): + client = TestClient() + client.save({"conanfile.py": GenConanfile("pkga", "0.1").with_package_file("file.h", "0.1")}) + client.run("create . user/channel") + + # Use a consumer with a version range + client.save({"conanfile.py": + GenConanfile("pkgb", "0.1").with_require("pkga/[>=0.1]@user/channel")}) + client.run("create . user/channel") + client.run("lock create --reference=pkgb/0.1@user/channel --lockfile-out=lock1.lock") + + # We can create a pkga/0.2, but it will not be used + client.save({"conanfile.py": GenConanfile("pkga", "0.2").with_package_file("file.h", "0.2")}) + client.run("create . user/channel") + + client.run("lock install lock1.lock -g deploy") + assert "pkga/0.1@user/channel from local cache" in client.out + file_h = client.load("pkga/file.h") + assert file_h == "0.1" + + +def test_install_recipes(): + client = TestClient(default_server_user=True) + client.save({"conanfile.py": GenConanfile("pkga", "0.1").with_package_file("file.h", "0.1")}) + client.run("create . user/channel") + + # Use a consumer with a version range + client.save({"conanfile.py": + GenConanfile("pkgb", "0.1").with_require("pkga/[>=0.1]@user/channel")}) + client.run("create . user/channel") + client.run("lock create --reference=pkgb/0.1@user/channel --lockfile-out=lock1.lock") + + # We can create a pkga/0.2, but it will not be used + client.save({"conanfile.py": GenConanfile("pkga", "0.2").with_package_file("file.h", "0.2")}) + client.run("create . user/channel") + + client.run("lock install lock1.lock --recipes") + assert "pkga/0.1@user/channel:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9 - Cache" in client.out + assert "pkgb/0.1@user/channel:cfd10f60aeaa00f5ca1f90b5fe97c3fe19e7ec23 - Cache" in client.out + + client.run("upload * --all -c") + client.run("remove * -f") + client.run("lock install lock1.lock --recipes") + + assert "pkga/0.1@user/channel:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9 - Download" in client.out + assert "pkgb/0.1@user/channel:cfd10f60aeaa00f5ca1f90b5fe97c3fe19e7ec23 - Download" in client.out +