Source code for rez.cli.cp

# SPDX-License-Identifier: Apache-2.0
# Copyright Contributors to the Rez Project


'''
Copy a package from one repository to another.
'''
from __future__ import print_function


[docs]def setup_parser(parser, completions=False): parser.add_argument( "--dest-path", metavar="PATH", help="package repository destination path. Defaults to the same " "repository as the given package (this is only supported for renaming " "and reversioning).") parser.add_argument( "--paths", metavar="PATHS", help="set package search path (ignores --no-local if set)") parser.add_argument( "--nl", "--no-local", dest="no_local", action="store_true", help="don't search local packages") parser.add_argument( "--reversion", metavar="VERSION", help="copy to a different package version") parser.add_argument( "--rename", metavar="NAME", help="copy to a different package name") parser.add_argument( "-o", "--overwrite", action="store_true", help="overwrite existing package/variants") parser.add_argument( "-s", "--shallow", action="store_true", help="perform a shallow copy (symlinks topmost directories)") parser.add_argument( "--follow-symlinks", action="store_true", help="follow symlinks when copying package payload, rather than copying " "the symlinks themselves.") parser.add_argument( "-k", "--keep-timestamp", action="store_true", help="keep timestamp of source package. Note that this is ignored if " "you're copying variant(s) into an existing package.") parser.add_argument( "-f", "--force", action="store_true", help="copy package even if it isn't relocatable (use at your own risk)") parser.add_argument( "--allow-empty", action="store_true", help="allow package copy into empty target repository") parser.add_argument( "--dry-run", action="store_true", help="dry run mode") parser.add_argument( "--variants", nargs='+', type=int, metavar="INDEX", help="select variants to copy (zero-indexed).") parser.add_argument( "--variant-uri", metavar="URI", help="copy variant with the given URI. Ignores --variants.") pkg_action = parser.add_argument( "PKG", nargs='?', help="package to copy") if completions: from rez.cli._complete_util import PackageCompleter pkg_action.completer = PackageCompleter
[docs]def command(opts, parser, extra_arg_groups=None): import os import sys from rez.config import config from rez.package_repository import package_repository_manager from rez.package_copy import copy_package from rez.utils.formatting import PackageRequest from rez.packages import iter_packages, get_variant_from_uri if opts.variant_uri: if opts.PKG: parser.error("Supply PKG or --variant-uri, not both.") elif not opts.PKG: parser.error("Expected PKG.") if (not opts.dest_path) and not (opts.rename or opts.reversion): parser.error("--dest-path must be specified unless --rename or " "--reversion are used.") # Load the source package. # if opts.variant_uri: variant = get_variant_from_uri(opts.variant_uri) if variant is None: print("Unknown variant: %s" % opts.variant_uri, file=sys.stderr) sys.exit(1) src_pkg = variant.parent variant_indexes = [variant.index] else: if opts.paths: paths = opts.paths.split(os.pathsep) paths = [x for x in paths if x] elif opts.no_local: paths = config.nonlocal_packages_path else: paths = None req = PackageRequest(opts.PKG) it = iter_packages( name=req.name, range_=req.range_, paths=paths ) src_pkgs = list(it) if not src_pkgs: print("No matching packages found.", file=sys.stderr) sys.exit(1) if len(src_pkgs) > 1: print("More than one package matches, please choose:", file=sys.stderr) for pkg in sorted(src_pkgs, key=lambda x: x.version): print(pkg.qualified_name, file=sys.stderr) sys.exit(1) src_pkg = src_pkgs[0] variant_indexes = opts.variants or None # Determine repo and perform checks. # # A common mistake may be to specify a dest package path, rather than the # _repo_ path. This would cause a mess, since a package would be installed # into a nested location within an existing package. # if opts.dest_path: dest_pkg_repo = package_repository_manager.get_repository(opts.dest_path) if (not opts.allow_empty) and dest_pkg_repo.is_empty(): print(( "Attempting to copy a package into an EMPTY repository. Are you " "sure that --dest-path is the correct path? This should not " "include package name and/or version." "\n\n" "If this is a valid new package repository, use the " "--allow-empty flag to continue." ), file=sys.stderr) sys.exit(1) else: dest_pkg_repo = src_pkg.repository # Perform the copy. # result = copy_package( package=src_pkg, dest_repository=dest_pkg_repo, dest_name=opts.rename, dest_version=opts.reversion, variants=variant_indexes, overwrite=opts.overwrite, shallow=opts.shallow, follow_symlinks=opts.follow_symlinks, keep_timestamp=opts.keep_timestamp, force=opts.force, verbose=opts.verbose, dry_run=opts.dry_run ) # Print info about the result. # copied = result["copied"] skipped = result["skipped"] if opts.dry_run: # show a good indication of target variant when it doesn't get created path = dest_pkg_repo.get_package_payload_path( package_name=opts.rename or src_pkg.name, package_version=opts.reversion or src_pkg.version ) dry_run_uri = path + "/?" verb = "would be" else: verb = "were" # specific output for non-varianted packages if src_pkg.num_variants == 0: if copied: dest_pkg = copied[0][1].parent print("Copied %s to %s" % (src_pkg.uri, dest_pkg.uri)) else: assert skipped dest_pkg = skipped[0][1].parent print( "Target package already exists: %s. Use 'overwrite' to replace it." % dest_pkg.uri ) # varianted package else: if copied: print("%d variants %s copied:" % (len(copied), verb)) for src_variant, dest_variant in copied: # None possible if dry_run if dest_variant is None: dest_uri = dry_run_uri else: dest_uri = dest_variant.uri print(" %s -> %s" % (src_variant.uri, dest_uri)) if skipped: print("%d variants %s skipped (target exists):" % (len(skipped), verb)) for src_variant, dest_variant in skipped: print(" %s !-> %s" % (src_variant.uri, dest_variant.uri))