def productDir(productName=None, versionName=Tag("setup"), eupsenv=None): """ return the installation directory (PRODUCT_DIR) for the specified product. None is returned if no matching product can be found @param productName the name of the product of interest; if None return a dictionary of all productDirs @param version the desired version. This can in one of the following forms: * an explicit version * a version expression (e.g. ">=3.3") * a Tag instance * None, in which case, the (most) preferred version will be returned. The default is the global tag "setup". @param eupsenv The Eups instance to use to find the product. If not provided, a default will created. """ if productName and versionName == Tag("setup"): # we can take a shortcut return os.environ.get(utils.dirEnvNameFor(productName)) if not eupsenv: eupsenv = Eups() if not productName: tags = None if versionName == Tag("setup"): tags = versionName versionName = "" productList = eupsenv.findProducts(productName, versionName, tags) productDirs = {} for prod in productList: pdir = prod.dir if pdir == "none": pdir = None productDirs[prod.name] = pdir return productDirs prod = eupsenv.findProduct(productName, versionName) if not prod: return None pdir = prod.dir if pdir == "none": pdir = None return pdir
def productDir(productName=None, versionName=Tag("setup"), eupsenv=None): """ return the installation directory (PRODUCT_DIR) for the specified product. None is returned if no matching product can be found @param productName the name of the product of interest; if None return a dictionary of all productDirs @param version the desired version. This can in one of the following forms: * an explicit version * a version expression (e.g. ">=3.3") * a Tag instance * None, in which case, the (most) preferred version will be returned. The default is the global tag "setup". @param eupsenv The Eups instance to use to find the product. If not provided, a default will created. """ if productName and versionName == Tag("setup"): # we can take a shortcut return os.environ.get(utils.dirEnvNameFor(productName)) if not eupsenv: eupsenv = Eups() if not productName: tags = None if versionName == Tag("setup"): tags = versionName versionName = "" productList = eupsenv.findProducts(productName, versionName, tags) productDirs = {} for prod in productList: pdir = prod.dir if pdir == "none": pdir = None productDirs[prod.name] = pdir return productDirs prod = eupsenv.findProduct(productName, versionName) if not prod: return None pdir = prod.dir if pdir == "none": pdir = None return pdir
def printUses(outstrm, productName, versionName=None, eupsenv=None, depth=9999, showOptional=False, tags=None, pickleFile=None): """ print a listing of products that make use of a given product. @param outstrm the output stream to write the listing to @parma productName the name of the product to find usage of for @param versionName the product version to query. If None, all versions will be considered @param eupsenv the Eups instance to use; if None, a default will be created. @param depth maximum number of dependency levels to examine @param showOptional if True, indicate if a dependency is optional. @param tags the preferred set of tags to choose when examining dependencies. @param pickleFile file to save uses dependencies to (or read from if starts with <) """ if not eupsenv: eupsenv = Eups() if tags: eupsenv.setPreferredTags(tags) # # To work # if pickleFile and pickleFile[0] == "<": # read it fd = open(pickleFile[1:]) usesInfo = cPickle.load(fd) fd.close() else: usesInfo = eupsenv.uses() if pickleFile: fd = open(pickleFile, "w") cPickle.dump(usesInfo, fd) fd.close() userList = eupsenv.uses(productName, versionName, depth, usesInfo=usesInfo) if len(userList) == 0: # nobody cares. Maybe the product doesn't exist? productList = eupsenv.findProducts(productName, versionName) if len(productList) == 0: raise ProductNotFound(productName, versionName) fmt = "%-25s %-15s" str = fmt % ("product", "version") if versionName: # we know the product version, so don't print it again fmt2 = None else: fmt2 = " %-15s" str += fmt2 % ("%s version" % productName) print >> outstrm, str for (p, pv, requestedInfo) in userList: if requestedInfo.optional and not showOptional: continue str = fmt % (("%*s%s" % (0*requestedInfo.depth, "", p)), pv) if fmt2: str += fmt2 % (requestedInfo.version) if showOptional: if requestedInfo.optional: str += "Optional" print >> outstrm, str
def printProducts(ostrm, productName=None, versionName=None, eupsenv=None, tags=None, setup=False, tablefile=False, directory=False, dependencies=False, showVersion=False, showName=False, depth=None, productDir=None, topological=False, checkCycles=False, raw=False): """ print out a listing of products. Returned is the number of products listed. @param ostrm the output stream to send listing to @param productName restrict the listing to this product @param versionName restrict the listing to this version of the product. @param eupsenv the Eups instance to use; if None, a default will be created. @param tags restrict the listing to products with these tag names @param setup restrict the listing to products that are currently setup (or print actually setup versions with dependencies) @param tablefile include the path to each product's table file @param directory include each product's installation directory @param dependencies print the product's dependencies @param showVersion Only print the product{'s,s'} version[s] (e.g. eups list -V -s afw) @param showName Only print the product{'s,s'} name[s] (e.g. eups list --name -t rhl) @param depth a string giving an expression for determining whether a dependency of a certain depth should be included. This string can be a simple integer which will be taken to mean, print all depths <= that integer. An expression having just a a logical operator and an integer (e.g. "> 3") implies a comparison with the depth of each dependency (i.e. "depth > 3"). @param topological List dependencies in topological-sorted order @param checkCycles Raise RuntimeError if topological sort detects a cycle @param raw Generate "raw" output (suitable for further processing) """ if not eupsenv: eupsenv = Eups() if tags: if isinstance(tags, str): tags = tags.split() checkTagsList(eupsenv, tags) elif setup and not dependencies: tags = ["setup"] # If productDir is provided only list its dependencies; we do this by setting it up if productDir: if not dependencies: raise EupsException("-r only makes sense with --dependencies") if productDir: ups_dir = os.path.join(productDir, "ups") if not os.path.isdir(ups_dir): raise EupsException("Unable to guess product name as product has no ups directory") p = utils.guessProduct(ups_dir) if productName: if p != productName: raise EupsException("Guessed product %s from ups directory, but %s from path" % \ (productName, p)) else: productName = p if tags: tag = tags[0] else: tag = None eupsenv.setup(productName, versionName, productRoot=os.path.abspath(productDir)) setup = True # only list this version productNameIsGlob = productName and re.search(r"[\[\]?*]", productName) # is productName actually a glob? productList = eupsenv.findProducts(productName, versionName, tags) if not productList: if productName: msg = productName if versionName: msg += " %s" % versionName if tags: msg += " tagged \"%s\"" % ", ".join([Tag(t).name for t in tags]) raise ProductNotFound(productName, versionName, msg="Unable to find product %s" % msg) productList.sort(lambda a,b: cmp(a, b), lambda p: ":".join([p.name, p.version])) if dependencies: _msgs = {} # maintain list of printed dependencies recursionDepth, indent = 0, "" if len(productList) > 1: if setup: productList = eupsenv.getSetupProducts(productName) else: raise EupsException("Please choose the version you want listed (%s)" % (", ".join([p.version for p in productList]))) else: if topological: raise EupsException("--topological only makes sense with --dependencies") productTags = {} # list of tags indexed by product oinfo = None # previous value of "info"; used to suppress repetitions due to e.g. # listing directories when there's a NULL and Linux declaration if depth is None: depth = "True" else: try: depth = "<= %d" % int(depth) except ValueError: pass if not re.search(r"depth", depth): depth = "depth" + depth def includeProduct(recursionDepth): """Should we include a product at this recursionDepth in the listing?""" depthExpr = VersionParser(depth) depthExpr.define("depth", recursionDepth) return depthExpr.eval() if dependencies: recursionDepth = 0 product = productList[0] if includeProduct(recursionDepth) and not (checkCycles and not topological): if raw: fmt = "%s|%s" else: fmt = "%-40s %s" print fmt % (product.name, product.version) for product, optional, recursionDepth in eupsenv.getDependentProducts(product, setup, topological=topological, checkCycles=checkCycles): if not includeProduct(recursionDepth) or (checkCycles and not topological): continue if eupsenv.verbose or not _msgs.has_key(product.name): _msgs[product.name] = product.version if not re.search(r"==", depth): indent = "| " * (recursionDepth/2) if recursionDepth%2 == 1: indent += "|" if raw: print "%s|%s" % (product.name, product.version) else: print "%-40s %s" % (("%s%s" % (indent, product.name)), product.version) return 1 # # See if some tag appears more than once; if so, they are from different stacks # tagsSeen = {} for pi in productList: for t in pi.tags: if not tagsSeen.has_key(t): tagsSeen[t] = {} if not tagsSeen[t].has_key(pi.name): tagsSeen[t][pi.name] = 0 tagsSeen[t][pi.name] += 1 # # Actually list the products # nprod = len(productList) for pi in productList: name, version, root = pi.name, pi.version, pi.stackRoot() # for convenience if root == "none": root = " (none)" info = "" if setup: if not eupsenv.isSetup(pi.name, pi.version, pi.stackRoot()): continue else: if not pi._prodStack: # only found in the environment if False: continue # Exclude environment-only products if directory or tablefile: if eupsenv.verbose: if raw: if info: info += "|" info += version else: info += "%-10s" % (version) if directory: if pi.dir: if raw and info: info += "|" info += pi.dir else: info += "" if tablefile: if info: if raw: info += "|" else: info += "\t" if pi.tablefile: info += pi.tablefile else: info += "none" elif showName: if raw: if info: info += "|" info += name else: info += "%-10s" % (name) elif showVersion: info += "%-10s" % (version) else: if raw: if info: info += "|" info += name + "|" + version else: if productName and not productNameIsGlob: info += " " else: info += "%-21s " % (name) info += "%-10s " % (version) if eupsenv.verbose: if raw: if info: info += "|" if eupsenv.verbose > 1: if raw: info += pi.flavor + "|" else: info += "%-10s" % (pi.flavor) if raw: info += root + "|" + pi.dir else: info += "%-20s %-55s" % (root, pi.dir) extra = pi.tags else: extra = [] for t in pi.tags: if not eupsenv.verbose: t = Tag(t).name # get the bare tag name, not e.g. user:foo if tagsSeen.get(t) and tagsSeen[t].get(pi.name) > 1: t = "%s[%s]" % (t, root) extra.append(t) if eupsenv.isSetup(pi.name, pi.version, pi.stackRoot()): extra += ["setup"] if raw and info: info += "|" if extra: if raw: info += ":".join(extra) else: info += "\t" + " ".join(extra) if info: if info != oinfo: print info oinfo = info return nprod
def printUses(outstrm, productName, versionName=None, eupsenv=None, depth=9999, showOptional=False, tags=None, pickleFile=None): """ print a listing of products that make use of a given product. @param outstrm the output stream to write the listing to @parma productName the name of the product to find usage of for @param versionName the product version to query. If None, all versions will be considered @param eupsenv the Eups instance to use; if None, a default will be created. @param depth maximum number of dependency levels to examine @param showOptional if True, indicate if a dependency is optional. @param tags the preferred set of tags to choose when examining dependencies. @param pickleFile file to save uses dependencies to (or read from if starts with <) """ if not eupsenv: eupsenv = Eups() if tags: eupsenv.setPreferredTags(tags) # # To work # if pickleFile and pickleFile[0] == "<": # read it fd = open(pickleFile[1:]) usesInfo = cPickle.load(fd) fd.close() else: usesInfo = eupsenv.uses() if pickleFile: fd = open(pickleFile, "w") cPickle.dump(usesInfo, fd) fd.close() userList = eupsenv.uses(productName, versionName, depth, usesInfo=usesInfo) if len(userList) == 0: # nobody cares. Maybe the product doesn't exist? productList = eupsenv.findProducts(productName, versionName) if len(productList) == 0: raise ProductNotFound(productName, versionName) fmt = "%-25s %-15s" str = fmt % ("product", "version") if versionName: # we know the product version, so don't print it again fmt2 = None else: fmt2 = " %-15s" str += fmt2 % ("%s version" % productName) print >> outstrm, str for (p, pv, requestedInfo) in userList: if requestedInfo.optional and not showOptional: continue str = fmt % (("%*s%s" % (0 * requestedInfo.depth, "", p)), pv) if fmt2: str += fmt2 % (requestedInfo.version) if showOptional: if requestedInfo.optional: str += "Optional" print >> outstrm, str
def printProducts(ostrm, productName=None, versionName=None, eupsenv=None, tags=None, setup=False, tablefile=False, directory=False, dependencies=False, showVersion=False, showName=False, depth=None, productDir=None, topological=False, checkCycles=False, raw=False): """ print out a listing of products. Returned is the number of products listed. @param ostrm the output stream to send listing to @param productName restrict the listing to this product @param versionName restrict the listing to this version of the product. @param eupsenv the Eups instance to use; if None, a default will be created. @param tags restrict the listing to products with these tag names @param setup restrict the listing to products that are currently setup (or print actually setup versions with dependencies) @param tablefile include the path to each product's table file @param directory include each product's installation directory @param dependencies print the product's dependencies @param showVersion Only print the product{'s,s'} version[s] (e.g. eups list -V -s afw) @param showName Only print the product{'s,s'} name[s] (e.g. eups list --name -t rhl) @param depth a string giving an expression for determining whether a dependency of a certain depth should be included. This string can be a simple integer which will be taken to mean, print all depths <= that integer. An expression having just a a logical operator and an integer (e.g. "> 3") implies a comparison with the depth of each dependency (i.e. "depth > 3"). @param topological List dependencies in topological-sorted order @param checkCycles Raise RuntimeError if topological sort detects a cycle @param raw Generate "raw" output (suitable for further processing) """ if not eupsenv: eupsenv = Eups() if tags: if isinstance(tags, str): tags = tags.split() checkTagsList(eupsenv, tags) elif setup and not dependencies: tags = ["setup"] # If productDir is provided only list its dependencies; we do this by setting it up if productDir: if not dependencies: raise EupsException("-r only makes sense with --dependencies") if productDir: ups_dir = os.path.join(productDir, "ups") if not os.path.isdir(ups_dir): raise EupsException( "Unable to guess product name as product has no ups directory" ) p = utils.guessProduct(ups_dir) if productName: if p != productName: raise EupsException("Guessed product %s from ups directory, but %s from path" % \ (productName, p)) else: productName = p if tags: tag = tags[0] else: tag = None eupsenv.setup(productName, versionName, productRoot=os.path.abspath(productDir)) setup = True # only list this version productNameIsGlob = productName and re.search( r"[\[\]?*]", productName) # is productName actually a glob? productList = eupsenv.findProducts(productName, versionName, tags) if not productList: if productName: msg = productName if versionName: msg += " %s" % versionName if tags: msg += " tagged \"%s\"" % ", ".join( [Tag(t).name for t in tags]) raise ProductNotFound(productName, versionName, msg="Unable to find product %s" % msg) productList.sort(lambda a, b: cmp(a, b), lambda p: ":".join([p.name, p.version])) if dependencies: _msgs = {} # maintain list of printed dependencies recursionDepth, indent = 0, "" if len(productList) > 1: if setup: productList = eupsenv.getSetupProducts(productName) else: raise EupsException( "Please choose the version you want listed (%s)" % (", ".join([p.version for p in productList]))) else: if topological: raise EupsException( "--topological only makes sense with --dependencies") productTags = {} # list of tags indexed by product oinfo = None # previous value of "info"; used to suppress repetitions due to e.g. # listing directories when there's a NULL and Linux declaration if depth is None: depth = "True" else: try: depth = "<= %d" % int(depth) except ValueError: pass if not re.search(r"depth", depth): depth = "depth" + depth def includeProduct(recursionDepth): """Should we include a product at this recursionDepth in the listing?""" depthExpr = VersionParser(depth) depthExpr.define("depth", recursionDepth) return depthExpr.eval() if dependencies: recursionDepth = 0 product = productList[0] if includeProduct(recursionDepth) and not (checkCycles and not topological): if raw: fmt = "%s|%s" else: fmt = "%-40s %s" print fmt % (product.name, product.version) for product, optional, recursionDepth in eupsenv.getDependentProducts( product, setup, topological=topological, checkCycles=checkCycles): if not includeProduct(recursionDepth) or (checkCycles and not topological): continue if eupsenv.verbose or not _msgs.has_key(product.name): _msgs[product.name] = product.version if not re.search(r"==", depth): indent = "| " * (recursionDepth / 2) if recursionDepth % 2 == 1: indent += "|" if raw: print "%s|%s" % (product.name, product.version) else: print "%-40s %s" % ( ("%s%s" % (indent, product.name)), product.version) return 1 # # See if some tag appears more than once; if so, they are from different stacks # tagsSeen = {} for pi in productList: for t in pi.tags: if not tagsSeen.has_key(t): tagsSeen[t] = {} if not tagsSeen[t].has_key(pi.name): tagsSeen[t][pi.name] = 0 tagsSeen[t][pi.name] += 1 # # Actually list the products # nprod = len(productList) for pi in productList: name, version, root = pi.name, pi.version, pi.stackRoot( ) # for convenience if root == "none": root = " (none)" info = "" if setup: if not eupsenv.isSetup(pi.name, pi.version, pi.stackRoot()): continue else: if not pi._prodStack: # only found in the environment if False: continue # Exclude environment-only products if directory or tablefile: if eupsenv.verbose: if raw: if info: info += "|" info += version else: info += "%-10s" % (version) if directory: if pi.dir: if raw and info: info += "|" info += pi.dir else: info += "" if tablefile: if info: if raw: info += "|" else: info += "\t" if pi.tablefile: info += pi.tablefile else: info += "none" elif showName: if raw: if info: info += "|" info += name else: info += "%-10s" % (name) elif showVersion: info += "%-10s" % (version) else: if raw: if info: info += "|" info += name + "|" + version else: if productName and not productNameIsGlob: info += " " else: info += "%-21s " % (name) info += "%-10s " % (version) if eupsenv.verbose: if raw: if info: info += "|" if eupsenv.verbose > 1: if raw: info += pi.flavor + "|" else: info += "%-10s" % (pi.flavor) if raw: info += root + "|" + pi.dir else: info += "%-20s %-55s" % (root, pi.dir) extra = pi.tags else: extra = [] for t in pi.tags: if not eupsenv.verbose: t = Tag( t).name # get the bare tag name, not e.g. user:foo if tagsSeen.get(t) and tagsSeen[t].get(pi.name) > 1: t = "%s[%s]" % (t, root) extra.append(t) if eupsenv.isSetup(pi.name, pi.version, pi.stackRoot()): extra += ["setup"] if raw and info: info += "|" if extra: if raw: info += ":".join(extra) else: info += "\t" + " ".join(extra) if info: if info != oinfo: print info oinfo = info return nprod