]> scripts.mit.edu Git - wizard.git/blob - wizard/command/upgrade.py
Massive refactor; use batons, wizard summary SUBCOMMAND
[wizard.git] / wizard / command / upgrade.py
1 import optparse
2 import sys
3 import os
4 import shutil
5 import logging.handlers
6 import errno
7 import tempfile
8
9 from wizard import deploy
10 from wizard import shell
11 from wizard import util
12 from wizard.command import _command
13
14 # XXX: WARNING EXPERIMENTAL DANGER DANGER WILL ROBINSON
15
16 # need errors for checking DAG integrity (if the user is on a completely
17 # different history tree, stuff is problems)
18
19 # we need an option that specifies the person making the update. Since n-b
20 # doesn't actually have a way to do this, username is probably what we want.
21 def main(argv, baton):
22     options, args = parse_args(argv)
23     dir = args[0]
24     _command.chdir(dir)
25     if not os.path.isdir(".git"):
26         raise NotAutoinstallError()
27     try:
28         d = deploy.Deployment.fromDir(".")
29     except IOError as e:
30         if e.errno == errno.ENOENT:
31             raise NotAutoinstallError()
32         else: raise e
33     repo = d.getApplication().getRepository()
34     # begin the command line process
35     sh = shell.Shell(options.dry_run)
36     # setup environment
37     util.set_git_env()
38     # commit their changes
39     message = "Pre-commit of %s locker before autoinstall upgrade.\n\n%s" % (util.get_dir_owner(), util.get_git_footer())
40     try:
41         message += "\nPre-commit-by: " + util.get_operator_git()
42     except util.NoOperatorInfo:
43         pass
44     try:
45         sh.call("git", "commit", "-a", "-m", "Pre-upgrade commit.")
46     except shell.CallError:
47         logging.info("No changes detected")
48         pass
49     # perform fetch to update repository state
50     sh.call("git", "fetch", repo)
51     # clone their website to a temporary directory
52     temp_dir = tempfile.mkdtemp()
53     temp_wc_dir = os.path.join(temp_dir, "repo")
54     logging.info("Using temporary directory: " + temp_wc_dir)
55     sh.call("git", "clone", "--shared", ".", temp_wc_dir)
56     with util.ChangeDirectory(temp_wc_dir):
57         # reconfigure the repository path
58         sh.call("git", "remote", "add", "scripts", repo)
59         sh.call("git", "fetch", "scripts")
60         # perform the merge
61         version, _ = sh.call(["git", "--git-dir="+repo, "describe", "--tags", "master"])
62         try:
63             message = "Upgraded autoinstall in %s to %s.\n\n%s" % (util.get_dir_owner(), version, util.get_git_footer())
64             try:
65                 message += "\nUpgraded-by: " + util.get_operator_git()
66             except util.NoOperatorInfo:
67                 pass
68             sh.call("git", "merge", "-m", message, "scripts/master")
69         except shell.CallError:
70             raise MergeFailed
71     # XXX: frob .htaccess to make site inaccessible
72     # git merge (which performs a fast forward)
73     #   - merge could fail (race)
74     sh.call("git", "pull", temp_wc_dir, "master")
75     # run update script
76     sh.call(".scripts/update")
77     # XXX: frob .htaccess to make site accessible
78     # XXX:  - check if .htaccess changed, first.  Upgrade
79     #       process might have frobbed it.  Don't be
80     #       particularly worried if the segment dissappeared
81
82 def parse_args(argv):
83     usage = """usage: %prog upgrade [ARGS] DIR
84
85 Upgrades an autoinstall to the latest version.  This involves
86 updating files and running .scripts/update.
87
88 WARNING: This is still experimental."""
89     parser = _command.WizardOptionParser(usage)
90     parser.add_option("--dry-run", dest="dry_run", action="store_true",
91             default=False, help="Prints would would be run without changing anything")
92     options, args = parser.parse_all(argv)
93     if len(args) > 1:
94         parser.error("too many arguments")
95     elif not args:
96         parser.error("must specify directory")
97     return options, args
98
99 class Error(_command.Error):
100     """Base exception for all exceptions raised by upgrade"""
101     pass
102
103 class NotAutoinstallError(Error):
104     def __str__(self):
105         return """
106
107 ERROR: Could not find .git file. Are you sure
108 this is an autoinstalled application? Did you remember
109 to migrate it?
110 """
111
112 class MergeFailed(Error):
113     pass