def _is_definition(package, format_, search=True): """Check for if a package defines a Rez package file. Except if we've already checked the Rez package's repository and still haven't found a good answer, stop searching and just return False, to avoid a cyclic loop. """ if not inspection.is_built_package(package): path = finder.get_package_root(package) try: packages_.get_developer_package(path, format=format_) except rez_exceptions.PackageMetadataError: return False return True if not search: return False repository = get_repository(package) repository_package = get_package(repository.working_dir, package.name) return _is_definition(repository_package, format_=format_, search=False)
def test_7(self): """test variant installation.""" repo_path = os.path.join(self.root, "packages") if not os.path.exists(repo_path): os.makedirs(repo_path) def _data(obj): d = obj.validated_data() keys = package_release_keys + ("base", ) for key in keys: d.pop(key, None) return d # package with variants and package without dev_pkgs_list = (("developer", "developer_changed"), ("developer_novar", "developer_novar_changed")) for path1, path2 in dev_pkgs_list: path = os.path.join(self.packages_base_path, path1) package = get_developer_package(path) # install variants of the developer package into new repo variant = package.iter_variants().next() result = variant.install(repo_path, dry_run=True) self.assertEqual(result, None) for variant in package.iter_variants(): variant.install(repo_path) variant = package.iter_variants().next() result = variant.install(repo_path, dry_run=True) self.assertNotEqual(result, None) # now there should be a package that matches the dev package installed_package = get_package(package.name, package.version, paths=[repo_path]) data = _data(package) data_ = _data(installed_package) self.assertDictEqual(data, data_) # make a change in the dev pkg, outside of the variants. path = os.path.join(self.packages_base_path, path2) package = get_developer_package(path) # install a variant again. Even though the variant is already installed, # this should update the package, because data outside the variant changed. variant = package.iter_variants().next() result = variant.install(repo_path, dry_run=True) self.assertEqual(result, None) variant.install(repo_path) # check that the change was applied. This effectively also checks that the # variant order hasn't changed. installed_package = get_package(package.name, package.version, paths=[repo_path]) data = _data(package) data_ = _data(installed_package) self.assertDictEqual(data, data_)
def test_7(self): """test variant installation.""" repo_path = os.path.join(self.root, "packages") if not os.path.exists(repo_path): os.makedirs(repo_path) def _data(obj): d = obj.validated_data() keys = package_release_keys + ("base",) for key in keys: d.pop(key, None) return d # package with variants and package without dev_pkgs_list = (("developer", "developer_changed"), ("developer_novar", "developer_novar_changed")) for path1, path2 in dev_pkgs_list: path = os.path.join(self.packages_base_path, path1) package = get_developer_package(path) # install variants of the developer package into new repo variant = package.iter_variants().next() result = variant.install(repo_path, dry_run=True) self.assertEqual(result, None) for variant in package.iter_variants(): variant.install(repo_path) variant = package.iter_variants().next() result = variant.install(repo_path, dry_run=True) self.assertNotEqual(result, None) # now there should be a package that matches the dev package installed_package = get_package(package.name, package.version, paths=[repo_path]) data = _data(package) data_ = _data(installed_package) self.assertDictEqual(data, data_) # make a change in the dev pkg, outside of the variants. path = os.path.join(self.packages_base_path, path2) package = get_developer_package(path) # install a variant again. Even though the variant is already installed, # this should update the package, because data outside the variant changed. variant = package.iter_variants().next() result = variant.install(repo_path, dry_run=True) self.assertEqual(result, None) variant.install(repo_path) # check that the change was applied. This effectively also checks that the # variant order hasn't changed. installed_package = get_package(package.name, package.version, paths=[repo_path]) data = _data(package) data_ = _data(installed_package) self.assertDictEqual(data, data_)
def test_get_context(self): """Check that Rez can resolve a context correctly and return it.""" directory = testing_packaging.make_fake_source_package( "some_package", textwrap.dedent("""\ name = "some_package" version = "1.0.0" requires = [ "some_dependency-1", ] """), ) self.delete_item_later(os.path.dirname(directory)) package = packages_.get_developer_package(directory) dependency_directory = testing_packaging.make_fake_source_package( "some_dependency", textwrap.dedent("""\ name = "some_dependency" version = "1.1.0" build_command = "echo 'foo'" """), ) self.delete_item_later(os.path.dirname(dependency_directory)) dependency_package = packages_.get_developer_package( dependency_directory) dependency_build_path = tempfile.mkdtemp( suffix="_dependency_build_path") self.delete_item_later(dependency_build_path) dependency_package = creator.build(dependency_package, dependency_build_path, quiet=True) dependency_path = inspection.get_packages_path_from_package( dependency_package) context = dict() with testing_packaging.override_packages_path([dependency_path], prepend=True): packaging.SourceResolvedContext.run(package, context) self.assertTrue(lint_constant.RESOLVED_SOURCE_CONTEXT in context) rez_resolved = context[lint_constant.RESOLVED_SOURCE_CONTEXT] self.assertEqual(os.path.join(directory), rez_resolved.get_environ()["REZ_SOME_PACKAGE_ROOT"]) self.assertEqual(set(), context[lint_constant.DEPENDENT_PACKAGES])
def _create_fake_rez_dependency_package(name, help_=common.DEFAULT_CODE): directory = os.path.join( tempfile.mkdtemp(suffix="package_{name}".format(name=name)), name) contents = textwrap.dedent("""\ name = "{name}" version = "1.0.0" description = "fake package" def commands(): import os env.PYTHONPATH.append(os.path.join("{{root}}", "python")) """) if help_ != common.DEFAULT_CODE: contents += "\nhelp = {help_!r}" os.makedirs(os.path.join(directory, "python", name)) with open(os.path.join(directory, "package.py"), "w") as handler: handler.write(contents.format(name=name, help_=help_)) open(os.path.join(directory, "python", name, "__init__.py"), "a").close() open(os.path.join(directory, "python", name, "some_module.py"), "a").close() return packages_.get_developer_package(directory)
def command(opts, parser, extra_arg_groups=None): from rez.packages_ import get_developer_package from rez.serialise import FileFormat import os.path import os import sys if opts.PATH: path = os.path.expanduser(opts.PATH) else: path = os.getcwd() if os.path.basename(path) == "package.yaml": path = os.path.dirname(path) filepath_yaml = os.path.join(path, "package.yaml") if not os.path.isfile(filepath_yaml): print >>sys.stderr, "Expected file '%s'" % filepath_yaml sys.exit(1) package = get_developer_package(path) if package is None: print >>sys.stderr, "Couldn't load the package at %r" % cwd sys.exit(1) package.print_info(format_=FileFormat.py)
def command(opts, parser, extra_arg_groups=None): from rez.packages_ import get_developer_package from rez.serialise import FileFormat import os.path import os import sys if opts.PATH: path = os.path.expanduser(opts.PATH) else: path = os.getcwd() if os.path.basename(path) == "package.yaml": path = os.path.dirname(path) filepath_yaml = os.path.join(path, "package.yaml") if not os.path.isfile(filepath_yaml): print >> sys.stderr, "Expected file '%s'" % filepath_yaml sys.exit(1) package = get_developer_package(path) if package is None: print >> sys.stderr, "Couldn't load the package at %r" % cwd sys.exit(1) package.print_info(format_=FileFormat.py)
def __init__(self, working_dir, build_system, vcs=None, ensure_latest=True, verbose=False): """Create a BuildProcess. Args: working_dir (str): Directory containing the package to build. build_system (`BuildSystem`): Build system used to build the package. vcs (`ReleaseVCS`): Version control system to use for the release process. If None, the package will only be built, not released. ensure_latest: If True, do not allow the release process to occur if an newer versioned package is already released. """ self.verbose = verbose self.working_dir = working_dir self.build_system = build_system self.vcs = vcs self.ensure_latest = ensure_latest if vcs and vcs.path != working_dir: raise BuildProcessError( "Build process was instantiated with a mismatched VCS instance" ) self.debug_print = config.debug_printer("package_release") self.package = get_developer_package(working_dir) hook_names = self.package.config.release_hooks or [] self.hooks = create_release_hooks(hook_names, working_dir) self.build_path = os.path.join(self.working_dir, self.package.config.build_directory)
def _search_current_folder(directory): """Find the user's Rez package or die trying. Args: directory (str): The absolute path to a folder which should have a package.py / package.yaml / package.txt underneath. Raises: :class:`.NoPackageFound`: If No Rez package could be found. Returns: :class:`rez.packages_.Package`: The found Rez package. """ try: package = packages_.get_developer_package(directory) except rez_exceptions.PackageMetadataError: raise exceptions.NoPackageFound( 'Directory "{directory}" does not define a Rez package.'.format( directory=directory ) ) if package: return package raise exceptions.NoPackageFound( 'Directory "{directory}" does not define a Rez package.'.format( directory=directory ) )
def make_fake_repository(packages, root): """Create a new git repository that contains the given Rez packages. This function is a bit hacky. It creates a git repository, which is fine, but Rez packages create "in-memory" packages based on actual package.py files on-disk. So the packages need to copied to the folder where the repository was created and "re-queried" in order to be "true" developer Rez packages. If there was a way to easily create a developer Rez package, I'd do that. But meh, too much work. Args: packages (iter[:class:`rez.developer_package.DeveloperPackage`]): The Rez packages that will be copied into the new git repository. root (str): The folder on-disk that represents the top-level folder for every Rez package in `packages`. Returns: tuple[:class:`git.Repo`, list[:class:`rez.developer_package.DeveloperPackage`]]: The newly created repository + the Rez packages that got copied into it. """ repository_root = os.path.join( tempfile.mkdtemp(suffix="_clone_repository"), "test_folder") os.makedirs(repository_root) initialized_packages = [] for package in packages: package_root = finder.get_package_root(package) relative = os.path.relpath(package_root, root) destination = os.path.join(repository_root, relative) parent = os.path.dirname(destination) if not os.path.isdir(parent): os.makedirs(parent) shutil.copytree(package_root, destination) initialized_packages.append( packages_.get_developer_package(destination)) remote_root = tempfile.mkdtemp(suffix="_remote_bare_repository") # `git.Repo.init` needs to build from a non-existent folder. So we `shutil.rmtree` here shutil.rmtree(remote_root) remote_root += ".git" # bare repositories, by convention, end in ".git" remote = git.Repo.init(remote_root, bare=True) repository = git.Repo.init(repository_root) repository.index.add( [item for item in os.listdir(repository_root) if item != ".git"]) repository.index.commit("initial commit") repository.create_remote("origin", url=remote.working_dir) origin = repository.remotes.origin origin.push(refspec="master:master") repository.heads.master.set_tracking_branch( origin.refs.master) # set local "master" to track remote "master return repository, initialized_packages, remote_root
def _get_safe_package(path): try: return {packages_.get_developer_package(path)}, set() except rez_exceptions.PackageMetadataError: return set(), set() except schema.SchemaError: return set(), {path}
def _make_installed_package(self, name, text, packages_path=None): """Create a Rez source package and install it into a temporary directory. All temporary directories will be marked for clean-up. Clean-up occurs after each test is run. Args: name (str): The name of the source Rez packge to create. text (str): The text that will be used for a "package.py" file. packages_path (list[str], optional): The paths that will be used to search for Rez packages while building. This is usually to make it easier to find package dependencies. If `packages_path` is not defined, Rez will use its default paths. Default is None. Returns: :class:`rez.developer_package.DeveloperPackage`: The package the represents the newly-built package. """ directory = make_fake_source_package(name, text) package = packages_.get_developer_package(directory) new_package = creator.build(package, tempfile.mkdtemp(), packages_path=packages_path, quiet=True) self.delete_item_later(os.path.dirname(directory)) self.delete_item_later( inspection.get_packages_path_from_package(new_package)) return new_package
def test_4(self): """Test package config overrides.""" conf = os.path.join(self.config_path, "test2.py") config2 = Config([self.root_config_file, conf]) with _replace_config(config2): pkg = get_developer_package(self.config_path) c = pkg.config self._test_basic(c) # check overrides from package.py are working os.environ["REZ_BUILD_DIRECTORY"] = "foo" # should have no effect self.assertEqual(c.build_directory, "weeble") self.assertEqual(c.plugins.release_vcs.tag_name, "tag") # check list modification is working self.assertEqual(c.release_hooks, ["foo", "bah"]) # check list modification within plugin settings is working self.assertEqual(c.plugins.release_hook.emailer.recipients, ["*****@*****.**", "*****@*****.**"]) # check system expansion in package overridden setting works expected_value = "*****@*****.**" % system.user self.assertEqual(c.plugins.release_hook.emailer.sender, expected_value) # check env-var expansion in package overridden setting works os.environ["FUNK"] = "dude" expected_value = ["FOO", "BAH_dude", "EEK"] self.assertEqual(c.parent_variables, expected_value) self._test_overrides(c)
def __init__(self, working_dir, opts=None, package=None, write_build_scripts=False, verbose=False, build_args=[], child_build_args=[]): """Create a build system instance. Args: working_dir: Directory to build source from. opts: argparse.Namespace object which may contain constructor params, as set by our bind_cli() classmethod. write_build_scripts: If True, create build scripts rather than perform the full build. The user can then run these scripts to place themselves into a build environment and invoke the build system directly. build_args: Extra cli build arguments. child_build_args: Extra cli args for child build system, ignored if there is no child build system. """ self.working_dir = working_dir if not self.is_valid_root(working_dir): raise BuildSystemError("Not a valid %s working directory: %s" % (self.name(), working_dir)) self.package = package or get_developer_package(working_dir) self.write_build_scripts = write_build_scripts self.build_args = build_args self.child_build_args = child_build_args self.verbose = verbose self.opts = opts
def __init__(self, working_dir, opts=None, write_build_scripts=False, verbose=False, build_args=[], child_build_args=[]): """Create a build system instance. Args: working_dir: Directory to build source from. opts: argparse.Namespace object which may contain constructor params, as set by our bind_cli() classmethod. write_build_scripts: If True, create build scripts rather than perform the full build. The user can then run these scripts to place themselves into a build environment and invoke the build system directly. build_args: Extra cli build arguments. child_build_args: Extra cli args for child build system, ignored if there is no child build system. """ self.working_dir = working_dir if not self.is_valid_root(working_dir): raise BuildSystemError("Not a valid %s working directory: %s" % (self.name(), working_dir)) self.package = get_developer_package(working_dir) self.write_build_scripts = write_build_scripts self.build_args = build_args self.child_build_args = child_build_args self.verbose = verbose
def has_package_conf(repository, package, directory="", keep=False): """Check if there is a Sphinx conf.py inside of a Rez package. Args: repository (str): The URL pointing to a git repository that contains `package` somewhere inside of it. package (str): The name of the Rez packge to find within `repository`. directory (str, optional): Part of checking for a conf.py file involves cloning the given `repository` to disk. If a root folder is given, the repository will be cloned as a child of this directory. If no folder is given, a temporary directory is chosen for the user. Default: "". keep (bool, optional): If False, delete temporary directories once they are no If longer needed. True, don't delete them. Default is False. Returns: bool: If a conf.py was found. """ repository = _get_repository(repository, directory=directory, keep=keep) for path in _iter_package_files(repository.working_dir): name = packages_.get_developer_package(os.path.dirname(path)).name if name == package: return bool(conf_manager.get_conf_file(os.path.dirname(path))) return False
def is_valid_root(cls, path): try: package = get_developer_package(path) except PackageMetadataError: return False return (getattr(package, "build_command", None) != None)
def is_valid_root(cls, path): try: package = get_developer_package(path) except PackageMetadataError: return False return bool(getattr(package, "build_command", None))
def is_valid_root(cls, path, package=None): if package is None: try: package = get_developer_package(path) except PackageMetadataError: return False return (getattr(package, "build_command", None) is not None)
def test_normal(self): """Release a package and make sure it is valid.""" def _make_fake_git_repository_at_directory(root): repository = git.Repo.init(root) repository.index.add(".") repository.index.commit("initial commit") source_path = tempfile.mkdtemp(suffix="_rez_package_source_path") self.delete_item_later(source_path) with open(os.path.join(source_path, "package.py"), "w") as handler: handler.write( textwrap.dedent("""\ name = "some_package" version = "1.0.0" build_command = "echo 'foo'" """)) _make_fake_git_repository_at_directory(source_path) package = packages_.get_developer_package(source_path) options = mock.MagicMock() options.cmd = "release" options.debug = False options.message = "Fake release message" options.no_message = False options.process = "local" options.variants = None options.vcs = None parser = mock.MagicMock() parser.prog = "rez release" release_path = tempfile.mkdtemp(suffix="_rez_package_release_path") self.delete_item_later(release_path) with wurlitzer.pipes(): creator.release(finder.get_package_root(package), options, parser, release_path) release_package = packages_.get_developer_package( os.path.join(release_path, "some_package", "1.0.0")) self.assertIsNotNone(release_package)
def make_package( # pylint: disable=too-many-arguments name, root, builder, version="1.0.0", dependencies=frozenset(), variants=None): """Make a source Rez package and its initial files. Args: name (str): The name of the Rez package that will be created. root (str): An absolute folder on-disk where the package.py will be written to. builder (callable[str, str, str, str] -> str): The function that is used to generate the "contents" of the Rez package. This function is only responsible for creating the package.py/rezbuild.py files, it doesn't create a Python package, for example. This parameter is responsible for creating the rest of the files of the package. version (str, optional): The major, minor, and patch information for the Rez package. Default: "1.0.0". dependencies (set[str]): The Rez package requirements for this package. e.g. {"project_a-1+"}. Default is empty. variants (list[list[str]]): The extra Rez package build configurations for this package. No variants will be installed if nothing is given. Default is None. Returns: :class:`rez.developer_package.DeveloperPackage`: The generated Rez package. """ template = textwrap.dedent("""\ name = "{name}" version = "{version}" requires = {requires} build_command = "echo 'do nothing'" """) requires = ", ".join( ['"{name}"'.format(name=dependency) for dependency in dependencies]) requires = "[{requires}]".format(requires=requires) if variants: template += "\nvariants = {variants!r}" text = template.format(name=name, version=version, requires=requires, variants=variants) package_file = builder(text, name, version, root) return packages_.get_developer_package(os.path.dirname(package_file))
def __init__(self, source_path): """Create a release hook. Args: source_path: Path containing source that was released. """ self.source_path = source_path self.package = get_developer_package(source_path) self.type_settings = self.package.config.plugins.release_hook self.settings = self.type_settings.get(self.name())
def command(opts, parser, extra_arg_groups=None): from rez.exceptions import BuildContextResolveError from rez.packages_ import get_developer_package from rez.build_process_ import create_build_process from rez.build_system import create_build_system from rez.serialise import FileFormat import sys # load package working_dir = os.getcwd() package = get_developer_package(working_dir) if opts.view_pre: package.print_info(format_=FileFormat.py, skip_attributes=["preprocess"]) sys.exit(0) # create build system build_args, child_build_args = get_build_args(opts, parser, extra_arg_groups) buildsys_type = opts.buildsys if ("buildsys" in opts) else None buildsys = create_build_system(working_dir, package=package, buildsys_type=buildsys_type, opts=opts, write_build_scripts=opts.scripts, verbose=True, build_args=build_args, child_build_args=child_build_args) # create and execute build process builder = create_build_process(opts.process, working_dir, package=package, build_system=buildsys, verbose=True) try: builder.build(install_path=opts.prefix, clean=opts.clean, install=opts.install, variants=opts.variants) except BuildContextResolveError as e: print >> sys.stderr, str(e) if opts.fail_graph: if e.context.graph: from rez.utils.graph_utils import view_graph g = e.context.graph(as_dot=True) view_graph(g) else: print >> sys.stderr, \ "the failed resolve context did not generate a graph." sys.exit(1)
def test_developer_dynamic_global_preprocess_string(self): """test developer package with a global preprocess function as string""" # a developer package with features such as expanding requirements, # global preprocessing self.update_settings( {"package_preprocess_function": "global_preprocess.inject_data"}) path = os.path.join(self.packages_base_path, "developer_dynamic_global_preprocess") package = get_developer_package(path) self.assertEqual(package.description, "This.") self.assertEqual(package.added_by_global_preprocess, True)
def test_undefined(self): """Define a new `help` attribute.""" folder = tempfile.mkdtemp(suffix="_InsertHelpEntry_test_undefined") atexit.register(functools.partial(shutil.rmtree, folder)) with open(os.path.join(folder, "package.py"), "w") as handler: handler.write('name = "some_package"') package = packages_.get_developer_package(folder) self.assertEqual( [["foo", "bar"]], url_help.insert_help_entry(package.help, "foo", "bar"), )
def test_5(self): """test developer package.""" path = os.path.join(self.packages_base_path, "developer") package = get_developer_package(path) expected_data = dict(name="foo", version=Version("3.0.1"), description="a foo type thing.", authors=["joe.bloggs"], requires=[PackageRequest('bah-1.2+<2')], variants=[[PackageRequest('floob-4.1')], [PackageRequest('floob-2.0')]], uuid="28d94bcd1a934bb4999bcf70a21106cc") data = package.validated_data() self.assertDictEqual(data, expected_data) # a developer package with features such as expanding requirements, # early-binding attribute functions, and preprocessing path = os.path.join(self.packages_base_path, "developer_dynamic") package = get_developer_package(path) self.assertEqual(package.description, "This.") self.assertEqual(package.requires, [PackageRequest('versioned-3')]) self.assertEqual(package.authors, ["tweedle-dee", "tweedle-dum"])
def get_current_developer_package(): from rez.packages_ import get_developer_package from rez.exceptions import PackageMetadataError global _package if _package is None: try: _package = get_developer_package(os.getcwd()) except PackageMetadataError: # no package, or bad package pass return _package
def test_developer(self): """test developer package.""" path = os.path.join(self.packages_base_path, "developer") package = get_developer_package(path) expected_data = dict(name="foo", version=Version("3.0.1"), description="a foo type thing.", authors=["joe.bloggs"], requires=[PackageRequest('bah-1.2+<2')], variants=[[PackageRequest('floob-4.1')], [PackageRequest('floob-2.0')]], uuid="28d94bcd1a934bb4999bcf70a21106cc") data = package.validated_data() self.assertDictEqual(data, expected_data)
def get_valid_build_systems(working_dir, package=None): """Returns the build system classes that could build the source in given dir. Args: working_dir (str): Dir containing the package definition and potentially build files. package (`Package`): Package to be built. This may or may not be needed to determine the build system. For eg, cmake just has to look for a CMakeLists.txt file, whereas the 'build_command' package field must be present for the 'custom' build system type. Returns: List of class: Valid build system class types. """ from rez.plugin_managers import plugin_manager from rez.exceptions import PackageMetadataError try: package = package or get_developer_package(working_dir) except PackageMetadataError: # no package, or bad package pass if package: if getattr(package, "build_command", None) is not None: buildsys_name = "custom" else: buildsys_name = getattr(package, "build_system", None) # package explicitly specifies build system if buildsys_name: cls = plugin_manager.get_plugin_class('build_system', buildsys_name) return [cls] # detect valid build systems clss = [] for buildsys_name in get_buildsys_types(): cls = plugin_manager.get_plugin_class('build_system', buildsys_name) if cls.is_valid_root(working_dir, package=package): clss.append(cls) # Sometimes files for multiple build systems can be present, because one # build system uses another (a 'child' build system) - eg, cmake uses # make. Detect this case and ignore files from the child build system. # child_clss = set(x.child_build_system() for x in clss) clss = list(set(clss) - child_clss) return clss
def _make_dependency_package(self, name, version): directory = tempfile.mkdtemp(suffix="_") self.delete_item_later(directory) install_package_root = os.path.join(directory, name, version) os.makedirs(install_package_root) template = textwrap.dedent("""\ name = "{name}" version = "{version}" """) with open(os.path.join(install_package_root, "package.py"), "w") as handler: handler.write(template.format(name=name, version=version)) return packages_.get_developer_package(install_package_root)
def test_5(self): """test developer package.""" path = os.path.join(self.packages_base_path, "developer") package = get_developer_package(path) expected_data = dict( name="foo", version=Version("3.0.1"), description="a foo type thing.", authors=["joe.bloggs"], requires=[PackageRequest('bah-1.2+<2')], variants=[[PackageRequest('floob-4.1')], [PackageRequest('floob-2.0')]], uuid="28d94bcd1a934bb4999bcf70a21106cc") data = package.validated_data() self.assertDictEqual(data, expected_data)
def __init__(self, pkg_root, vcs_root=None): if vcs_root is None: result = self.find_vcs_root(pkg_root) if not result: raise ReleaseVCSError("Could not find %s repository for the " "path %s" % (self.name(), pkg_root)) vcs_root = result[0] else: assert(self.is_valid_root(vcs_root)) self.vcs_root = vcs_root self.pkg_root = pkg_root self.package = get_developer_package(pkg_root) self.type_settings = self.package.config.plugins.release_vcs self.settings = self.type_settings.get(self.name())
def __init__(self, pkg_root, vcs_root=None): if vcs_root is None: result = self.find_vcs_root(pkg_root) if not result: raise ReleaseVCSError("Could not find %s repository for the " "path %s" % (self.name(), pkg_root)) vcs_root = result[0] else: assert (self.is_valid_root(vcs_root)) self.vcs_root = vcs_root self.pkg_root = pkg_root self.package = get_developer_package(pkg_root) self.type_settings = self.package.config.plugins.release_vcs self.settings = self.type_settings.get(self.name())
def test_5(self): """test developer package.""" path = os.path.join(self.packages_base_path, "developer") package = get_developer_package(path) expected_data = dict( name="foo", version=Version("3.0.1"), description="a foo type thing.", authors=["joe.bloggs"], requires=[PackageRequest('bah-1.2+<2')], variants=[[PackageRequest('floob-4.1')], [PackageRequest('floob-2.0')]], uuid="28d94bcd1a934bb4999bcf70a21106cc") data = package.validated_data() self.assertDictEqual(data, expected_data) # a developer package with features such as expanding requirements, # early-binding attribute functions, and preprocessing path = os.path.join(self.packages_base_path, "developer_dynamic") package = get_developer_package(path) self.assertEqual(package.description, "This.") self.assertEqual(package.requires, [PackageRequest('versioned-3')]) self.assertEqual(package.authors, ["tweedle-dee", "tweedle-dum"])
def test_developer_dynamic_global_preprocess_func(self): """test developer package with a global preprocess function as function""" # a developer package with features such as expanding requirements, # global preprocessing def preprocess(this, data): data["dynamic_attribute_added"] = {'test': True} self.update_settings({"package_preprocess_function": preprocess}) path = os.path.join(self.packages_base_path, "developer_dynamic_global_preprocess") package = get_developer_package(path) self.assertEqual(package.description, "This.") self.assertEqual(package.dynamic_attribute_added, {'test': True})
def __init__(self, working_dir, build_system, package=None, vcs=None, ensure_latest=True, skip_repo_errors=False, ignore_existing_tag=False, verbose=False): """Create a BuildProcess. Args: working_dir (str): Directory containing the package to build. build_system (`BuildSystem`): Build system used to build the package. vcs (`ReleaseVCS`): Version control system to use for the release process. ensure_latest: If True, do not allow the release process to occur if an newer versioned package is already released. skip_repo_errors: If True, proceed with the release even when errors occur. BE CAREFUL using this option, it is here in case a package needs to be released urgently even though there is some problem with reading or writing the repository. ignore_existing_tag: Perform the release even if the repository is already tagged at the current version. If the config setting plugins.release_vcs.check_tag is False, this has no effect. """ self.verbose = verbose self.working_dir = working_dir self.build_system = build_system self.vcs = vcs self.ensure_latest = ensure_latest self.skip_repo_errors = skip_repo_errors self.ignore_existing_tag = ignore_existing_tag if vcs and vcs.pkg_root != working_dir: raise BuildProcessError( "Build process was instantiated with a mismatched VCS instance" ) self.debug_print = config.debug_printer("package_release") self.package = package or get_developer_package(working_dir) hook_names = self.package.config.release_hooks or [] self.hooks = create_release_hooks(hook_names, working_dir) self.build_path = os.path.join(self.working_dir, self.package.config.build_directory)
def _FWD__spawn_build_shell(working_dir, build_dir, variant_index): # This spawns a shell that the user can run 'make' in directly context = ResolvedContext.load(os.path.join(build_dir, "build.rxt")) package = get_developer_package(working_dir) variant = package.get_variant(variant_index) config.override("prompt", "BUILD>") callback = functools.partial(CMakeBuildSystem._add_build_actions, context=context, package=package, variant=variant, build_type=BuildType.local) retcode, _, _ = context.execute_shell(block=True, cwd=build_dir, actions_callback=callback) sys.exit(retcode)
def test_4(self): """Test package config overrides.""" pkg = get_developer_package(self.config_path) c = pkg.config self._test_basic(c) # check overrides from package.yaml are working os.environ["REZ_BUILD_DIRECTORY"] = "foo" # should have no effect self.assertEqual(c.build_directory, "weeble") self.assertEqual(c.plugins.release_vcs.tag_name, "tag") # check system expansion in package overridden setting works expected_value = "*****@*****.**" % system.user self.assertEqual(c.plugins.release_hook.emailer.sender, expected_value) # check env-var expansion in package overridden setting works os.environ["FUNK"] = "dude" expected_value = ["FOO", "BAH_dude", "EEK"] self.assertEqual(c.parent_variables, expected_value) self._test_overrides(c)
def __init__(self, working_dir, build_system, package=None, vcs=None, ensure_latest=True, skip_repo_errors=False, ignore_existing_tag=False, verbose=False): """Create a BuildProcess. Args: working_dir (str): Directory containing the package to build. build_system (`BuildSystem`): Build system used to build the package. vcs (`ReleaseVCS`): Version control system to use for the release process. ensure_latest: If True, do not allow the release process to occur if an newer versioned package is already released. skip_repo_errors: If True, proceed with the release even when errors occur. BE CAREFUL using this option, it is here in case a package needs to be released urgently even though there is some problem with reading or writing the repository. ignore_existing_tag: Perform the release even if the repository is already tagged at the current version. If the config setting plugins.release_vcs.check_tag is False, this has no effect. """ self.verbose = verbose self.working_dir = working_dir self.build_system = build_system self.vcs = vcs self.ensure_latest = ensure_latest self.skip_repo_errors = skip_repo_errors self.ignore_existing_tag = ignore_existing_tag if vcs and vcs.pkg_root != working_dir: raise BuildProcessError( "Build process was instantiated with a mismatched VCS instance") self.debug_print = config.debug_printer("package_release") self.package = package or get_developer_package(working_dir) hook_names = self.package.config.release_hooks or [] self.hooks = create_release_hooks(hook_names, working_dir) self.build_path = os.path.join(self.working_dir, self.package.config.build_directory)
def get_package_info(path, variant_index): """ Get valuable information about a package that can be used in different contexts. :param path: Path to the root of a project :param variant: index of the variant to resolve :return: Dict with various info about a package """ data = { "variants": [], } package = get_developer_package(path) variants = list(package.iter_variants()) for v in variants: data["variants"].append(v.qualified_name) variant = variants[variant_index] request = variant.get_requires(build_requires=True, private_build_requires=True) context = ResolvedContext(request) data["name"] = package.name data["interpreter"] = context.which("python") data["dependencies"] = get_dependencies(context) return data
def command(opts, parser, extra_arg_groups=None): from rez.packages_ import get_developer_package from rez.build_process_ import create_build_process from rez.build_system import create_build_system from rez.release_vcs import create_release_vcs from rez.cli.build import get_build_args from rez.config import config # load package working_dir = os.getcwd() package = get_developer_package(working_dir) # create vcs vcs = create_release_vcs(working_dir, opts.vcs) # create build system build_args, child_build_args = get_build_args(opts, parser, extra_arg_groups) buildsys_type = opts.buildsys if ("buildsys" in opts) else None buildsys = create_build_system(working_dir, package=package, buildsys_type=buildsys_type, opts=opts, verbose=True, build_args=build_args, child_build_args=child_build_args) # create and execute release process builder = create_build_process(opts.process, working_dir, package=package, build_system=buildsys, vcs=vcs, ensure_latest=(not opts.no_latest), skip_repo_errors=opts.skip_repo_errors, ignore_existing_tag=opts.ignore_existing_tag, verbose=True) # get release message release_msg = opts.message filepath = None if config.prompt_release_message and not release_msg and not opts.no_message: from hashlib import sha1 h = sha1(working_dir).hexdigest() filename = "rez-release-message-%s.txt" % h filepath = os.path.join(config.tmpdir, filename) header = "<Enter your release notes here>" changelog_token = "###<CHANGELOG>" if not os.path.exists(filepath): txt = header # get changelog and add to release notes file, for reference. They # get stripped out again before being added as package release notes. try: changelog = builder.get_changelog() except: pass if changelog: txt += ("\n\n%s This is for reference only - this line and all " "following lines will be stripped from the release " "notes.\n\n" % changelog_token) txt += changelog with open(filepath, 'w') as f: print >> f, txt call([config.editor, filepath]) with open(filepath) as f: release_msg = f.read() # strip changelog out try: i = release_msg.index(changelog_token) release_msg = release_msg[:i] except ValueError: pass # strip header out release_msg = release_msg.replace(header, "") release_msg = release_msg.strip() if not release_msg: ch = None while ch not in ('A', 'a', 'C', 'c'): print "Empty release message. [A]bort or [C]ontinue release?" ch = raw_input() if ch in ('A', 'a'): print "Release aborted." sys.exit(1) # perform the release builder.release(release_message=release_msg or None, variants=opts.variants) # remove the release message file if filepath: try: os.remove(filepath) except: pass