Rev 4795: (abentley) add support for shelving with an editor. in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Thu Nov 12 08:40:23 GMT 2009
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 4795 [merge]
revision-id: pqm at pqm.ubuntu.com-20091112084021-z1abucfx1bwampnq
parent: pqm at pqm.ubuntu.com-20091112003735-0e7h1y9j2fo0kbnv
parent: aaron at aaronbentley.com-20091112075013-p9qy6y50so3x6bxk
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2009-11-12 08:40:21 +0000
message:
(abentley) add support for shelving with an editor.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/config.py config.py-20051011043216-070c74f4e9e338e8
bzrlib/diff.py diff.py-20050309040759-26944fbbf2ebbf36
bzrlib/shelf_ui.py shelver.py-20081005210102-33worgzwrtdw0yrm-1
bzrlib/tests/test_config.py testconfig.py-20051011041908-742d0c15d8d8c8eb
bzrlib/tests/test_diff.py testdiff.py-20050727164403-d1a3496ebb12e339
bzrlib/tests/test_shelf_ui.py test_shelf_ui.py-20081027155203-wtcuazg85wp9u4fv-1
=== modified file 'NEWS'
--- a/NEWS 2009-11-11 06:50:40 +0000
+++ b/NEWS 2009-11-12 07:50:13 +0000
@@ -18,6 +18,9 @@
New Features
************
+* Users can define a shelve editor to provide shelf functionality at a
+ granularity finer than per-patch-hunk. (Aaron Bentley)
+
Bug Fixes
*********
=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py 2009-11-04 22:32:13 +0000
+++ b/bzrlib/builtins.py 2009-11-12 07:47:19 +0000
@@ -5671,7 +5671,7 @@
try:
shelver.run()
finally:
- shelver.work_tree.unlock()
+ shelver.finalize()
except errors.UserAbort:
return 0
=== modified file 'bzrlib/config.py'
--- a/bzrlib/config.py 2009-08-20 04:53:23 +0000
+++ b/bzrlib/config.py 2009-10-31 01:43:48 +0000
@@ -153,6 +153,15 @@
"""Get the users pop up editor."""
raise NotImplementedError
+ def get_change_editor(self, old_tree, new_tree):
+ from bzrlib import diff
+ cmd = self._get_change_editor()
+ if cmd is None:
+ return None
+ return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
+ sys.stdout)
+
+
def get_mail_client(self):
"""Get a mail client to use"""
selected_client = self.get_user_option('mail_client')
@@ -346,6 +355,9 @@
"""Return the policy for the given (section, option_name) pair."""
return POLICY_NONE
+ def _get_change_editor(self):
+ return self.get_user_option('change_editor')
+
def _get_signature_checking(self):
"""See Config._get_signature_checking."""
policy = self._get_user_option('check_signatures')
@@ -679,6 +691,9 @@
return self._get_best_value('_get_user_id')
+ def _get_change_editor(self):
+ return self._get_best_value('_get_change_editor')
+
def _get_signature_checking(self):
"""See Config._get_signature_checking."""
return self._get_best_value('_get_signature_checking')
=== modified file 'bzrlib/diff.py'
--- a/bzrlib/diff.py 2009-10-13 13:05:16 +0000
+++ b/bzrlib/diff.py 2009-11-03 01:15:09 +0000
@@ -18,6 +18,7 @@
import os
import re
import shutil
+import string
import sys
from bzrlib.lazy_import import lazy_import
@@ -46,6 +47,12 @@
from bzrlib.trace import mutter, note, warning
+class AtTemplate(string.Template):
+ """Templating class that uses @ instead of $."""
+
+ delimiter = '@'
+
+
# TODO: Rather than building a changeset object, we should probably
# invoke callbacks on an object. That object can either accumulate a
# list, write them out directly, etc etc.
@@ -672,7 +679,8 @@
def from_string(klass, command_string, old_tree, new_tree, to_file,
path_encoding='utf-8'):
command_template = commands.shlex_split_unicode(command_string)
- command_template.extend(['%(old_path)s', '%(new_path)s'])
+ if '@' not in command_string:
+ command_template.extend(['@old_path', '@new_path'])
return klass(command_template, old_tree, new_tree, to_file,
path_encoding)
@@ -685,7 +693,8 @@
def _get_command(self, old_path, new_path):
my_map = {'old_path': old_path, 'new_path': new_path}
- return [t % my_map for t in self.command_template]
+ return [AtTemplate(t).substitute(my_map) for t in
+ self.command_template]
def _execute(self, old_path, new_path):
command = self._get_command(old_path, new_path)
@@ -711,9 +720,10 @@
raise
return True
- def _write_file(self, file_id, tree, prefix, relpath):
+ def _write_file(self, file_id, tree, prefix, relpath, force_temp=False,
+ allow_write=False):
full_path = osutils.pathjoin(self._root, prefix, relpath)
- if self._try_symlink_root(tree, prefix):
+ if not force_temp and self._try_symlink_root(tree, prefix):
return full_path
parent_dir = osutils.dirname(full_path)
try:
@@ -730,16 +740,19 @@
target.close()
finally:
source.close()
- osutils.make_readonly(full_path)
+ if not allow_write:
+ osutils.make_readonly(full_path)
mtime = tree.get_file_mtime(file_id)
os.utime(full_path, (mtime, mtime))
return full_path
- def _prepare_files(self, file_id, old_path, new_path):
+ def _prepare_files(self, file_id, old_path, new_path, force_temp=False,
+ allow_write_new=False):
old_disk_path = self._write_file(file_id, self.old_tree, 'old',
- old_path)
+ old_path, force_temp)
new_disk_path = self._write_file(file_id, self.new_tree, 'new',
- new_path)
+ new_path, force_temp,
+ allow_write=allow_write_new)
return old_disk_path, new_disk_path
def finish(self):
@@ -757,6 +770,29 @@
self._execute(osutils.pathjoin('old', old_path),
osutils.pathjoin('new', new_path))
+ def edit_file(self, file_id):
+ """Use this tool to edit a file.
+
+ A temporary copy will be edited, and the new contents will be
+ returned.
+
+ :param file_id: The id of the file to edit.
+ :return: The new contents of the file.
+ """
+ old_path = self.old_tree.id2path(file_id)
+ new_path = self.new_tree.id2path(file_id)
+ new_abs_path = self._prepare_files(file_id, old_path, new_path,
+ allow_write_new=True,
+ force_temp=True)[1]
+ command = self._get_command(osutils.pathjoin('old', old_path),
+ osutils.pathjoin('new', new_path))
+ subprocess.call(command, cwd=self._root)
+ new_file = open(new_abs_path, 'r')
+ try:
+ return new_file.read()
+ finally:
+ new_file.close()
+
class DiffTree(object):
"""Provides textual representations of the difference between two trees.
=== modified file 'bzrlib/shelf_ui.py'
--- a/bzrlib/shelf_ui.py 2009-09-11 07:55:48 +0000
+++ b/bzrlib/shelf_ui.py 2009-11-02 21:56:42 +0000
@@ -22,11 +22,13 @@
from bzrlib import (
builtins,
+ commands,
delta,
diff,
errors,
osutils,
patches,
+ patiencediff,
shelf,
textfile,
trace,
@@ -35,6 +37,10 @@
)
+class UseEditor(Exception):
+ """Use an editor instead of selecting hunks."""
+
+
class ShelfReporter(object):
vocab = {'add file': 'Shelve adding file "%(path)s"?',
@@ -143,6 +149,9 @@
if reporter is None:
reporter = ShelfReporter()
self.reporter = reporter
+ config = self.work_tree.branch.get_config()
+ self.change_editor = config.get_change_editor(target_tree, work_tree)
+ self.work_tree.lock_tree_write()
@classmethod
def from_args(klass, diff_writer, revision=None, all=False, file_list=None,
@@ -168,11 +177,10 @@
target_tree = builtins._get_one_revision_tree('shelf2', revision,
tree.branch, tree)
files = builtins.safe_relpath_files(tree, file_list)
- except:
+ return klass(tree, target_tree, diff_writer, all, all, files,
+ message, destroy)
+ finally:
tree.unlock()
- raise
- return klass(tree, target_tree, diff_writer, all, all, files, message,
- destroy)
def run(self):
"""Interactively shelve the changes."""
@@ -211,6 +219,12 @@
shutil.rmtree(self.tempdir)
creator.finalize()
+ def finalize(self):
+ if self.change_editor is not None:
+ self.change_editor.finish()
+ self.work_tree.unlock()
+
+
def get_parsed_patch(self, file_id, invert=False):
"""Return a parsed version of a file's patch.
@@ -245,7 +259,7 @@
sys.stdout.flush()
return char
- def prompt_bool(self, question, long=False):
+ def prompt_bool(self, question, long=False, allow_editor=False):
"""Prompt the user with a yes/no question.
This may be overridden by self.auto. It may also *set* self.auto. It
@@ -255,13 +269,20 @@
"""
if self.auto:
return True
+ editor_string = ''
if long:
- prompt = ' [(y)es, (N)o, (f)inish, or (q)uit]'
+ if allow_editor:
+ editor_string = '(E)dit manually, '
+ prompt = ' [(y)es, (N)o, %s(f)inish, or (q)uit]' % editor_string
else:
- prompt = ' [yNfq?]'
+ if allow_editor:
+ editor_string = 'e'
+ prompt = ' [yN%sfq?]' % editor_string
char = self.prompt(question + prompt)
if char == 'y':
return True
+ elif char == 'e' and allow_editor:
+ raise UseEditor
elif char == 'f':
self.auto = True
return True
@@ -273,6 +294,23 @@
return False
def handle_modify_text(self, creator, file_id):
+ """Handle modified text, by using hunk selection or file editing.
+
+ :param creator: A ShelfCreator.
+ :param file_id: The id of the file that was modified.
+ :return: The number of changes.
+ """
+ work_tree_lines = self.work_tree.get_file_lines(file_id)
+ try:
+ lines, change_count = self._select_hunks(creator, file_id,
+ work_tree_lines)
+ except UseEditor:
+ lines, change_count = self._edit_file(file_id, work_tree_lines)
+ if change_count != 0:
+ creator.shelve_lines(file_id, lines)
+ return change_count
+
+ def _select_hunks(self, creator, file_id, work_tree_lines):
"""Provide diff hunk selection for modified text.
If self.reporter.invert_diff is True, the diff is inverted so that
@@ -280,13 +318,14 @@
:param creator: a ShelfCreator
:param file_id: The id of the file to shelve.
+ :param work_tree_lines: Line contents of the file in the working tree.
:return: number of shelved hunks.
"""
if self.reporter.invert_diff:
- target_lines = self.work_tree.get_file_lines(file_id)
+ target_lines = work_tree_lines
else:
target_lines = self.target_tree.get_file_lines(file_id)
- textfile.check_text_lines(self.work_tree.get_file_lines(file_id))
+ textfile.check_text_lines(work_tree_lines)
textfile.check_text_lines(target_lines)
parsed = self.get_parsed_patch(file_id, self.reporter.invert_diff)
final_hunks = []
@@ -295,7 +334,9 @@
self.diff_writer.write(parsed.get_header())
for hunk in parsed.hunks:
self.diff_writer.write(str(hunk))
- selected = self.prompt_bool(self.reporter.vocab['hunk'])
+ selected = self.prompt_bool(self.reporter.vocab['hunk'],
+ allow_editor=(self.change_editor
+ is not None))
if not self.reporter.invert_diff:
selected = (not selected)
if selected:
@@ -304,16 +345,32 @@
else:
offset -= (hunk.mod_range - hunk.orig_range)
sys.stdout.flush()
- if not self.reporter.invert_diff and (
- len(parsed.hunks) == len(final_hunks)):
- return 0
- if self.reporter.invert_diff and len(final_hunks) == 0:
- return 0
- patched = patches.iter_patched_from_hunks(target_lines, final_hunks)
- creator.shelve_lines(file_id, list(patched))
if self.reporter.invert_diff:
- return len(final_hunks)
- return len(parsed.hunks) - len(final_hunks)
+ change_count = len(final_hunks)
+ else:
+ change_count = len(parsed.hunks) - len(final_hunks)
+ patched = patches.iter_patched_from_hunks(target_lines,
+ final_hunks)
+ lines = list(patched)
+ return lines, change_count
+
+ def _edit_file(self, file_id, work_tree_lines):
+ """
+ :param file_id: id of the file to edit.
+ :param work_tree_lines: Line contents of the file in the working tree.
+ :return: (lines, change_region_count), where lines is the new line
+ content of the file, and change_region_count is the number of
+ changed regions.
+ """
+ lines = osutils.split_lines(self.change_editor.edit_file(file_id))
+ return lines, self._count_changed_regions(work_tree_lines, lines)
+
+ @staticmethod
+ def _count_changed_regions(old_lines, new_lines):
+ matcher = patiencediff.PatienceSequenceMatcher(None, old_lines,
+ new_lines)
+ blocks = matcher.get_matching_blocks()
+ return len(blocks) - 2
class Unshelver(object):
=== modified file 'bzrlib/tests/test_config.py'
--- a/bzrlib/tests/test_config.py 2009-08-20 04:53:23 +0000
+++ b/bzrlib/tests/test_config.py 2009-10-31 01:43:48 +0000
@@ -25,6 +25,7 @@
branch,
bzrdir,
config,
+ diff,
errors,
osutils,
mail_client,
@@ -42,6 +43,7 @@
[DEFAULT]
email=Erik B\u00e5gfors <erik at bagfors.nu>
editor=vim
+change_editor=vimdiff -of @new_path @old_path
gpg_signing_command=gnome-gpg
log_format=short
user_global_option=something
@@ -208,6 +210,10 @@
self._calls.append('_get_signature_checking')
return self._signatures
+ def _get_change_editor(self):
+ self._calls.append('_get_change_editor')
+ return 'vimdiff -fo @new_path @old_path'
+
bool_config = """[DEFAULT]
active = true
@@ -314,6 +320,14 @@
my_config = config.Config()
self.assertEqual('long', my_config.log_format())
+ def test_get_change_editor(self):
+ my_config = InstrumentedConfig()
+ change_editor = my_config.get_change_editor('old_tree', 'new_tree')
+ self.assertEqual(['_get_change_editor'], my_config._calls)
+ self.assertIs(diff.DiffFromTool, change_editor.__class__)
+ self.assertEqual(['vimdiff', '-fo', '@new_path', '@old_path'],
+ change_editor.command_template)
+
class TestConfigPath(tests.TestCase):
@@ -625,6 +639,18 @@
my_config = self._get_sample_config()
self.assertEqual(sample_long_alias, my_config.get_alias('ll'))
+ def test_get_change_editor(self):
+ my_config = self._get_sample_config()
+ change_editor = my_config.get_change_editor('old', 'new')
+ self.assertIs(diff.DiffFromTool, change_editor.__class__)
+ self.assertEqual('vimdiff -of @new_path @old_path',
+ ' '.join(change_editor.command_template))
+
+ def test_get_no_change_editor(self):
+ my_config = self._get_empty_config()
+ change_editor = my_config.get_change_editor('old', 'new')
+ self.assertIs(None, change_editor)
+
class TestGlobalConfigSavingOptions(tests.TestCaseInTempDir):
=== modified file 'bzrlib/tests/test_diff.py'
--- a/bzrlib/tests/test_diff.py 2009-10-08 16:32:43 +0000
+++ b/bzrlib/tests/test_diff.py 2009-10-31 01:16:23 +0000
@@ -1299,13 +1299,13 @@
def test_from_string(self):
diff_obj = DiffFromTool.from_string('diff', None, None, None)
self.addCleanup(diff_obj.finish)
- self.assertEqual(['diff', '%(old_path)s', '%(new_path)s'],
+ self.assertEqual(['diff', '@old_path', '@new_path'],
diff_obj.command_template)
def test_from_string_u5(self):
diff_obj = DiffFromTool.from_string('diff -u\\ 5', None, None, None)
self.addCleanup(diff_obj.finish)
- self.assertEqual(['diff', '-u 5', '%(old_path)s', '%(new_path)s'],
+ self.assertEqual(['diff', '-u 5', '@old_path', '@new_path'],
diff_obj.command_template)
self.assertEqual(['diff', '-u 5', 'old-path', 'new-path'],
diff_obj._get_command('old-path', 'new-path'))
@@ -1313,7 +1313,7 @@
def test_execute(self):
output = StringIO()
diff_obj = DiffFromTool(['python', '-c',
- 'print "%(old_path)s %(new_path)s"'],
+ 'print "@old_path @new_path"'],
None, None, output)
self.addCleanup(diff_obj.finish)
diff_obj._execute('old', 'new')
@@ -1338,7 +1338,7 @@
tree.lock_read()
self.addCleanup(tree.unlock)
diff_obj = DiffFromTool(['python', '-c',
- 'print "%(old_path)s %(new_path)s"'],
+ 'print "@old_path @new_path"'],
tree, tree, output)
diff_obj._prepare_files('file-id', 'file', 'file')
self.assertReadableByAttrib(diff_obj._root, 'old\\file', r'old\\file')
@@ -1370,7 +1370,7 @@
tree.lock_read()
self.addCleanup(tree.unlock)
diff_obj = DiffFromTool(['python', '-c',
- 'print "%(old_path)s %(new_path)s"'],
+ 'print "@old_path @new_path"'],
old_tree, tree, output)
self.addCleanup(diff_obj.finish)
self.assertContainsRe(diff_obj._root, 'bzr-diff-[^/]*')
=== modified file 'bzrlib/tests/test_shelf_ui.py'
--- a/bzrlib/tests/test_shelf_ui.py 2009-09-11 07:55:48 +0000
+++ b/bzrlib/tests/test_shelf_ui.py 2009-10-23 03:35:32 +0000
@@ -76,6 +76,7 @@
tree.lock_tree_write()
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree())
+ self.addCleanup(shelver.finalize)
e = self.assertRaises(AssertionError, shelver.run)
self.assertEqual('Unexpected prompt: Shelve? [yNfq?]', str(e))
@@ -84,6 +85,7 @@
tree.lock_tree_write()
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree())
+ self.addCleanup(shelver.finalize)
shelver.expect('foo', 'y')
e = self.assertRaises(AssertionError, shelver.run)
self.assertEqual('Wrong prompt: Shelve? [yNfq?]', str(e))
@@ -93,6 +95,7 @@
tree.lock_tree_write()
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree())
+ self.addCleanup(shelver.finalize)
shelver.expect('Shelve? [yNfq?]', 'n')
shelver.expect('Shelve? [yNfq?]', 'n')
# No final shelving prompt because no changes were selected
@@ -104,6 +107,7 @@
tree.lock_tree_write()
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree())
+ self.addCleanup(shelver.finalize)
shelver.expect('Shelve? [yNfq?]', 'y')
shelver.expect('Shelve? [yNfq?]', 'y')
shelver.expect('Shelve 2 change(s)? [yNfq?]', 'n')
@@ -115,6 +119,7 @@
tree.lock_tree_write()
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree())
+ self.addCleanup(shelver.finalize)
shelver.expect('Shelve? [yNfq?]', 'y')
shelver.expect('Shelve? [yNfq?]', 'y')
shelver.expect('Shelve 2 change(s)? [yNfq?]', 'y')
@@ -126,6 +131,7 @@
tree.lock_tree_write()
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree())
+ self.addCleanup(shelver.finalize)
shelver.expect('Shelve? [yNfq?]', 'y')
shelver.expect('Shelve? [yNfq?]', 'n')
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
@@ -138,6 +144,7 @@
tree.lock_tree_write()
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree())
+ self.addCleanup(shelver.finalize)
shelver.expect('Shelve binary changes? [yNfq?]', 'y')
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
shelver.run()
@@ -149,6 +156,7 @@
tree.lock_tree_write()
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree())
+ self.addCleanup(shelver.finalize)
shelver.expect('Shelve renaming "foo" => "bar"? [yNfq?]', 'y')
shelver.expect('Shelve? [yNfq?]', 'y')
shelver.expect('Shelve? [yNfq?]', 'y')
@@ -162,6 +170,7 @@
tree.lock_tree_write()
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree())
+ self.addCleanup(shelver.finalize)
shelver.expect('Shelve removing file "foo"? [yNfq?]', 'y')
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
shelver.run()
@@ -175,6 +184,7 @@
tree.lock_tree_write()
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree())
+ self.addCleanup(shelver.finalize)
shelver.expect('Shelve adding file "foo"? [yNfq?]', 'y')
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
shelver.run()
@@ -187,6 +197,7 @@
tree.lock_tree_write()
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree())
+ self.addCleanup(shelver.finalize)
shelver.expect('Shelve changing "foo" from file to directory? [yNfq?]',
'y')
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
@@ -202,6 +213,7 @@
tree.lock_tree_write()
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree())
+ self.addCleanup(shelver.finalize)
shelver.expect('Shelve changing target of "baz" from "bar" to '
'"vax"? [yNfq?]', 'y')
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
@@ -213,6 +225,7 @@
tree.lock_tree_write()
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree())
+ self.addCleanup(shelver.finalize)
shelver.expect('Shelve? [yNfq?]', 'f')
shelver.expect('Shelve 2 change(s)? [yNfq?]', 'y')
shelver.run()
@@ -223,6 +236,7 @@
tree.lock_tree_write()
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree())
+ self.addCleanup(shelver.finalize)
shelver.expect('Shelve? [yNfq?]', 'q')
self.assertRaises(errors.UserAbort, shelver.run)
self.assertFileEqual(LINES_ZY, 'tree/foo')
@@ -234,7 +248,7 @@
try:
shelver.run()
finally:
- shelver.work_tree.unlock()
+ shelver.finalize()
self.assertFileEqual(LINES_AJ, 'tree/foo')
def test_shelve_filename(self):
@@ -244,6 +258,7 @@
tree.lock_tree_write()
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree(), file_list=['bar'])
+ self.addCleanup(shelver.finalize)
shelver.expect('Shelve adding file "bar"? [yNfq?]', 'y')
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
shelver.run()
@@ -253,19 +268,18 @@
tree.lock_tree_write()
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree())
+ self.addCleanup(shelver.finalize)
shelver.expect('Shelve? [yNfq?]', '?')
shelver.expect('Shelve? [(y)es, (N)o, (f)inish, or (q)uit]', 'f')
shelver.expect('Shelve 2 change(s)? [yNfq?]', 'y')
shelver.run()
- def test_shelve_distroy(self):
+ def test_shelve_destroy(self):
tree = self.create_shelvable_tree()
shelver = shelf_ui.Shelver.from_args(sys.stdout, all=True,
directory='tree', destroy=True)
- try:
- shelver.run()
- finally:
- shelver.work_tree.unlock()
+ self.addCleanup(shelver.finalize)
+ shelver.run()
self.assertIs(None, tree.get_shelf_manager().last_shelf())
self.assertFileEqual(LINES_AJ, 'tree/foo')
@@ -276,7 +290,10 @@
target = tree.branch.repository.revision_tree(target_revision_id)
shelver = shelf_ui.Shelver(tree, target, auto=True,
auto_apply=True)
- shelver.run()
+ try:
+ shelver.run()
+ finally:
+ shelver.finalize()
finally:
tree.unlock()
@@ -316,6 +333,7 @@
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree(),
reporter=shelf_ui.ApplyReporter())
+ self.addCleanup(shelver.finalize)
shelver.expect('Apply change? [yNfq?]', 'n')
shelver.expect('Apply change? [yNfq?]', 'n')
# No final shelving prompt because no changes were selected
@@ -328,6 +346,7 @@
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree(),
reporter=shelf_ui.ApplyReporter())
+ self.addCleanup(shelver.finalize)
shelver.expect('Apply change? [yNfq?]', 'y')
shelver.expect('Apply change? [yNfq?]', 'y')
shelver.expect('Apply 2 change(s)? [yNfq?]', 'n')
@@ -340,6 +359,7 @@
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree(),
reporter=shelf_ui.ApplyReporter())
+ self.addCleanup(shelver.finalize)
shelver.expect('Apply change? [yNfq?]', 'y')
shelver.expect('Apply change? [yNfq?]', 'y')
shelver.expect('Apply 2 change(s)? [yNfq?]', 'y')
@@ -353,6 +373,7 @@
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree(),
reporter=shelf_ui.ApplyReporter())
+ self.addCleanup(shelver.finalize)
shelver.expect('Apply binary changes? [yNfq?]', 'y')
shelver.expect('Apply 1 change(s)? [yNfq?]', 'y')
shelver.run()
@@ -365,6 +386,7 @@
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree(),
reporter=shelf_ui.ApplyReporter())
+ self.addCleanup(shelver.finalize)
shelver.expect('Rename "bar" => "foo"? [yNfq?]', 'y')
shelver.expect('Apply change? [yNfq?]', 'y')
shelver.expect('Apply change? [yNfq?]', 'y')
@@ -379,6 +401,7 @@
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree(),
reporter=shelf_ui.ApplyReporter())
+ self.addCleanup(shelver.finalize)
shelver.expect('Add file "foo"? [yNfq?]', 'y')
shelver.expect('Apply 1 change(s)? [yNfq?]', 'y')
shelver.run()
@@ -393,6 +416,7 @@
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree(),
reporter=shelf_ui.ApplyReporter())
+ self.addCleanup(shelver.finalize)
shelver.expect('Delete file "foo"? [yNfq?]', 'y')
shelver.expect('Apply 1 change(s)? [yNfq?]', 'y')
shelver.run()
@@ -406,6 +430,7 @@
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree(),
reporter=shelf_ui.ApplyReporter())
+ self.addCleanup(shelver.finalize)
shelver.expect('Change "foo" from directory to a file? [yNfq?]', 'y')
shelver.expect('Apply 1 change(s)? [yNfq?]', 'y')
@@ -421,6 +446,7 @@
self.addCleanup(tree.unlock)
shelver = ExpectShelver(tree, tree.basis_tree(),
reporter=shelf_ui.ApplyReporter())
+ self.addCleanup(shelver.finalize)
shelver.expect('Change target of "baz" from "vax" to "bar"? [yNfq?]',
'y')
shelver.expect('Apply 1 change(s)? [yNfq?]', 'y')
@@ -438,8 +464,12 @@
tree.add('foo', 'foo-id')
tree.commit('added foo')
self.build_tree_contents([('tree/foo', LINES_ZY)])
- shelf_ui.Shelver(tree, tree.basis_tree(), auto_apply=True,
- auto=True).run()
+ shelver = shelf_ui.Shelver(tree, tree.basis_tree(),
+ auto_apply=True, auto=True)
+ try:
+ shelver.run()
+ finally:
+ shelver.finalize()
finally:
tree.unlock()
return tree
More information about the bazaar-commits
mailing list