def set_packages_root(resource, codebase):
    """
    Set the root_path attribute as the path to the root Resource for a given
    package package or build script that may exist in a `resource`.
    """
    # only files can have a package
    if not resource.is_file:
        return

    packages = resource.packages
    if not packages:
        return
    # NOTE: we are dealing with a single file therefore there should be only be
    # a single package detected. But some package manifests can document more
    # than one package at a time such as multiple arches/platforms for a gempsec
    # or multiple sub package (with "%package") in an RPM .spec file.

    modified = False
    for package in packages:
        package_class = get_package_class(package)
        package_root = package_class.get_package_root(resource, codebase)
        if not package_root:
            # this can happen if we scan a single resource that is a package package
            continue
        # What if the target resource (e.g. a parent) is the root and we are in stripped root mode?
        if package_root.is_root and codebase.strip_root:
            continue
        package['root_path'] = package_root.path
        modified = True

    if modified:
        # we did set the root_path
        codebase.save_resource(resource)
    return resource
Beispiel #2
0
 def create(cls, ignore_unknown=True, **kwargs):
     """
     Return a Package built from kwargs.
     Optionally `ignore_unknown` attributes provided in `kwargs`.
     """
     from packagedcode import get_package_class
     cls = get_package_class(kwargs, default=cls)
     return super(BasePackage, cls).create(ignore_unknown=ignore_unknown, **kwargs)
 def create(cls, **kwargs):
     """
     Return a Package built from ``kwargs``. Always ignore unknown attributes
     provided in ``kwargs`` that do not exist as declared attr fields in
     ``cls``.
     """
     from packagedcode import get_package_class
     type_cls = get_package_class(kwargs, default=cls)
     return super(BasePackage, type_cls).create(**kwargs)
Beispiel #4
0
    def process_codebase(self, codebase, classify, **kwargs):
        """
        Tag resource as key or top level files based on Package type-specific
        rules.
        """
        if not classify:
            logger_debug('PackageTopAndKeyFilesTagger: return')
            return

        from packagedcode import get_package_class

        if codebase.has_single_resource:
            # What if we scanned a single file and we do not have a root proper?
            return

        root_path = codebase.root.path

        has_packages = hasattr(codebase.root, 'packages')
        if not has_packages:
            # FIXME: this is not correct... we may still have cases where this
            # is wrong: e.g. a META-INF directory and we may not have a package 
            return


        for resource in codebase.walk(topdown=True):
            packages_info = resource.packages or []

            if not packages_info:
                continue
            if not resource.has_children():
                continue

            descendants = None

            for package_info in packages_info:
                package_class = get_package_class(package_info)
                extra_root_dirs = package_class.extra_root_dirs()
                extra_key_files = package_class.extra_key_files()
                if TRACE:
                    logger_debug('PackageTopAndKeyFilesTagger: extra_root_dirs:', extra_root_dirs)
                    logger_debug('PackageTopAndKeyFilesTagger: extra_key_files:', extra_key_files)

                if not (extra_root_dirs or extra_key_files):
                    # FIXME: this is not correct!
                    # we may still have other files under the actual root.
                    continue

                if not descendants:
                    descendants = {
                        get_relative_path(root_path, r.path): r
                                   for r in resource.descendants(codebase)}

                    if TRACE:
                        logger_debug('PackageTopAndKeyFilesTagger: descendants')
                        for rpath, desc in descendants.items():
                            logger_debug('rpath:', rpath, 'desc:', desc)

                for rpath, desc in descendants.items():
                    if extra_root_dirs and get_matches(rpath, extra_root_dirs):
                        if TRACE:
                            logger_debug('PackageTopAndKeyFilesTagger: get_matches for:', rpath, desc)
                        desc.is_top_level = True
                        if desc.is_file:
                            set_classification_flags(desc)
                        desc.save(codebase)

                        for child in desc.children(codebase):
                            if TRACE:
                                logger_debug('PackageTopAndKeyFilesTagger: set is_top_level for:', child)

                            child.is_top_level = True
                            if child.is_file:
                                set_classification_flags(child)
                            child.save(codebase)

                    if extra_key_files and get_matches(rpath, extra_key_files):
                        desc.is_key_file = True
                        desc.save(codebase)
