]> scripts.mit.edu Git - wizard.git/blob - wizard/command/install.py
Implement interactive mode without validation.
[wizard.git] / wizard / command / install.py
1 import os
2 import sys
3 import distutils
4
5 import wizard
6 from wizard import app, command, git, prompt, shell, util
7 from wizard.install import installopt, interactive
8
9 def main(argv, baton):
10     old_options, args = parse_args(argv, baton)
11
12     input = prompt.make(old_options.prompt, old_options.non_interactive)
13
14     if len(args) < 1:
15         # XXX: Obviously not correct ;-)
16         appstr = "mediawiki"
17     else:
18         appstr = args[0]
19
20     first_time = True
21     locker = None
22     # XXX: this is kind of grody
23     while 1:
24         if len(args) < 2:
25             # XXX: Scripts specific
26             if first_time:
27                 type = input.menu("""
28 Who are you performing this install for?  If you don't know, select 1.""", cmdopt="directory",
29                     choices=[
30                         ("1", "Your personal Athena account"),
31                         ("2", "A locker you control (i.e. a club or course)"),
32                         ])
33                 if type == "1":
34                     locker = os.getenv("ATHENA_USER") or os.getenv("USER")
35                 else:
36                     locker = input.inputbox("""
37 Enter the name of the selected locker that you control.  For locker /mit/lsc, you would simply enter lsc.
38
39 Locker name:""")
40                 # XXX: check for control/existence of locker.
41             # fi
42             path = input.inputbox("""
43 Your new install will appear on the web at a URL that starts with \
44 http://%s.scripts.mit.edu/.  Please decide on a complete URL and \
45 enter it below.  You must enter one or more characters after mit.edu. \
46 The completed address must contain only a-z, 0-9 and /.
47
48 Desired address:""" % locker, init="http://%s.scripts.mit.edu/" % locker)
49             dir = os.path.join("/mit", locker, "web_scripts", path)
50         else:
51             dir = args[1]
52
53         if os.path.exists(dir):
54             if locker:
55                 input.msgbox("Directory already exists; please select another address or delete the old directory.")
56                 first_time = False
57                 continue
58             raise DirectoryExistsError
59         break
60
61     appname, _, version = appstr.partition('-')
62     application = app.applications()[appname]
63
64     # get configuration
65     schema = application.install_schema
66     options = None
67     if old_options.non_interactive:
68         handler = installopt.Controller(dir, schema)
69         parser = command.WizardOptionParser()
70         handler.push(parser)
71         options, _ = parser.parse_all(args[2:] + command.make_base_args(old_options)) # accumulate
72         handler.handle(options)
73     else:
74         handler = interactive.Controller(dir, schema, input)
75         handler.ask(old_options)
76         options = old_options
77
78     sh = shell.Shell()
79     input.infobox("Copying files (this may take a while)...")
80     sh.call("git", "clone", "-q", "--shared", application.repository(old_options.srv_path), dir)
81     with util.ChangeDirectory(dir):
82         if version:
83             # XXX: do something smart if -scripts is not at the end
84             sh.call("git", "reset", "-q", "--hard", appstr)
85         input.infobox("Installing...")
86         application.install(distutils.version.LooseVersion(version), options)
87         git.commit_configure()
88     input.infobox("Congratulations, your new install is now accessible at http://%s%s" % (options.web_host, options.web_path))
89
90 def parse_args(argv, baton):
91     usage = """usage: %prog install [APP [DIR -- [SETUPARGS]]]
92
93 Autoinstalls the application APP in the directory
94 DIR.  SETUPARGS are arguments that are passed to
95 'wizard configure', see 'wizard configure APP --help'
96 for possible arguments.  If arguments are missing
97 this command will interactively ask for them.
98 """
99     parser = command.WizardOptionParser(usage)
100     parser.add_option("--prompt", dest="prompt", action="store_true",
101             default=False, help="Force to use non-ncurses interactive interface")
102     parser.add_option("--non-interactive", dest="non_interactive", action="store_true",
103             default=False, help="Force program to be non-interactive")
104     baton.push(parser, "srv_path")
105     return parser.parse_all(argv)
106
107 class DirectoryExistsError(wizard.Error):
108     def __str__(self):
109         return "Directory already exists"