Exemplo n.º 1
0
    def loadTables(self, productName=None, flavors=None):
        """
        ensure all tables for a given product have been parsed and cached
        into memory.
        @param productName   the name of the product to cache tables for.  If
                                None, cache for all products
        @param flavors       the flavors of products to cache tables fo.
        """
        if productName and utils.is_string(productName):
            productName = productName.split()

        if not flavors:
            flavors = self.getFlavors()
        elif utils.is_string(flavors):
            flavors = flavors.split()

        for flavor in flavors:
            if flavor not in self.lookup:
                continue

            names = productName
            if not productName:
                names = self.getProductNames(flavor)

            for name in names:
                try:
                    self.lookup[flavor][name].loadTables()
                except KeyError:
                    pass
Exemplo n.º 2
0
    def getChainFile(self, tag, productName, searchUserDB=False):
        """
        return the ChainFile for the version name of the product that has the given tag assigned
        to it.  None is return if the tag is not assigned to any version.
        ProductNotFound is raised if no version of the product is declared.
        @param tag          the string name for the tag.  A user tag must be
                              prepended by a "user:"******"""
        pdir = self._productDir(productName)
        if not os.path.exists(pdir):
            raise ProductNotFound(productName, stack=self.dbpath)

        if is_string(tag):
            tag = eups.tags.Tag(tag)

        pdirs = []
        if searchUserDB and tag.isUser():
            for d in self._getUserTagDb(values=True):
                if d:
                    pdirs.append(self._productDir(productName, d))
        else:
            pdirs.append(pdir)

        for pdir in pdirs:
            tfile = self._tagFileInDir(pdir, tag.name)
            if os.path.exists(tfile):
                return ChainFile(tfile)

        return None
Exemplo n.º 3
0
    def getChainFile(self, tag, productName, searchUserDB=False):
        """
        return the ChainFile for the version name of the product that has the given tag assigned
        to it.  None is return if the tag is not assigned to any version.
        ProductNotFound is raised if no version of the product is declared.
        @param tag          the string name for the tag.  A user tag must be
                              prepended by a "user:"******"""
        pdir = self._productDir(productName)
        if not os.path.exists(pdir):
            raise ProductNotFound(productName, stack=self.dbpath);

        if is_string(tag):
            tag = eups.tags.Tag(tag)

        pdirs = []
        if searchUserDB and tag.isUser():
            for d in self._getUserTagDb(values=True):
                if d:
                    pdirs.append(self._productDir(productName, d))
        else:
            pdirs.append(pdir)

        for pdir in pdirs:
            tfile = self._tagFileInDir(pdir, tag.name)
            if os.path.exists(tfile):
                return ChainFile(tfile)

        return None
Exemplo n.º 4
0
    def assignTag(self, tag, productName, version, flavors=None, writeableDB=None):
        """
        assign a tag to a given product.

        @param tag :         the name of the tag to assign.  If the name is
                               prepended with the "user:"******"""

        if is_string(tag):
            tag = eups.tags.Tag(tag)

        vf = VersionFile(self._versionFile(productName, version))
        declaredFlavors = vf.getFlavors()
        if len(declaredFlavors) == 0:
            raise ProductNotFound(productName, version)

        if flavors is None:
            flavors = list(declaredFlavors)
        elif not isinstance(flavors, list):
            flavors = [flavors]
        else:
            flavors = list(flavors)  # make a copy; we're gonna mess with it
        if len(flavors) == 0:
            flavors = list(declaredFlavors)

        # reduce the list of flavors to ones actually declared
        for i in xrange(len(flavors)):
            flavor = flavors.pop(0)
            if flavor in declaredFlavors and flavor not in flavors:
                flavors.append(flavor)
        if len(flavors) == 0:
            raise ProductNotFound(productName, version,
                               msg="Requested flavors not declared for %s %s"
                                   % (productName, version))

        if not writeableDB and tag.isUser():
            if not self._getUserTagDb():
                raise RuntimeError("Unable to assign user tags (user db not available)")

            writeableDB = self._getUserTagDb()

        if writeableDB:
            pdir = self._productDir(productName, writeableDB)

            if not os.path.exists(pdir):
                os.makedirs(pdir)
        else:
            pdir = self._productDir(productName)

        tfile = self._tagFileInDir(pdir, tag.name)
        tagFile = ChainFile(tfile, productName, tag.name)

        tagFile.setVersion(version, flavors)
        tagFile.write()
