import logging
import traceback
-import os.path
+import itertools
+import random
from wizard import command, deploy, shell, util
def main(argv, baton):
options, show = parse_args(argv, baton)
sh = shell.Shell()
- for d in deploy.parse_install_lines(show, options.versions_path):
- try:
- d.verify()
- d.verifyTag(options.srv_path)
- d.verifyGit(options.srv_path)
- d.verifyConfigured()
- print d.location
- with util.ChangeDirectory(d.location):
- print sh.safeCall('git', 'diff', '--stat', d.app_version.scripts_tag, 'HEAD', strip=True)
- except deploy.Error as e:
- continue
+ deploys = deploy.parse_install_lines(show, options.versions_path)
+ stats = {}
+ iffy = 0
+ clean = 0
+ total = 0
+ deploys = itertools.islice(deploys, options.limit)
+ if options.sample:
+ deploys = random.sample(list(deploys), options.sample)
+ try:
+ for d in deploys:
+ logging.info("Processing " + d.location)
+ try:
+ d.verify()
+ d.verifyTag(options.srv_path)
+ d.verifyGit(options.srv_path)
+ d.verifyConfigured()
+ with util.ChangeDirectory(d.location):
+ results = []
+ out = sh.safeCall('git', 'diff', '--numstat', d.app_version.scripts_tag, strip=True)
+ total += 1
+ for line in out.split("\n"):
+ added, deleted, filename = line.split(None, 3)
+ if filename.endswith("php.ini"): continue
+ if added == '-': continue
+ if deleted == '-': continue
+ added = int(added)
+ deleted = int(deleted)
+ # hook
+ if filename == "LocalSettings.php":
+ if added == deleted == 10:
+ continue
+ elif added == deleted == 9:
+ continue
+ elif filename == "AdminSettings.php":
+ if added == 0 and deleted == 20:
+ continue
+ elif filename == "config/index.php" or filename == "config/index.php5":
+ if added == 0:
+ continue
+ if not added and not deleted:
+ continue
+ results.append((added,deleted,filename))
+ if len(results) > options.filter:
+ print "- - " + d.location
+ iffy += 1
+ continue
+ if not results:
+ clean += 1
+ for added,deleted,filename in results:
+ stats.setdefault(filename, 0)
+ stats[filename] += 1
+ # hook
+ if filename == "LocalSettings.php" and not options.verbose:
+ continue
+ print "%-7d %-7d %s/%s" % (added,deleted,d.location,filename)
+ except (deploy.NotConfiguredError, deploy.NotMigratedError):
+ # XXX: These should error, but for now don't
+ pass
+ except (deploy.Error, shell.CallError):
+ # XXX: Maybe should also do app.Error
+ logging.error("%s in %s" % (traceback.format_exc(), d.location))
+ except KeyboardInterrupt:
+ raise
+ except:
+ logging.critical("%s in %s" % (traceback.format_exc(), d.location))
+ except KeyboardInterrupt:
+ print
+ print "Caught signal..."
+ pass
+ print '-' * 50
+ for filename in sorted(stats.keys()):
+ count = stats[filename]
+ if not count: continue
+ print "%-7d %s" % (count, filename)
+ print '-' * 50
+ print "%d out of %d (%.1f%%) had large diffstats" % (iffy, total, float(iffy)/total*100)
+ print "%d out of %d (%.1f%%) had clean diffstats" % (clean, total, float(clean)/total*100)
def parse_args(argv, baton):
usage = """usage: %prog research APP
Tells you how spectacularly an upgrade here will explode."""
parser = command.WizardOptionParser(usage)
+ parser.add_option("--limit", dest="limit", type="int",
+ default=None, help="Limit the number of autoinstalls to look at.")
+ parser.add_option("--sample", dest="sample", type="int", metavar="N",
+ default=None, help="Instead of researching all installs, research a random sample of N size.")
+ parser.add_option("--filter", dest="filter", type="int", metavar="N",
+ default=4, help="How many files are permitted in a diffstat before treating the install as having a 'large diffstat'")
baton.push(parser, "srv_path")
baton.push(parser, "versions_path")
options, args = parser.parse_all(argv)