+ # Read patch from user-provided description.
+ if options.message == None:
+ failed_diff = None
+ else:
+ cd, failed_diff = update_patch_description(stack.repository, cd,
+ options.message)
+
+ # Modify author and committer data.
+ if options.author != None:
+ options.authname, options.authemail = common.name_email(options.author)
+ for p, f, val in [('author', 'name', options.authname),
+ ('author', 'email', options.authemail),
+ ('author', 'date', gitlib.Date.maybe(options.authdate)),
+ ('committer', 'name', options.commname),
+ ('committer', 'email', options.commemail)]:
+ if val != None:
+ cd = getattr(cd, 'set_' + p)(
+ getattr(getattr(cd, p), 'set_' + f)(val))
+
+ # Add Signed-off-by: or similar.
+ if options.sign_str != None:
+ cd = cd.set_message(utils.add_sign_line(
+ cd.message, options.sign_str, gitlib.Person.committer().name,
+ gitlib.Person.committer().email))
+
+ if options.save_template:
+ options.save_template(
+ patch_desc(stack.repository, cd, failed_diff,
+ options.diff, options.diff_flags))
+ return utils.STGIT_SUCCESS
+
+ # Let user edit the patch manually.
+ if cd == orig_cd or options.edit:
+ fn = '.stgit-edit.' + ['txt', 'patch'][bool(options.diff)]
+ cd, failed_diff = update_patch_description(
+ stack.repository, cd, utils.edit_string(
+ patch_desc(stack.repository, cd, failed_diff,
+ options.diff, options.diff_flags),
+ fn))
+
+ def failed():
+ fn = '.stgit-failed.patch'
+ f = file(fn, 'w')
+ f.write(patch_desc(stack.repository, cd, failed_diff,
+ options.diff, options.diff_flags))
+ f.close()
+ out.error('Edited patch did not apply.',
+ 'It has been saved to "%s".' % fn)
+ return utils.STGIT_COMMAND_ERROR
+
+ # If we couldn't apply the patch, fail without even trying to
+ # effect any of the changes.
+ if failed_diff:
+ return failed()
+
+ # The patch applied, so now we have to rewrite the StGit patch
+ # (and any patches on top of it).
+ iw = stack.repository.default_iw
+ trans = transaction.StackTransaction(stack, 'stg edit')
+ if patchname in trans.applied:
+ popped = trans.applied[trans.applied.index(patchname)+1:]
+ assert not trans.pop_patches(lambda pn: pn in popped)
+ else:
+ popped = []
+ trans.patches[patchname] = stack.repository.commit(cd)
+ try:
+ for pn in popped:
+ trans.push_patch(pn, iw)
+ except transaction.TransactionHalted:
+ pass
+ try:
+ # Either a complete success, or a conflict during push. But in
+ # either case, we've successfully effected the edits the user
+ # asked us for.
+ return trans.run(iw)
+ except transaction.TransactionException:
+ # Transaction aborted -- we couldn't check out files due to
+ # dirty index/worktree. The edits were not carried out.
+ return failed()