Commit | Line | Data |
---|---|---|
ed60fdae CM |
1 | """Patch editing command |
2 | """ | |
3 | ||
4 | __copyright__ = """ | |
5 | Copyright (C) 2007, Catalin Marinas <catalin.marinas@gmail.com> | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License version 2 as | |
9 | published by the Free Software Foundation. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 | """ | |
20 | ||
575bbdae | 21 | from stgit.argparse import opt |
20a52e06 | 22 | from stgit import argparse, git, utils |
4491d19b | 23 | from stgit.commands import common |
ef954fe6 | 24 | from stgit.lib import git as gitlib, transaction, edit |
ed60fdae | 25 | from stgit.out import * |
ed60fdae CM |
26 | |
27 | help = 'edit a patch description or diff' | |
33ff9cdd | 28 | kind = 'patch' |
575bbdae KH |
29 | usage = ['[options] [<patch>]'] |
30 | description = """ | |
b52f3780 KH |
31 | Edit the description and author information of the given patch (or the |
32 | current patch if no patch name was given). With --diff, also edit the | |
33 | diff. | |
ed60fdae | 34 | |
b52f3780 | 35 | The editor is invoked with the following contents: |
ed60fdae | 36 | |
b52f3780 | 37 | From: A U Thor <author@example.com> |
ed60fdae CM |
38 | Date: creation date |
39 | ||
7e301a73 | 40 | Patch description |
b52f3780 KH |
41 | |
42 | If --diff was specified, the diff appears at the bottom, after a | |
43 | separator: | |
44 | ||
45 | --- | |
ed60fdae | 46 | |
b52f3780 | 47 | Diff text |
ed60fdae CM |
48 | |
49 | Command-line options can be used to modify specific information | |
4491d19b KH |
50 | without invoking the editor. (With the --edit option, the editor is |
51 | invoked even if such command-line options are given.) | |
ed60fdae | 52 | |
4491d19b KH |
53 | If the patch diff is edited but does not apply, no changes are made to |
54 | the patch at all. The edited patch is saved to a file which you can | |
55 | feed to "stg edit --file", once you have made sure it does apply.""" | |
ed60fdae | 56 | |
575bbdae KH |
57 | options = [ |
58 | opt('-d', '--diff', action = 'store_true', | |
59 | short = 'Edit the patch diff'), | |
60 | opt('-e', '--edit', action = 'store_true', | |
61 | short = 'Invoke interactive editor'), | |
f9d69fc4 KH |
62 | ] + (argparse.sign_options() + |
63 | argparse.message_options(save_template = True) + | |
575bbdae KH |
64 | argparse.author_committer_options() + argparse.diff_opts_option()) |
65 | ||
4491d19b | 66 | directory = common.DirectoryHasRepositoryLib() |
ed60fdae | 67 | |
ed60fdae CM |
68 | def func(parser, options, args): |
69 | """Edit the given patch or the current one. | |
70 | """ | |
4491d19b | 71 | stack = directory.repository.current_stack |
ed60fdae | 72 | |
4491d19b KH |
73 | if len(args) == 0: |
74 | if not stack.patchorder.applied: | |
75 | raise common.CmdException( | |
76 | 'Cannot edit top patch, because no patches are applied') | |
77 | patchname = stack.patchorder.applied[-1] | |
ed60fdae | 78 | elif len(args) == 1: |
4491d19b KH |
79 | [patchname] = args |
80 | if not stack.patches.exists(patchname): | |
81 | raise common.CmdException('%s: no such patch' % patchname) | |
ed60fdae | 82 | else: |
4491d19b KH |
83 | parser.error('Cannot edit more than one patch') |
84 | ||
85 | cd = orig_cd = stack.patches.get(patchname).commit.data | |
ed60fdae | 86 | |
ef954fe6 KH |
87 | cd, failed_diff = edit.auto_edit_patch( |
88 | stack.repository, cd, msg = options.message, contains_diff = True, | |
89 | author = options.author, committer = options.committer, | |
90 | sign_str = options.sign_str) | |
4491d19b KH |
91 | |
92 | if options.save_template: | |
93 | options.save_template( | |
ef954fe6 KH |
94 | edit.patch_desc(stack.repository, cd, |
95 | options.diff, options.diff_flags, failed_diff)) | |
4491d19b KH |
96 | return utils.STGIT_SUCCESS |
97 | ||
4491d19b | 98 | if cd == orig_cd or options.edit: |
ef954fe6 KH |
99 | cd, failed_diff = edit.interactive_edit_patch( |
100 | stack.repository, cd, options.diff, options.diff_flags, failed_diff) | |
4491d19b KH |
101 | |
102 | def failed(): | |
103 | fn = '.stgit-failed.patch' | |
104 | f = file(fn, 'w') | |
ef954fe6 KH |
105 | f.write(edit.patch_desc(stack.repository, cd, |
106 | options.diff, options.diff_flags, failed_diff)) | |
4491d19b KH |
107 | f.close() |
108 | out.error('Edited patch did not apply.', | |
109 | 'It has been saved to "%s".' % fn) | |
110 | return utils.STGIT_COMMAND_ERROR | |
111 | ||
112 | # If we couldn't apply the patch, fail without even trying to | |
113 | # effect any of the changes. | |
114 | if failed_diff: | |
115 | return failed() | |
116 | ||
117 | # The patch applied, so now we have to rewrite the StGit patch | |
118 | # (and any patches on top of it). | |
119 | iw = stack.repository.default_iw | |
781e549a | 120 | trans = transaction.StackTransaction(stack, 'edit', allow_conflicts = True) |
4491d19b KH |
121 | if patchname in trans.applied: |
122 | popped = trans.applied[trans.applied.index(patchname)+1:] | |
123 | assert not trans.pop_patches(lambda pn: pn in popped) | |
124 | else: | |
125 | popped = [] | |
126 | trans.patches[patchname] = stack.repository.commit(cd) | |
127 | try: | |
128 | for pn in popped: | |
129 | trans.push_patch(pn, iw) | |
130 | except transaction.TransactionHalted: | |
131 | pass | |
132 | try: | |
133 | # Either a complete success, or a conflict during push. But in | |
134 | # either case, we've successfully effected the edits the user | |
135 | # asked us for. | |
136 | return trans.run(iw) | |
137 | except transaction.TransactionException: | |
138 | # Transaction aborted -- we couldn't check out files due to | |
139 | # dirty index/worktree. The edits were not carried out. | |
140 | return failed() |