def main(argv, baton):
options, args = parse_args(argv, baton)
- command.chdir(args[0])
- d = make_deployment_from_cwd()
- repo = d.application.repository(options.srv_path)
- util.set_git_env()
+ if args:
+ command.chdir(args[0])
sh = shell.Shell()
- if not options.dry_run:
- perform_pre_commit(sh)
- temp_wc_dir = perform_tmp_clone(sh)
- with util.ChangeDirectory(temp_wc_dir):
- if options.dry_run:
- # we delayed performing the pre upgrade commit
- # until we're in the temporary directory
+ util.set_git_env()
+ if options.continue_:
+ temp_wc_dir = os.getcwd()
+ user_commit, next_commit = open(".git/WIZARD_PARENTS", "r").read().split()
+ repo = open(".git/WIZARD_REPO", "r").read()
+ version = open(".git/WIZARD_UPGRADE_VERSION", "r").read()
+ command.chdir(sh.eval("git", "config", "remote.origin.url"))
+ else:
+ d = make_deployment_from_cwd()
+ repo = d.application.repository(options.srv_path)
+ version = calculate_newest_version(sh, repo)
+ if not options.dry_run:
perform_pre_commit(sh)
- sh.call("git", "remote", "add", "scripts", repo)
- sh.call("git", "fetch", "scripts")
- version = sh.eval("git", "--git-dir="+repo, "describe", "--tags", "master")
- user_commit = sh.eval("git", "rev-parse", "HEAD")
- next_commit = sh.eval("git", "rev-parse", version)
- perform_merge(sh, repo, d, version)
- # Make it possible to resume here
- new_tree = sh.eval("git", "rev-parse", "HEAD^{tree}")
+ temp_wc_dir = perform_tmp_clone(sh)
+ with util.ChangeDirectory(temp_wc_dir):
+ if options.dry_run:
+ # we delayed performing the pre upgrade commit
+ # until we're in the temporary directory
+ perform_pre_commit(sh)
+ sh.call("git", "remote", "add", "scripts", repo)
+ sh.call("git", "fetch", "scripts")
+ user_commit, next_commit = calculate_parents(sh, version)
+ # save variables so that --continue will work
+ # yeah yeah no trailing newline whatever
+ open(".git/WIZARD_REPO", "w").write(repo)
+ open(".git/WIZARD_UPGRADE_VERSION", "w").write(version)
+ open(".git/WIZARD_PARENTS", "w").write("%s\n%s" % (user_commit, next_commit))
+ perform_merge(sh, repo, d, version)
+ # variables: version, user_commit, next_commit, temp_wc_dir
+ with util.ChangeDirectory(temp_wc_dir):
message = make_commit_message(version)
+ new_tree = sh.eval("git", "rev-parse", "HEAD^{tree}")
final_commit = sh.eval("git", "commit-tree", new_tree, "-p", user_commit, "-p", next_commit, input=message)
+ # a master branch may not necessarily exist if the user
+ # was manually installed to an earlier version
try:
sh.call("git", "checkout", "-b", "master", "--")
except shell.CallError:
message += "\nUpgraded-by: " + util.get_operator_git()
except util.NoOperatorInfo:
pass
+ return message
+
+def calculate_newest_version(sh, repo):
+ return sh.eval("git", "--git-dir="+repo, "describe", "--tags", "master")
+
+def calculate_parents(sh, version):
+ user_commit = sh.eval("git", "rev-parse", "HEAD")
+ next_commit = sh.eval("git", "rev-parse", version)
+ return user_commit, next_commit
def perform_pre_commit(sh):
try:
return temp_wc_dir
def perform_merge(sh, repo, d, version):
+ # naive merge algorithm:
+ # sh.call("git", "merge", "-m", message, "scripts/master")
+ # crazy merge algorithm:
+ def make_virtual_commit(tag, parents = []):
+ """WARNING: Changes state of Git repository"""
+ sh.call("git", "checkout", tag, "--")
+ d.parametrize(".")
+ for file in d.application.parametrized_files:
+ try:
+ sh.call("git", "add", "--", file)
+ except shell.CallError:
+ pass
+ virtual_tree = sh.eval("git", "write-tree")
+ parent_args = itertools.chain(*(["-p", p] for p in parents))
+ virtual_commit = sh.eval("git", "commit-tree", virtual_tree, *parent_args, input="")
+ sh.call("git", "reset", "--hard")
+ return virtual_commit
+ user_tree = sh.eval("git", "rev-parse", "HEAD^{tree}")
+ base_virtual_commit = make_virtual_commit(d.app_version.pristine_tag)
+ next_virtual_commit = make_virtual_commit(version, [base_virtual_commit])
+ user_virtual_commit = sh.eval("git", "commit-tree", user_tree, "-p", base_virtual_commit, input="")
+ sh.call("git", "checkout", user_virtual_commit, "--")
try:
- # naive merge algorithm:
- # sh.call("git", "merge", "-m", message, "scripts/master")
- # crazy merge algorithm:
- def make_virtual_commit(tag, parents = []):
- """WARNING: Changes state of Git repository"""
- sh.call("git", "checkout", tag, "--")
- d.parametrize(".")
- for file in d.application.parametrized_files:
- try:
- sh.call("git", "add", "--", file)
- except shell.CallError:
- pass
- virtual_tree = sh.eval("git", "write-tree")
- parent_args = itertools.chain(*(["-p", p] for p in parents))
- virtual_commit = sh.eval("git", "commit-tree", virtual_tree, *parent_args, input="")
- sh.call("git", "reset", "--hard")
- return virtual_commit
- user_tree = sh.eval("git", "rev-parse", "HEAD^{tree}")
- base_virtual_commit = make_virtual_commit(d.app_version.pristine_tag)
- next_virtual_commit = make_virtual_commit(version, [base_virtual_commit])
- user_virtual_commit = sh.eval("git", "commit-tree", user_tree, "-p", base_virtual_commit, input="")
- sh.call("git", "checkout", user_virtual_commit, "--")
sh.call("git", "merge", next_virtual_commit)
except shell.CallError:
print os.getcwd()
raise MergeFailed
def parse_args(argv, baton):
- usage = """usage: %prog upgrade [ARGS] DIR
+ usage = """usage: %prog upgrade [ARGS] [DIR]
Upgrades an autoinstall to the latest version. This involves
updating files and running .scripts/update.
parser = command.WizardOptionParser(usage)
parser.add_option("--dry-run", dest="dry_run", action="store_true",
default=False, help="Prints would would be run without changing anything")
+ # notice trailing underscore
+ parser.add_option("--continue", dest="continue_", action="store_true",
+ default=False, help="Continues an upgrade that has had its merge manually resolved using the current working directory as the resolved copy.")
baton.push(parser, "srv_path")
options, args = parser.parse_all(argv)
if len(args) > 1:
parser.error("too many arguments")
- elif not args:
- parser.error("must specify directory")
return options, args
class Error(command.Error):
def __str__(self):
return """
-ERROR: Merge failed. Change directory to the temporary
-directory and manually resolve the merge.
-"""
+ERROR: Merge failed. Resolve the merge by cd'ing to the
+temporary directory, finding conflicted files with `git status`,
+resolving the files, adding them using `git add`, and then
+committing your changes with `git commit` (your log message
+will be ignored), and then running `wizard upgrade --continue`."""