import os
import optparse
-import fileinput
-import math
import sys
-from distutils.version import LooseVersion as Version
-class NoSuchApplication(Exception):
- pass
-
-class DeploymentParseError(Exception):
- pass
-
-class Deployment(object):
- def __init__(self, location, version):
- self.location = location
- self.version = version
- self.application = version.application
- @staticmethod
- def parse(line):
- """Parses a line from the results of parallel-find.pl.
- This will work out of the box with fileinput"""
- try:
- location, deploydir = line.rstrip().split(":")
- except ValueError:
- raise DeploymentParseError
- name = deploydir.split("/")[-1]
- if name.find("-") != -1:
- app, version = name.split("-")
- elif name == "deploy":
- # Assume that it's django, since those were botched
- app = "django"
- version = "0.1-scripts"
- else:
- raise DeploymentParseError
- try:
- return Deployment(location, applications[app].getVersion(version))
- except KeyError:
- raise NoSuchApplication
- def count(self):
- """Simple method which registers the deployment as a +1 on the
- appropriate version. No further inspection is done."""
- self.version.count(self)
- return True
- def count_exists(self, file):
- """Checks if the codebase has a certain file/directory in it."""
- if os.path.exists(self.location + "/" + file):
- self.version.count_exists(self, file)
- return True
- return False
-
-class Application(object):
- HISTOGRAM_WIDTH = 30
- def __init__(self, name):
- self.name = name
- self.versions = {}
- # Some cache variables for fast access of calculated data
- self._total = 0
- self._max = 0
- self._c_exists = {}
- def getVersion(self, version):
- if version not in self.versions:
- self.versions[version] = ApplicationVersion(Version(version), self)
- return self.versions[version]
- def _graph(self, v):
- return '+' * int(math.ceil(float(v)/self._max * self.HISTOGRAM_WIDTH))
- def __str__(self):
- if not self.versions: return "%-11s no installs" % self.name
- ret = \
- ["%-16s %3d installs" % (self.name, self._total)] + \
- [str(v) for v in sorted(self.versions.values())]
- for f,c in self._c_exists.items():
- ret.append("%d users have %s" % (c,f))
- return "\n".join(ret)
-
-class ApplicationVersion(object):
- def __init__(self, version, application):
- self.version = version
- self.application = application
- self.c = 0
- self.c_exists = {}
- def __cmp__(x, y):
- return cmp(x.version, y.version)
- def count(self, deployment):
- self.c += 1
- self.application._total += 1
- if self.c > self.application._max:
- self.application._max = self.c
- def count_exists(self, deployment, n):
- if n in self.c_exists: self.c_exists[n] += 1
- else: self.c_exists[n] = 1
- if n in self.application._c_exists: self.application._c_exists[n] += 1
- else: self.application._c_exists[n] = 1
- def __str__(self):
- return " %-12s %3d %s" \
- % (self.version, self.c, self.application._graph(self.c))
-
-class Printer(object):
- def __init__(self, quiet, verbose):
- self.i = 0
- self.quiet = quiet
- self.verbose = verbose
- self.hanging = False
- def tick(self):
- self.i += 1
- if not self.quiet and self.i % 10 == 0:
- sys.stdout.write(".")
- sys.stdout.flush()
- self.hanging = True
- def _hang(self):
- if self.hanging:
- self.hanging = False
- print
- def write(self, str = ""):
- self._hang()
- print str
- def qwrite(self, str = ""):
- if not self.quiet:
- self._hang
- print str
- def tweet(self, str = ""):
- if not self.quiet:
- self._hang()
- print str, # note comma
- def chat(self, str = ""):
- if self.verbose:
- self._hang()
- print str
-
-application_list = [
- "mediawiki", "wordpress", "joomla", "e107", "gallery2",
- "phpBB", "advancedbook", "phpical", "trac", "turbogears", "django",
- # these are technically deprecated
- "advancedpoll", "gallery",
-]
-
-"""Hash table for looking up string application name to instance"""
-applications = dict([(n,Application(n)) for n in application_list ])
-
-def getInstallLines(global_options):
- vd = global_options.version_dir
- try:
- return fileinput.input([vd + "/" + f for f in os.listdir(vd)])
- except OSError:
- print "No permissions; check if AFS is mounted"
- raise SystemExit(-1)
+# Add lib to path
+sys.path.insert(0,os.path.abspath(os.path.join(__file__,'../../lib')))
+import wizard.command
def main():
usage = """usage: %prog [-d|--version-dir] COMMAND [ARGS]
options, args = parser.parse_args(sys.argv[1:i+1])
rest_argv = sys.argv[i+1:]
command = args[0] # shouldn't fail
- commands = {
- "stat": stat
- }
if command == "help":
try:
- commands[rest_argv[0]](['-h'], options)
+ getattr(wizard.command, rest_argv[0])(['-h'], options)
except KeyError:
parser.error("invalid action")
except IndexError:
parser.print_usage()
raise SystemExit(-1)
# Dispatch commands
- if command not in commands:
+ try:
+ getattr(wizard.command, command).main(rest_argv, options)
+ except AttributeError:
parser.error("invalid action")
- return commands[command](rest_argv, options)
-
-def stat(argv, global_options):
- usage = """usage: %prog stat [ARGS] APPS
-
-Scans all of the collected data from parallel-find.pl, and
-determines version histograms for our applications. You may
-optionally pass application parameters to filter the installs.
-
-Examples:
- %prog stat
- Basic usage
- %prog stat mediawiki
- Displays only MediaWiki statistics
- %prog stat -v -q mediawiki-1.2.3
- Displays all deployments of this version"""
- parser = optparse.OptionParser(usage)
- parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
- default=False, help="Print interesting directories")
- parser.add_option("-q", "--quiet", dest="quiet", action="store_true",
- default=False, help="Suppresses progress output")
- parser.add_option("--count-exists", dest="count_exists",
- default=False, help="Count deployments that contain a file")
- options, show = parser.parse_args(argv)
- fi = getInstallLines(global_options)
- if not show: show = applications.keys()
- show = frozenset(show)
- errors = 0
- unrecognized = 0
- processed = 0
- printer = Printer(options.quiet, options.verbose)
- printer.tweet("Processing")
- for line in fi:
- printer.tick()
- try:
- deploy = Deployment.parse(line)
- except DeploymentParseError:
- errors += 1
- continue
- except NoSuchApplication:
- unrecognized += 1
- continue
- if deploy.application.name + "-" + str(deploy.version.version) in show:
- printer.write("%s-%s deployment at %s" \
- % (deploy.application.name, deploy.version.version, deploy.location))
- elif deploy.application.name in show:
- pass
- else:
- continue
- deploy.count()
- if options.count_exists:
- r = deploy.count_exists(options.count_exists)
- if r:
- printer.chat("Found " + options.count_exists + " in " + deploy.location)
- printer.write()
- for app in applications.values():
- if app.name not in show: continue
- printer.write(app)
- printer.write()
- printer.write("With %d errors and %d unrecognized applications" % (errors, unrecognized))
if __name__ == "__main__":
main()
--- /dev/null
+import optparse
+import wizard.deploy as wd
+import sys
+
+class Printer(object):
+ def __init__(self, quiet, verbose):
+ self.i = 0
+ self.quiet = quiet
+ self.verbose = verbose
+ self.hanging = False
+ def tick(self):
+ self.i += 1
+ if not self.quiet and self.i % 10 == 0:
+ sys.stdout.write(".")
+ sys.stdout.flush()
+ self.hanging = True
+ def _hang(self):
+ if self.hanging:
+ self.hanging = False
+ print
+ def write(self, str = ""):
+ self._hang()
+ print str
+ def qwrite(self, str = ""):
+ if not self.quiet:
+ self._hang
+ print str
+ def tweet(self, str = ""):
+ if not self.quiet:
+ self._hang()
+ print str, # note comma
+ def chat(self, str = ""):
+ if self.verbose:
+ self._hang()
+ print str
+
+def main(argv, global_options):
+ usage = """usage: %prog stat [ARGS] APPS
+
+Scans all of the collected data from parallel-find.pl, and
+determines version histograms for our applications. You may
+optionally pass application parameters to filter the installs.
+
+Examples:
+ %prog stat
+ Basic usage
+ %prog stat mediawiki
+ Displays only MediaWiki statistics
+ %prog stat -v -q mediawiki-1.2.3
+ Displays all deployments of this version"""
+ parser = optparse.OptionParser(usage)
+ parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
+ default=False, help="Print interesting directories")
+ parser.add_option("-q", "--quiet", dest="quiet", action="store_true",
+ default=False, help="Suppresses progress output")
+ parser.add_option("--count-exists", dest="count_exists",
+ default=False, help="Count deployments that contain a file")
+ options, show = parser.parse_args(argv)
+ fi = wd.getInstallLines(global_options)
+ if not show: show = wd.applications.keys()
+ show = frozenset(show)
+ errors = 0
+ unrecognized = 0
+ processed = 0
+ printer = Printer(options.quiet, options.verbose)
+ printer.tweet("Processing")
+ for line in fi:
+ printer.tick()
+ try:
+ deploy = wd.Deployment.parse(line)
+ except wd.DeploymentParseError:
+ errors += 1
+ continue
+ except wd.NoSuchApplication:
+ unrecognized += 1
+ continue
+ if deploy.application.name + "-" + str(deploy.version.version) in show:
+ printer.write("%s-%s deployment at %s" \
+ % (deploy.application.name, deploy.version.version, deploy.location))
+ elif deploy.application.name in show:
+ pass
+ else:
+ continue
+ deploy.count()
+ if options.count_exists:
+ r = deploy.count_exists(options.count_exists)
+ if r:
+ printer.chat("Found " + options.count_exists + " in " + deploy.location)
+ printer.write()
+ for app in wd.applications.values():
+ if app.name not in show: continue
+ printer.write(app)
+ printer.write()
+ printer.write("With %d errors and %d unrecognized applications" % (errors, unrecognized))
+
--- /dev/null
+import os.path
+import math
+import fileinput
+from distutils.version import LooseVersion as Version
+
+def getInstallLines(global_options):
+ vd = global_options.version_dir
+ try:
+ return fileinput.input([vd + "/" + f for f in os.listdir(vd)])
+ except OSError:
+ print "No permissions; check if AFS is mounted"
+ raise SystemExit(-1)
+
+class NoSuchApplication(Exception):
+ pass
+
+class DeploymentParseError(Exception):
+ pass
+
+class Deployment(object):
+ def __init__(self, location, version):
+ self.location = location
+ self.version = version
+ self.application = version.application
+ @staticmethod
+ def parse(line):
+ """Parses a line from the results of parallel-find.pl.
+ This will work out of the box with fileinput"""
+ try:
+ location, deploydir = line.rstrip().split(":")
+ except ValueError:
+ raise DeploymentParseError
+ name = deploydir.split("/")[-1]
+ if name.find("-") != -1:
+ app, version = name.split("-")
+ elif name == "deploy":
+ # Assume that it's django, since those were botched
+ app = "django"
+ version = "0.1-scripts"
+ else:
+ raise DeploymentParseError
+ try:
+ return Deployment(location, applications[app].getVersion(version))
+ except KeyError:
+ raise NoSuchApplication
+ def count(self):
+ """Simple method which registers the deployment as a +1 on the
+ appropriate version. No further inspection is done."""
+ self.version.count(self)
+ return True
+ def count_exists(self, file):
+ """Checks if the codebase has a certain file/directory in it."""
+ if os.path.exists(self.location + "/" + file):
+ self.version.count_exists(self, file)
+ return True
+ return False
+
+class Application(object):
+ HISTOGRAM_WIDTH = 30
+ def __init__(self, name):
+ self.name = name
+ self.versions = {}
+ # Some cache variables for fast access of calculated data
+ self._total = 0
+ self._max = 0
+ self._c_exists = {}
+ def getVersion(self, version):
+ if version not in self.versions:
+ self.versions[version] = ApplicationVersion(Version(version), self)
+ return self.versions[version]
+ def _graph(self, v):
+ return '+' * int(math.ceil(float(v)/self._max * self.HISTOGRAM_WIDTH))
+ def __str__(self):
+ if not self.versions: return "%-11s no installs" % self.name
+ ret = \
+ ["%-16s %3d installs" % (self.name, self._total)] + \
+ [str(v) for v in sorted(self.versions.values())]
+ for f,c in self._c_exists.items():
+ ret.append("%d users have %s" % (c,f))
+ return "\n".join(ret)
+
+class ApplicationVersion(object):
+ def __init__(self, version, application):
+ self.version = version
+ self.application = application
+ self.c = 0
+ self.c_exists = {}
+ def __cmp__(x, y):
+ return cmp(x.version, y.version)
+ def count(self, deployment):
+ self.c += 1
+ self.application._total += 1
+ if self.c > self.application._max:
+ self.application._max = self.c
+ def count_exists(self, deployment, n):
+ if n in self.c_exists: self.c_exists[n] += 1
+ else: self.c_exists[n] = 1
+ if n in self.application._c_exists: self.application._c_exists[n] += 1
+ else: self.application._c_exists[n] = 1
+ def __str__(self):
+ return " %-12s %3d %s" \
+ % (self.version, self.c, self.application._graph(self.c))
+
+application_list = [
+ "mediawiki", "wordpress", "joomla", "e107", "gallery2",
+ "phpBB", "advancedbook", "phpical", "trac", "turbogears", "django",
+ # these are technically deprecated
+ "advancedpoll", "gallery",
+]
+
+"""Hash table for looking up string application name to instance"""
+applications = dict([(n,Application(n)) for n in application_list ])
+