Exemplo n.º 5
0
    def cacheIsInSync(self, flavors=None):
        """
        return False if it appears that disk caches have been updated
        since they were last read in.

        Note that this is different from cacheIsUpToDate()
        """
        if not flavors:
            flavors = self.getFlavors()
        if utils.is_string(flavors):
            flavors = [flavors]
        for flavor in flavors:
            file = self._persistPath(flavor)
            if not self._cacheFileIsInSync(file):
                return False
        return True
Exemplo n.º 6
0
    def checkInit(self, forserver=True):
        """Check that self is properly initialised; this matters for subclasses 
        with special needs"""
        if not eupsDistrib.Distrib.checkInit(self, forserver):
            return False

        if forserver:
            if 'pacmanCache' not in self.options:
                print("Option 'pacmanCache' not set", file=self.log)
                return False

            msg = "Illegal value for Option 'pacmanCache': "
            if not utils.is_string(self.options['pacmanCache']):
                print(msg + self.options['pacmanCache'], file=self.log)
                return False

            self.options['pacmanCache'] = self.options['pacmanCache'].strip()
            if len(self.options['pacmanCache']) == 0:
                print(msg + self.options['pacmanCache'], file=self.log)
                return False

        return True
Exemplo n.º 7
0
    def checkInit(self, forserver=True):
        """Check that self is properly initialised; this matters for subclasses
        with special needs"""
        if not eupsDistrib.Distrib.checkInit(self, forserver):
            return False

        if forserver:
            if 'pacmanCache' not in self.options:
                print("Option 'pacmanCache' not set", file=self.log)
                return False

            msg = "Illegal value for Option 'pacmanCache': "
            if not utils.is_string(self.options['pacmanCache']):
                print(msg + self.options['pacmanCache'], file=self.log)
                return False

            self.options['pacmanCache'] = self.options['pacmanCache'].strip()
            if len(self.options['pacmanCache']) == 0:
                print(msg + self.options['pacmanCache'], file=self.log)
                return False

        return True
Exemplo n.º 8
0
    def __init__(self, eupsenv, pkgroot, flavor=None, options=None,
                 distFactory=None, verbosity=0, log=sys.stderr):
        """
        create a Repository for a given server base URL (pkgroot)
        @param eupsenv       the Eups controller instance to use
        @param pkgroot       the base URL for the package server to pull
                                packages from or deploy packages to.
        @param flavor        the platform flavor of interest.
                                #--CUT
                                When installing
                                packages, this value is ignored and the version
                                set in the Eups controller is assumed to be
                                the target platform.  For all other actions
                                (creating server packages, listing available
                                packages), this value will be assumed.
                                #--
                                If
                                None or "generic", then a generic platform
                                is assumed.
        @param options       a dictionary of options to pass to Distrib
                                instances used to install and create packages
        @param distFactory   a DistFactory instance to use.  If not provided
                                a default one is created.
        @param verbosity     if > 0, print status messages; the higher the
                               number, the more messages that are printed
                               (default=0).
        @param log           the destination for status messages (default:
                               sys.stderr)
        """
        self.eups = eupsenv
        if not flavor:
            flavor = self.eups.flavor
        self.flavor = flavor
        self.distFactory = None
        if distFactory:
            self.distFactory = distFactory.clone()
        self.options = options
        self.verbose = verbosity
        if not isinstance(self.verbose, int):
            self.verbose = 0
        self.log = log
        self.distServer = None
        if self.options is None:
            self.options = {}
        if not isinstance(self.options, dict):
            raise RuntimeError("Non-dictionary passed to options parameter: " +
                               repr(self.options))
        self.pkgroot = pkgroot
        if pkgroot:
            override = None
            if 'serverconf' in self.options:
                override = options['serverconf']
            self.distServer = ServerConf.makeServer(pkgroot, eupsenv=eupsenv, override=override,
                                                    verbosity=self.verbose, log=self.log)
        if self.distFactory is None:
            self.distFactory = DistribFactory(self.eups, self.distServer)
        elif not self.distServer:
            self.distFactory.resetDistribServer(self.distServer)

        # a cache of the supported tag names
        self._supportedTags = None

        # a cache of supported packages
        self._pkgList = None

        # True if servers should always be queried when looking for a
        # repository to get a package from.  If False, an internal cache
        # of available products will be used.
        self._alwaysQueryServer = False
        if "alwaysQueryServer" in self.options:
            if is_string(self.options["alwaysQueryServer"]):
                self.options["alwaysQueryServer"] = \
                    self.options["alwaysQueryServer"].upper()
                if "TRUE".startswith(self.options["alwaysQueryServer"]):
                    self.options["alwaysQueryServer"] = True
                else:
                    self.options["alwaysQueryServer"] = False
            if self.options["alwaysQueryServer"]:
                self._alwaysQueryServer = True
        if self.distServer is not None and self.distServer.NOCACHE:
            self._alwaysQueryServer = True
