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
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)
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)
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)
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)