]> scripts.mit.edu Git - wizard.git/blobdiff - wizard/command/install.py
Convert ad hoc shell calls to singleton instance; fix upgrade bug.
[wizard.git] / wizard / command / install.py
index e736fc967a4763870ef548ba859f929b8a6fbffa..4ae9058a3880953f3568fb41c57a7c9158fb90f5 100644 (file)
@@ -1,53 +1,95 @@
 import os
-import shutil
-import logging
-import errno
 import sys
+import distutils
 
 import wizard
-from wizard import command, deploy, shell, util
+from wizard import app, command, git, prompt, shell, util
+from wizard.install import installopt, interactive
 
 def main(argv, baton):
-    options, args = parse_args(argv, baton)
-    # XXX: do something smart if -scripts is not at the end
-    app = args[0]
-    dir = args[1]
-    if os.path.exists(dir):
+    old_options, args = parse_args(argv, baton)
+
+    input = prompt.make(old_options.prompt, old_options.non_interactive)
+
+    appstr = args[0]
+    dir = os.path.abspath(args[1])
+
+    if not old_options.retry and not old_options.help and os.path.exists(dir) and os.listdir(dir):
         raise DirectoryExistsError
-    appname, _, version = app.partition('-')
-    application = deploy.applications()[appname]
-    sh = shell.Shell()
-    sh.call("git", "clone", "--shared", application.repository(options.srv_path), dir)
+
+    appname, _, version = appstr.partition('-')
+    application = app.applications()[appname]
+
+    # get configuration
+    schema = application.install_schema
+    schema.commit(application, dir)
+    options = None
+    opthandler = installopt.Controller(dir, schema)
+    parser = command.WizardOptionParser("""usage: %%prog install %s DIR [ -- SETUPARGS ]
+
+Autoinstalls the application %s in the directory DIR.""" % (appname, appname))
+    configure_parser(parser, baton)
+    opthandler.push(parser)
+    if old_options.help:
+        parser.print_help()
+        sys.exit(1)
+    ihandler = interactive.Controller(dir, schema, input)
+    options, _ = parser.parse_all(args[2:] + command.make_base_args(old_options))
+    if old_options.non_interactive:
+        opthandler.handle(options)
+    else:
+        ihandler.ask(options)
+
+    input.infobox("Copying files (this may take a while)...")
+    if not os.path.exists(dir):
+        shell.call("git", "clone", "-q", "--shared", application.repository(old_options.srv_path), dir)
     with util.ChangeDirectory(dir):
-        if version:
-            sh.call("git", "reset", "--hard", app)
-        # this command's stdin should be hooked up to ours
-        try:
-            configure_args = args[2:] + command.makeBaseArgs(options)
-            sh.call("wizard", "configure", *configure_args, interactive=True)
-        except shell.PythonCallError:
-            sys.exit(1)
+        if not old_options.retry and version and version != "head-scripts": # for ease in testing
+            shell.call("git", "reset", "-q", "--hard", appstr)
+        input.infobox("Installing...")
+        application.install(distutils.version.LooseVersion(version), options)
+        if not old_options.no_commit:
+            git.commit_configure()
+    if not hasattr(options, "web_inferred"):
+        open(os.path.join(dir, ".scripts/url"), "w").write("http://%s%s" % (options.web_host, options.web_path)) # XXX: no support for https yet!
+    input.infobox("Congratulations, your new install is now accessible at:\n\nhttp://%s%s" % (options.web_host, options.web_path), width=80)
+
+def configure_parser(parser, baton):
+    parser.add_option("--prompt", dest="prompt", action="store_true",
+            default=False, help="Force to use non-ncurses interactive interface")
+    parser.add_option("--non-interactive", dest="non_interactive", action="store_true",
+            default=False, help="Force program to be non-interactive and use SETUPARGS.  Use --help with APP to find argument names.")
+    parser.add_option("--no-commit", dest="no_commit", action="store_true",
+            default=command.boolish(os.getenv("WIZARD_NO_COMMIT")), help="Do not generate an 'installation commit' after configuring the application. Envvar is WIZARD_NO_COMMIT")
+    parser.add_option("--retry", dest="retry", action="store_true",
+            default=False, help="Do not complain if directory already exists and reinstall application.")
+    baton.push(parser, "srv_path")
 
 def parse_args(argv, baton):
-    usage = """usage: %prog install [APP [DIR -- [SETUPARGS]]]
+    usage = """usage: %prog install APP DIR [ -- SETUPARGS ]
 
-Autoinstalls the application APP in the directory
-DIR.  SETUPARGS are arguments that are passed to
-'wizard configure', see 'wizard configure APP --help'
-for possible arguments.
+Autoinstalls the application APP in the directory DIR.
+This command will interactively ask for information to
+complete the autoinstall.
 
-WARNING: This command's API may change."""
-    parser = command.WizardOptionParser(usage)
-    baton.push(parser, "srv_path")
+You can also use --help with APP and DIR to find out what
+are required SETUPARGS if you want to run this non-interactively
+(the distribution of required and optional arguments may change
+depending on what directory you are installing to.)"""
+    parser = command.WizardOptionParser(usage, store_help=True)
+    configure_parser(parser, baton)
     options, args = parser.parse_all(argv)
-    # XXX: in the future, not specifying stuff is supported, since
-    # we'll prompt for it interactively
-    if not args:
-        parser.error("must specify application and directory")
-    elif len(args) == 1:
-        parser.error("must specify directory")
+    if options.help:
+        if len(args) == 0:
+            parser.print_help()
+            sys.exit(1)
+        elif len(args) == 1:
+            args.append(os.getcwd())
+    else:
+        if len(args) < 2:
+            parser.error("not enough arguments")
     return options, args
 
 class DirectoryExistsError(wizard.Error):
     def __str__(self):
-        return "Directory already exists"
+        return "Directory already exists and is not empty"