Skip to content

Commit

Permalink
moving code from cli to conan_api
Browse files Browse the repository at this point in the history
  • Loading branch information
memsharded committed Jan 14, 2025
1 parent 13d4c3d commit d27fef9
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 32 deletions.
15 changes: 13 additions & 2 deletions conan/api/subapi/graph.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from conan.api.output import ConanOutput
from conan.internal.conan_app import ConanApp, ConanBasicApp
from conans.client.graph.graph import Node, RECIPE_CONSUMER, CONTEXT_HOST, RECIPE_VIRTUAL, \
CONTEXT_BUILD
CONTEXT_BUILD, BINARY_MISSING
from conans.client.graph.graph_binaries import GraphBinariesAnalyzer
from conans.client.graph.graph_builder import DepsGraphBuilder
from conans.client.graph.profile_node_definer import initialize_conanfile_profile, consumer_definer
from conan.errors import ConanException
from conan.internal.model.recipe_ref import RecipeReference
from conan.internal.model.recipe_ref import RecipeReference, ref_matches


class GraphAPI:
Expand Down Expand Up @@ -200,3 +200,14 @@ def analyze_binaries(self, graph, build_mode=None, remotes=None, update=None, lo
binaries_analyzer = GraphBinariesAnalyzer(conan_app, self.conan_api.config.global_conf)
binaries_analyzer.evaluate_graph(graph, build_mode, lockfile, remotes, update,
build_modes_test, tested_graph)

@staticmethod
def find_first_missing_binary(graph, missing=None):
""" (Experimental) Given a dependency graph, will return the first node with a
missing binary package
"""
for node in graph.ordered_iterate():
if ((not missing and node.binary == BINARY_MISSING) # First missing binary or specified
or (missing and ref_matches(node.ref, missing, is_consumer=None))):
return node.ref, node.conanfile.info
raise ConanException("There is no missing binary")
6 changes: 5 additions & 1 deletion conan/api/subapi/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def install_consumer(self, deps_graph, generators=None, source_folder=None, outp
# Issue related: https://github.com/conan-io/conan/issues/16543
base_folder = os.path.abspath(deploy_folder) if deploy_folder \
else conanfile.folders.base_build
do_deploys(self.conan_api, deps_graph, deploy, deploy_package, base_folder)
do_deploys(self.conan_api.home_folder, deps_graph, deploy, deploy_package, base_folder)

final_generators = []
# Don't use set for uniqueness because order matters
Expand All @@ -89,3 +89,7 @@ def install_consumer(self, deps_graph, generators=None, source_folder=None, outp
hook_manager = HookManager(HomePaths(self.conan_api.home_folder).hooks_path)
write_generators(conanfile, hook_manager, self.conan_api.home_folder,
envs_generation=envs_generation)

def deploy(self, graph, deployer, deploy_package=None, deploy_folder=None):
return do_deploys(self.conan_api.home_folder, graph, deployer, deploy_package=deploy_package,
deploy_folder=deploy_folder)
2 changes: 2 additions & 0 deletions conan/api/subapi/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ def msg_format(msg, item, total):
return select_bundle

def explain_missing_binaries(self, ref, conaninfo, remotes):
""" (Experimental) Explain why a binary is missing in the cache
"""
ConanOutput().info(f"Missing binary: {ref}")
ConanOutput().info(f"With conaninfo.txt (package_id):\n{conaninfo.dumps()}")
conaninfo = load_binary_info(conaninfo.dumps())
Expand Down
9 changes: 9 additions & 0 deletions conan/api/subapi/lockfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ def update_lockfile(lockfile, graph, lock_packages=False, clean=False):
lockfile.update_lock(graph, lock_packages)
return lockfile

@staticmethod
def merge_lockfiles(lockfiles):
result = Lockfile()
for lockfile in lockfiles:
lockfile = make_abs_path(lockfile)
graph_lock = Lockfile.load(lockfile)
result.merge(graph_lock)
return result

@staticmethod
def add_lockfile(lockfile=None, requires=None, build_requires=None, python_requires=None,
config_requires=None):
Expand Down
19 changes: 4 additions & 15 deletions conan/cli/commands/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@
from conan.cli.printers import print_profiles
from conan.cli.printers.graph import print_graph_packages, print_graph_basic
from conan.errors import ConanException
from conan.internal.deploy import do_deploys
from conans.client.graph.graph import BINARY_MISSING
from conans.client.graph.install_graph import InstallGraph, ProfileArgs
from conan.internal.errors import NotFoundException
from conan.internal.model.recipe_ref import ref_matches, RecipeReference
from conan.internal.model.recipe_ref import RecipeReference


def explain_formatter_text(data):
Expand Down Expand Up @@ -239,7 +237,7 @@ def graph_info(conan_api, parser, subparser, *args):
conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out, cwd)
if args.deployer:
base_folder = args.deployer_folder or os.getcwd()
do_deploys(conan_api, deps_graph, args.deployer, None, base_folder)
conan_api.install.deploy(deps_graph, args.deployer, None, base_folder)

return {"graph": deps_graph,
"field_filter": args.filter,
Expand Down Expand Up @@ -303,17 +301,8 @@ def graph_explain(conan_api, parser, subparser, *args):
print_graph_packages(deps_graph)

ConanOutput().title("Retrieving and computing closest binaries")
# compute ref and conaninfo
missing = args.missing
for node in deps_graph.ordered_iterate():
if ((not missing and node.binary == BINARY_MISSING) # First missing binary or
or (missing and ref_matches(node.ref, missing, is_consumer=None))): # specified one
ref = node.ref
conaninfo = node.conanfile.info
break
else:
raise ConanException("There is no missing binary")

# compute ref and conaninfo of the first missing binary
ref, conaninfo = conan_api.graph.first_missing_binary(deps_graph, args.missing)
pkglist = conan_api.list.explain_missing_binaries(ref, conaninfo, remotes)

ConanOutput().title("Closest binaries")
Expand Down
17 changes: 5 additions & 12 deletions conan/cli/commands/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from conan.cli import make_abs_path
from conan.cli.args import common_graph_args, validate_common_graph_args
from conan.cli.printers.graph import print_graph_packages, print_graph_basic
from conan.internal.model.lockfile import Lockfile, LOCKFILE
from conan.internal.model.recipe_ref import RecipeReference


Expand Down Expand Up @@ -68,17 +67,11 @@ def lock_merge(conan_api, parser, subparser, *args): # noqa
Merge 2 or more lockfiles.
"""
subparser.add_argument('--lockfile', action="append", help='Path to lockfile to be merged')
subparser.add_argument("--lockfile-out", action=OnceArgument, default=LOCKFILE,
subparser.add_argument("--lockfile-out", action=OnceArgument, default="conan.lock",
help="Filename of the created lockfile")

args = parser.parse_args(*args)

result = Lockfile()
for lockfile in args.lockfile:
lockfile = make_abs_path(lockfile)
graph_lock = Lockfile.load(lockfile)
result.merge(graph_lock)

result = conan_api.lockfile.merge_lockfiles(args.lockfile)
lockfile_out = make_abs_path(args.lockfile_out)
result.save(lockfile_out)
ConanOutput().info("Generated lockfile: %s" % lockfile_out)
Expand All @@ -100,7 +93,7 @@ def lock_add(conan_api, parser, subparser, *args):
help='Add python-requires to lockfile')
subparser.add_argument('--config-requires', action="append",
help='Add config-requires to lockfile')
subparser.add_argument("--lockfile-out", action=OnceArgument, default=LOCKFILE,
subparser.add_argument("--lockfile-out", action=OnceArgument, default="conan.lock",
help="Filename of the created lockfile")
subparser.add_argument("--lockfile", action=OnceArgument, help="Filename of the input lockfile")
args = parser.parse_args(*args)
Expand Down Expand Up @@ -142,7 +135,7 @@ def lock_remove(conan_api, parser, subparser, *args):
help='Remove python-requires from lockfile')
subparser.add_argument('--config-requires', action="append",
help='Remove config-requires from lockfile')
subparser.add_argument("--lockfile-out", action=OnceArgument, default=LOCKFILE,
subparser.add_argument("--lockfile-out", action=OnceArgument, default="conan.lock",
help="Filename of the created lockfile")
subparser.add_argument("--lockfile", action=OnceArgument, help="Filename of the input lockfile")
args = parser.parse_args(*args)
Expand Down Expand Up @@ -170,7 +163,7 @@ def lock_update(conan_api, parser, subparser, *args):
help='Update python-requires from lockfile')
subparser.add_argument('--config-requires', action="append",
help='Update config-requires from lockfile')
subparser.add_argument("--lockfile-out", action=OnceArgument, default=LOCKFILE,
subparser.add_argument("--lockfile-out", action=OnceArgument, default="conan.lock",
help="Filename of the created lockfile")
subparser.add_argument("--lockfile", action=OnceArgument, help="Filename of the input lockfile")
args = parser.parse_args(*args)
Expand Down
4 changes: 2 additions & 2 deletions conan/internal/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def _load(path):
raise ConanException(f"Cannot find deployer '{d}'")


def do_deploys(conan_api, graph, deploy, deploy_package, deploy_folder):
def do_deploys(home_folder, graph, deploy, deploy_package, deploy_folder):
try:
mkdir(deploy_folder)
except Exception as e:
Expand All @@ -68,7 +68,7 @@ def do_deploys(conan_api, graph, deploy, deploy_package, deploy_folder):
with conanfile_exception_formatter(conanfile, "deploy"):
conanfile.deploy()
# Handle the deploys
cache = HomePaths(conan_api.cache_folder)
cache = HomePaths(home_folder)
for d in deploy or []:
deployer = _find_deployer(d, cache.deployers_path)
# IMPORTANT: Use always kwargs to not break if it changes in the future
Expand Down
4 changes: 4 additions & 0 deletions conans/client/graph/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,10 @@ def __init__(self):
self.options_conflicts = {}
self.error = False

def lockfile(self):
from conan.internal.model.lockfile import Lockfile
return Lockfile(self)

def overrides(self):
return Overrides.create(self.nodes)

Expand Down

0 comments on commit d27fef9

Please sign in to comment.