Beispiel #5
0
    def process_codebase(self, codebase, **kwargs):
        """
        Move package manifest scan information to the proper file or
        directory level given a package type.
        """
        from packagedcode import get_package_class

        if codebase.has_single_resource:
            # What if we scanned a single file and we do not have a root proper?
            return

        for resource in codebase.walk(topdown=False):
            # only files can have a manifest
            if not resource.is_file:
                continue

            if resource.is_root:
                continue

            packages_info = resource.packages
            if not packages_info:
                continue

            # NOTE: we are dealing with a single file therefore there should be
            # only be a single package detected. But some package manifests can
            # document more than one package at a time such as multiple
            # arches/platforms for a gempsec or multiple sub package (with
            # "%package") in an RPM .spec file.
            for package_info in packages_info:
                # Break if this Resource has already been set as a new Package root
                manifest_path = package_info.get('manifest_path')
                if manifest_path and manifest_path != resource.path:
                    break

                package_class = get_package_class(package_info)
                new_package_root = package_class.get_package_root(
                    resource, codebase)

                if not new_package_root:
                    # this can happen if we scan a single resource that is a package manifest
                    continue

                if new_package_root == resource:
                    continue

                # here new_package_root != resource:

                # What if the target resource (e.g. a parent) is the root and we are in stripped root mode?
                if new_package_root.is_root and codebase.strip_root:
                    continue

                # Determine if this package applies to more than just the manifest
                # file (typically it means the whole parent directory is the
                # package) and if yes:
                # 1. fetch this resource
                # 2. move the package data to this new resource
                # 3. set the manifest_path if needed.
                # 4. save.

                # TODO: this is a hack for the ABOUT file Package parser, ABOUT files are kept alongside
                # the resource its for
                if new_package_root.is_file and resource.path.endswith(
                        '.ABOUT'):
                    new_manifest_path = os.path.join(
                        parent_directory(new_package_root.path), resource.name)
                else:
                    # here we have a relocated Resource and we compute the manifest path
                    # relative to the new package root
                    # TODO: We should have codebase relative paths for manifests
                    new_package_root_path = new_package_root.path and new_package_root.path.strip(
                        '/')
                    if new_package_root_path:
                        _, _, new_manifest_path = resource.path.partition(
                            new_package_root_path)
                        # note we could have also deserialized and serialized again instead
                package_info['manifest_path'] = new_manifest_path.lstrip('/')

                new_package_root.packages.append(package_info)
                codebase.save_resource(new_package_root)
                resource.packages = []
                codebase.save_resource(resource)
Beispiel #6
0
    def process_codebase(self, codebase, **kwargs):
        """
        Move package manifest scan information to the proper file or
        directory level given a package type.
        """
        from packagedcode import get_package_class

        if codebase.has_single_resource:
            # What if we scanned a single file and we do not have a root proper?
            return

        for resource in codebase.walk(topdown=False):
            # only files can have a manifest
            if not resource.is_file:
                continue

            if resource.is_root:
                continue

            packages_info = resource.packages
            if not packages_info:
                continue

            # NOTE: we are dealing with a single file therefore there should be
            # only be a single package detected. But some package manifests can
            # document more than one package at a time such as multiple
            # arches/platforms for a gempsec or multiple sub package (with
            # "%package") in an RPM .spec file.
            for package_info in packages_info:
                package_class = get_package_class(package_info)
                new_package_root = package_class.get_package_root(
                    resource, codebase)

                if not new_package_root:
                    # this can happen if we scan a single resource that is a package manifest
                    continue

                if new_package_root == resource:
                    continue

                # here new_package_root != resource:

                # What if the target resource (e.g. a parent) is the root and we are in stripped root mode?
                if new_package_root.is_root and codebase.strip_root:
                    continue

                # Determine if this package applies to more than just the manifest
                # file (typically it means the whole parent directory is the
                # package) and if yes:
                # 1. fetch this resource
                # 2. move the package data to this new resource
                # 3. set the manifest_path if needed.
                # 4. save.

                # NOTE: do not do this if the new_package_root is not an ancestor
                # FIXME: this may not hold at all times?
                ancestors = resource.ancestors(codebase)
                if new_package_root not in ancestors:
                    continue
                # here we have a relocated Resource and we compute the manifest path
                # relative to the new package root
                new_package_root_path = new_package_root.path and new_package_root.path.strip(
                    '/')
                if new_package_root_path:
                    _, _, manifest_path = resource.path.partition(
                        new_package_root_path)
                    # note we could have also deserialized and serialized again instead
                    package_info['manifest_path'] = manifest_path.lstrip('/')

                new_package_root.packages.append(package_info)
                codebase.save_resource(new_package_root)
                resource.packages = []
                codebase.save_resource(resource)