]> scripts.mit.edu Git - wizard.git/blobdiff - lib/wizard/command/migrate.py
Downgrade AlreadyMigratedError to result in an informational notice.
[wizard.git] / lib / wizard / command / migrate.py
index e7ced10ec998176a6117ad6eada6635b99ce5b88..056d4482de6d6295fb346e357b72dccb42c6eb73 100644 (file)
@@ -2,70 +2,130 @@ import optparse
 import sys
 import os
 import shutil
+import logging.handlers
 
+from wizard import *
 import wizard.deploy as wd
 import wizard.shell as sh
 
-def main(argv, global_options):
+class PermissionsError(UserException):
+    def __init__(self, dir):
+        self.dir = dir
+    def __str__(self):
+        return """
+
+ERROR: You don't have permissions to access this directory.
+Do you have tickets for AFS with your root instance, and
+is your root instance on scripts-security-upd?
+
+You can check by running the commands 'klist' and
+'blanche scripts-security-upd'.  We recommend getting
+root tickets using Nelson Elhage's krbroot script
+at /mit/nelhage/Public/krbroot (for which you run
+'krbroot shell' and then 'aklog').
+"""
+
+class NoSuchDirectoryError(UserException):
+    def __init__(self, dir):
+        self.dir = dir
+    def __str__(self):
+        return """
+
+ERROR: No such directory... check your typing
+"""
+
+class AlreadyMigratedError(UserException):
+    def __init__(self, dir):
+        self.dir = dir
+    def __str__(self):
+        return """
+
+ERROR: Directory already contains a .git directory.
+Did you already migrate it?
+"""
+
+class NotAutoinstallError(UserException):
+    def __init__(self, dir):
+        self.dir = dir
+    def __str__(self):
+        return """
+
+ERROR: Could not find .scripts-version file. Are you sure
+this is an autoinstalled application?
+"""
+
+class NoRepositoryError(UserException):
+    def __init__(self, app):
+        self.app = app
+    def __str__(self):
+        return """
+
+ERROR: Could not find repository for this application. Have
+you converted the repository over? Is the name %s
+the same as the name of the .git folder?
+""" % self.app
+
+class NoTagError(UserException):
+    def __init__(self, version):
+        self.version = version
+    def __str__(self):
+        return """
+
+ERROR: Could not find tag v%s-scripts in repository
+for %s.  Double check and make sure
+the repository was prepared with all necessary tags!
+""" % (self.version.version, self.version.application.name)
+
+def migrate(argv, global_options, logger = None):
     usage = """usage: %prog migrate [ARGS] DIR
 
 Migrates a directory to our Git-based autoinstall format.
 Performs basic sanity checking and intelligently determines
 what repository and tag to use."""
-    parser = optparse.OptionParser(usage)
-    parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
-            default=False, help="Print all commands and outputs")
+    parser = WizardOptionParser(usage)
     parser.add_option("--dry-run", dest="dry_run", action="store_true",
             default=False, help="Prints would would be run without changing anything")
-    options, args = parser.parse_args(argv)
+    parser.add_option("--force", "-f", dest="force", action="store_true",
+            default=False, help="If .git or .scripts directory already exists, delete them and migrate")
+    options, args, logger = parser.parse_all(argv, logger)
     if len(args) > 1:
         parser.error("too many arguments")
     elif not args:
         parser.error("must specify directory")
     dir = args[0]
-    print "Changing working directory to autoinstall directory"
     try:
         os.chdir(dir)
     except OSError as e:
         if e.errno == 13:
-            print
-            print "ERROR: You don't have permissions to access this directory."
-            print "Do you have tickets for AFS with your root instance, and"
-            print "is your root instance on scripts-security-upd?"
-            print
-            print "You can check by running the commands 'klist' and"
-            print "'blanche scripts-security-upd'.  We recommend getting"
-            print "root tickets using Nelson Elhage's krbroot script"
-            print "at /mit/nelhage/Public/krbroot (for which you run"
-            print "'krbroot shell' and then 'aklog')."
-            raise SystemExit(-1)
+            raise PermissionsError(dir)
         elif e.errno == 2:
-            print
-            print "ERROR: No such directory... check your typing"
-            raise SystemExit(-1)
+            raise NoSuchDirectoryError(dir)
         else: raise e
+    if os.path.isdir(".git") or os.path.isdir(".scripts"):
+        if not options.force:
+            raise AlreadyMigratedError(dir)
+        else:
+            if os.path.isdir(".git"):
+                logger.warning("Force removing .git directory")
+                if not options.dry_run: shutil.rmtree(".git")
+            if os.path.isdir(".scripts"):
+                logger.warning("Force removing .scripts directory")
+                if not options.dry_run: shutil.rmtree(".scripts")
     try:
         deploy = wd.Deployment.fromDir(".")
         version = deploy.getAppVersion()
     except IOError as e:
         if e.errno == 2:
-            print
-            print "ERROR: Could not find .scripts-version file.  Are you sure"
-            print "this is an autoinstalled application?"
-            raise SystemExit(-1)
+            raise NotAutoinstallError(dir)
         else: raise e
     # calculate the repository we'll be pulling out of
     application = version.application
     app = application.name
     repo = os.path.join("/afs/athena.mit.edu/contrib/scripts/wizard/srv", app + ".git")
     if not os.path.isdir(repo):
-        print
-        print "ERROR: Could not find repository for this application. Have"
-        print "you converted the repository over? Is the name %s" % app
-        print "the same as the the name of the foo.git folder?"
-        raise SystemExit(-1)
+        raise NoRepositoryError(app)
     # begin the command line process
-    shell = sh.Shell(options.verbose, options.dry_run)
+    shell = sh.Shell(logger, options.dry_run)
     # check if the version we're trying to convert exists. We assume
     # a convention here, namely, v1.2.3-scripts is what we want. If
     # you broke the convention... shame on you.
@@ -73,16 +133,12 @@ what repository and tag to use."""
         tag = "v%s-scripts" % version.version
         shell.call("git", "--git-dir", repo, "rev-parse", tag)
     except sh.CalledProcessError:
-        print
-        print "ERROR: Could not find tag v%s-scripts for" % version.version
-        print "this application's version.  Double check and make sure"
-        print "the repository was prepared with all necessary tags!"
-        raise SystemExit(-1)
+        raise NoTagError(version)
     did_git_init = False
     did_git_checkout_scripts = False
     try:
         # create repository
-        shell.call("git", "init")
+        shell.call("git", "--git-dir=.git", "init")
         did_git_init = True
         # configure our remote
         shell.call("git", "remote", "add", "origin", repo)
@@ -92,21 +148,20 @@ what repository and tag to use."""
         # perform the initial fetch
         shell.call("git", "fetch", "origin")
         # soft reset to our tag
-        shell.call("git", "reset", tag)
+        shell.call("git", "reset", tag, "--")
         # checkout the .scripts directory
         shell.call("git", "checkout", ".scripts")
         did_git_checkout_scripts = True
         # XXX: setup .scripts/version???
         # for verbose purposes, give us a git status and git diff
-        shell.call("git", "status")
-        shell.call("git", "diff")
+        if options.verbose:
+            shell.call("git", "status")
+            shell.call("git", "diff")
     except:
-        print
-        print "ERROR: Exception detected! Rolling back..."
+        # this... is pretty bad
+        logger.critical("ERROR: Exception detected! Rolling back...")
         if did_git_init:
-            print "Deleting .git directory"
             shell.call("rm", "-Rf", ".git")
         if did_git_checkout_scripts:
-            print "Deleting .scripts directory"
             shell.call("rm", "-Rf", ".scripts")
         raise