Exemplo n.º 9
0
    def listPackages(self, product=None, version=None, flavor=None, tag=None,
                     queryServer=None, noaction=False):
        """
        return a list of available products on the server.  Each item
        in the list is a list of the form, (product, version, flavor).
        The optional inputs will restrict the list to those matching the
        values.
        @param product     the name of the product.  If None, all available
                             products are returned.
        @param version     the desired version.  This can either be a version
                             version string or an instance of Tag.  If None,
                             all available versions are returned.
        @param flavor      the desired platform flavor.  If None, all
                             available versions are returned.
        @param tag         list only products matching this tag.  If version
                             is also specified, an empty list will be returned
                             if the version (or matching versions) is (are) not
                             assigned this tag.
        @param queryServer if True, this will force a query to the repository
                             server.  If False, an internal cache will be used
                             if possible.  If None (default), the behavior is
                             controlled by the "alwaysQueryServer" passed to
                             the constructor of this Repository (which defaults
                             to False).
        """
        if queryServer is None:
            queryServer = self._alwaysQueryServer

        if isinstance(version, Tag) and version.name != "latest":
            tag = version
            version = None

        if queryServer or tag:
            if self.distServer is None:
                raise RuntimeError("No distribution server set")

            if tag:
                if isinstance(tag, Tag):
                    tagName = tag.name
                else:
                    tagName = tag
                    tag = self.eups.tags.getTag(tag)

                if not tag.isGlobal():
                    raise TagNotRecognized(tagName, "global",
                                           msg="Non-global tag \"%s\" requested." % tagName)
                if tagName == "latest":
                    return self._listLatestProducts(product, flavor)

                if tagName not in self.getSupportedTags():
                    raise TagNotRecognized(tag, "global",
                                           msg="tag %s not supported by server" % tag)

            return self.distServer.listAvailableProducts(product, version, flavor, tagName)

        else:
            if self._pkgList is None:
                self._pkgList = self._getPackageLookup()
            out = []

            prods = self._pkgList["_sortOrder"]
            if product:
                if product not in self._pkgList:
                    return []
                prods = [product]

            for prod in prods:
                flavs = self._pkgList[prod]["_sortOrder"]
                if flavor:
                    if flavor not in self._pkgList[prod]:
                        continue
                    flavs = [flavor]

                for flav in flavs:
                    if version is None:
                        out.extend( (prod, v, flav) for v in self._pkgList[prod][flav] )
                    elif version and is_string(version):
                        if version not in self._pkgList[prod][flav]:
                            continue
                        out.append( (prod, version, flav) )
                    else:
                        # looking for latest
                        out.append((prod,self._pkgList[prod][flav][-1],flav))

            return out
