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 | |
6c8a90e1 KH |
57 | args = [argparse.applied_patches, argparse.unapplied_patches, |
58 | argparse.hidden_patches] | |
575bbdae KH |
59 | options = [ |
60 | opt('-d', '--diff', action = 'store_true', | |
61 | short = 'Edit the patch diff'), | |
62 | opt('-e', '--edit', action = 'store_true', | |
63 | short = 'Invoke interactive editor'), | |
f9d69fc4 KH |
64 | ] + (argparse.sign_options() + |
65 | argparse.message_options(save_template = True) + | |
53388a71 | 66 | argparse.author_options() + argparse.diff_opts_option()) |
575bbdae | 67 | |
4491d19b | 68 | directory = common.DirectoryHasRepositoryLib() |
ed60fdae | 69 | |
ed60fdae CM |
70 | def func(parser, options, args): |
71 | """Edit the given patch or the current one. | |
72 | """ | |
4491d19b | 73 | stack = directory.repository.current_stack |
ed60fdae | 74 | |
4491d19b KH |
75 | if len(args) == 0: |
76 | if not stack.patchorder.applied: | |
77 | raise common.CmdException( | |
78 | 'Cannot edit top patch, because no patches are applied') | |
79 | patchname = stack.patchorder.applied[-1] | |
ed60fdae | 80 | elif len(args) == 1: |
4491d19b KH |
81 | [patchname] = args |
82 | if not stack.patches.exists(patchname): | |
83 | raise common.CmdException('%s: no such patch' % patchname) | |
ed60fdae | 84 | else: |
4491d19b KH |
85 | parser.error('Cannot edit more than one patch') |
86 | ||
87 | cd = orig_cd = stack.patches.get(patchname).commit.data | |
ed60fdae | 88 | |
ef954fe6 KH |
89 | cd, failed_diff = edit.auto_edit_patch( |
90 | stack.repository, cd, msg = options.message, contains_diff = True, | |
53388a71 | 91 | author = options.author, committer = lambda p: p, |
ef954fe6 | 92 | sign_str = options.sign_str) |
4491d19b KH |
93 | |
94 | if options.save_template: | |
95 | options.save_template( | |
ef954fe6 KH |
96 | edit.patch_desc(stack.repository, cd, |
97 | options.diff, options.diff_flags, failed_diff)) | |
4491d19b KH |
98 | return utils.STGIT_SUCCESS |
99 | ||
4491d19b | 100 | if cd == orig_cd or options.edit: |
ef954fe6 KH |
101 | cd, failed_diff = edit.interactive_edit_patch( |
102 | stack.repository, cd, options.diff, options.diff_flags, failed_diff) | |
4491d19b KH |
103 | |
104 | def failed(): | |
105 | fn = '.stgit-failed.patch' | |
106 | f = file(fn, 'w') | |
ef954fe6 KH |
107 | f.write(edit.patch_desc(stack.repository, cd, |
108 | options.diff, options.diff_flags, failed_diff)) | |
4491d19b KH |
109 | f.close() |
110 | out.error('Edited patch did not apply.', | |
111 | 'It has been saved to "%s".' % fn) | |
112 | return utils.STGIT_COMMAND_ERROR | |
113 | ||
114 | # If we couldn't apply the patch, fail without even trying to | |
115 | # effect any of the changes. | |
116 | if failed_diff: | |
117 | return failed() | |
118 | ||
119 | # The patch applied, so now we have to rewrite the StGit patch | |
120 | # (and any patches on top of it). | |
121 | iw = stack.repository.default_iw | |
781e549a | 122 | trans = transaction.StackTransaction(stack, 'edit', allow_conflicts = True) |
4491d19b KH |
123 | if patchname in trans.applied: |
124 | popped = trans.applied[trans.applied.index(patchname)+1:] | |
125 | assert not trans.pop_patches(lambda pn: pn in popped) | |
126 | else: | |
127 | popped = [] | |
128 | trans.patches[patchname] = stack.repository.commit(cd) | |
129 | try: | |
130 | for pn in popped: | |
131 | trans.push_patch(pn, iw) | |
132 | except transaction.TransactionHalted: | |
133 | pass | |
134 | try: | |
135 | # Either a complete success, or a conflict during push. But in | |
136 | # either case, we've successfully effected the edits the user | |
137 | # asked us for. | |
138 | return trans.run(iw) | |
139 | except transaction.TransactionException: | |
140 | # Transaction aborted -- we couldn't check out files due to | |
141 | # dirty index/worktree. The edits were not carried out. | |
142 | return failed() |