def __deserialize(self, queueName, fileName): try: queue = open(os.path.join(config.workDir, fileName), "r") except IOError: return for line in queue.readlines(): if not line.startswith("#"): line = line.strip() if not os.path.exists(line): # try to guess abosolute path from package name try: component = InstallDB().get_package(line).partOf except: continue if component: path = "%s/%s/%s/pspec.xml" % (config.localPspecRepo, component.replace(".", "/"), line) if os.path.exists(path): queueName.append(path) else: queueName.append(line) queue.close()
def __deserialize(self, queueName, fileName): try: queue = open(os.path.join(conf.buildfarmdir, fileName), "r") except IOError: return for line in queue.readlines(): if not line.startswith("#"): line = line.strip() if not os.path.exists(line): # Try to guess absolute path from package name try: component = InstallDB().get_package(line).partOf except: continue if component: path = "%s/%s/%s/pspec.xml" % ( utils.get_local_repository_url(), component.replace(".", "/"), line) if os.path.exists(path): queueName.append(path) else: queueName.append(line) queue.close()
def __init__(self): """ Allows us to do look ups on all packages """ self.idb = InstallDB() self.pdb = PackageDB() self.fdb = FilesDB() # Cache the pkgconfigs known in the pdb self.pkgConfigs, self.pkgConfigs32 = self.pdb.get_pkgconfig_providers()
def __deserialize(self, queueName, filePath): try: queue = open(filePath, "r") except IOError: return for line in queue.readlines(): if not line.startswith("#"): for path in line.strip().split(): if not os.path.exists(path): # Try to guess absolute path from package name try: component = InstallDB().get_package(path).partOf except: continue if component: path = "%s/%s/%s/pspec.xml" % (utils.get_local_repository_url(), component.replace(".", "/"), path) if os.path.exists(path): queueName.append(path) else: queueName.append(path) queue.close()
def __init__(self): """ Initialise the potential driver bundle set """ self.drivers = [ DriverBundleNvidia390(), DriverBundleNvidia(), DriverBundleBroadcom(), ] self.allDrivers = list() self.uniqueDrivers = list() self.emul32Triggers = dict() self.context = OSContext() self.db = InstallDB() for driver in self.drivers: for pkg in driver.triggers_emul32(): if self.db.has_package(pkg): self.emul32Triggers[driver] = True
class BundleSet: drivers = None allDrivers = None uniqueDrivers = None emul32Triggers = None db = None context = None def __init__(self): """ Initialise the potential driver bundle set """ self.drivers = [ DriverBundleNvidia340(), DriverBundleNvidia390(), DriverBundleNvidia(), DriverBundleBroadcom(), ] self.allDrivers = list() self.uniqueDrivers = list() self.emul32Triggers = dict() self.context = OSContext() self.db = InstallDB() for driver in self.drivers: for pkg in driver.triggers_emul32(): if self.db.has_package(pkg): self.emul32Triggers[driver] = True def detect(self): """ Perform main detection routine """ for driver in self.drivers: if driver.is_present(): self.add_driver(driver) def add_driver(self, driver): """ Attempt to add a driver to the set and avoid conflicts """ b = driver.get_base() self.allDrivers.append(driver) if b is not None: otherDrivers = [x for x in self.uniqueDrivers if x.get_base() == b] for existing in otherDrivers: if existing.get_priority() > driver.get_priority(): print("DEBUG: {} shadowed by existing {}".format( driver.get_name(), existing.get_name())) return elif driver.get_priority() > existing.get_priority(): self.uniqueDrivers.remove(existing) self.uniqueDrivers.append(driver) if len(otherDrivers) < 1: self.uniqueDrivers.append(driver) else: self.uniqueDrivers.append(driver)
def detect_drivers(self): self.installdb = InstallDB() self.packagedb = PackageDB() for child in self.listbox.get_children(): child.destroy() self.bundleset = BundleSet() self.bundleset.detect() pkgs = detection.detect_hardware_packages() GObject.idle_add(lambda: self.add_pkgs()) if len(pkgs) == 0: d = "No drivers were found for your system" GObject.idle_add(lambda: self.rs.set_markup("<b>{}</b>".format(d)))
class DependencyResolver: idb = None pdb = None fdb = None global_rpaths = set() global_rpaths32 = set() global_sonames = dict() global_sonames32 = dict() global_pkgconfigs = dict() global_pkgconfig32s = dict() global_kernels = dict() gene = None bindeps_cache = dict() bindeps_emul32 = dict() pkgconfig_cache = dict() pkgconfig32_cache = dict() files_cache = dict() kernel_cache = dict() deadends = dict() # Cached from packagedb pkgConfigs = None pkgConfigs32 = None def search_file(self, fname): if fname[0] == '/': fname = fname[1:] if fname in self.deadends: return None if self.fdb.has_file(fname): return self.fdb.get_file(fname) # Nasty file conflict crap happened on update and the filesdb # is now inconsistent .. ret = self.fdb.search_file(fname) if len(ret) == 1: return ret[0] # Just blacklist further lookups here self.deadends[fname] = 0 return None def __init__(self): """ Allows us to do look ups on all packages """ self.idb = InstallDB() self.pdb = PackageDB() self.fdb = FilesDB() # Cache the pkgconfigs known in the pdb self.pkgConfigs, self.pkgConfigs32 = self.pdb.get_pkgconfig_providers() def get_symbol_provider(self, info, symbol): """ Grab the symbol from the local packages """ if info.emul32: tgtMap = self.global_sonames32 rPaths = self.global_rpaths32 else: tgtMap = self.global_sonames rPaths = self.global_rpaths if symbol in tgtMap: pkgname = tgtMap[symbol] return self.ctx.spec.get_package_name(pkgname) # Check if its in any rpath for rpath in rPaths: fpath = os.path.join(rpath, symbol) pkg = self.gene.get_file_owner(fpath) if pkg: return self.ctx.spec.get_package_name(pkg.name) return None def get_symbol_external(self, info, symbol, paths=None): """ Get the provider of the required symbol from the files database, i.e. installed binary dependencies """ # Try a cached approach first. if info.emul32: if symbol in self.bindeps_emul32: return self.bindeps_emul32[symbol] else: if symbol in self.bindeps_cache: return self.bindeps_cache[symbol] if symbol in ExceptionRules: if info.emul32: return "libglvnd-32bit" else: return "libglvnd" if not paths: paths = ["/usr/lib64", "/usr/lib"] if info.emul32: paths = ["/usr/lib32", "/usr/lib", "/usr/lib64"] if info.rpaths: paths.extend(info.rpaths) pkg = None for path in paths: fpath = os.path.join(path, symbol) if not os.path.exists(fpath): continue lpkg = None if fpath in self.files_cache: lpkg = self.files_cache[fpath] else: pkg = self.search_file(fpath) if pkg: lpkg = pkg[0] if lpkg: if info.emul32: self.bindeps_emul32[symbol] = lpkg else: self.bindeps_cache[symbol] = lpkg console_ui.emit_info( "Dependency", "{} adds dependency on {} from {}".format( info.pretty, symbol, lpkg)) # Populate a global files cache, basically there is a high # chance that each package depends on multiple things in a # single package. for file in self.idb.get_files(lpkg).list: self.files_cache["/" + file.path] = lpkg return lpkg return None def get_pkgconfig_provider(self, info, name): """ Get the internal provider for a pkgconfig name """ if info.emul32: if name in self.global_pkgconfig32s: pkg = self.global_pkgconfig32s[name] return self.ctx.spec.get_package_name(pkg) if name in self.global_pkgconfigs: pkg = self.global_pkgconfigs[name] return self.ctx.spec.get_package_name(pkg) return None def get_pkgconfig_external(self, info, name): """ Get the external provider of a pkgconfig name """ pkg = None if info.emul32: if name in self.pkgconfig32_cache: return self.pkgconfig32_cache[name] else: if name in self.pkgconfig_cache: return self.pkgconfig_cache[name] if info.emul32: # InstallDB set nom = self.fdb.get_pkgconfig32_provider(name) if nom: pkg = self.idb.get_package(nom[0]) if not pkg: nom = self.fdb.get_pkgconfig_provider(name) if nom: pkg = self.idb.get_package(nom[0]) # PackageDB set if not pkg: if name in self.pkgConfigs32: pkg = self.pdb.get_package(self.pkgConfigs32[name]) if not pkg: if name in self.pkgConfigs: pkg = self.pdb.get_package(self.pkgConfigs[name]) else: nom = self.fdb.get_pkgconfig_provider(name) if nom: pkg = self.idb.get_package(nom[0]) if not pkg: if name in self.pkgConfigs: pkg = self.pdb.get_package(self.pkgConfigs[name]) if not pkg: return None if info.emul32: self.pkgconfig32_cache[name] = pkg.name else: self.pkgconfig_cache[name] = pkg.name return pkg.name def handle_binary_deps(self, packageName, info): """ Handle direct binary dependencies """ pkgName = self.ctx.spec.get_package_name(packageName) for sym in info.symbol_deps: r = self.get_symbol_provider(info, sym) if not r: r = self.get_symbol_external(info, sym) if not r: print("Fatal: Unknown symbol: {}".format(sym)) continue # Don't self depend if pkgName == r: continue self.gene.packages[packageName].depend_packages.add(r) def handle_pkgconfig_deps(self, packageName, info): """ Handle pkgconfig dependencies """ pkgName = self.ctx.spec.get_package_name(packageName) for item in info.pkgconfig_deps: prov = self.get_pkgconfig_provider(info, item) if not prov: prov = self.get_pkgconfig_external(info, item) if not prov: console_ui.emit_warning( "PKGCONFIG", "Not adding unknown" " dependency {} to {}".format(item, pkgName)) continue tgtPkg = self.gene.packages[packageName] # Yes, it's a set, but i dont want the ui emission spam if prov in tgtPkg.depend_packages: continue # Forbid circular dependencies if pkgName == prov: continue tgtPkg.depend_packages.add(prov) console_ui.emit_info( "PKGCONFIG", "{} adds dependency on {}".format(pkgName, prov)) def handle_pkgconfig_provides(self, packageName, info): adder = None if info.emul32: adder = "pkgconfig32({})".format(info.pkgconfig_name) else: adder = "pkgconfig({})".format(info.pkgconfig_name) # TODO: Add versioning in examine.py .. ? self.gene.packages[packageName].provided_symbols.add(adder) pass def handle_soname_links(self, packageName, info): """ Add dependencies between packages due to a .so splitting """ ourName = self.ctx.spec.get_package_name(packageName) for link in info.soname_links: fi = self.gene.get_file_owner(link) if not fi: console_ui.emit_warning( "SOLINK", "{} depends on non existing " "soname link: {}".format(packageName, link)) continue pkgName = self.ctx.spec.get_package_name(fi.name) if pkgName == ourName: continue self.gene.packages[packageName].depend_packages.add(pkgName) console_ui.emit_info( "SOLINK", "{} depends on {} through .so link".format(ourName, pkgName)) def get_kernel_provider(self, info, version): """ i.e. self dependency situation """ if version in self.global_kernels: pkg = self.global_kernels[version] return self.ctx.spec.get_package_name(pkg) return None def get_kernel_external(self, info, version): """ Try to find the owning kernel for a version """ if version in self.kernel_cache: return self.kernel_cache[version] paths = ["/usr/lib/kernel", "/usr/lib64/kernel"] pkg = None for path in paths: # Special file in the main kernel package fpath = "{}/System.map-{}".format(path, version) if not os.path.exists(fpath): continue lpkg = None if fpath in self.files_cache: lpkg = self.files_cache[fpath] else: pkg = self.search_file(fpath) if pkg: lpkg = pkg[0] if lpkg: self.kernel_cache[version] = lpkg console_ui.emit_info( "Kernel", "{} adds module dependency on {} from {}".format( info.pretty, version, lpkg)) # Populate a global files cache, basically there is a high # chance that each package depends on multiple things in a # single package. for file in self.idb.get_files(lpkg).list: self.files_cache["/" + file.path] = lpkg return lpkg return None def handle_kernel_deps(self, packageName, info): """ Add dependency between packages due to kernel version """ pkgName = self.ctx.spec.get_package_name(packageName) r = self.get_kernel_provider(info, info.dep_kernel) if not r: r = self.get_kernel_external(info, info.dep_kernel) if not r: print("Fatal: Unknown kernel: {}".format(sym)) return # Don't self depend if pkgName == r: return self.gene.packages[packageName].depend_packages.add(r) def compute_for_packages(self, context, gene, packageSet): """ packageSet is a dict mapping here. """ self.gene = gene self.packageSet = packageSet self.ctx = context # First iteration, collect the globals for packageName in packageSet: for info in packageSet[packageName]: if info.rpaths: if info.emul32: self.global_rpaths32.update(info.rpaths) else: self.global_rpaths.update(info.rpaths) if info.soname: if info.emul32: self.global_sonames32[info.soname] = packageName else: self.global_sonames[info.soname] = packageName if info.pkgconfig_name: pcName = info.pkgconfig_name if info.emul32: self.global_pkgconfig32s[pcName] = packageName else: self.global_pkgconfigs[pcName] = packageName if info.prov_kernel: self.global_kernels[info.prov_kernel] = packageName # Ok now find the dependencies for packageName in packageSet: for info in packageSet[packageName]: if info.symbol_deps: self.handle_binary_deps(packageName, info) if info.pkgconfig_deps: self.handle_pkgconfig_deps(packageName, info) if info.pkgconfig_name: self.handle_pkgconfig_provides(packageName, info) if info.soname_links: self.handle_soname_links(packageName, info) if info.dep_kernel: self.handle_kernel_deps(packageName, info) return True
def __init__(self): """ Allows us to do look ups on all packages """ self.idb = InstallDB() self.pdb = PackageDB() self.fdb = FilesDB()
class DependencyResolver: idb = None pdb = None fdb = None global_rpaths = set() global_sonames = dict() global_pkgconfigs = dict() global_pkgconfig32s = dict() gene = None bindeps_cache = dict() bindeps_emul32 = dict() pkgconfig_cache = dict() pkgconfig32_cache = dict() files_cache = dict() def search_file(self, fname): if fname[0] == '/': fname = fname[1:] return self.fdb.search_file(fname) def __init__(self): """ Allows us to do look ups on all packages """ self.idb = InstallDB() self.pdb = PackageDB() self.fdb = FilesDB() def get_symbol_provider(self, symbol): """ Grab the symbol from the local packages """ if symbol in self.global_sonames: pkgname = self.global_sonames[symbol] return self.ctx.spec.get_package_name(pkgname) # Check if its in any rpath for rpath in self.global_rpaths: fpath = os.path.join(rpath, symbol) pkg = self.gene.get_file_owner(fpath) if pkg: return self.ctx.spec.get_package_name(pkg.name) return None def get_symbol_external(self, info, symbol, paths=None): """ Get the provider of the required symbol from the files database, i.e. installed binary dependencies """ # Try a cached approach first. if info.emul32: if symbol in self.bindeps_emul32: return self.bindeps_emul32[symbol] else: if symbol in self.bindeps_cache: return self.bindeps_cache[symbol] if symbol in ExceptionRules: if info.emul32: return "mesalib-32bit" else: return "mesalib" if not paths: paths = ["/usr/lib64", "/usr/lib"] if info.emul32: paths = ["/usr/lib32", "/usr/lib", "/usr/lib64"] if info.rpaths: paths.extend(info.rpaths) pkg = None for path in paths: fpath = os.path.join(path, symbol) lpkg = None if fpath in self.files_cache: lpkg = self.files_cache[fpath] else: pkg = self.search_file(fpath) if pkg: lpkg = pkg[0][0] if lpkg: if info.emul32: self.bindeps_emul32[symbol] = lpkg else: self.bindeps_cache[symbol] = lpkg console_ui.emit_info( "Dependency", "{} adds dependency on {} from {}".format( info.pretty, symbol, lpkg)) # Populate a global files cache, basically there is a high # chance that each package depends on multiple things in a # single package. for file in self.idb.get_files(lpkg).list: self.files_cache["/" + file.path] = lpkg return lpkg return None def get_pkgconfig_provider(self, info, name): """ Get the internal provider for a pkgconfig name """ if info.emul32: if name in self.global_pkgconfig32s: pkg = self.global_pkgconfig32s[name] return self.ctx.spec.get_package_name(pkg) if name in self.global_pkgconfigs: pkg = self.global_pkgconfigs[name] return self.ctx.spec.get_package_name(pkg) def get_pkgconfig_external(self, info, name): """ Get the external provider of a pkgconfig name """ pkg = None if info.emul32: if name in self.pkgconfig32_cache: return self.pkgconfig32_cache[name] if name in self.pkgconfig_cache: return self.pkgconfig_cache[name] if info.emul32: pkg = self.idb.get_package_by_pkgconfig32(name) if not pkg: pkg = self.idb.get_package_by_pkgconfig(name) if not pkg: pkg = self.pdb.get_package_by_pkgconfig32(name) if not pkg: pkg = self.pdb.get_package_by_pkgconfig(name) else: pkg = self.idb.get_package_by_pkgconfig(name) if not pkg: pkg = self.pdb.get_package_by_pkgconfig(name) if not pkg: return None if info.emul32: self.pkgconfig32_cache[name] = pkg.name else: self.pkgconfig_cache[name] = pkg.name return pkg.name def handle_binary_deps(self, packageName, info): """ Handle direct binary dependencies """ for sym in info.symbol_deps: r = self.get_symbol_provider(sym) if not r: r = self.get_symbol_external(info, sym) if not r: print("Fatal: Unknown symbol: {}".format(sym)) continue self.gene.packages[packageName].depend_packages.add(r) def handle_pkgconfig_deps(self, packageName, info): """ Handle pkgconfig dependencies """ for item in info.pkgconfig_deps: pkgName = self.ctx.spec.get_package_name(packageName) prov = self.get_pkgconfig_provider(info, item) if not prov: prov = self.get_pkgconfig_external(info, item) if not prov: console_ui.emit_warning( "PKGCONFIG", "Not adding unknown" " dependency {} to {}".format(item, pkgName)) continue tgtPkg = self.gene.packages[packageName] # Yes, it's a set, but i dont want the ui emission spam if prov in tgtPkg.depend_packages: continue tgtPkg.depend_packages.add(prov) console_ui.emit_info("PKGCONFIG", "{} adds depend on {}".format(pkgName, prov)) def handle_pkgconfig_provides(self, packageName, info): adder = None if info.emul32: adder = "pkgconfig32({})".format(info.pkgconfig_name) else: adder = "pkgconfig({})".format(info.pkgconfig_name) # TODO: Add versioning in examine.py .. ? self.gene.packages[packageName].provided_symbols.add(adder) pass def handle_soname_links(self, packageName, info): """ Add dependencies between packages due to a .so splitting """ ourName = self.ctx.spec.get_package_name(packageName) for link in info.soname_links: fi = self.gene.get_file_owner(link) if not fi: console_ui.emit_warning( "SOLINK", "{} depends on non existing" "soname link: {}".format(packageName, link)) continue pkgName = self.ctx.spec.get_package_name(fi.name) if pkgName == ourName: continue self.gene.packages[packageName].depend_packages.add(pkgName) console_ui.emit_info( "SOLINK", "{} depends on {} through .so link".format(ourName, pkgName)) def compute_for_packages(self, context, gene, packageSet): """ packageSet is a dict mapping here. """ self.gene = gene self.packageSet = packageSet self.ctx = context # First iteration, collect the globals for packageName in packageSet: for info in packageSet[packageName]: if info.rpaths: self.global_rpaths.update(info.rpaths) if info.soname: self.global_sonames[info.soname] = packageName if info.pkgconfig_name: pcName = info.pkgconfig_name if info.emul32: self.global_pkgconfig32s[pcName] = packageName else: self.global_pkgconfigs[pcName] = packageName # Ok now find the dependencies for packageName in packageSet: for info in packageSet[packageName]: if info.symbol_deps: self.handle_binary_deps(packageName, info) if info.pkgconfig_deps: self.handle_pkgconfig_deps(packageName, info) if info.pkgconfig_name: self.handle_pkgconfig_provides(packageName, info) if info.soname_links: self.handle_soname_links(packageName, info) return True
def handle_dependencies(context, gene, metadata, package, files): """ Insert providers and dependencies into the spec """ global idb # Insert the simple guys first, replaces/conflicts, as these don't map # to internal names at all and are completely from the user if package.name in context.spec.replaces: for item in sorted(set(context.spec.replaces[package.name])): repl = pisi.replace.Replace() repl.package = str(item) metadata.package.replaces.append(repl) # conflicts if package.name in context.spec.conflicts: for item in sorted(set(context.spec.conflicts[package.name])): conf = pisi.conflict.Conflict() conf.package = str(item) metadata.package.conflicts.append(conf) if len(package.provided_symbols) > 0: for sym in package.provided_symbols: spc = None name = None g = pkgconfig32_dep.match(sym) if g: spc = pisi.specfile.PkgConfig32Provide() spc.om = g.group(1) metadata.package.providesPkgConfig32.append(spc) g = pkgconfig_dep.match(sym) if g: spc = pisi.specfile.PkgConfigProvide() spc.om = g.group(1) metadata.package.providesPkgConfig.append(spc) all_names = set() for i in gene.packages: all_names.add(context.spec.get_package_name(i)) dependencies = set(package.depend_packages) # Ensure some sane defaults are in place if package.name == "32bit" and "main" in gene.packages: if context.spec.get_component("main") != "kernel.drivers": dependencies.add(context.spec.get_package_name("main")) elif package.name == "32bit-devel": if "32bit" in gene.packages: dependencies.add(context.spec.get_package_name("32bit")) if "devel" in gene.packages: dependencies.add(context.spec.get_package_name("devel")) elif package.name == "devel": if "main" in gene.packages: dependencies.add(context.spec.get_package_name("main")) elif package.name == "dbginfo": if "main" in gene.packages: dependencies.add(context.spec.get_package_name("main")) elif package.name == "32bit-dbginfo": if "32bit" in gene.packages: dependencies.add(context.spec.get_package_name("32bit")) for dependency in dependencies: release = context.spec.pkg_release newDep = pisi.dependency.Dependency() local_fullname = context.spec.get_package_name(package.name) # Don't self depend. if dependency == local_fullname: continue if dependency not in all_names: # External dependency if not idb: idb = InstallDB() pkg = idb.get_package(dependency) newDep.package = dependency # Special case, kernel.image is an explicit dependency if pkg.partOf == "kernel.image": newDep.release = str(pkg.release) else: newDep.releaseFrom = str(pkg.release) else: newDep.package = dependency newDep.release = str(release) metadata.package.packageDependencies.append(newDep) if package.name not in context.spec.rundeps: return # Handle pattern/ypkg spec rundep for depname in context.spec.rundeps[package.name]: if depname in dependencies: continue dep = pisi.dependency.Dependency() if depname in all_names: dep.releaseFrom = str(context.spec.pkg_release) dep.package = str(depname) metadata.package.packageDependencies.append(dep)
def handle_dependencies(context, gene, metadata, package, files): """ Insert providers and dependencies into the spec """ global idb # Insert the simple guys first, replaces/conflicts, as these don't map # to internal names at all and are completely from the user if package.name in context.spec.replaces: for item in sorted(set(context.spec.replaces[package.name])): repl = pisi.replace.Replace() repl.package = str(item) metadata.package.replaces.append(repl) # conflicts if package.name in context.spec.conflicts: for item in sorted(set(context.spec.conflicts[package.name])): conf = pisi.conflict.Conflict() conf.package = str(item) metadata.package.conflicts.append(conf) if len(package.provided_symbols) > 0: for sym in package.provided_symbols: spc = None name = None g = pkgconfig32_dep.match(sym) if g: spc = pisi.specfile.PkgConfig32Provide() spc.om = g.group(1) metadata.package.providesPkgConfig32.append(spc) g = pkgconfig_dep.match(sym) if g: spc = pisi.specfile.PkgConfigProvide() spc.om = g.group(1) metadata.package.providesPkgConfig.append(spc) all_names = set() for i in gene.packages: all_names.add(context.spec.get_package_name(i)) dependencies = set(package.depend_packages) # Ensure some sane defaults are in place if package.name == "32bit" and "main" in gene.packages: dependencies.add(context.spec.get_package_name("main")) elif package.name == "32bit-devel": if "32bit" in gene.packages: dependencies.add(context.spec.get_package_name("32bit")) if "devel" in gene.packages: dependencies.add(context.spec.get_package_name("devel")) elif package.name == "devel": if "main" in gene.packages: dependencies.add(context.spec.get_package_name("main")) elif package.name == "dbginfo": if "main" in gene.packages: dependencies.add(context.spec.get_package_name("main")) elif package.name == "32bit-dbginfo": if "32bit" in gene.packages: dependencies.add(context.spec.get_package_name("32bit")) for dependency in dependencies: release = context.spec.pkg_release newDep = pisi.dependency.Dependency() local_fullname = context.spec.get_package_name(package.name) # Don't self depend. if dependency == local_fullname: continue if dependency not in all_names: # External dependency if not idb: idb = InstallDB() pkg = idb.get_package(dependency) newDep.package = dependency newDep.releaseFrom = str(pkg.release) else: newDep.package = dependency newDep.release = str(release) metadata.package.packageDependencies.append(newDep) if package.name not in context.spec.rundeps: return # Handle pattern/ypkg spec rundep for depname in context.spec.rundeps[package.name]: if depname in dependencies: continue dep = pisi.dependency.Dependency() if depname in all_names: dep.releaseFrom = str(context.spec.pkg_release) dep.package = str(depname) metadata.package.packageDependencies.append(dep)
for f in glob.glob("%s/.revdep-rebuild*" % os.environ["HOME"]): os.remove(f) if not options.soname and not options.soname_regexp and not options.package: search_broken = True elif options.soname and options.soname_regexp: print "%suse --soname and --soname-regexp separately%s" % (RD, NO) sys.exit(1) elif options.package and (options.soname or options.soname_regexp): print "%suse --package and (--soname or --soname-regexp) separately%s" % (RD, NO) sys.exit(1) else: search_broken = False print "\n%sCollecting installed packages and files...%s" % (GR, NO) installdb = InstallDB() idb = installdb.installed_db pkgfs = {} pkgls = {} for pkg, vr in idb.iteritems(): if re.search(DOCPKGPATTERN, pkg): continue ver = re.sub(VRPATTERN, "\\1", vr) files_xml = open(os.path.join(installdb.package_path(pkg), ctx.const.files_xml)).read() pkgfs[pkg] = re.compile('<Path>(.*?)</Path>', re.I).findall(files_xml) pkgls[pkg] = re.compile('<Path>(.*?\.so[\.\d]*)</Path>', re.I).findall(files_xml) print " done." print "\n%sCollecting old paths info...%s" % (GR, NO) oldpkgfs = {}
class DependencyResolver: idb = None pdb = None fdb = None global_rpaths = set() global_sonames = dict() global_pkgconfigs = dict() global_pkgconfig32s = dict() gene = None bindeps_cache = dict() bindeps_emul32 = dict() pkgconfig_cache = dict() pkgconfig32_cache = dict() files_cache = dict() def search_file(self, fname): if fname[0] == '/': fname = fname[1:] return self.fdb.search_file(fname) def __init__(self): """ Allows us to do look ups on all packages """ self.idb = InstallDB() self.pdb = PackageDB() self.fdb = FilesDB() def get_symbol_provider(self, symbol): """ Grab the symbol from the local packages """ if symbol in self.global_sonames: pkgname = self.global_sonames[symbol] return self.ctx.spec.get_package_name(pkgname) # Check if its in any rpath for rpath in self.global_rpaths: fpath = os.path.join(rpath, symbol) pkg = self.gene.get_file_owner(fpath) if pkg: return self.ctx.spec.get_package_name(pkg.name) return None def get_symbol_external(self, info, symbol, paths=None): """ Get the provider of the required symbol from the files database, i.e. installed binary dependencies """ # Try a cached approach first. if info.emul32: if symbol in self.bindeps_emul32: return self.bindeps_emul32[symbol] else: if symbol in self.bindeps_cache: return self.bindeps_cache[symbol] if symbol in ExceptionRules: if info.emul32: return "mesalib-32bit" else: return "mesalib" if not paths: paths = ["/usr/lib64", "/usr/lib"] if info.emul32: paths = ["/usr/lib32", "/usr/lib", "/usr/lib64"] if info.rpaths: paths.extend(info.rpaths) pkg = None for path in paths: fpath = os.path.join(path, symbol) lpkg = None if fpath in self.files_cache: lpkg = self.files_cache[fpath] else: pkg = self.search_file(fpath) if pkg: lpkg = pkg[0][0] if lpkg: if info.emul32: self.bindeps_emul32[symbol] = lpkg else: self.bindeps_cache[symbol] = lpkg console_ui.emit_info("Dependency", "{} adds dependency on {} from {}". format(info.pretty, symbol, lpkg)) # Populate a global files cache, basically there is a high # chance that each package depends on multiple things in a # single package. for file in self.idb.get_files(lpkg).list: self.files_cache["/" + file.path] = lpkg return lpkg return None def get_pkgconfig_provider(self, info, name): """ Get the internal provider for a pkgconfig name """ if info.emul32: if name in self.global_pkgconfig32s: pkg = self.global_pkgconfig32s[name] return self.ctx.spec.get_package_name(pkg) if name in self.global_pkgconfigs: pkg = self.global_pkgconfigs[name] return self.ctx.spec.get_package_name(pkg) def get_pkgconfig_external(self, info, name): """ Get the external provider of a pkgconfig name """ pkg = None if info.emul32: if name in self.pkgconfig32_cache: return self.pkgconfig32_cache[name] if name in self.pkgconfig_cache: return self.pkgconfig_cache[name] if info.emul32: pkg = self.idb.get_package_by_pkgconfig32(name) if not pkg: pkg = self.idb.get_package_by_pkgconfig(name) if not pkg: pkg = self.pdb.get_package_by_pkgconfig32(name) if not pkg: pkg = self.pdb.get_package_by_pkgconfig(name) else: pkg = self.idb.get_package_by_pkgconfig(name) if not pkg: pkg = self.pdb.get_package_by_pkgconfig(name) if not pkg: return None if info.emul32: self.pkgconfig32_cache[name] = pkg.name else: self.pkgconfig_cache[name] = pkg.name return pkg.name def handle_binary_deps(self, packageName, info): """ Handle direct binary dependencies """ for sym in info.symbol_deps: r = self.get_symbol_provider(sym) if not r: r = self.get_symbol_external(info, sym) if not r: print("Fatal: Unknown symbol: {}".format(sym)) continue self.gene.packages[packageName].depend_packages.add(r) def handle_pkgconfig_deps(self, packageName, info): """ Handle pkgconfig dependencies """ for item in info.pkgconfig_deps: pkgName = self.ctx.spec.get_package_name(packageName) prov = self.get_pkgconfig_provider(info, item) if not prov: prov = self.get_pkgconfig_external(info, item) if not prov: console_ui.emit_warning("PKGCONFIG", "Not adding unknown" " dependency {} to {}". format(item, pkgName)) continue tgtPkg = self.gene.packages[packageName] # Yes, it's a set, but i dont want the ui emission spam if prov in tgtPkg.depend_packages: continue tgtPkg.depend_packages.add(prov) console_ui.emit_info("PKGCONFIG", "{} adds depend on {}". format(pkgName, prov)) def handle_pkgconfig_provides(self, packageName, info): adder = None if info.emul32: adder = "pkgconfig32({})".format(info.pkgconfig_name) else: adder = "pkgconfig({})".format(info.pkgconfig_name) # TODO: Add versioning in examine.py .. ? self.gene.packages[packageName].provided_symbols.add(adder) pass def handle_soname_links(self, packageName, info): """ Add dependencies between packages due to a .so splitting """ ourName = self.ctx.spec.get_package_name(packageName) for link in info.soname_links: fi = self.gene.get_file_owner(link) if not fi: console_ui.emit_warning("SOLINK", "{} depends on non existing" "soname link: {}". format(packageName, link)) continue pkgName = self.ctx.spec.get_package_name(fi.name) if pkgName == ourName: continue self.gene.packages[packageName].depend_packages.add(pkgName) console_ui.emit_info("SOLINK", "{} depends on {} through .so link". format(ourName, pkgName)) def compute_for_packages(self, context, gene, packageSet): """ packageSet is a dict mapping here. """ self.gene = gene self.packageSet = packageSet self.ctx = context # First iteration, collect the globals for packageName in packageSet: for info in packageSet[packageName]: if info.rpaths: self.global_rpaths.update(info.rpaths) if info.soname: self.global_sonames[info.soname] = packageName if info.pkgconfig_name: pcName = info.pkgconfig_name if info.emul32: self.global_pkgconfig32s[pcName] = packageName else: self.global_pkgconfigs[pcName] = packageName # Ok now find the dependencies for packageName in packageSet: for info in packageSet[packageName]: if info.symbol_deps: self.handle_binary_deps(packageName, info) if info.pkgconfig_deps: self.handle_pkgconfig_deps(packageName, info) if info.pkgconfig_name: self.handle_pkgconfig_provides(packageName, info) if info.soname_links: self.handle_soname_links(packageName, info) return True
if not options.soname and not options.soname_regexp and not options.package: search_broken = True elif options.soname and options.soname_regexp: print "%suse --soname and --soname-regexp separately%s" % (RD, NO) sys.exit(1) elif options.package and (options.soname or options.soname_regexp): print "%suse --package and (--soname or --soname-regexp) separately%s" % ( RD, NO) sys.exit(1) else: search_broken = False print "\n%sCollecting installed packages and files...%s" % (GR, NO) installdb = InstallDB() idb = installdb.installed_db pkgfs = {} pkgls = {} for pkg, vr in idb.iteritems(): if re.search(DOCPKGPATTERN, pkg): continue ver = re.sub(VRPATTERN, "\\1", vr) files_xml = open( os.path.join(installdb.package_path(pkg), ctx.const.files_xml)).read() pkgfs[pkg] = re.compile('<Path>(.*?)</Path>', re.I).findall(files_xml) pkgls[pkg] = re.compile('<Path>(.*?\.so[\.\d]*)</Path>', re.I).findall(files_xml) print " done."