Exemplo n.º 10
0
    def assignTag(self,
                  tag,
                  productName,
                  version,
                  flavors=None,
                  writeableDB=None):
        """
        assign a tag to a given product.

        @param tag :         the name of the tag to assign.  If the name is
                               prepended with the "user:"******"""

        if is_string(tag):
            tag = eups.tags.Tag(tag)

        vf = VersionFile(self._versionFile(productName, version))
        declaredFlavors = vf.getFlavors()
        if len(declaredFlavors) == 0:
            raise ProductNotFound(productName, version)

        if flavors is None:
            flavors = list(declaredFlavors)
        elif not isinstance(flavors, list):
            flavors = [flavors]
        else:
            flavors = list(flavors)  # make a copy; we're gonna mess with it
        if len(flavors) == 0:
            flavors = list(declaredFlavors)

        # reduce the list of flavors to ones actually declared
        for i in xrange(len(flavors)):
            flavor = flavors.pop(0)
            if flavor in declaredFlavors and flavor not in flavors:
                flavors.append(flavor)
        if len(flavors) == 0:
            raise ProductNotFound(
                productName,
                version,
                msg="Requested flavors not declared for %s %s" %
                (productName, version))

        if not writeableDB and tag.isUser():
            if not self._getUserTagDb():
                raise RuntimeError(
                    "Unable to assign user tags (user db not available)")

            writeableDB = self._getUserTagDb()

        if writeableDB:
            pdir = self._productDir(productName, writeableDB)

            if not os.path.exists(pdir):
                os.makedirs(pdir)
        else:
            pdir = self._productDir(productName)

        tfile = self._tagFileInDir(pdir, tag.name)
        tagFile = ChainFile(tfile, productName, tag.name)

        tagFile.setVersion(version, flavors)
        tagFile.write()
Exemplo n.º 11
0
    def __init__(self, pkgroots, options=None, eupsenv=None,
                 installFlavor=None, distribClasses=None, override=None, allowEmptyPkgroot=False,
                 verbosity=None, log=sys.stderr):

        """
        @param pkgroots   the base URLs for the distribution repositories.  This
                            can either be a list or a pipe-delimited ("|")
                            string.
        @param options    a dictionary of named options that are used to fine-
                            tune the behavior of the repositories.  These are
                            passed onto the constructors for the underlying
                            Reposistory classes.
        @param eupsenv    an instance of a Eups class containing the Eups
                            environment to assume
        @param installFlavor   the desired flavor any install requests
        @param distribClasses  a dictionary by name of the Distrib classes
                            to support.  This will augmented by those specified
                            by a server.
        @param override   a dictionary of server configuration parameters that
                            should override the configuration received from
                            each server.
        @param allowEmptyPkgroot     we are creating a distribution, so it's OK for pkgroot to be empty
        @param verbosity  if > 0, print status messages; the higher the
                            number, the more messages that are printed
                            (default is the value of eupsenv.verbose).
        @param log        the destination for status messages (default:
                            sys.stderr)
        """
        if utils.is_string(pkgroots):
            pkgroots = [p.strip() for p in pkgroots.split("|")]
        if not allowEmptyPkgroot and len(pkgroots) == 0:
            raise EupsException("No package servers to query; set -r or $EUPS_PKGROOT")

        # the Eups environment
        self.eups = eupsenv
        if not self.eups:
            self.eups = Eups()

        self.verbose = verbosity
        if self.verbose is None:
            self.verbose = self.eups.verbose
        self.log = log
        if self.log is None:
            self.log = sys.stdout

        if not distribClasses:
            distribClasses = {}

        # the list of repository base URLs
        self.pkgroots = []

        # a lookup of Repository instances by its base URL
        self.repos = {}

        # the preferred installation flavor
        self.flavor = installFlavor
        if not self.flavor:
            self.flavor = self.eups.flavor

        df = DistribFactory(self.eups)
        for name in distribClasses.keys():
            # note: this will override the server's recommendation
            # if we want change this, use:
            #   if not df.supportsName(name):
            #       df.register(distribClasses[name], name)
            #
            df.register(distribClasses[name], name)

        for pkgroot in pkgroots:
#            if pkgroot == None:
#                ds = None
#            else:
#                ds = ServerConf.makeServer(pkgroot, eupsenv=eupsenv,
#                                           override=override,
#                                           verbosity=self.eups.verbose)
#
            try:
                dist = Repository(self.eups, pkgroot, options=options,
                                  flavor=installFlavor, distFactory=df,
                                  verbosity=self.eups.verbose)

                self.pkgroots += [pkgroot]
                self.repos[pkgroot] = dist

            except ImportError as e:
                msg =  "Unable to use server %s: \"%s\"" % (pkgroot, e)
                if self.eups.force:
                    print(msg + "; continuing", file=self.log)
                else:
                    raise RuntimeError(msg + ". Remove server from PKGROOT or use force")

        if len(self.pkgroots) == 0:
            msg = "No usable package repositories are loaded"
            if allowEmptyPkgroot or self.eups.force:
                print("WARNING: %s" % msg, file=self.log)
            else:
                raise RuntimeError(msg)

        # a cache of the union of tag names supported by the repositories
        self._supportedTags = None

        # used by install() to control repeated error messages
        self._msgs = {}
