import os
+import os.path
import shutil
import logging
-from wizard import command, deploy, shell, util
+from wizard import app, command, deploy, shell, util
def main(argv, baton):
options, args = parse_args(argv, baton)
- dir = args[0]
-
+ dir = os.path.abspath(args[0]) if args else os.getcwd()
shell.drop_priviledges(dir, options.log_file)
-
util.chdir(dir)
+
sh = shell.Shell(options.dry_run)
logging.info("Migrating %s" % dir)
deployment = deploy.ProductionCopy(".")
- # deal with old-style migration, remove this later
- if os.path.isfile(".scripts/old-version") and not os.path.isfile(".scripts-version"):
- os.rename(".scripts/old-version", ".scripts-version")
-
os.unsetenv("GIT_DIR") # prevent some perverse errors
try:
deployment.verify()
raise AlreadyMigratedError(deployment.location)
+ except deploy.NotAutoinstallError:
+ # Previously, this was a fatal error, but now let's try
+ # a little harder.
+ # XXX: The user still has to tell us what application ; a more
+ # user friendly thing to do is figure it out automatically
+ if not options.force_app:
+ raise
+ # actual version number will get overwritten shortly
+ deployment.setAppVersion(app.ApplicationVersion.make(options.force_app, "unknown"))
except deploy.NotMigratedError:
+ # LEGACY
pass
except (deploy.CorruptedAutoinstallError, AlreadyMigratedError):
if not options.force:
raise
- deployment.verifyTag(options.srv_path)
-
if options.force_version:
- version = deployment.application.makeVersion(options.force_version)
+ deployment.setAppVersion(deployment.application.makeVersion(options.force_version))
else:
- deployment.verifyVersion()
- version = deployment.app_version
- repo = version.application.repository(options.srv_path)
- tag = version.scripts_tag
+ try:
+ deployment.verifyVersion()
+ except deploy.VersionMismatchError as e:
+ # well, we'll use that then
+ deployment.setAppVersion(deployment.application.makeVersion(str(e.real_version)))
- with util.LockDirectory(".scripts-migrate-lock"):
+ deployment.verifyTag(options.srv_path)
+
+ repo = deployment.application.repository(options.srv_path)
+ tag = deployment.app_version.wizard_tag
+ try:
+ sh.call("git", "--git-dir=%s" % repo, "rev-parse", tag)
+ except shell.CallError:
+ raise UnsupportedVersion(deployment.version)
+
+ with util.LockDirectory(".wizard-migrate-lock"):
try:
if options.force:
perform_force(options)
check_variables(deployment, options)
except KeyboardInterrupt:
# revert it; barring zany race conditions this is safe
- if os.path.exists(".scripts"):
- shutil.rmtree(".scripts")
+ if os.path.exists(".wizard"):
+ shutil.rmtree(".wizard")
if os.path.exists(".git"):
shutil.rmtree(".git")
Performs basic sanity checking and intelligently determines
what repository and tag to use.
-This command is meant to be run as the owner of the install
-it is upgrading (see the scripts AFS kernel patch). Do
-NOT run this command as root."""
+This command is meant to be run as the owner of the install it is
+upgrading . Do NOT run this command as root."""
parser = command.WizardOptionParser(usage)
baton.push(parser, "srv_path")
parser.add_option("--dry-run", dest="dry_run", action="store_true",
default=False, help="Prints would would be run without changing anything")
parser.add_option("--force", "-f", dest="force", action="store_true",
- default=False, help="If .git or .scripts directory already exists,"
+ default=False, help="If .git or .wizard directory already exists, "
"delete them and migrate")
parser.add_option("--force-version", dest="force_version",
- default=None, help="If .scripts-version tells lies, explicitly specify"
+ default=None, help="If .scripts-version is corrupted or non-existent, explicitly specify "
"a version to migrate to.")
+ parser.add_option("--force-app", dest="force_app",
+ default=None, help="If .scripts-version is corrupted or non-existent, explicitly specify "
+ "an application to migrate to.")
options, args = parser.parse_all(argv)
if len(args) > 1:
parser.error("too many arguments")
- elif not args:
- parser.error("must specify directory")
return (options, args)
def perform_force(options):
has_git = os.path.isdir(".git")
- has_scripts = os.path.isdir(".scripts")
+ has_wizard = os.path.isdir(".wizard")
if has_git:
logging.warning("Force removing .git directory")
if not options.dry_run: backup = util.safe_unlink(".git")
logging.info(".git backed up to %s" % backup)
- if has_scripts:
- logging.warning("Force removing .scripts directory")
- if not options.dry_run: backup = util.safe_unlink(".scripts")
- logging.info(".scripts backed up to %s" % backup)
+ if has_wizard:
+ logging.warning("Force removing .wizard directory")
+ if not options.dry_run: backup = util.safe_unlink(".wizard")
+ logging.info(".wizard backed up to %s" % backup)
def make_repository(sh, options, repo, tag):
sh.call("git", "init") # create repository
else:
logging.info("# create %s containing \"%s\"" % (file, data))
logging.info('# create .htaccess containing "Deny from all"')
- # configure our remote (this is merely for convenience; wizard scripts
+ # configure our remote (this is merely for convenience; wizard
# will not rely on this)
sh.call("git", "remote", "add", "origin", repo)
# configure what would normally be set up on a 'git clone' for consistency
sh.call("git", "fetch", "origin")
# soft reset to our tag
sh.call("git", "reset", tag, "--")
- # checkout the .scripts directory
- sh.call("git", "checkout", ".scripts")
+ # initialize the .wizard directory
+ util.init_wizard_dir()
logging.info("Diffstat:\n" + sh.eval("git", "diff", "--stat"))
# commit user local changes
- message = "Autoinstall migration of %s locker.\n\n%s" % (util.get_dir_owner(), util.get_git_footer())
+ message = "Autoinstall migration.\n\n%s" % util.get_git_footer()
util.set_git_env()
try:
message += "\nMigrated-by: " + util.get_operator_git()
pass
class AlreadyMigratedError(Error):
+ quiet = True
def __init__(self, dir):
self.dir = dir
def __str__(self):
return """
-ERROR: Directory already contains a .git and
-.scripts directory. If you force this migration,
-both of these directories will be removed.
+This autoinstall is already migrated; move along, nothing to
+see here. (If you really want to, you can force a re-migration
+with --force, but this will blow away the existing .git and
+.scripts directories (i.e. your history and Wizard configuration).)
"""
+class UnsupportedVersion(Error):
+ def __init__(self, version):
+ self.version = version
+ def __str__(self):
+ return """
+
+ERROR: This autoinstall is presently on %s, which is unsupported by
+Wizard. Please manually upgrade it to one that is supported,
+and then retry the migration; usually the latest version is supported.
+""" % self.version