.. autoclass:: WorkingCopy
:members:
:show-inheritance:
-.. autoclass:: Application
- :members:
-.. autoclass:: ApplicationVersion
- :members:
Functions
---------
.. autofunction:: get_install_lines
.. autofunction:: parse_install_lines
-.. autofunction:: applications
.. autofunction:: chdir_to_location
Exceptions
----------
.. autoexception:: Error
-.. autoexception:: NoSuchApplication
- :members:
-.. autoexception:: DeploymentParseError
- :members:
-.. autoexception:: NoRepositoryError
- :members:
.. autoexception:: AlreadyVersionedError
:members:
.. autoexception:: NotMigratedError
--- /dev/null
+#!/bin/sh
+bold="`tput -T${TERM:-dumb} bold`"
+red="`tput -T${TERM:-dumb} setf 4`"
+sgr0="`tput -T${TERM:-dumb} sgr0`"
+for i in test-*.sh; do
+ ./$i "$1"
+ if [ $? -eq 0 ]
+ then
+ echo "${bold}OK${sgr0}"
+ else
+ echo "${bold}${red}FAIL${sgr0}"
+ fi
+ echo
+done
import os.path
import re
+import distutils.version
import wizard
+_application_list = [
+ "mediawiki", "wordpress", "joomla", "e107", "gallery2",
+ "phpBB", "advancedbook", "phpical", "trac", "turbogears", "django",
+ # these are technically deprecated
+ "advancedpoll", "gallery",
+]
+_applications = None
+
+def applications():
+ """Hash table for looking up string application name to instance"""
+ global _applications
+ if not _applications:
+ _applications = dict([(n,Application.make(n)) for n in _application_list ])
+ return _applications
+
+
+class Application(object):
+ """
+ Represents an application, i.e. mediawiki or phpbb.
+
+ .. note::
+ Many of these methods assume a specific working
+ directory; prefer using the corresponding methods
+ in :class:`deploy.Deployment` and its subclasses.
+ """
+ #: String name of the application
+ name = None
+ #: Dictionary of version strings to :class:`ApplicationVersion`.
+ #: See also :meth:`makeVersion`.
+ versions = None
+ #: List of files that need to be modified when parametrizing.
+ #: This is a class-wide constant, and should not normally be modified.
+ parametrized_files = []
+ #: Keys that are used in older versions of the application, but
+ #: not for the most recent version.
+ deprecated_keys = []
+ def __init__(self, name):
+ self.name = name
+ self.versions = {}
+ # cache variables
+ self._extractors = {}
+ self._substitutions = {}
+ def repository(self, srv_path):
+ """
+ Returns the Git repository that would contain this application.
+ ``srv_path`` corresponds to ``options.srv_path`` from the global baton.
+ """
+ repo = os.path.join(srv_path, self.name + ".git")
+ if not os.path.isdir(repo):
+ repo = os.path.join(srv_path, self.name, ".git")
+ if not os.path.isdir(repo):
+ raise NoRepositoryError(self.name)
+ return repo
+ def makeVersion(self, version):
+ """
+ Creates or retrieves the :class:`ApplicationVersion` singleton for the
+ specified version.
+ """
+ if version not in self.versions:
+ self.versions[version] = ApplicationVersion(distutils.version.LooseVersion(version), self)
+ return self.versions[version]
+ def extract(self, deployment):
+ """Extracts wizard variables from a deployment."""
+ result = {}
+ for k,extractor in self.extractors.items():
+ result[k] = extractor(deployment)
+ return result
+ def parametrize(self, deployment):
+ """
+ Takes a generic source checkout and parametrizes
+ it according to the values of deployment. This function
+ operates on the current working directory.
+ """
+ variables = deployment.extract()
+ for file in self.parametrized_files:
+ try:
+ contents = open(file, "r").read()
+ except IOError:
+ continue
+ for key, value in variables.items():
+ if value is None: continue
+ contents = contents.replace(key, value)
+ f = open(file, "w")
+ f.write(contents)
+ def resolveConflicts(self, deployment):
+ """
+ Resolves conflicted files in the current working
+ directory. Returns whether or not all conflicted
+ files were resolved or not. Fully resolved files are
+ added to the index, but no commit is made. By default
+ this is a no-op and returns ``False``.
+ """
+ return False
+ def prepareMerge(self, deployment):
+ """
+ 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. If you add new files,
+ you have to 'git add' them; this is not necessary for edits.
+ By default this is a no-op.
+ """
+ pass
+ def prepareConfig(self, deployment):
+ """
+ Takes a deployment and replaces any explicit instances
+ of a configuration variable with generic ``WIZARD_*`` constants.
+ The default implementation uses :attr:`substitutions`;
+ you can override this method to provide arbitrary extra
+ behavior.
+ """
+ for key, subst in self.substitutions.items():
+ subs = subst(deployment)
+ if not subs and key not in self.deprecated_keys:
+ logging.warning("No substitutions for %s" % key)
+ def install(self, version, options):
+ """
+ Run for 'wizard configure' (and, by proxy, 'wizard install')
+ to configure an application. This assumes that the current
+ working directory is a deployment. (This function does not take
+ a :class:`deploy.Deployment` as a parameter, as those operations are
+ not meaningful yet.)
+ """
+ raise NotImplemented
+ def upgrade(self, deployment, version, options):
+ """
+ Run for 'wizard upgrade' to upgrade database schemas and other
+ non-versioned data in an application. This assumes that
+ the current working directory is the deployment.
+ """
+ raise NotImplemented
+ def backup(self, deployment, options):
+ """
+ Run for 'wizard backup' and upgrades to backup database schemas
+ and other non-versioned data in an application. This assumes
+ that the current working directory is the deployment.
+ """
+ raise NotImplemented
+ def restore(self, deployment, backup, options):
+ """
+ Run for 'wizard restore' and failed upgrades to restore database
+ and other non-versioned data to a backed up version. This assumes
+ that the current working directory is the deployment.
+ """
+ raise NotImplemented
+ def detectVersion(self, deployment):
+ """
+ Checks source files to determine the version manually. This assumes
+ that the current working directory is the deployment.
+ """
+ return None
+ def checkWeb(self, deployment, output=None):
+ """
+ Checks if the autoinstall is viewable from the web. To get
+ the HTML source that was retrieved, pass a variable containing
+ an empty list to ``output``; it will be mutated to have its
+ first element be the output.
+ """
+ raise NotImplemented
+ def checkConfig(self, deployment):
+ """
+ Checks whether or not an autoinstall has been configured/installed
+ for use. Assumes that the current working directory is the deployment.
+ """
+ raise NotImplemented
+ @property
+ def extractors(self):
+ """
+ Dictionary of variable names to extractor functions. These functions
+ take a :class:`deploy.Deployment` as an argument and return the value of
+ the variable, or ``None`` if it could not be found.
+ See also :func:`wizard.app.filename_regex_extractor`.
+ """
+ return {}
+ @property
+ def substitutions(self):
+ """
+ Dictionary of variable names to substitution functions. These functions
+ take a :class:`deploy.Deployment` as an argument and modify the deployment such
+ that an explicit instance of the variable is released with the generic
+ WIZARD_* constant. See also :func:`wizard.app.filename_regex_substitution`.
+ """
+ return {}
+ @staticmethod
+ def make(name):
+ """Makes an application, but uses the correct subtype if available."""
+ try:
+ __import__("wizard.app." + name)
+ return getattr(wizard.app, name).Application(name)
+ except ImportError:
+ return Application(name)
+
+class ApplicationVersion(object):
+ """Represents an abstract notion of a version for an application, where
+ ``version`` is a :class:`distutils.version.LooseVersion` and
+ ``application`` is a :class:`Application`."""
+ #: The :class:`distutils.version.LooseVersion` of this instance.
+ version = None
+ #: The :class:`Application` of this instance.
+ application = None
+ def __init__(self, version, application):
+ self.version = version
+ self.application = application
+ @property
+ def tag(self):
+ """
+ Returns the name of the git describe tag for the commit the user is
+ presently on, something like mediawiki-1.2.3-scripts-4-g123abcd
+ """
+ return "%s-%s" % (self.application, self.version)
+ @property
+ def scripts_tag(self):
+ """
+ Returns the name of the Git tag for this version.
+ """
+ end = str(self.version).partition('-scripts')[2].partition('-')[0]
+ return "%s-scripts%s" % (self.pristine_tag, end)
+ @property
+ def pristine_tag(self):
+ """
+ Returns the name of the Git tag for the pristine version corresponding
+ to this version.
+ """
+ return "%s-%s" % (self.application.name, str(self.version).partition('-scripts')[0])
+ def __cmp__(self, y):
+ return cmp(self.version, y.version)
+ @staticmethod
+ def parse(value):
+ """
+ Parses a line from the :term:`versions store` and return
+ :class:`ApplicationVersion`.
+
+ Use this only for cases when speed is of primary importance;
+ the data in version is unreliable and when possible, you should
+ prefer directly instantiating a :class:`deploy.Deployment` and having it query
+ the autoinstall itself for information.
+
+ The `value` to parse will vary. For old style installs, it
+ will look like::
+
+ /afs/athena.mit.edu/contrib/scripts/deploy/APP-x.y.z
+
+ For new style installs, it will look like::
+
+ APP-x.y.z-scripts
+ """
+ name = value.split("/")[-1]
+ try:
+ if name.find("-") != -1:
+ app, _, version = name.partition("-")
+ else:
+ # kind of poor, maybe should error. Generally this
+ # will actually result in a not found error
+ app = name
+ version = "trunk"
+ except ValueError:
+ raise DeploymentParseError(value)
+ return ApplicationVersion.make(app, version)
+ @staticmethod
+ def make(app, version):
+ """
+ Makes/retrieves a singleton :class:`ApplicationVersion` from
+ a``app`` and ``version`` string.
+ """
+ try:
+ # defer to the application for version creation to enforce
+ # singletons
+ return applications()[app].makeVersion(version)
+ except KeyError:
+ raise NoSuchApplication(app)
+
def expand_re(val):
if isinstance(val, str):
return re.escape(val)
"""Generic error class for this module."""
pass
+class NoRepositoryError(Error):
+ """
+ :class:`Application` does not appear to have a Git repository
+ in the normal location.
+ """
+ #: The name of the application that does not have a Git repository.
+ app = None
+ def __init__(self, app):
+ self.app = app
+ def __str__(self):
+ return """Could not find Git repository for '%s'. If you would like to use a local version, try specifying --srv-path or WIZARD_SRV_PATH.""" % self.app
+
+class DeploymentParseError(Error):
+ """
+ Could not parse ``value`` from :term:`versions store`.
+ """
+ #: The value that failed to parse.
+ value = None
+ #: The location of the autoinstall that threw this variable.
+ #: This should be set by error handling code when it is available.
+ location = None
+ def __init__(self, value):
+ self.value = value
+
+class NoSuchApplication(Error):
+ """
+ You attempted to reference a :class:`Application` named
+ ``app``, which is not recognized by Wizard.
+ """
+ #: The name of the application that does not exist.
+ app = None
+ #: The location of the autoinstall that threw this variable.
+ #: This should be set by error handling code when it is availble.
+ location = None
+ def __init__(self, app):
+ self.app = app
+
class UpgradeFailure(Error):
"""Upgrade script failed."""
#: String details of failure (possibly stdout or stderr output)
]
}
-class Application(deploy.Application):
+class Application(app.Application):
parametrized_files = ['LocalSettings.php', 'php.ini']
deprecated_keys = set(['WIZARD_IP']) | php.deprecated_keys
@property
import sys
import distutils.version
-from wizard import command, deploy, git, shell, util
+from wizard import command, git, shell, util
def main(argv, baton):
options, args = parse_args(argv, baton)
import sys
import distutils.version
-from wizard import command, deploy, git, shell, util
+from wizard import app, command, git, shell, util
def main(argv, baton):
tag = git.describe()
application, _, version = tag.partition('-')
- app = deploy.applications()[application]
- handler = app.install_handler
+ application = app.applications()[application]
+ handler = application.install_handler
parser = command.WizardOptionParser(usage)
handler.push(parser)
options, args = parser.parse_all(argv)
handler.handle(options)
- app.install(distutils.version.LooseVersion(version), options)
+ application.install(distutils.version.LooseVersion(version), options)
sh = shell.Shell()
message = "Autoinstall configuration of %s locker.\n\n%s" % (util.get_dir_owner(), util.get_git_footer())
import logging
-from wizard import deploy, command
+from wizard import app, deploy, command
def main(argv, baton):
options, show = parse_args(argv, baton)
for e in deploy.parse_install_lines(show, options.versions_path, True):
- if not isinstance(e, deploy.Error):
+ if not isinstance(e, deploy.Error) and not isinstance(e, app.Error):
if isinstance(e, Exception):
raise e
continue
if options.verbose:
- if isinstance(e, deploy.NoSuchApplication):
+ if isinstance(e, app.NoSuchApplication):
print "Application %s does not exist, at %s" % (e.app, e.location)
elif isinstance(e, deploy.DeploymentParseError):
print "Parse error for line '%s', at %s" % (e.value, e.location)
import sys
import wizard
-from wizard import command, deploy, shell, util
+from wizard import app, command, shell, util
def main(argv, baton):
options, args = parse_args(argv, baton)
# XXX: do something smart if -scripts is not at the end
- app = args[0]
+ appstr = args[0]
dir = args[1]
if os.path.exists(dir):
raise DirectoryExistsError
- appname, _, version = app.partition('-')
- application = deploy.applications()[appname]
+ appname, _, version = appstr.partition('-')
+ application = app.applications()[appname]
sh = shell.Shell()
sh.call("git", "clone", "-q", "--shared", application.repository(options.srv_path), dir)
with util.ChangeDirectory(dir):
if version:
- sh.call("git", "reset", "-q", "--hard", app)
+ sh.call("git", "reset", "-q", "--hard", appstr)
# this command's stdin should be hooked up to ours
try:
configure_args = args[2:] + command.make_base_args(options)
# 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
"""
Object model for querying information and manipulating deployments
-of autoinstalls. Every :class:`Deployment` has an :class:`ApplicationVersion`
-which in turn has an :class:`Application`.
+of autoinstalls. Every :class:`Deployment` has an :class:`app.ApplicationVersion`
+which in turn has an :class:`app.Application`.
"""
import os.path
import fileinput
import dateutil.parser
-import distutils.version
import tempfile
import logging
import shutil
import decorator
-import functools
import wizard
-from wizard import git, old_log, scripts, shell, util
+from wizard import app, git, old_log, scripts, shell, util
## -- Global Functions --
log output.
"""
if not show:
- show = applications()
+ show = app.applications()
elif isinstance(show, str):
# otherwise, frozenset will treat string as an iterable
show = frozenset([show])
try:
d = Deployment.parse(line)
name = d.application.name
- except NoSuchApplication as e:
+ except app.NoSuchApplication as e:
if yield_errors:
yield e
continue
return os.path.join(self.scripts_dir, 'version')
@property
def application(self):
- """The :class:`Application` of this deployment."""
+ """The :class:`app.Application` of this deployment."""
return self.app_version.application
@property
def old_log(self):
return self.app_version.version
@property
def app_version(self):
- """The :class:`ApplicationVersion` of this deployment."""
+ """The :class:`app.ApplicationVersion` of this deployment."""
if not self._app_version:
if os.path.isdir(os.path.join(self.location, ".git")):
try:
with util.ChangeDirectory(self.location):
appname, _, version = git.describe().partition('-')
- self._app_version = ApplicationVersion.make(appname, version)
+ self._app_version = app.ApplicationVersion.make(appname, version)
except shell.CallError:
pass
if not self._app_version:
except ValueError:
return ProductionCopy(line) # lazy loaded version
try:
- return ProductionCopy(location, version=ApplicationVersion.parse(deploydir))
+ return ProductionCopy(location, version=app.ApplicationVersion.parse(deploydir))
except Error as e:
e.location = location
raise e
"""
return self.application.prepareMerge(self)
-class Application(object):
- """
- Represents an application, i.e. mediawiki or phpbb.
-
- .. note::
- Many of these methods assume a specific working
- directory; prefer using the corresponding methods
- in :class:`Deployment` and its subclasses.
- """
- #: String name of the application
- name = None
- #: Dictionary of version strings to :class:`ApplicationVersion`.
- #: See also :meth:`makeVersion`.
- versions = None
- #: List of files that need to be modified when parametrizing.
- #: This is a class-wide constant, and should not normally be modified.
- parametrized_files = []
- #: Keys that are used in older versions of the application, but
- #: not for the most recent version.
- deprecated_keys = []
- def __init__(self, name):
- self.name = name
- self.versions = {}
- # cache variables
- self._extractors = {}
- self._substitutions = {}
- def repository(self, srv_path):
- """
- Returns the Git repository that would contain this application.
- ``srv_path`` corresponds to ``options.srv_path`` from the global baton.
- """
- repo = os.path.join(srv_path, self.name + ".git")
- if not os.path.isdir(repo):
- repo = os.path.join(srv_path, self.name, ".git")
- if not os.path.isdir(repo):
- raise NoRepositoryError(self.name)
- return repo
- def makeVersion(self, version):
- """
- Creates or retrieves the :class:`ApplicationVersion` singleton for the
- specified version.
- """
- if version not in self.versions:
- self.versions[version] = ApplicationVersion(distutils.version.LooseVersion(version), self)
- return self.versions[version]
- def extract(self, deployment):
- """Extracts wizard variables from a deployment."""
- result = {}
- for k,extractor in self.extractors.items():
- result[k] = extractor(deployment)
- return result
- def parametrize(self, deployment):
- """
- Takes a generic source checkout and parametrizes
- it according to the values of deployment. This function
- operates on the current working directory.
- """
- variables = deployment.extract()
- for file in self.parametrized_files:
- try:
- contents = open(file, "r").read()
- except IOError:
- continue
- for key, value in variables.items():
- if value is None: continue
- contents = contents.replace(key, value)
- f = open(file, "w")
- f.write(contents)
- def resolveConflicts(self, deployment):
- """
- Resolves conflicted files in the current working
- directory. Returns whether or not all conflicted
- files were resolved or not. Fully resolved files are
- added to the index, but no commit is made. By default
- this is a no-op and returns ``False``.
- """
- return False
- def prepareMerge(self, deployment):
- """
- 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. If you add new files,
- you have to 'git add' them; this is not necessary for edits.
- By default this is a no-op.
- """
- pass
- def prepareConfig(self, deployment):
- """
- Takes a deployment and replaces any explicit instances
- of a configuration variable with generic ``WIZARD_*`` constants.
- The default implementation uses :attr:`substitutions`;
- you can override this method to provide arbitrary extra
- behavior.
- """
- for key, subst in self.substitutions.items():
- subs = subst(deployment)
- if not subs and key not in self.deprecated_keys:
- logging.warning("No substitutions for %s" % key)
- def install(self, version, options):
- """
- Run for 'wizard configure' (and, by proxy, 'wizard install')
- to configure an application. This assumes that the current
- working directory is a deployment. (This function does not take
- a :class:`Deployment` as a parameter, as those operations are
- not meaningful yet.)
- """
- raise NotImplemented
- def upgrade(self, deployment, version, options):
- """
- Run for 'wizard upgrade' to upgrade database schemas and other
- non-versioned data in an application. This assumes that
- the current working directory is the deployment.
- """
- raise NotImplemented
- def backup(self, deployment, options):
- """
- Run for 'wizard backup' and upgrades to backup database schemas
- and other non-versioned data in an application. This assumes
- that the current working directory is the deployment.
- """
- raise NotImplemented
- def restore(self, deployment, backup, options):
- """
- Run for 'wizard restore' and failed upgrades to restore database
- and other non-versioned data to a backed up version. This assumes
- that the current working directory is the deployment.
- """
- raise NotImplemented
- def detectVersion(self, deployment):
- """
- Checks source files to determine the version manually. This assumes
- that the current working directory is the deployment.
- """
- return None
- def checkWeb(self, deployment, output=None):
- """
- Checks if the autoinstall is viewable from the web. To get
- the HTML source that was retrieved, pass a variable containing
- an empty list to ``output``; it will be mutated to have its
- first element be the output.
- """
- raise NotImplemented
- def checkConfig(self, deployment):
- """
- Checks whether or not an autoinstall has been configured/installed
- for use. Assumes that the current working directory is the deployment.
- """
- raise NotImplemented
- @property
- def extractors(self):
- """
- Dictionary of variable names to extractor functions. These functions
- take a :class:`Deployment` as an argument and return the value of
- the variable, or ``None`` if it could not be found.
- See also :func:`wizard.app.filename_regex_extractor`.
- """
- return {}
- @property
- def substitutions(self):
- """
- Dictionary of variable names to substitution functions. These functions
- take a :class:`Deployment` as an argument and modify the deployment such
- that an explicit instance of the variable is released with the generic
- WIZARD_* constant. See also :func:`wizard.app.filename_regex_substitution`.
- """
- return {}
- @staticmethod
- def make(name):
- """Makes an application, but uses the correct subtype if available."""
- try:
- __import__("wizard.app." + name)
- return getattr(wizard.app, name).Application(name)
- except ImportError:
- return Application(name)
-
-class ApplicationVersion(object):
- """Represents an abstract notion of a version for an application, where
- ``version`` is a :class:`distutils.version.LooseVersion` and
- ``application`` is a :class:`Application`."""
- #: The :class:`distutils.version.LooseVersion` of this instance.
- version = None
- #: The :class:`Application` of this instance.
- application = None
- def __init__(self, version, application):
- self.version = version
- self.application = application
- @property
- def tag(self):
- """
- Returns the name of the git describe tag for the commit the user is
- presently on, something like mediawiki-1.2.3-scripts-4-g123abcd
- """
- return "%s-%s" % (self.application, self.version)
- @property
- def scripts_tag(self):
- """
- Returns the name of the Git tag for this version.
- """
- end = str(self.version).partition('-scripts')[2].partition('-')[0]
- return "%s-scripts%s" % (self.pristine_tag, end)
- @property
- def pristine_tag(self):
- """
- Returns the name of the Git tag for the pristine version corresponding
- to this version.
- """
- return "%s-%s" % (self.application.name, str(self.version).partition('-scripts')[0])
- def __cmp__(self, y):
- return cmp(self.version, y.version)
- @staticmethod
- def parse(value):
- """
- Parses a line from the :term:`versions store` and return
- :class:`ApplicationVersion`.
-
- Use this only for cases when speed is of primary importance;
- the data in version is unreliable and when possible, you should
- prefer directly instantiating a Deployment and having it query
- the autoinstall itself for information.
-
- The `value` to parse will vary. For old style installs, it
- will look like::
-
- /afs/athena.mit.edu/contrib/scripts/deploy/APP-x.y.z
-
- For new style installs, it will look like::
-
- APP-x.y.z-scripts
- """
- name = value.split("/")[-1]
- try:
- if name.find("-") != -1:
- app, _, version = name.partition("-")
- else:
- # kind of poor, maybe should error. Generally this
- # will actually result in a not found error
- app = name
- version = "trunk"
- except ValueError:
- raise DeploymentParseError(value)
- return ApplicationVersion.make(app, version)
- @staticmethod
- def make(app, version):
- """
- Makes/retrieves a singleton :class:`ApplicationVersion` from
- a``app`` and ``version`` string.
- """
- try:
- # defer to the application for version creation to enforce
- # singletons
- return applications()[app].makeVersion(version)
- except KeyError:
- raise NoSuchApplication(app)
-
## -- Exceptions --
class Error(wizard.Error):
"""Base error class for this module"""
pass
-class NoSuchApplication(Error):
- """
- You attempted to reference a :class:`Application` named
- ``app``, which is not recognized by Wizard.
- """
- #: The name of the application that does not exist.
- app = None
- #: The location of the autoinstall that threw this variable.
- #: This should be set by error handling code when it is availble.
- location = None
- def __init__(self, app):
- self.app = app
-
-class DeploymentParseError(Error):
- """
- Could not parse ``value`` from :term:`versions store`.
- """
- #: The value that failed to parse.
- value = None
- #: The location of the autoinstall that threw this variable.
- #: This should be set by error handling code when it is available.
- location = None
- def __init__(self, value):
- self.value = value
-
-class NoRepositoryError(Error):
- """
- :class:`Application` does not appear to have a Git repository
- in the normal location.
- """
- #: The name of the application that does not have a Git repository.
- app = None
- def __init__(self, app):
- self.app = app
- def __str__(self):
- return """Could not find Git repository for '%s'. If you would like to use a local version, try specifying --srv-path or WIZARD_SRV_PATH.""" % self.app
-
class NotMigratedError(Error):
"""
The deployment contains a .scripts-version file, but no .git
the WIZARD_WEB_HOST and WIZARD_WEB_PATH environment
variables."""
-_application_list = [
- "mediawiki", "wordpress", "joomla", "e107", "gallery2",
- "phpBB", "advancedbook", "phpical", "trac", "turbogears", "django",
- # these are technically deprecated
- "advancedpoll", "gallery",
-]
-_applications = None
-
-def applications():
- """Hash table for looking up string application name to instance"""
- global _applications
- if not _applications:
- _applications = dict([(n,Application.make(n)) for n in _application_list ])
- return _applications
-
import dateutil.parser
import wizard
+from wizard import app
import wizard.deploy # to break circular loop
# This code operates off of the assumption of .scripts-version, which
rev.source = DeploySource.parse(line)
elif i == 3:
try:
- rev.version = wizard.deploy.ApplicationVersion.parse(line)
- except wizard.deploy.Error as e:
+ rev.version = app.ApplicationVersion.parse(line)
+ except (wizard.deploy.Error, app.Error) as e:
e.location = deployment.location
raise e, None, sys.exc_info()[2]
else:
this revision, what application version this is, etc."""
def __init__(self, datetime=None, user=None, source=None, version=None):
""" `datetime` Time this revision was deployed
- `user` Person who deployed this revision, in user@host format.
- `source` Instance of DeploySource
- `version` Instance of ApplicationVersion
+ `user` Person who deployed this revision, in ``user@host`` format.
+ `source` Instance of :class:`DeploySource`
+ `version` Instance of :class:`app.ApplicationVersion`
Note: This object is typically built incrementally."""
self.datetime = datetime
self.user = user
import datetime
import dateutil.tz
-from wizard import deploy
+from wizard import app, deploy
def test_deployment_parse():
result = deploy.Deployment.parse("/afs/athena.mit.edu/user/e/z/ezyang/web_scripts/test-wiki:/afs/athena.mit.edu/contrib/scripts/deploy/mediawiki-1.11.0\n")
try:
deploy.Deployment.parse("a:/foo/obviouslybogus-1.11.0\n")
assert False
- except deploy.NoSuchApplication:
+ except app.NoSuchApplication:
pass
def test_deployment_from_dir():
from dateutil.tz import tzoffset
from datetime import datetime
-from wizard import deploy, old_log
+from wizard import app, deploy, old_log
def getTestFile(file):
return os.path.join(os.path.dirname(os.path.abspath(__file__)), file)
assert isinstance(dlog[0].source, old_log.TarballInstall)
assert dlog[0].source.location == "/afs/athena.mit.edu/contrib/scripts/deploy/mediawiki.tar.gz"
assert dlog[0].source.isDev == False
- assert dlog[0].version == deploy.applications()["mediawiki"].makeVersion('1.5.6')
+ assert dlog[0].version == app.applications()["mediawiki"].makeVersion('1.5.6')
assert dlog[1].datetime == datetime(2007, 10, 17, 3, 38, 2, tzinfo=tzoffset(None, -4 * 60 * 60))
assert dlog[1].user == "quentin@QUICHE-LORRAINE.MIT.EDU"
assert isinstance(dlog[1].source, old_log.OldUpdate)
assert dlog[1].source.isDev == True
- assert dlog[1].version == deploy.applications()["mediawiki"].makeVersion('1.5.6')
+ assert dlog[1].version == app.applications()["mediawiki"].makeVersion('1.5.6')