Exemplo n.º 12
0
    def install(self, product, version=None, updateTags=None, alsoTag=None,
                depends=DEPS_ALL, noclean=False, noeups=False, options=None,
                manifest=None, searchDep=None):
        """
        Install a product and all its dependencies.
        @param product     the name of the product to install
        @param version     the desired version of the product.  This can either
                            be a version string or an instance of Tag.  If
                            not provided (or None) the most preferred version
                            will be installed.
        @param updateTags  when None (default), server-assigned tags will
                            be updated for this product and all its dependcies
                            to match those recommended on the server (even if
                            a product is already installed); otherwise it's the
                            name of the tag that should be updated (so e.g. '' => none)
        @param alsoTag     A list of tags to assign to all installed products
                            (in addition to server tags).  This can either be
                            a space-delimited list, a list of string names,
                            a Tag instance, or a list of Tag instances.
        @param depends     If DEPS_ALL, product and dependencies will be installed
                              DEPS_NONE, dependencies will not be installed
                              DEPS_ONLY, only dependencies will be installed,
                              usefull for developement purpose (before a
                              setup -r .)
        @param noclean     If False (default), the build directory will get
                            cleaned up after a successful install.  A True
                            value prevents this.
        @param noeups      if False (default), needed products that are already
                            installed will be skipped over.  If True, an
                            attempt is made to install them anyway.  This
                            allows a product to be installed in the target
                            install stack even if it is available in another
                            stack managed by EUPS.  Note, however, that if a
                            needed product is already installed into the target
                            stack, the installation may fail.  Use with caution.
        @param options     a dictionary of named options that are used to fine-
                            tune the behavior of this Distrib class.  See
                            discussion above for a description of the options
                            supported by this implementation; sub-classes may
                            support different ones.
        @param manifest    use this manifest (a local file) as the manifest for
                            the requested product instead of downloading manifest
                            from the server.
        @param searchDep   if False, install will be prevented from recursively
                            looking for dependencies of dependencies listed in
                            manifests.  In this case, it is assumed that a
                            manifest contains all necessary dependencies.  If
                            True, the distribution identifiers in the manifest
                            file are ignored and the dependencies will always
                            be recursively searched for.  If None,
                            the choice to recurse is left up to the server
                            where the manifest comes from (which usually
                            defaults to False).
        """
        if alsoTag is not None:
            if utils.is_string(alsoTag):
                alsoTag = [self.eups.tags.getTag(t) for t in alsoTag.split()]
            elif isinstance(alsoTag, Tag):
                alsoTag = [alsoTag]

        pkg = self.findPackage(product, version)
        if not pkg:
            raise ProductNotFound(product, version,
                    msg="Product %s %s not found in any package repository" %
                        (product, version))

        (product, version, flavor, pkgroot) = pkg
        productRoot = self.getInstallRoot()
        if productRoot is None:
            raise EupsException("Unable to find writable place to install in EUPS_PATH")

        if manifest is not None:
            if not manifest or os.path.exists(manifest):
                raise EupsException("%s: user-provided manifest not found" %
                                    manifest)
            man = Manifest.fromFile(manifest, self.eups,
                                    verbosity=self.eups.verbose-1)
        else:
            man = self.repos[pkgroot].getManifest(product, version, flavor)

        man.remapEntries()              # allow user to rewrite entries in the manifest
        if product not in [p.product for p in man.getProducts()]:
            raise EupsException("You asked to install %s %s but it is not in the manifest\nCheck manifest.remap (see \"eups startup\") and/or increase the verbosity" % (product, version))

        self._msgs = {}
        self._recursiveInstall(0, man, product, version, flavor, pkgroot,
                               productRoot, updateTags, alsoTag, options,
                               depends, noclean, noeups)