+ self.application.backup(self, tmpdir, options)
+ except app.BackupFailure:
+ # the backup is bogus, don't let it show up
+ shutil.rmtree(tmpdir)
+ raise
+ backup = None
+ with util.LockDirectory(os.path.join(backupdir, "lock")):
+ while 1:
+ backup = str(self.version) + "-" + datetime.datetime.today().strftime("%Y-%m-%dT%H%M%S")
+ outdir = os.path.join(backupdir, backup)
+ if os.path.exists(outdir):
+ logging.warning("Backup: A backup occurred in the last second. Trying again in a second...")
+ time.sleep(1)
+ continue
+ try:
+ shutil.move(tmpdir, outdir)
+ except:
+ # don't leave half-baked stuff lying around
+ try:
+ shutil.rmtree(outdir)
+ except OSError:
+ pass
+ raise
+ break
+ return backup
+ @chdir_to_location
+ def restore(self, backup, options):
+ """
+ Restores a backup. Destroys state, so be careful! Also, this does
+ NOT restore the file-level backup, which is what 'wizard restore'
+ does, so you probably do NOT want to call this elsewhere unless
+ you know what you're doing (call 'wizard restore' instead).
+ """
+ backup_dir = os.path.join(".scripts", "backups", backup)
+ return self.application.restore(self, backup_dir, options)
+ @chdir_to_location
+ def remove(self, options):
+ """
+ Deletes all non-local or non-filesystem data (such as databases) that
+ this application uses.
+ """
+ self.application.remove(self, options)
+ def verifyDatabase(self):
+ """
+ Checks if the autoinstall has a properly configured database.
+ """
+ if not self.application.checkDatabase(self):
+ raise DatabaseVerificationError
+ def verifyWeb(self):
+ """
+ Checks if the autoinstall is viewable from the web.
+ """
+ if not self.application.checkWeb(self):
+ raise WebVerificationError
+ def fetch(self, path, post=None):
+ """
+ Performs a HTTP request on the website.
+ """
+ return util.fetch(self.url.netloc, self.url.path, path, post) # pylint: disable-msg=E1103
+
+class WorkingCopy(Deployment):
+ """
+ Represents a temporary clone of a deployment that we can make
+ modifications to without fear of interfering with a production
+ deployment. More operations are permitted on these copies.
+ """
+ def setAppVersion(self, app_version):
+ """
+ Manually resets the application version; useful if the working
+ copy is off in space (i.e. not anchored to something we can
+ git describe off of.)
+ """
+ self._app_version = app_version
+ @chdir_to_location
+ def parametrize(self, deployment):
+ """
+ Edits files in ``dir`` to replace WIZARD_* variables with literal
+ instances based on ``deployment``. This is used for constructing
+ virtual merge bases, and as such ``deployment`` will generally not
+ equal ``self``.
+ """
+ return self.application.parametrize(self, deployment)
+ @chdir_to_location
+ def prepareConfig(self):
+ """
+ Edits files in the deployment such that any user-specific configuration
+ is replaced with generic WIZARD_* variables.
+ """
+ return self.application.prepareConfig(self)
+ @chdir_to_location
+ def resolveConflicts(self):
+ """
+ Resolves conflicted files in this working copy. Returns whether or
+ not all conflicted files were resolved or not. Fully resolved
+ files are added to the index, but no commit is made.
+ """
+ return self.application.resolveConflicts(self)
+ @chdir_to_location
+ def prepareMerge(self):
+ """
+ Performs various edits to files in the current working directory in
+ order to make a merge go more smoothly. This is usually
+ used to fix botched line-endings.
+ """
+ return self.application.prepareMerge(self)