Пример #1
0
    def _remove_feature_parameters(self):
        # Remove feature parameters from unlocked packages only
        if self.options.get("package_type") != "Unlocked":
            return

        # Copy existing files to new zipfile
        package_xml = None
        zip_dest = zipfile.ZipFile(io.BytesIO(), "w", zipfile.ZIP_DEFLATED)
        for name in self.zf.namelist():
            if name == "package.xml":
                package_xml = self.zf.open(name)
            elif name.startswith("featureParameters/"):
                # skip feature parameters
                self.logger.info(f"Skipping {name} in unlocked package")
                continue
            else:
                content = self.zf.read(name)
                zip_dest.writestr(name, content)

        # Remove from package.xml
        if package_xml is not None:
            Package = metadata_tree.parse(package_xml)
            for mdtype in (
                    "FeatureParameterInteger",
                    "FeatureParameterString",
                    "FeatureParameterBoolean",
            ):
                section = Package.find("types", name=mdtype)
                if section is not None:
                    Package.remove(section)
            package_xml = Package.tostring(xml_declaration=True)
            zip_dest.writestr("package.xml", package_xml)

        self.zf.close()
        self.zf = zip_dest
Пример #2
0
    def test_pathlib_support(self):
        from cumulusci.tasks.metadata import tests

        path = (Path(tests.__file__).parent /
                "package_metadata/namespaced_report_folder/package.xml")
        tree = parse(path)
        assert tree
Пример #3
0
    def _process_static_resources(self, zip_src):
        relpath = self.options.get("static_resource_path")
        if not relpath or not os.path.exists(relpath):
            return zip_src
        path = os.path.realpath(relpath)

        # We need to build a new zip file so that we can replace package.xml
        zip_dest = zipfile.ZipFile(io.BytesIO(), "w", zipfile.ZIP_DEFLATED)
        for name in zip_src.namelist():
            if name == "package.xml":
                package_xml = zip_src.open(name)
            else:
                content = zip_src.read(name)
                zip_dest.writestr(name, content)

        # Build static resource bundles and add to package zip
        with temporary_dir():
            os.mkdir("staticresources")
            bundles = []
            for name in os.listdir(path):
                bundle_relpath = os.path.join(relpath, name)
                bundle_path = os.path.join(path, name)
                if not os.path.isdir(bundle_path):
                    continue
                self.logger.info(
                    "Zipping {} to add to staticresources".format(bundle_relpath)
                )

                # Add resource-meta.xml file
                meta_name = "{}.resource-meta.xml".format(name)
                meta_path = os.path.join(path, meta_name)
                with open(meta_path, "rb") as f:
                    zip_dest.writestr("staticresources/{}".format(meta_name), f.read())

                # Add bundle
                zip_path = os.path.join("staticresources", "{}.resource".format(name))
                with open(zip_path, "wb") as bundle_fp:
                    bundle_zip = zipfile.ZipFile(bundle_fp, "w", zipfile.ZIP_DEFLATED)
                    with cd(bundle_path):
                        for resource_file in self._get_static_resource_files():
                            bundle_zip.write(resource_file)
                    bundle_zip.close()
                zip_dest.write(zip_path)
                bundles.append(name)

        # Update package.xml
        Package = metadata_tree.parse(package_xml)
        sections = Package.findall("types", name="StaticResource")
        section = sections[0] if sections else None
        if not section:
            section = Package.append("types")
            section.append("name", text="StaticResource")
        for name in bundles:
            section.insert_before(section.find("name"), tag="members", text=name)
        package_xml = Package.tostring(xml_declaration=True)
        zip_dest.writestr("package.xml", package_xml)
        return zip_dest
Пример #4
0
    def test_whitespace(self):
        from cumulusci.tasks.metadata import tests

        path = (Path(tests.__file__).parent /
                "package_metadata/namespaced_report_folder/package.xml")
        with open(path) as f:
            raw = f.read()

        # get rid of whitespace to see if we can replace it faithfully
        raw_flattened = raw.replace("    ", "").replace("\n", "")
        Package = parse(BytesIO(raw_flattened.encode("utf-8")))
        x = Package.tostring(xml_declaration=True).strip()
        assert x == raw
Пример #5
0
    def _transform(self):
        # call _transform_entity once per retrieved entity
        # if the entity is an XML file, provide a parsed version
        # and write the returned metadata into the deploy directory

        parser = PackageXmlGenerator(
            None, self.api_version)  # We'll use it for its metadata_map
        entity_configurations = [
            entry for entry in parser.metadata_map if any([
                subentry["type"] == self.entity
                for subentry in parser.metadata_map[entry]
            ])
        ]
        if not entity_configurations:
            raise CumulusCIException(
                f"Unable to locate configuration for entity {self.entity}")

        configuration = parser.metadata_map[entity_configurations[0]][0]
        if configuration["class"] not in [
                "MetadataFilenameParser",
                "CustomObjectParser",
        ]:
            raise CumulusCIException(
                f"MetadataSingleEntityTransformTask only supports manipulating complete, file-based XML entities (not {self.entity})"
            )

        extension = configuration["extension"]
        directory = entity_configurations[0]
        source_metadata_dir = self.retrieve_dir / directory

        if "*" in self.api_names:
            # Walk the retrieved directory to get the actual suite
            # of API names retrieved and rebuild our api_names list.
            self.api_names.remove("*")
            self.api_names = self.api_names.union(
                metadata_file.stem
                for metadata_file in source_metadata_dir.iterdir()
                if metadata_file.suffix == f".{extension}")

        removed_api_names = set()

        for api_name in self.api_names:
            # Page Layout names can contain spaces, but parentheses and other
            # characters like ' and < are quoted.
            # We quote user-specified API names so we can locate the corresponding
            # metadata files, but present them un-quoted in messages to the user.
            unquoted_api_name = unquote(api_name)

            path = source_metadata_dir / f"{api_name}.{extension}"
            if not path.exists():
                raise CumulusCIException(f"Cannot find metadata file {path}")

            try:
                tree = metadata_tree.parse(str(path))
            except SyntaxError as err:
                err.filename = path
                raise err
            transformed_xml = self._transform_entity(tree, unquoted_api_name)
            if transformed_xml:
                parent_dir = self.deploy_dir / directory
                if not parent_dir.exists():
                    parent_dir.mkdir()
                destination_path = parent_dir / f"{api_name}.{extension}"

                with destination_path.open(mode="w", encoding="utf-8") as f:
                    f.write(transformed_xml.tostring(xml_declaration=True))
            else:
                # Make sure to remove from our package.xml
                removed_api_names.add(api_name)

        self.api_names = self.api_names - removed_api_names