]> scripts.mit.edu Git - wizard.git/blobdiff - wizard/command/upgrade.py
Major updates to resolution code from runs.
[wizard.git] / wizard / command / upgrade.py
index 18e7f9efe837d3d7990015fc7c2e8714bd858cc9..f56d00b821e73f90359b4c9443b3c408d93a1f6a 100644 (file)
@@ -8,7 +8,9 @@ import errno
 import tempfile
 import itertools
 
-from wizard import app, command, deploy, shell, util
+from wizard import app, command, deploy, scripts, shell, util
+
+kib_buffer = 1024 * 30 # 30 MiB we will always leave available
 
 def main(argv, baton):
     options, args = parse_args(argv, baton)
@@ -58,6 +60,9 @@ def main(argv, baton):
             sys.stderr.write("Traceback:\n  (n/a)\nAlreadyUpgraded\n")
             sys.exit(1)
         logging.info("Upgrading %s" % os.getcwd())
+        kib_usage, kib_limit = scripts.get_quota_usage_and_limit()
+        if kib_limit is not None and (kib_limit - kib_usage) < kib_buffer: # 10 mebibytes
+            raise QuotaTooLow
         if not options.dry_run:
             perform_pre_commit(sh)
         # If /dev/shm exists, it's a tmpfs and we can use it
@@ -79,8 +84,10 @@ def main(argv, baton):
             open(".git/WIZARD_REPO", "w").write(repo)
             open(".git/WIZARD_UPGRADE_VERSION", "w").write(version)
             open(".git/WIZARD_PARENTS", "w").write("%s\n%s" % (user_commit, next_commit))
-            if options.log_file: open(".git/WIZARD_LOG_FILE", "w").write(options.log_file)
-            perform_merge(sh, repo, d, version, use_shm)
+            open(".git/WIZARD_SIZE", "w").write(str(scripts.get_disk_usage()))
+            if options.log_file:
+                open(".git/WIZARD_LOG_FILE", "w").write(options.log_file)
+            perform_merge(sh, repo, d, version, use_shm, kib_limit and kib_limit - kib_usage or None)
     # variables: version, user_commit, next_commit, temp_wc_dir
     with util.ChangeDirectory(temp_wc_dir):
         try:
@@ -106,8 +113,15 @@ def main(argv, baton):
     if options.dry_run:
         logging.info("Dry run, bailing.  See results at %s" % temp_wc_dir)
         return
-    # perform database backup
+    # Ok, now we have to do a crazy complicated dance to see if we're
+    # going to have enough quota to finish what we need
+    pre_size = int(open(os.path.join(temp_wc_dir, ".git/WIZARD_SIZE"), "r").read())
+    post_size = scripts.get_disk_usage(temp_wc_dir)
+    kib_usage, kib_limit = scripts.get_quota_usage_and_limit()
     backup = d.backup(options)
+    if kib_limit is not None and (kib_limit - kib_usage) - (post_size - pre_size) / 1024 < kib_buffer:
+        shutil.rmtree(os.path.join(".scripts/backups", sh.eval("wizard", "restore").splitlines()[0]))
+        raise QuotaTooLow
     # XXX: frob .htaccess to make site inaccessible
     with util.IgnoreKeyboardInterrupts():
         with util.LockDirectory(".scripts-upgrade-lock"):
@@ -131,9 +145,8 @@ def main(argv, baton):
                 raise
             except deploy.WebVerificationError as e:
                 logging.warning("Web verification failed: rolling back")
-                logging.info("Web page that was output was:\n\n%s" % e.contents)
                 perform_restore(d, backup)
-                raise app.UpgradeVerificationFailure("Upgrade caused website to become inaccessible; site was rolled back")
+                raise app.UpgradeVerificationFailure(e.contents)
     # XXX: frob .htaccess to make site accessible
     #       to do this, check if .htaccess changed, first.  Upgrade
     #       process might have frobbed it.  Don't be
@@ -181,6 +194,7 @@ def perform_tmp_clone(sh, use_shm):
         dir = "/dev/shm/wizard"
         if not os.path.exists(dir):
             os.mkdir(dir)
+            os.chmod(dir, 0o777)
     else:
         dir = None
     temp_dir = tempfile.mkdtemp(prefix="wizard", dir=dir)
@@ -189,7 +203,8 @@ def perform_tmp_clone(sh, use_shm):
     sh.call("git", "clone", "-q", "--shared", ".", temp_wc_dir)
     return temp_dir, temp_wc_dir
 
-def perform_merge(sh, repo, d, version, use_shm):
+def perform_merge(sh, repo, d, version, use_shm, kib_avail):
+    # Note: avail_quota == None means unlimited
     # naive merge algorithm:
     # sh.call("git", "merge", "-m", message, "scripts/master")
     # crazy merge algorithm:
@@ -214,10 +229,12 @@ def perform_merge(sh, repo, d, version, use_shm):
     user_virtual_commit = sh.eval("git", "commit-tree", user_tree,
             "-p", base_virtual_commit, input="", log=True)
     sh.call("git", "checkout", user_virtual_commit, "--")
+    d.application.prepareMerge(os.getcwd())
+    sh.call("git", "commit", "--amend", "-a", "-m", "amendment")
     try:
         sh.call("git", "merge", next_virtual_commit)
     except shell.CallError as e:
-        conflicts = e.stderr.count("CONFLICT") # not perfect, if there is a file named CONFLICT
+        conflicts = e.stdout.count("CONFLICT") # not perfect, if there is a file named CONFLICT
         logging.info("Merge failed with these messages:\n\n" + e.stderr)
         # Run the application's specific merge resolution algorithms
         # and see if we can salvage it
@@ -239,6 +256,7 @@ def perform_merge(sh, repo, d, version, use_shm):
             shutil.move(curdir, newdir)
             shutil.rmtree(os.path.dirname(curdir))
             curdir = os.path.join(newdir, "repo")
+            os.chdir(curdir)
         print "%d %s" % (conflicts, curdir)
         raise MergeFailed
 
@@ -268,6 +286,14 @@ class Error(command.Error):
     """Base exception for all exceptions raised by upgrade"""
     pass
 
+class QuotaTooLow(Error):
+    def __str__(self):
+        return """
+
+ERROR: The locker quota was too low to complete the autoinstall
+upgrade.
+"""
+
 class AlreadyUpgraded(Error):
     def __str__(self):
         return """