Beispiel #1
0
    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()
Beispiel #2
0
    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()
Beispiel #3
0
    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()
Beispiel #4
0
    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()
Beispiel #5
0
    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
Beispiel #6
0
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)
Beispiel #7
0
    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)))
Beispiel #8
0
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
Beispiel #9
0
 def __init__(self):
     """ Allows us to do look ups on all packages """
     self.idb = InstallDB()
     self.pdb = PackageDB()
     self.fdb = FilesDB()
Beispiel #10
0
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
Beispiel #11
0
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)
Beispiel #12
0
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)
Beispiel #13
0
        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 = {}
Beispiel #14
0
 def __init__(self):
     """ Allows us to do look ups on all packages """
     self.idb = InstallDB()
     self.pdb = PackageDB()
     self.fdb = FilesDB()
Beispiel #15
0
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
Beispiel #16
0
    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."