7 from wizard import command, deploy, shell, util
10 options, args = parse_args(argv)
13 logging.debug("uid is %d" % os.getuid())
16 check_if_already_migrated(options)
18 deployment = make_deployment() # uses chdir
19 version = deployment.app_version
20 repo = version.application.repository
21 tag = version.scripts_tag
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)
28 make_variables(deployment, options)
30 if not options.dry_run:
31 deployment.updateVersion()
32 os.rename(".scripts-version", ".scripts/old-version") # archive
34 logging.info("# create .scripts/version containing \"%s-%s\"" % (deployment.application.name, deployment.version))
35 logging.info("mv .scripts-version .scripts/old-version")
38 usage = """usage: %prog migrate [ARGS] DIR
40 Migrates a directory to our Git-based autoinstall format.
41 Performs basic sanity checking and intelligently determines
42 what repository and tag to use.
44 This command is meant to be run as the owner of the install
45 it is upgrading (see the scripts AFS kernel patch). Do
46 NOT run this command as root."""
47 parser = command.WizardOptionParser(usage)
48 parser.add_option("--dry-run", dest="dry_run", action="store_true",
49 default=False, help="Prints would would be run without changing anything")
50 parser.add_option("--force", "-f", dest="force", action="store_true",
51 default=False, help="If .git or .scripts directory already exists, delete them and migrate")
52 options, args = parser.parse_all(argv)
54 parser.error("too many arguments")
56 parser.error("must specify directory")
57 return (options, args)
59 def check_if_already_migrated(options):
60 if os.path.isdir(".git") or os.path.isdir(".scripts"):
62 raise AlreadyMigratedError(dir)
64 if os.path.isdir(".git"):
65 logging.warning("Force removing .git directory")
66 if not options.dry_run: shutil.rmtree(".git")
67 if os.path.isdir(".scripts"):
68 logging.warning("Force removing .scripts directory")
69 if not options.dry_run: shutil.rmtree(".scripts")
71 def make_deployment():
73 return deploy.Deployment(".")
75 if e.errno == errno.ENOENT:
76 raise NotAutoinstallError(dir)
79 def check_if_tag_exists(sh, repo, tag):
80 # check if the version we're trying to convert exists. We assume
81 # a convention here, namely, v1.2.3-scripts is what we want. If
82 # you broke the convention... shame on you.
84 sh.call("git", "--git-dir", repo, "rev-parse", tag)
85 except shell.CallError:
86 raise NoTagError(version)
88 def make_repository(sh, options, repo, tag):
89 sh.call("git", "init") # create repository
90 # configure our alternates (to save space and make this quick)
91 data = os.path.join(repo, "objects")
92 file = ".git/objects/info/alternates"
93 if not options.dry_run:
94 alternates = open(file, "w")
95 alternates.write(data)
97 htaccess = open(".git/.htaccess", "w")
98 htaccess.write("Deny from all\n")
101 logging.info("# create %s containing \"%s\"" % (file, data))
102 logging.info('# create .htaccess containing "Deny from all"')
103 # configure our remote (this is merely for convenience; wizard scripts
104 # will not rely on this)
105 sh.call("git", "remote", "add", "origin", repo)
106 # configure what would normally be set up on a 'git clone' for consistency
107 sh.call("git", "config", "branch.master.remote", "origin")
108 sh.call("git", "config", "branch.master.merge", "refs/heads/master")
109 # perform the initial fetch
110 sh.call("git", "fetch", "origin")
111 # soft reset to our tag
112 sh.call("git", "reset", tag, "--")
113 # checkout the .scripts directory
114 sh.call("git", "checkout", ".scripts")
115 # commit user local changes
116 message = "Autoinstall migration of %s locker.\n\n%s" % (util.get_dir_owner(), util.get_git_footer())
119 message += "\nMigrated-by: " + util.get_operator_git()
120 except util.NoOperatorInfo:
122 sh.call("git", "commit", "--allow-empty", "-a", "-m", message)
123 # for verbose purposes, give us a git status and git diff
126 sh.call("git", "status")
127 except shell.CallError:
130 sh.call("git", "diff")
131 except shell.CallError:
134 def make_variables(d, options):
135 """Make .scripts/variables which contains variables based off of
136 what was regexed out of existing configuration files."""
137 variables = d.extract()
138 if not options.dry_run: f = open(".scripts/variables", "w")
139 for k,v in variables.items():
141 # once we get everything on the same version, you should
142 # actually start paying attention to these warnings
143 logging.warning("Variable %s not found" % k)
145 logging.debug("Variable %s is %s" % (k,v))
146 if not options.dry_run:
147 f.write("%s %s\n" % (k,v))
149 logging.info('# write line "%s %s" to .scripts/variables' % (k,v))
150 if not options.dry_run: f.close()
152 class Error(command.Error):
153 """Base exception for all exceptions raised by migrate"""
156 class AlreadyMigratedError(Error):
157 def __init__(self, dir):
162 ERROR: Directory already contains a .git and/or
163 .scripts directory. Did you already migrate it?
166 class NotAutoinstallError(Error):
167 def __init__(self, dir):
172 ERROR: Could not find .scripts-version file. Are you sure
173 this is an autoinstalled application?
176 class NoTagError(Error):
177 def __init__(self, version):
178 self.version = version
182 ERROR: Could not find tag v%s-scripts in repository
183 for %s. Double check and make sure
184 the repository was prepared with all necessary tags!
185 """ % (self.version.version, self.version.application.name)