]> scripts.mit.edu Git - wizard.git/commitdiff
Make wizard remaster safer, suggest it in wizard upgrade.
authorEdward Z. Yang <ezyang@mit.edu>
Sun, 17 Jul 2011 05:18:57 +0000 (01:18 -0400)
committerEdward Z. Yang <ezyang@mit.edu>
Sun, 17 Jul 2011 05:18:57 +0000 (01:18 -0400)
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
wizard/command/remaster.py
wizard/deploy.py

index e60150000fb15a75b3b0e6cff04e383adc63a245..b07401486bda7e16d8ca697d9e5f19143d85596c 100644 (file)
@@ -3,16 +3,24 @@ import tempfile
 import os
 import sys
 
-from wizard import command, shell
+import wizard
+from wizard import deploy, command, shell
 
 def main(argv, baton):
     options, args = parse_args(argv, baton)
+    # Make sure this is a Wizard repo
+    if not options.generic:
+        d = deploy.ProductionCopy('.')
+        try:
+            d.verify()
+        except deploy.AlreadyVersionedError:
+            raise NotWizardError
     # Determine upstream commit history
     # XXX This is a little sloppy (since it also pulls in remotes and
     # originals), but if the upstream repo has a clean set of remotes,
     # that shouldn't be a problem.
     excludes = map(lambda line: line.partition("\t")[0],
-                   shell.eval("git", "ls-remote", "origin").splitlines())
+                   shell.eval("git", "ls-remote", options.remote).splitlines())
     # Determine local commits and their parents
     local_commits = set()
     all_parents = set()
@@ -34,6 +42,13 @@ def main(argv, baton):
         if len(candidates) != 1:
             raise "Failed looking for " + hash
         mapping[hash] = candidates[0]
+    # Delete no-ops
+    for search, replace in mapping.items():
+        if search == replace:
+            del mapping[search]
+    # Bail out if nothing to do
+    if not mapping:
+        raise NothingToDo
 
     # XXX Make this more robust: given our pre-processing, there is a
     # very specific set of parent IDs we expect to see (not necessarily
@@ -52,8 +67,11 @@ def main(argv, baton):
         shell.call("chmod", "a+x", t.name) # necessary?
         logging.info("Sed script %s", t.name)
         # Do the rewrite
+        maybe_force = []
+        if options.force: maybe_force = ['--force']
+        extra_args = maybe_force + excludes
         shell.call("git", "filter-branch", "--parent-filter", t.name, "--",
-                   "--branches", "--not", *excludes,
+                   "--branches", "--not", *extra_args,
                    stdout=sys.stdout, stderr=sys.stderr)
     finally:
         # Cleanup
@@ -103,8 +121,34 @@ if this heuristic fails (not implemented yet).
 """
     parser = command.WizardOptionParser(usage)
     parser.add_option("-f", "--force", dest="force", action="store_true",
-            default=False, help="Force overwriting.")
+            default=False, help="Force overwriting (passed to filter-branch).")
+    parser.add_option("--generic", dest="generic", action="store_true",
+            default=False, help="Allow remastering of non-Wizard repositories.")
+    parser.add_option("--remote", dest="remote", metavar="REMOTE",
+            default="origin", help="Rebased remote to remaster off of.")
     options, args = parser.parse_all(argv)
     if len(args) > 0:
         parser.error("too many arguments")
     return options, args
+
+## -- Exceptions --
+
+class Error(wizard.Error):
+    """Base error class for this module"""
+    pass
+
+class NotWizardError(Error):
+    """The deployment was not a Wizard installation."""
+    def __str__(self):
+        return """
+
+ERROR: This is not a Wizard Git repository!  If you really want to
+use 'wizard remaster' on a non-Wizard repository, pass in
+'--generic'."""
+
+class NothingToDo(Error):
+    """No rewriting necessary."""
+    def __str__(self):
+        return """
+
+ERROR: Nothing to do!"""
index 12a27818cff1b4b4e235cd7830863b9ab048ae10..ac7dae8e31e395642fcec9281b677aa982fbc5a4 100644 (file)
@@ -247,6 +247,7 @@ class Deployment(object):
             parent = repo_rev_parse(self.app_version.wizard_tag)
             merge_base = shell.safeCall("git", "merge-base", parent, "HEAD", strip=True)
             if merge_base != parent:
+                # XXX Try remastering
                 raise HeadNotDescendantError(self.app_version.wizard_tag)
 
     def verifyConfigured(self):
@@ -678,7 +679,8 @@ class HeadNotDescendantError(Error):
 
 ERROR: HEAD is not a descendant of %s.  This probably
 means that an upstream rebase occurred, and new tags were
-pulled, but local user commits were never rebased.""" % self.tag
+pulled, but local user commits were never rebased.  Try
+running 'wizard remaster'.""" % self.tag
 
 class VersionDetectionError(Error):
     """Could not detect real version of application."""