diff --git a/conan/cli/commands/workspace.py b/conan/cli/commands/workspace.py index 36ab1368dc9..5eaa7390076 100644 --- a/conan/cli/commands/workspace.py +++ b/conan/cli/commands/workspace.py @@ -9,6 +9,7 @@ from conan.cli.args import add_reference_args, add_common_install_arguments, add_lockfile_args from conan.cli.command import conan_command, conan_subcommand from conan.cli.commands.list import print_serial +from conan.cli.formatters.graph import format_graph_json from conan.cli.printers import print_profiles from conan.cli.printers.graph import print_graph_packages, print_graph_basic from conan.errors import ConanException @@ -187,7 +188,7 @@ def _install_build(conan_api: ConanAPI, parser, subparser, build, *args): conan_api.command.run(cmd) -@conan_subcommand() +@conan_subcommand(formatters={"json": format_graph_json}) def workspace_super_install(conan_api: ConanAPI, parser, subparser, *args): """ Install the workspace as a monolith, installing only external dependencies to the workspace, @@ -197,6 +198,14 @@ def workspace_super_install(conan_api: ConanAPI, parser, subparser, *args): subparser.add_argument("-g", "--generator", action="append", help='Generators to use') subparser.add_argument("-of", "--output-folder", help='The root output folder for generated and build files') + subparser.add_argument("-d", "--deployer", action="append", + help="Deploy using the provided deployer to the output folder. " + "Built-in deployers: 'full_deploy', 'direct_deploy', 'runtime_deploy'") + subparser.add_argument("--deployer-folder", + help="Deployer output folder, base build folder by default if not set") + subparser.add_argument("--deployer-package", action="append", + help="Execute the deploy() method of the packages matching " + "the provided patterns") subparser.add_argument("--envs-generation", default=None, choices=["false"], help="Generation strategy for virtual environment files for the root") add_common_install_arguments(subparser) @@ -229,9 +238,16 @@ def workspace_super_install(conan_api: ConanAPI, parser, subparser, *args): lockfile=lockfile) print_graph_packages(ws_graph) conan_api.install.install_binaries(deps_graph=ws_graph, remotes=remotes) + ConanOutput().title("Finalizing install (deploy, generators)") output_folder = make_abs_path(args.output_folder) if args.output_folder else None conan_api.install.install_consumer(ws_graph, args.generator, ws_folder, output_folder, + deploy=args.deployer, deploy_package=args.deployer_package, + deploy_folder=args.deployer_folder, envs_generation=args.envs_generation) + ConanOutput().success("Install finished successfully") + + return {"graph": ws_graph, + "conan_api": conan_api} @conan_subcommand() diff --git a/test/integration/workspace/test_workspace.py b/test/integration/workspace/test_workspace.py index b5c92f9a999..44c4f7814b7 100644 --- a/test/integration/workspace/test_workspace.py +++ b/test/integration/workspace/test_workspace.py @@ -785,6 +785,46 @@ def test_intermediate_non_editable(self): assert ("Workspace definition error. Package libb/0.1 in the Conan cache " "has dependencies to packages in the workspace: [liba/0.1]") in c.out + def test_deployers_json(self): + c = TestClient() + dep = textwrap.dedent(""" + import os + from conan.tools.files import save + from conan import ConanFile + class Dep(ConanFile): + name = "dep" + version = "1.0" + + def package(self): + save(self, os.path.join(self.package_folder, "myfile.txt"), "content") + """) + pkg = textwrap.dedent(""" + import os + from conan.tools.files import save + from conan import ConanFile + class Dep(ConanFile): + name = "pkg" + version = "1.0" + requires = "dep/1.0" + + def package(self): + save(self, os.path.join(self.package_folder, "myfile.txt"), "content") + """) + c.save({"dep/conanfile.py": dep, + "pkg/conanfile.py": pkg}) + c.run("workspace init") + c.run("create dep") + c.run("workspace add pkg") + c.run("workspace super-install --format=json --deployer=full_deploy") + graph = json.loads(c.stdout) + # Only 1 node, pkg is not a node in the graph! + assert graph["graph"]["nodes"]["1"]["name"] == "dep" + deploy_folder = os.path.join(c.current_folder, "full_deploy", "host") + folders = os.listdir(deploy_folder) + assert "dep" in folders + assert "pkg" not in folders + assert os.path.isfile(os.path.join(deploy_folder, "dep", "1.0", "myfile.txt")) + def test_workspace_with_local_recipes_index(): c3i_folder = temp_folder()