~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/shelf_ui.py

  • Committer: Aaron Bentley
  • Date: 2009-08-14 15:26:25 UTC
  • mto: (4603.1.22 shelve-editor)
  • mto: This revision was merged to the branch mainline in revision 4795.
  • Revision ID: aaron@aaronbentley.com-20090814152625-mq53zoazsepp1xtw
Initial pass at shelve-via-editor.

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
)
36
36
 
37
37
 
 
38
class UseEditor(Exception):
 
39
    """Use an editor instead of selecting hunks."""
 
40
 
 
41
 
38
42
class ShelfReporter(object):
39
43
 
40
44
    vocab = {'add file': 'Shelve adding file "%(path)s"?',
235
239
        sys.stdout.flush()
236
240
        return char
237
241
 
238
 
    def prompt_bool(self, question, long=False):
 
242
    def prompt_bool(self, question, long=False, allow_editor=False):
239
243
        """Prompt the user with a yes/no question.
240
244
 
241
245
        This may be overridden by self.auto.  It may also *set* self.auto.  It
245
249
        """
246
250
        if self.auto:
247
251
            return True
 
252
        editor_string = ''
248
253
        if long:
249
 
            prompt = ' [(y)es, (N)o, (f)inish, or (q)uit]'
 
254
            if allow_editor:
 
255
                editor_string = '(E)dit manually, '
 
256
            prompt = ' [(y)es, (N)o, %s(f)inish, or (q)uit]' % editor_string
250
257
        else:
251
 
            prompt = ' [yNfq?]'
 
258
            if allow_editor:
 
259
                editor_string = 'e'
 
260
            prompt = ' [yN%sfq?]' % editor_string
252
261
        char = self.prompt(question + prompt)
253
262
        if char == 'y':
254
263
            return True
 
264
        elif char == 'e' and allow_editor:
 
265
            raise UseEditor
255
266
        elif char == 'f':
256
267
            self.auto = True
257
268
            return True
263
274
            return False
264
275
 
265
276
    def handle_modify_text(self, creator, file_id):
 
277
        try:
 
278
            lines, change_count = self._select_hunks(creator, file_id)
 
279
        except UseEditor:
 
280
            lines, change_count = self._edit_file(creator, file_id)
 
281
        if change_count != 0:
 
282
            creator.shelve_lines(file_id, lines)
 
283
        return change_count
 
284
 
 
285
    def _select_hunks(self, creator, file_id):
266
286
        """Provide diff hunk selection for modified text.
267
287
 
268
288
        If self.reporter.invert_diff is True, the diff is inverted so that
276
296
            target_lines = self.work_tree.get_file_lines(file_id)
277
297
        else:
278
298
            target_lines = self.target_tree.get_file_lines(file_id)
279
 
        textfile.check_text_lines(self.work_tree.get_file_lines(file_id))
 
299
        work_tree_lines = self.work_tree.get_file_lines(file_id)
 
300
        textfile.check_text_lines(work_tree_lines)
280
301
        textfile.check_text_lines(target_lines)
281
302
        parsed = self.get_parsed_patch(file_id, self.reporter.invert_diff)
282
303
        final_hunks = []
285
306
            self.diff_writer.write(parsed.get_header())
286
307
            for hunk in parsed.hunks:
287
308
                self.diff_writer.write(str(hunk))
288
 
                selected = self.prompt_bool(self.reporter.vocab['hunk'])
 
309
                selected = self.prompt_bool(self.reporter.vocab['hunk'],
 
310
                                            allow_editor=True)
289
311
                if not self.reporter.invert_diff:
290
312
                    selected = (not selected)
291
313
                if selected:
296
318
        sys.stdout.flush()
297
319
        if not self.reporter.invert_diff and (
298
320
            len(parsed.hunks) == len(final_hunks)):
299
 
            return 0
 
321
            return work_tree_lines, 0
300
322
        if self.reporter.invert_diff and len(final_hunks) == 0:
301
 
            return 0
 
323
            return work_tree_lines, 0
302
324
        patched = patches.iter_patched_from_hunks(target_lines, final_hunks)
303
 
        creator.shelve_lines(file_id, list(patched))
 
325
        lines = list(patched)
304
326
        if self.reporter.invert_diff:
305
 
            return len(final_hunks)
306
 
        return len(parsed.hunks) - len(final_hunks)
 
327
            change_count = len(final_hunks)
 
328
        else:
 
329
            change_count = len(parsed.hunks) - len(final_hunks)
 
330
        return lines, change_count
 
331
 
 
332
    def _edit_file(self, creator, file_id):
 
333
        old_tree = self.target_tree
 
334
        new_tree = self.work_tree
 
335
        differ = diff.DiffFromTool.from_string('gvimdiff -f -o',
 
336
                                               old_tree, new_tree,
 
337
                                               sys.stdout)
 
338
        try:
 
339
            differ.force_temp = True
 
340
            differ.allow_write = True
 
341
            old_path = old_tree.id2path(file_id)
 
342
            new_path = new_tree.id2path(file_id)
 
343
            differ.diff(file_id, old_path, new_path, 'file', 'file')
 
344
            new_abs_path = differ.get_new_path(new_path, abspath=True)
 
345
            new_lines_file = open(new_abs_path, 'r')
 
346
            try:
 
347
                lines = osutils.split_lines(new_lines_file.read())
 
348
                return lines, len(lines)
 
349
            finally:
 
350
                new_lines_file.close()
 
351
        finally:
 
352
            differ.finish()
 
353
 
307
354
 
308
355
 
309
356
class Unshelver(object):