38
38
class ShelfReporter(object):
39
vocab = {'add file': 'Shelve adding file "%(path)s"?',
40
'binary': 'Shelve binary changes?',
41
'change kind': 'Shelve changing "%s" from %(other)s'
43
'delete file': 'Shelve removing file "%(path)s"?',
44
'final': 'Shelve %d change(s)?',
46
'modify target': 'Shelve changing target of'
47
' "%(path)s" from "%(other)s" to "%(this)s"?',
48
'rename': 'Shelve renaming "%(other)s" =>'
40
54
def __init__(self):
41
55
self.delta_reporter = delta._ChangeReporter()
46
60
def shelved_id(self, shelf_id):
47
61
trace.note('Changes shelved with id "%d".' % shelf_id)
63
def changes_destroyed(self):
64
trace.note('Selected changes destroyed.')
49
66
def selected_changes(self, transform):
50
67
trace.note("Selected changes:")
51
68
changes = transform.iter_changes()
52
69
delta.report_changes(changes, self.delta_reporter)
71
def prompt_change(self, change):
72
if change[0] == 'rename':
73
vals = {'this': change[3], 'other': change[2]}
74
elif change[0] == 'change kind':
75
vals = {'path': change[4], 'other': change[2], 'this': change[3]}
76
elif change[0] == 'modify target':
77
vals = {'path': change[2], 'other': change[3], 'this': change[4]}
79
vals = {'path': change[3]}
80
prompt = self.vocab[change[0]] % vals
84
class ApplyReporter(ShelfReporter):
86
vocab = {'add file': 'Delete file "%(path)s"?',
87
'binary': 'Apply binary changes?',
88
'change kind': 'Change "%(path)s" from %(this)s'
90
'delete file': 'Add file "%(path)s"?',
91
'final': 'Apply %d change(s)?',
92
'hunk': 'Apply change?',
93
'modify target': 'Change target of'
94
' "%(path)s" from "%(this)s" to "%(other)s"?',
95
'rename': 'Rename "%(this)s" => "%(other)s"?',
100
def changes_destroyed(self):
55
104
class Shelver(object):
56
105
"""Interactively shelve the changes in a working tree."""
58
107
def __init__(self, work_tree, target_tree, diff_writer=None, auto=False,
59
108
auto_apply=False, file_list=None, message=None,
60
destroy=False, manager=None, reporter=None,
109
destroy=False, manager=None, reporter=None):
64
112
:param work_tree: The working tree to shelve changes from.
88
136
if reporter is None:
89
137
reporter = ShelfReporter()
90
138
self.reporter = reporter
91
self.vocab_apply=vocab_apply
93
self.vocab = {'add file': 'Delete file "%(path)s"?',
94
'binary': 'Apply binary changes?',
95
'change kind': 'Change "%(path)s" from %(this)s'
97
'delete file': 'Add file "%(path)s"?',
98
'final': 'Apply %d change(s)?',
99
'hunk': 'Apply change?',
100
'modify target': 'Change target of'
101
' "%(path)s" from "%(this)s" to "%(other)s"?',
102
'rename': 'Rename "%(this)s" => "%(other)s"?',
105
self.vocab = {'add file': 'Shelve adding file "%(path)s"?',
106
'binary': 'Shelve binary changes?',
107
'change kind': 'Shelve changing "%s" from %(other)s'
109
'delete file': 'Shelve removing file "%(path)s"?',
110
'final': 'Shelve %d change(s)?',
112
'modify target': 'Shelve changing target of'
113
' "%(path)s" from "%(other)s" to "%(this)s"?',
114
'rename': 'Shelve renaming "%(other)s" =>'
120
141
def from_args(klass, diff_writer, revision=None, all=False, file_list=None,
149
170
changes_shelved += self.handle_modify_text(creator,
151
172
except errors.BinaryFile:
152
if self.prompt_bool(self.vocab['binary']):
173
if self.prompt_bool(self.reporter.vocab['binary']):
153
174
changes_shelved += 1
154
175
creator.shelve_content_change(change[1])
156
if self.prompt_change(change):
177
if self.prompt_bool(self.reporter.prompt_change(change)):
157
178
creator.shelve_change(change)
158
179
changes_shelved += 1
159
180
if changes_shelved > 0:
160
181
self.reporter.selected_changes(creator.work_transform)
161
if (self.auto_apply or self.prompt_bool(self.vocab['final']
182
if (self.auto_apply or self.prompt_bool(
183
self.reporter.vocab['final'] % changes_shelved)):
164
185
creator.transform()
165
trace.note('Selected changes destroyed.')
186
self.reporter.changes_destroyed()
167
188
shelf_id = self.manager.shelve_changes(creator,
173
194
shutil.rmtree(self.tempdir)
174
195
creator.finalize()
176
def prompt_change(self, change):
177
if change[0] == 'rename':
178
vals = {'this': change[3], 'other': change[2]}
179
elif change[0] == 'change kind':
180
vals = {'path': change[4], 'other': change[2], 'this': change[3]}
181
elif change[0] == 'modify target':
182
vals = {'path': change[2], 'other': change[3], 'this': change[4]}
184
vals = {'path': change[3]}
185
prompt = self.vocab[change[0]] % vals
186
return self.prompt_bool(prompt)
188
197
def get_parsed_patch(self, file_id, invert=False):
189
198
"""Return a parsed version of a file's patch.
191
200
:param file_id: The id of the file to generate a patch for.
192
201
:return: A patches.Patch.
194
old_path = self.target_tree.id2path(file_id)
195
new_path = self.work_tree.id2path(file_id)
196
203
diff_file = StringIO()
198
205
old_tree = self.work_tree
201
208
old_tree = self.target_tree
202
209
new_tree = self.work_tree
210
old_path = old_tree.id2path(file_id)
211
new_path = new_tree.id2path(file_id)
203
212
text_differ = diff.DiffText(old_tree, new_tree, diff_file)
204
213
patch = text_differ.diff(file_id, old_path, new_path, 'file', 'file')
205
214
diff_file.seek(0)
251
260
:param file_id: The id of the file to shelve.
252
261
:return: number of shelved hunks.
263
if self.reporter.invert_diff:
255
264
target_lines = self.work_tree.get_file_lines(file_id)
257
266
target_lines = self.target_tree.get_file_lines(file_id)
258
267
textfile.check_text_lines(self.work_tree.get_file_lines(file_id))
259
268
textfile.check_text_lines(target_lines)
260
parsed = self.get_parsed_patch(file_id, self.vocab_apply)
269
parsed = self.get_parsed_patch(file_id, self.reporter.invert_diff)
262
271
if not self.auto:
264
273
self.diff_writer.write(parsed.get_header())
265
274
for hunk in parsed.hunks:
266
275
self.diff_writer.write(str(hunk))
267
selected = self.prompt_bool(self.vocab['hunk'])
268
if not self.vocab_apply:
276
selected = self.prompt_bool(self.reporter.vocab['hunk'])
277
if not self.reporter.invert_diff:
269
278
selected = (not selected)
271
280
hunk.mod_pos += offset
274
283
offset -= (hunk.mod_range - hunk.orig_range)
275
284
sys.stdout.flush()
276
if not self.vocab_apply and len(parsed.hunks) == len(final_hunks):
285
if not self.reporter.invert_diff and (
286
len(parsed.hunks) == len(final_hunks)):
278
if self.vocab_apply and len(final_hunks) == 0:
288
if self.reporter.invert_diff and len(final_hunks) == 0:
280
290
patched = patches.iter_patched_from_hunks(target_lines, final_hunks)
281
291
creator.shelve_lines(file_id, list(patched))
292
if self.reporter.invert_diff:
283
293
return len(final_hunks)
284
294
return len(parsed.hunks) - len(final_hunks)