Skip to content

Commit

Permalink
Add eups diff subcommand
Browse files Browse the repository at this point in the history
  • Loading branch information
leeskelvin committed Jan 16, 2024
1 parent ea2e117 commit f6218a8
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 9 deletions.
42 changes: 37 additions & 5 deletions python/eups/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from .utils import cmp_or_key, cmp

def printProducts(ostrm, productName=None, versionName=None, eupsenv=None,
tags=None, setup=False, tablefile=False, directory=False,
tags=None, baseTags=None, setup=False, tablefile=False, directory=False,
dependencies=False, showVersion=False, showName=False, showTagsGlob="*",
depth=None, productDir=None, topological=False, checkCycles=False, raw=False):
"""
Expand All @@ -33,6 +33,8 @@ def printProducts(ostrm, productName=None, versionName=None, eupsenv=None,
@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 baseTags restrict the listing to products which differ from a baseline
reference set as defined by 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
Expand All @@ -49,6 +51,7 @@ def printProducts(ostrm, productName=None, versionName=None, eupsenv=None,
a logical operator and an integer (e.g.
"> 3") implies a comparison with the depth
of each dependency (i.e. "depth > 3").
@param productDir List dependencies of this product directory
@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)
Expand All @@ -62,6 +65,10 @@ def printProducts(ostrm, productName=None, versionName=None, eupsenv=None,
checkTagsList(eupsenv, tags)
elif setup and not dependencies:
tags = ["setup"]
if baseTags:
if utils.is_string(baseTags):
baseTags = baseTags.split()
checkTagsList(eupsenv, baseTags)

if showTagsGlob == "*":
showTagsGlob = None
Expand All @@ -88,9 +95,34 @@ def printProducts(ostrm, productName=None, versionName=None, eupsenv=None,
eupsenv.setup(productName, versionName, productRoot=os.path.abspath(productDir))
setup = True # only list this version

productList = eupsenv.getSetupProducts(productName) if setup else \
eupsenv.findProducts(productName, versionName, tags)
if not productList:
# get a list of products to print
if baseTags:
diffMsg = ""
# if a product is explicitly named, use that to generate baseline tags
if productName:
baseProduct = eupsenv.findProducts(productName, versionName) if versionName else \
eupsenv.getSetupProducts(productName)
if not baseProduct:
errmsg = "%s is not currently setup; please choose the version that you want (%s)" % \
(productName, ", ".join(p.version for p in eupsenv.findProducts(productName)))
raise EupsException(errmsg)
baseTags = baseProduct[0].tags
baseTagsFull = baseTags + ["setup"] if eupsenv.isSetup(baseProduct[0].name, baseProduct[0].version, baseProduct[0].stackRoot()) else baseTags
diffMsg += "%-21s %-10s \t %s\n" % \
(productName, baseProduct[0].version, " ".join([Tag(t).name for t in baseTagsFull]))

targetProducts = set(eupsenv.findProducts(tags=tags))
baseProducts = set(eupsenv.findProducts(tags=baseTags))
productList = list(targetProducts - baseProducts)
diffMsg += "Products tagged as \"%s\" and not \"%s\":" % \
(", ".join([Tag(t).name for t in tags]), ", ".join([Tag(t).name for t in baseTags]))
print(diffMsg, file=ostrm)
else:
productList = eupsenv.getSetupProducts(productName) if setup else \
eupsenv.findProducts(productName, versionName, tags)

# raise an exception if we didn't find the product and it's not a baseline reference
if not productList and not baseTags:
if productName:
msg = productName
if versionName:
Expand Down Expand Up @@ -252,7 +284,7 @@ def includeProduct(recursionDepth):
info += "|"
info += name + "|" + version
else:
if productName and not utils.isGlob(productName):
if productName and not utils.isGlob(productName) and not baseTags:
info += " "
else:
info += "%-21s " % (name)
Expand Down
97 changes: 93 additions & 4 deletions python/eups/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ def addOptions(self):

# these are specific to this command
self.clo.add_option("-c", "--current", dest="currentTag", action="store_true", default=False,
help="same as --postTag=current")
help="same as --tag=current")
self.clo.add_option("-D", "--dependencies", dest="depends", action="store_true", default=False,
help="Print product's dependencies (must specify version if ambiguous). With --setup print the versions of dependent products that are actually setup.")
self.clo.add_option("--depth", dest="depth", action="store",
Expand Down Expand Up @@ -511,10 +511,12 @@ def execute(self):
tablefile=self.opts.tablefile,
directory=self.opts.printdir,
dependencies=self.opts.depends,
showVersion=self.opts.version, showName=self.opts.showName,
showVersion=self.opts.version,
showName=self.opts.showName,
showTagsGlob=self.opts.showTagsGlob,
depth=self.opts.depth,
productDir=self.opts.productDir, topological=self.opts.topological,
productDir=self.opts.productDir,
topological=self.opts.topological,
checkCycles=self.opts.checkCycles,
raw=self.opts.raw
)
Expand All @@ -535,6 +537,93 @@ def execute(self):

return 0

class DiffCmd(EupsCmd):

usage = "%prog diff [-h|--help] [options] [product [version]]"

# set this to True if the description is preformatted. If false, it
# will be automatically reformatted to fit the screen
noDescriptionFormatting = True

description = \
"""Print information about products that differ from a baseline set.
List all target products that differ from their equivalents in a baseline
reference set. By default, the target set is defined as those that are
currently set up (i.e., products that have the tag "setup") and the baseline
set is defined as those that are current (i.e., products that have the tag
"current").
If product and version arguments are provided, the tags associated with the
specified product will be used in lieu of an explicit baseline tag. If a
product argument is given without a version, the currently setup version of
that product will be used (when possible).
"""

def addOptions(self):
# always call the super-version so that the core options are set
EupsCmd.addOptions(self)

# these options are used to configure the Eups instance
self.addEupsOptions()

# these are specific to this command
self.clo.add_option("-b", "--baseline", dest="baseTags", action="append",
help="Use this tag name to identify a baseline reference set of products "
"(ignored if a product is specified)")
self.clo.add_option("-d", "--directory", dest="printdir", action="store_true", default=False,
help="Include the product's installation directory")
self.clo.add_option("-m", "--table", dest="tablefile", action="store_true", default=False,
help="Print the name of the product's table file")
self.clo.add_option("--name", dest="showName", action="store_true", default=False,
help="Print the product's name")
self.clo.add_option("--raw", action="store_true",
help="Generate \"raw\" output (suitable for further processing)")
self.clo.add_option("-r", "--root", dest="productDir", action="store",
help="Root directory where the reference product is installed")
self.clo.add_option("-T", "--type", dest="setupType", action="store", default="",
help="The setup type to assume (ignored unless -d is specified)")
self.clo.add_option("-t", "--target", dest="targetTags", action="append",
help="Use this tag name to identify a target set of products")
self.clo.add_option("-V", "--version", dest="version", action="store_true", default=False,
help="Print product version")

def execute(self):
# set product/version and baseline/target defaults
product, version = (self.args + [None, None])[:2]
self.opts.baseTags = self.opts.baseTags or ["current"]
self.opts.targetTags = self.opts.targetTags or ["setup"]

# attempt to print the diff
try:
n = eups.printProducts(sys.stdout, product, version,
self.createEups(self.opts, versionName=version, quiet=1),
tags=self.opts.targetTags,
baseTags=self.opts.baseTags,
tablefile=self.opts.tablefile,
directory=self.opts.printdir,
showVersion=self.opts.version,
showName=self.opts.showName,
productDir=self.opts.productDir,
raw=self.opts.raw,
)
if n == 0:
msg = 'No products found'
self.err(msg)

except eups.ProductNotFound as e:
msg = e.getMessage()
if product == "distrib":
e.msg += '; Maybe you meant "eups distrib list"?'
e.status = 1
raise

except eups.EupsException as e:
e.status = 2
raise

return 0

class FlagsCmd(EupsCmd):

usage = "%prog flags [-h|--help]"
Expand Down Expand Up @@ -2886,7 +2975,6 @@ def execute(self):

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-


class TagsCmd(EupsCmd):

usage = """%prog tags [-h|--help] [options] [tagname] [product]
Expand Down Expand Up @@ -3183,6 +3271,7 @@ def format_description(self, formatter):
register("pkgroot", PkgrootCmd, lockType=None)
register("flags", FlagsCmd, lockType=None)
register("list", ListCmd, lockType=lock.LOCK_SH)
register("diff", DiffCmd, lockType=lock.LOCK_SH)
register("pkg-config", PkgconfigCmd, lockType=lock.LOCK_SH)
register("uses", UsesCmd, lockType=lock.LOCK_SH)
register("expandbuild", ExpandbuildCmd, lockType=lock.LOCK_SH)
Expand Down

0 comments on commit f6218a8

Please sign in to comment.