6 from wizard import deploy
7 from wizard import shell
8 from wizard.command import _base
10 def main(argv, global_options):
11 options, args = parse_args(argv)
14 logging.debug("uid is %d" % os.getuid())
17 check_if_already_migrated(options)
19 version = calculate_version()
20 repo = version.application.getRepository()
21 tag = version.getScriptsTag()
23 os.unsetenv("GIT_DIR") # prevent some perverse errors
25 sh = shell.Shell(options.dry_run)
26 check_if_tag_exists(sh, repo, tag)
27 make_repository(sh, options, repo, tag)
30 usage = """usage: %prog migrate [ARGS] DIR
32 Migrates a directory to our Git-based autoinstall format.
33 Performs basic sanity checking and intelligently determines
34 what repository and tag to use.
36 This command is meant to be run as the owner of the install
37 it is upgrading (see the scripts AFS kernel patch). Do
38 NOT run this command as root."""
39 parser = _base.WizardOptionParser(usage)
40 parser.add_option("--dry-run", dest="dry_run", action="store_true",
41 default=False, help="Prints would would be run without changing anything")
42 parser.add_option("--force", "-f", dest="force", action="store_true",
43 default=False, help="If .git or .scripts directory already exists, delete them and migrate")
44 options, args = parser.parse_all(argv)
46 parser.error("too many arguments")
48 parser.error("must specify directory")
49 return (options, args)
51 def check_if_already_migrated(options):
52 if os.path.isdir(".git") or os.path.isdir(".scripts"):
54 raise AlreadyMigratedError(dir)
56 if os.path.isdir(".git"):
57 logging.warning("Force removing .git directory")
58 if not options.dry_run: shutil.rmtree(".git")
59 if os.path.isdir(".scripts"):
60 logging.warning("Force removing .scripts directory")
61 if not options.dry_run: shutil.rmtree(".scripts")
63 def calculate_version():
65 d = deploy.Deployment.fromDir(".")
66 return d.getAppVersion()
68 if e.errno == errno.ENOENT:
69 raise NotAutoinstallError(dir)
72 def check_if_tag_exists(sh, repo, tag):
73 # check if the version we're trying to convert exists. We assume
74 # a convention here, namely, v1.2.3-scripts is what we want. If
75 # you broke the convention... shame on you.
77 sh.call("git", "--git-dir", repo, "rev-parse", tag)
78 except shell.CallError:
79 raise NoTagError(version)
81 def make_repository(sh, options, repo, tag):
82 sh.call("git", "init") # create repository
83 # configure our alternates (to save space and make this quick)
84 data = os.path.join(repo, "objects")
85 file = ".git/objects/info/alternates"
86 if not options.dry_run:
87 alternates = open(file, "w")
88 alternates.write(data)
91 logging.info("# create %s containing \"%s\"" % (file, data))
92 # configure our remote
93 # (later on, we won't actually use these ourselves, since we
94 # might want to use an arbitrary repository)
95 sh.call("git", "remote", "add", "origin", repo)
96 # configure what would normally be set up on a 'git clone' for consistency
97 sh.call("git", "config", "branch.master.remote", "origin")
98 sh.call("git", "config", "branch.master.merge", "refs/heads/master")
99 # perform the initial fetch
100 sh.call("git", "fetch", "origin")
101 # soft reset to our tag
102 sh.call("git", "reset", tag, "--")
103 # checkout the .scripts directory
104 sh.call("git", "checkout", ".scripts")
105 # XXX: setup .scripts/version???
106 # for verbose purposes, give us a git status and git diff
109 sh.call("git", "status")
110 except shell.CallError:
113 sh.call("git", "diff")
114 except shell.CallError:
117 class Error(_base.Error):
118 """Base exception for all exceptions raised by migrate"""
121 class AlreadyMigratedError(Error):
122 def __init__(self, dir):
127 ERROR: Directory already contains a .git and/or
128 .scripts directory. Did you already migrate it?
131 class NotAutoinstallError(Error):
132 def __init__(self, dir):
137 ERROR: Could not find .scripts-version file. Are you sure
138 this is an autoinstalled application?
141 class NoRepositoryError(Error):
142 def __init__(self, app):
147 ERROR: Could not find repository for this application. Have
148 you converted the repository over? Is the name %s
149 the same as the name of the .git folder?
152 class NoTagError(Error):
153 def __init__(self, version):
154 self.version = version
158 ERROR: Could not find tag v%s-scripts in repository
159 for %s. Double check and make sure
160 the repository was prepared with all necessary tags!
161 """ % (self.version.version, self.version.application.name)