]> scripts.mit.edu Git - wizard.git/blob - wizard/command/prepare_pristine.py
3f16e2f40d142fa01b9a0e00e9f9e33e74b89620
[wizard.git] / wizard / command / prepare_pristine.py
1 import urllib
2 import shutil
3 import os
4
5 from wizard import app, command, shell
6
7 def main(argv, baton):
8     options, args = parse_args(argv, baton)
9     sh = shell.Shell() 
10     check_directory(options)
11     if not os.path.exists(args[0]):
12         appname, _, version = args[0].partition("-")
13         application = app.applications()[appname]
14         url = application.download(version)
15         base = os.path.basename(url)
16         with open(base, "w") as outfile:
17             infile = urllib.urlopen(url)
18             shutil.copyfileobj(infile, outfile)
19         sh.call("tar", "xf", base)
20         os.unlink(base)
21     else:
22         base = args[0]
23         sh.call("tar", "xf", base)
24     # extract the files, but be smart: if only one directory is output,
25     # move the contents of that directory here
26     items = [f for f in os.listdir(os.getcwd()) if f[0] != "."]
27     if len(items) == 1 and os.path.isdir(items[0]):
28         os.rename(items[0], "_wizard_source")
29         sh.call("cp", "-R", "_wizard_source/.", ".")
30         shutil.rmtree("_wizard_source")
31         # populate empty directories with blank files
32         for dirpath, dirnames, filenames in os.walk(os.getcwd()):
33             if "/.git" in dirpath: continue
34             if not filenames and not dirnames:
35                 open(os.path.join(dirpath, ".preserve-dir"), "w").write("")
36         sh.call("git", "add", ".")
37
38 def parse_args(argv, baton):
39     usage = """usage: %prog prepare-pristine APP-VERSION
40
41 This is the first command to run when preparing an update.
42
43 Clears out the current working directory (preserving only the .git directory),
44 and then download, extract and rm the tarball.  It will then add .preserve-dir
45 files to all empty directories, and then run 'git add .'.  It will refuse to do
46 this if there are any untracked files in the directory, or if you have any
47 local diffs: you can override this safety mechanism with --force.
48 """
49     parser = command.WizardOptionParser(usage)
50     parser.add_option("-f", "--force", dest="force", action="store_true",
51         default=False, help="Force a replacement, even if unversioned files exist.")
52     options, args = parser.parse_all(argv)
53     if len(args) < 1:
54         parser.error("not enough arguments")
55     elif len(args) > 1:
56         parser.error("too many arguments")
57     return options, args
58
59 def check_directory(options):
60     sh = shell.Shell()
61     files = sh.eval("git", "ls-files", "-o")
62     if files:
63         raise Exception("Unversioned files exist, refusing to remove (override with --force)")
64     try:
65         sh.call("git", "rev-parse", "HEAD")
66         _, _, ref = open(".git/HEAD").read().rstrip().partition(' ')
67         if not options.force:
68             if ref != "refs/heads/pristine" and os.path.exists(os.path.join(".git", ref)):
69                 raise Exception("Not on pristine branch (override with --force)")
70             try:
71                 sh.call("git", "status")
72                 raise Exception("Working copy is dirty (override with --force)")
73             except shell.CallError:
74                 pass
75         for f in os.listdir(os.getcwd()):
76             if f == ".git": continue
77             try:
78                 os.unlink(f)
79             except OSError as e:
80                 shutil.rmtree(f)
81     except shell.CallError:
82         # We're on a git repo with no HEAD
83         pass