summaryrefslogtreecommitdiff
path: root/cpp/install/common/components.py
diff options
context:
space:
mode:
authorBrent Eagles <brent@zeroc.com>2005-12-08 19:27:22 +0000
committerBrent Eagles <brent@zeroc.com>2005-12-08 19:27:22 +0000
commitafba20bc64e154c18fc80e78540702b03f4a1192 (patch)
tree595e5ece8c9628a0ea2ffd9c80f1b33b19d827dd /cpp/install/common/components.py
parentadding missing installer components and worked out way to filter out demo (diff)
downloadice-afba20bc64e154c18fc80e78540702b03f4a1192.tar.bz2
ice-afba20bc64e154c18fc80e78540702b03f4a1192.tar.xz
ice-afba20bc64e154c18fc80e78540702b03f4a1192.zip
moving makewindist.py to using new staging logic... the vc71 installer does
not build correctly yet
Diffstat (limited to 'cpp/install/common/components.py')
-rwxr-xr-xcpp/install/common/components.py320
1 files changed, 320 insertions, 0 deletions
diff --git a/cpp/install/common/components.py b/cpp/install/common/components.py
new file mode 100755
index 00000000000..13df10db731
--- /dev/null
+++ b/cpp/install/common/components.py
@@ -0,0 +1,320 @@
+#
+# Defines Ice components
+#
+
+import ConfigParser, sys, os, logging, fnmatch, os.path, shutil, re
+
+def listFileLists():
+ """Information routine for getting lists of file lists from a components file"""
+ cfg = ConfigParser.SafeConfigParser()
+ cfg.read("./components/components.ini")
+ for f in cfg.sections():
+ try:
+ if cfg.getint(f, "active") == 1:
+ for item, value in cfg.items(f):
+ if item.startswith("filelist"):
+ print value
+ except ConfigParser.NoOptionError:
+ continue
+
+class StageFileError:
+ """Thrown when there is a problem with the stage configuration file."""
+ def __init__(self, msg = None):
+ self.msg = msg
+
+ def __str__(self):
+ return repr(self.msg)
+
+class ComponentDefError:
+ """Indicates a component definition file has an error that provides
+ proper interpretation"""
+
+ def __init__(self, msg = None):
+ self.msg = msg
+
+ def __str__(self):
+ return repr(self.msg)
+
+class FileSpecError(ComponentDefError):
+ """Indicates a filespec component definition file has a syntactical
+ error"""
+ def __init__(self, msg = None):
+ ComponentDefError.__init__(self, msg)
+
+def recursiveListing(path):
+ """Provides a recursive directory listing based in path"""
+ result = []
+ files = os.listdir(path)
+ for x in files:
+ fullpath = os.path.join(path, x);
+ if os.path.isdir(fullpath) and not os.path.islink(fullpath):
+ result.extend(recursiveListing(fullpath))
+ else:
+ result.append(fullpath)
+ return result
+
+class FileSpecWorker:
+ def __init__(self, source, dest):
+ self.source = source
+ self.dest = dest
+ self.include = []
+ self.exclude = []
+ self.explicit = []
+
+ def add(self, filename):
+ parts = filename.split("=")
+ if len(parts) < 2:
+ #
+ # This line doesn"t have a separator and so assume its an
+ # explicit listing
+ #
+ self.explicit.append(filename)
+ return
+
+ if parts[0].startswith("include"):
+ self.include.append(parts[1].strip())
+ elif parts[0].startswith("exclude"):
+ self.exclude.append(parts[1].strip())
+ elif parts[0].startswith("expect"):
+ pass
+ else:
+ raise FileSpecError("Line \'%s\' does not match filespec schema." % filename)
+
+ def execute(self, fake = False):
+ """Copy all of the specified files."""
+ recursiveIncludes = []
+ recursiveExcludes = []
+
+ midmatchIncludes = []
+ midmatchExcludes = []
+
+ localIncludes = []
+ localExcludes = []
+
+ for f in self.include:
+ if f.startswith("**/"):
+ if f.endswith("/**"):
+ midmatchIncludes.append(".*%s.*" %f[3:len(f) -3].replace('/', '.'))
+ else:
+ recursiveIncludes.append(f[3:])
+ else:
+ if f.endswith("/**"):
+ midmatchIncludes.append("%s.*" %f[0:len(f) -3].replace('/', '.'))
+ else:
+ localIncludes.append(f)
+
+ for f in self.exclude:
+ if f.startswith("**/"):
+ if f.endswith("/**"):
+ midmatchExcludes.append(".*%s.*" % f[3:len(f) -3].replace('/', '.'))
+ else:
+ recursiveExcludes.append(f[3:])
+ else:
+ if f.endswith("/**"):
+ midmatchExcludes.append("%s.*" %f[0:len(f) -3].replace('/', '.'))
+ else:
+ localExcludes.append(f)
+
+ logging.debug('localIncludes: ' + str(localIncludes))
+ logging.debug('localExcludes: ' + str(localExcludes))
+ logging.debug('recursiveIncludes: ' + str(recursiveIncludes))
+ logging.debug('recursiveExcludes: ' + str(recursiveExcludes))
+ logging.debug('midmatchIncludes: ' + str(midmatchIncludes))
+ logging.debug('midmatchExcludes: ' + str(midmatchExcludes))
+
+ fullListing = []
+ result = []
+ files = os.listdir(self.source)
+
+ for f in files:
+ fullpath = os.path.join(self.source, f);
+ if os.path.isdir(fullpath) and not os.path.islink(fullpath):
+ fullListing.extend(recursiveListing(fullpath))
+ continue
+
+ for p in localIncludes + recursiveIncludes:
+ if fnmatch.fnmatch(f, p):
+ found = False
+ for x in localExcludes + recursiveExcludes:
+ if fnmatch.fnmatch(f, x):
+ found = True
+ break
+ if not found: result.append(f)
+
+ inmatches = []
+ for p in recursiveIncludes:
+ inmatches.extend(fnmatch.filter(fullListing, p))
+
+ inSet = set(inmatches)
+
+ for p in midmatchIncludes:
+ r = re.compile(p)
+ inmatches = []
+ for f in fullListing(f):
+ rel = f[len(self.source):].strip('\\/')
+ if not r.match(rel) == None:
+ inmatches.append(f)
+ inSet = inSet.union(set(inmatches))
+
+ outmatches = []
+ for x in recursiveExcludes:
+ outmatches.extend(fnmatch.filter(fullListing, x))
+
+ outSet = set(outmatches)
+
+ for x in midmatchExcludes:
+ r = re.compile(x)
+ outmatches = []
+ for f in fullListing:
+ rel = f[len(self.source):].strip('\\/')
+ if not r.match(rel) == None:
+ outmatches.append(f)
+ outSet = outSet.union(set(outmatches))
+
+
+ #
+ # Using sets is the "easiest" way to do this. If Python"s set
+ # implementation is/gets buggy then this needs to be written
+ # "longhand".
+ #
+ diff = inSet - outSet
+ result.extend(list(diff))
+
+ for i in range(0, len(result)):
+ if result[i].startswith(self.source):
+ result[i] = result[i][len(self.source):].strip('\\/')
+
+ result.sort()
+ result.extend(self.explicit)
+
+ if fake:
+ for f in result:
+ print "Copying %s from %s to %s" % (f, self.source, self.dest)
+ return
+
+ if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
+ logging.debug("Files to be copied:")
+ for f in result:
+ logging.debug(f)
+
+ for f in result:
+ #
+ # an f, prefix means flatten.
+ #
+ flatten = False
+ current = f
+ if f.startswith('f,'):
+ flatten = True
+ current = current[2:]
+
+ targetDirectory = self.dest
+ targetFile = os.path.basename(current)
+ if not flatten:
+ targetDirectory = os.path.join(self.dest, os.path.dirname(current))
+
+ if not os.path.exists(targetDirectory):
+ os.makedirs(targetDirectory)
+
+ s = os.path.join(self.source, current)
+ d = os.path.join(targetDirectory, targetFile)
+ try:
+ shutil.copy2(s, d)
+ except IOError, e:
+ logging.info('Copying %s to %s failed: %s' % (s, d, str(e)))
+ raise
+
+def stage(filename, componentdir, stageDirectory, group, defaults):
+ cfg = ConfigParser.SafeConfigParser()
+ cfg.read(filename)
+ if not cfg.has_section(group):
+ raise StageFileError("Section %s is missing from component list file." % group)
+
+ sections = []
+ for entry in cfg.options(group):
+ section = cfg.get(group, entry)
+ if not cfg.has_section(section):
+ raise StageFileError("Section %s is missing from component list file." % section)
+ sections.append((entry, section))
+
+ for stageLoc, section in sections:
+ try:
+ currentBase = stageDirectory
+ for f in stageLoc.split('-'):
+ currentBase = os.path.join(currentBase, f)
+
+ if not os.path.exists(currentBase):
+ os.makedirs(currentBase)
+
+ elementCount = cfg.getint(section, "elements")
+ if elementCount < 0:
+ raise StageFileError("Section %s elements field is negative value" % section)
+
+ for i in range(1, elementCount + 1):
+ try:
+ if cfg.has_option(section, "targets"):
+ target = cfg.get(section, "targets", False, defaults).strip()
+
+ if "~" + defaults["target"] in target:
+ continue
+ elif not defaults["target"] in target:
+ continue
+
+ source = cfg.get(section, "source%d" % i, False, defaults)
+ filelist = cfg.get(section, "filelist%d" % i, False, defaults)
+ dest = cfg.get(section, "dest%d" % i, False, defaults)
+ #
+ # Most configurations won"t have file templates. These are usually only used so that file lists can
+ # be reused but need to be slightly modified for each use case.
+ #
+ template = None
+ mapping = None
+ if cfg.has_option(section, "filetemplate%d" % i):
+ #
+ # We need to get the raw value!
+ #
+ template = cfg.get(section, "filetemplate%d" %i, True)
+ mapping = defaults
+
+ filename = os.path.join(componentdir, filelist)
+ if not (os.path.exists(filename) and os.path.isfile(filename)):
+ raise StageFileError("Component file %s does not exist or is not a file" % filename)
+
+ componentFile = file(filename, "r")
+ try:
+ worker = FileSpecWorker(source, os.path.join(currentBase, dest))
+ for line in componentFile:
+ current = line.strip()
+ if line.startswith('#'):
+ continue
+
+ if len(current) == 0:
+ continue
+ if not template == None:
+ mapping['name'] = current
+ computedName = template % mapping
+ logging.log(logging.DEBUG, 'Adding templatized name %s' % computedName)
+ worker.add(computedName)
+ else:
+ worker.add(current % defaults)
+
+ if worker == None:
+ msg = "Component file %s is empty." % filename
+ logging.warning(msg)
+ else:
+ #
+ # XXX- fake is set to true while we are
+ # debugging.
+ #
+ worker.execute(False)
+
+ finally:
+ componentFile.close()
+
+ except ConfigParser.NoOptionError:
+ raise StageFileError("Section %s has invalid value for element %d" % (section, i))
+
+ except ConfigParser.NoOptionError:
+ raise StageFileError("Section %s has invalid or missing elements field" % section)
+
+if __name__ == "__main__":
+ print 'components'