~bzr-pqm/bzr/bzr.dev

0.16.101 by Aaron Bentley
Update GPL formatting and copyright
1
# Copyright (C) 2008 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
0.16.1 by Aaron Bentley
Begin implementing UI
16
17
18
from cStringIO import StringIO
0.16.5 by Aaron Bentley
Get text shelving working
19
import shutil
0.16.1 by Aaron Bentley
Begin implementing UI
20
import sys
0.16.5 by Aaron Bentley
Get text shelving working
21
import tempfile
0.16.1 by Aaron Bentley
Begin implementing UI
22
0.16.25 by Aaron Bentley
Show selected changes before shelving
23
from bzrlib import (
24
    builtins,
25
    delta,
26
    diff,
27
    errors,
0.16.79 by Aaron Bentley
Remove dependencies on bzrtools
28
    osutils,
0.16.25 by Aaron Bentley
Show selected changes before shelving
29
    patches,
0.16.74 by Aaron Bentley
Merge with shelf-manager
30
    shelf,
0.16.72 by Aaron Bentley
Allow shelving binary changes
31
    textfile,
0.16.54 by Aaron Bentley
Inform user about shelf ids.
32
    trace,
0.16.64 by Aaron Bentley
Implement dry-run option for Unshelve
33
    ui,
0.16.102 by Aaron Bentley
Minor updates
34
    workingtree,
35
)
3835.2.6 by Aaron Bentley
Restore vila's colordiff change
36
37
4459.4.1 by Aaron Bentley
Provide control over switch and shelver messaging.
38
class ShelfReporter(object):
4526.7.2 by Aaron Bentley
Update docs.
39
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
40
    vocab = {'add file': 'Shelve adding file "%(path)s"?',
41
             'binary': 'Shelve binary changes?',
42
             'change kind': 'Shelve changing "%s" from %(other)s'
43
             ' to %(this)s?',
44
             'delete file': 'Shelve removing file "%(path)s"?',
45
             'final': 'Shelve %d change(s)?',
46
             'hunk': 'Shelve?',
47
             'modify target': 'Shelve changing target of'
48
             ' "%(path)s" from "%(other)s" to "%(this)s"?',
49
             'rename': 'Shelve renaming "%(other)s" =>'
50
                        ' "%(this)s"?'
51
             }
52
53
    invert_diff = False
4459.4.1 by Aaron Bentley
Provide control over switch and shelver messaging.
54
55
    def __init__(self):
56
        self.delta_reporter = delta._ChangeReporter()
57
58
    def no_changes(self):
4526.7.2 by Aaron Bentley
Update docs.
59
        """Report that no changes were selected to apply."""
4459.4.1 by Aaron Bentley
Provide control over switch and shelver messaging.
60
        trace.warning('No changes to shelve.')
61
62
    def shelved_id(self, shelf_id):
4526.7.2 by Aaron Bentley
Update docs.
63
        """Report the id changes were shelved to."""
4459.4.1 by Aaron Bentley
Provide control over switch and shelver messaging.
64
        trace.note('Changes shelved with id "%d".' % shelf_id)
65
4526.6.4 by Aaron Bentley
Remove changes_destroyed message.
66
    def changes_destroyed(self):
4526.7.2 by Aaron Bentley
Update docs.
67
        """Report that changes were made without shelving."""
4526.6.4 by Aaron Bentley
Remove changes_destroyed message.
68
        trace.note('Selected changes destroyed.')
69
4459.4.1 by Aaron Bentley
Provide control over switch and shelver messaging.
70
    def selected_changes(self, transform):
4526.7.2 by Aaron Bentley
Update docs.
71
        """Report the changes that were selected."""
4459.4.1 by Aaron Bentley
Provide control over switch and shelver messaging.
72
        trace.note("Selected changes:")
73
        changes = transform.iter_changes()
74
        delta.report_changes(changes, self.delta_reporter)
75
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
76
    def prompt_change(self, change):
4526.7.2 by Aaron Bentley
Update docs.
77
        """Determine the prompt for a change to apply."""
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
78
        if change[0] == 'rename':
79
            vals = {'this': change[3], 'other': change[2]}
80
        elif change[0] == 'change kind':
81
            vals = {'path': change[4], 'other': change[2], 'this': change[3]}
82
        elif change[0] == 'modify target':
83
            vals = {'path': change[2], 'other': change[3], 'this': change[4]}
84
        else:
85
            vals = {'path': change[3]}
86
        prompt = self.vocab[change[0]] % vals
87
        return prompt
88
89
90
class ApplyReporter(ShelfReporter):
91
92
    vocab = {'add file': 'Delete file "%(path)s"?',
93
             'binary': 'Apply binary changes?',
94
             'change kind': 'Change "%(path)s" from %(this)s'
95
             ' to %(other)s?',
96
             'delete file': 'Add file "%(path)s"?',
97
             'final': 'Apply %d change(s)?',
98
             'hunk': 'Apply change?',
99
             'modify target': 'Change target of'
100
             ' "%(path)s" from "%(this)s" to "%(other)s"?',
101
             'rename': 'Rename "%(this)s" => "%(other)s"?',
102
             }
103
104
    invert_diff = True
105
106
    def changes_destroyed(self):
107
        pass
108
4459.4.1 by Aaron Bentley
Provide control over switch and shelver messaging.
109
0.16.1 by Aaron Bentley
Begin implementing UI
110
class Shelver(object):
0.16.97 by Aaron Bentley
Turn diff_file and text_differ into instance variables.
111
    """Interactively shelve the changes in a working tree."""
0.16.1 by Aaron Bentley
Begin implementing UI
112
0.16.108 by Aaron Bentley
Shelf supports multiple diff writers.
113
    def __init__(self, work_tree, target_tree, diff_writer=None, auto=False,
4100.3.1 by Aaron Bentley
Implement shelve --destroy
114
                 auto_apply=False, file_list=None, message=None,
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
115
                 destroy=False, manager=None, reporter=None):
0.16.97 by Aaron Bentley
Turn diff_file and text_differ into instance variables.
116
        """Constructor.
117
118
        :param work_tree: The working tree to shelve changes from.
119
        :param target_tree: The "unchanged" / old tree to compare the
120
            work_tree to.
121
        :param auto: If True, shelve each possible change.
122
        :param auto_apply: If True, shelve changes with no final prompt.
0.16.102 by Aaron Bentley
Minor updates
123
        :param file_list: If supplied, only files in this list may be shelved.
0.16.97 by Aaron Bentley
Turn diff_file and text_differ into instance variables.
124
        :param message: The message to associate with the shelved changes.
4100.3.2 by Aaron Bentley
Update docs
125
        :param destroy: Change the working tree without storing the shelved
126
            changes.
4465.1.2 by Aaron Bentley
Accept manager as a parameter to Shelver()
127
        :param manager: The shelf manager to use.
4526.7.2 by Aaron Bentley
Update docs.
128
        :param reporter: Object for reporting changes to user.
0.16.97 by Aaron Bentley
Turn diff_file and text_differ into instance variables.
129
        """
0.16.1 by Aaron Bentley
Begin implementing UI
130
        self.work_tree = work_tree
131
        self.target_tree = target_tree
0.16.108 by Aaron Bentley
Shelf supports multiple diff writers.
132
        self.diff_writer = diff_writer
133
        if self.diff_writer is None:
0.16.79 by Aaron Bentley
Remove dependencies on bzrtools
134
            self.diff_writer = sys.stdout
4465.1.2 by Aaron Bentley
Accept manager as a parameter to Shelver()
135
        if manager is None:
136
            manager = work_tree.get_shelf_manager()
137
        self.manager = manager
0.16.15 by Aaron Bentley
Implement auto mode
138
        self.auto = auto
0.16.23 by Aaron Bentley
Improve prompting
139
        self.auto_apply = auto_apply
0.16.47 by Aaron Bentley
Support selecting files to shelve
140
        self.file_list = file_list
0.16.57 by Aaron Bentley
Expose messages in the UI
141
        self.message = message
4100.3.1 by Aaron Bentley
Implement shelve --destroy
142
        self.destroy = destroy
4459.4.1 by Aaron Bentley
Provide control over switch and shelver messaging.
143
        if reporter is None:
144
            reporter = ShelfReporter()
145
        self.reporter = reporter
0.16.1 by Aaron Bentley
Begin implementing UI
146
147
    @classmethod
0.16.108 by Aaron Bentley
Shelf supports multiple diff writers.
148
    def from_args(klass, diff_writer, revision=None, all=False, file_list=None,
4100.3.1 by Aaron Bentley
Implement shelve --destroy
149
                  message=None, directory='.', destroy=False):
0.16.97 by Aaron Bentley
Turn diff_file and text_differ into instance variables.
150
        """Create a shelver from commandline arguments.
151
152
        :param revision: RevisionSpec of the revision to compare to.
153
        :param all: If True, shelve all changes without prompting.
154
        :param file_list: If supplied, only files in this list may be  shelved.
155
        :param message: The message to associate with the shelved changes.
156
        :param directory: The directory containing the working tree.
4100.3.1 by Aaron Bentley
Implement shelve --destroy
157
        :param destroy: Change the working tree without storing the shelved
158
            changes.
0.16.97 by Aaron Bentley
Turn diff_file and text_differ into instance variables.
159
        """
0.16.94 by Aaron Bentley
Add unshelve tests
160
        tree, path = workingtree.WorkingTree.open_containing(directory)
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
161
        target_tree = builtins._get_one_revision_tree('shelf2', revision,
162
            tree.branch, tree)
0.16.120 by Aaron Bentley
Use relative paths with shelve
163
        files = builtins.safe_relpath_files(tree, file_list)
4100.3.1 by Aaron Bentley
Implement shelve --destroy
164
        return klass(tree, target_tree, diff_writer, all, all, files, message,
165
                     destroy)
0.16.1 by Aaron Bentley
Begin implementing UI
166
167
    def run(self):
0.16.97 by Aaron Bentley
Turn diff_file and text_differ into instance variables.
168
        """Interactively shelve the changes."""
0.16.47 by Aaron Bentley
Support selecting files to shelve
169
        creator = shelf.ShelfCreator(self.work_tree, self.target_tree,
170
                                     self.file_list)
0.16.5 by Aaron Bentley
Get text shelving working
171
        self.tempdir = tempfile.mkdtemp()
0.16.22 by Aaron Bentley
Only prompt when there are changes to shelve.
172
        changes_shelved = 0
0.16.1 by Aaron Bentley
Begin implementing UI
173
        try:
0.16.86 by Aaron Bentley
Switch to iter_shelvable
174
            for change in creator.iter_shelvable():
0.16.5 by Aaron Bentley
Get text shelving working
175
                if change[0] == 'modify text':
0.16.72 by Aaron Bentley
Allow shelving binary changes
176
                    try:
177
                        changes_shelved += self.handle_modify_text(creator,
178
                                                                   change[1])
179
                    except errors.BinaryFile:
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
180
                        if self.prompt_bool(self.reporter.vocab['binary']):
0.16.72 by Aaron Bentley
Allow shelving binary changes
181
                            changes_shelved += 1
182
                            creator.shelve_content_change(change[1])
4526.6.1 by Aaron Bentley
Reverse the way changes are described by Shelver.
183
                else:
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
184
                    if self.prompt_bool(self.reporter.prompt_change(change)):
4526.6.1 by Aaron Bentley
Reverse the way changes are described by Shelver.
185
                        creator.shelve_change(change)
4119.5.1 by James Westby
Shelve can now shelve changes to a symlink's target.
186
                        changes_shelved += 1
0.16.22 by Aaron Bentley
Only prompt when there are changes to shelve.
187
            if changes_shelved > 0:
4459.4.1 by Aaron Bentley
Provide control over switch and shelver messaging.
188
                self.reporter.selected_changes(creator.work_transform)
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
189
                if (self.auto_apply or self.prompt_bool(
190
                    self.reporter.vocab['final'] % changes_shelved)):
4100.3.1 by Aaron Bentley
Implement shelve --destroy
191
                    if self.destroy:
192
                        creator.transform()
4526.6.4 by Aaron Bentley
Remove changes_destroyed message.
193
                        self.reporter.changes_destroyed()
4100.3.1 by Aaron Bentley
Implement shelve --destroy
194
                    else:
195
                        shelf_id = self.manager.shelve_changes(creator,
196
                                                               self.message)
4459.4.1 by Aaron Bentley
Provide control over switch and shelver messaging.
197
                        self.reporter.shelved_id(shelf_id)
0.16.22 by Aaron Bentley
Only prompt when there are changes to shelve.
198
            else:
4459.4.1 by Aaron Bentley
Provide control over switch and shelver messaging.
199
                self.reporter.no_changes()
0.16.1 by Aaron Bentley
Begin implementing UI
200
        finally:
0.16.5 by Aaron Bentley
Get text shelving working
201
            shutil.rmtree(self.tempdir)
0.16.1 by Aaron Bentley
Begin implementing UI
202
            creator.finalize()
203
4526.6.2 by Aaron Bentley
Fix display of diffs for apply mode
204
    def get_parsed_patch(self, file_id, invert=False):
0.16.98 by Aaron Bentley
Update docs and prompting
205
        """Return a parsed version of a file's patch.
206
207
        :param file_id: The id of the file to generate a patch for.
4526.7.2 by Aaron Bentley
Update docs.
208
        :param invert: If True, provide an inverted patch (insertions displayed
209
            as removals, removals displayed as insertions).
0.16.98 by Aaron Bentley
Update docs and prompting
210
        :return: A patches.Patch.
211
        """
0.16.97 by Aaron Bentley
Turn diff_file and text_differ into instance variables.
212
        diff_file = StringIO()
4526.6.2 by Aaron Bentley
Fix display of diffs for apply mode
213
        if invert:
214
            old_tree = self.work_tree
215
            new_tree = self.target_tree
216
        else:
217
            old_tree = self.target_tree
218
            new_tree = self.work_tree
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
219
        old_path = old_tree.id2path(file_id)
220
        new_path = new_tree.id2path(file_id)
4526.6.2 by Aaron Bentley
Fix display of diffs for apply mode
221
        text_differ = diff.DiffText(old_tree, new_tree, diff_file)
0.16.97 by Aaron Bentley
Turn diff_file and text_differ into instance variables.
222
        patch = text_differ.diff(file_id, old_path, new_path, 'file', 'file')
223
        diff_file.seek(0)
224
        return patches.parse_patch(diff_file)
0.16.1 by Aaron Bentley
Begin implementing UI
225
0.16.89 by Aaron Bentley
Add tests for Shelver
226
    def prompt(self, message):
0.16.98 by Aaron Bentley
Update docs and prompting
227
        """Prompt the user for a character.
228
229
        :param message: The message to prompt a user with.
230
        :return: A character.
231
        """
0.16.89 by Aaron Bentley
Add tests for Shelver
232
        sys.stdout.write(message)
233
        char = osutils.getchar()
234
        sys.stdout.write("\r" + ' ' * len(message) + '\r')
235
        sys.stdout.flush()
236
        return char
237
3990.4.3 by Daniel Watkins
Added help option to shelve prompt.
238
    def prompt_bool(self, question, long=False):
0.16.98 by Aaron Bentley
Update docs and prompting
239
        """Prompt the user with a yes/no question.
240
0.16.102 by Aaron Bentley
Minor updates
241
        This may be overridden by self.auto.  It may also *set* self.auto.  It
0.16.103 by Aaron Bentley
raise UserAbort instead of doing sys.exit
242
        may also raise UserAbort.
0.16.98 by Aaron Bentley
Update docs and prompting
243
        :param question: The question to ask the user.
244
        :return: True or False
245
        """
246
        if self.auto:
0.16.23 by Aaron Bentley
Improve prompting
247
            return True
3990.4.3 by Daniel Watkins
Added help option to shelve prompt.
248
        if long:
249
            prompt = ' [(y)es, (N)o, (f)inish, or (q)uit]'
250
        else:
251
            prompt = ' [yNfq?]'
252
        char = self.prompt(question + prompt)
0.16.23 by Aaron Bentley
Improve prompting
253
        if char == 'y':
254
            return True
255
        elif char == 'f':
256
            self.auto = True
257
            return True
3990.4.3 by Daniel Watkins
Added help option to shelve prompt.
258
        elif char == '?':
259
            return self.prompt_bool(question, long=True)
0.16.24 by Aaron Bentley
Regularize prompts
260
        if char == 'q':
0.16.103 by Aaron Bentley
raise UserAbort instead of doing sys.exit
261
            raise errors.UserAbort()
0.16.23 by Aaron Bentley
Improve prompting
262
        else:
263
            return False
0.16.1 by Aaron Bentley
Begin implementing UI
264
0.16.5 by Aaron Bentley
Get text shelving working
265
    def handle_modify_text(self, creator, file_id):
0.16.98 by Aaron Bentley
Update docs and prompting
266
        """Provide diff hunk selection for modified text.
267
4526.7.2 by Aaron Bentley
Update docs.
268
        If self.reporter.invert_diff is True, the diff is inverted so that
269
        insertions are displayed as removals and vice versa.
270
0.16.98 by Aaron Bentley
Update docs and prompting
271
        :param creator: a ShelfCreator
272
        :param file_id: The id of the file to shelve.
273
        :return: number of shelved hunks.
274
        """
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
275
        if self.reporter.invert_diff:
4526.6.2 by Aaron Bentley
Fix display of diffs for apply mode
276
            target_lines = self.work_tree.get_file_lines(file_id)
277
        else:
278
            target_lines = self.target_tree.get_file_lines(file_id)
0.16.102 by Aaron Bentley
Minor updates
279
        textfile.check_text_lines(self.work_tree.get_file_lines(file_id))
0.16.72 by Aaron Bentley
Allow shelving binary changes
280
        textfile.check_text_lines(target_lines)
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
281
        parsed = self.get_parsed_patch(file_id, self.reporter.invert_diff)
0.16.43 by Aaron Bentley
Reduce API friction.
282
        final_hunks = []
0.16.15 by Aaron Bentley
Implement auto mode
283
        if not self.auto:
0.16.41 by Aaron Bentley
Implement shelving with internal patch
284
            offset = 0
0.16.61 by Aaron Bentley
Show file name when shelving
285
            self.diff_writer.write(parsed.get_header())
0.16.15 by Aaron Bentley
Implement auto mode
286
            for hunk in parsed.hunks:
287
                self.diff_writer.write(str(hunk))
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
288
                selected = self.prompt_bool(self.reporter.vocab['hunk'])
289
                if not self.reporter.invert_diff:
4526.6.2 by Aaron Bentley
Fix display of diffs for apply mode
290
                    selected = (not selected)
291
                if selected:
0.16.41 by Aaron Bentley
Implement shelving with internal patch
292
                    hunk.mod_pos += offset
0.16.43 by Aaron Bentley
Reduce API friction.
293
                    final_hunks.append(hunk)
0.16.41 by Aaron Bentley
Implement shelving with internal patch
294
                else:
295
                    offset -= (hunk.mod_range - hunk.orig_range)
0.16.68 by Aaron Bentley
Avoid having escape codes affect the wrong text.
296
        sys.stdout.flush()
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
297
        if not self.reporter.invert_diff and (
298
            len(parsed.hunks) == len(final_hunks)):
4526.6.2 by Aaron Bentley
Fix display of diffs for apply mode
299
            return 0
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
300
        if self.reporter.invert_diff and len(final_hunks) == 0:
0.16.62 by Aaron Bentley
Make status nicer by not shelving lines for files not being changed
301
            return 0
0.16.43 by Aaron Bentley
Reduce API friction.
302
        patched = patches.iter_patched_from_hunks(target_lines, final_hunks)
0.16.45 by Aaron Bentley
switch to shelve_lines
303
        creator.shelve_lines(file_id, list(patched))
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
304
        if self.reporter.invert_diff:
4526.6.2 by Aaron Bentley
Fix display of diffs for apply mode
305
            return len(final_hunks)
0.16.43 by Aaron Bentley
Reduce API friction.
306
        return len(parsed.hunks) - len(final_hunks)
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
307
308
309
class Unshelver(object):
0.16.98 by Aaron Bentley
Update docs and prompting
310
    """Unshelve changes into a working tree."""
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
311
312
    @classmethod
0.16.94 by Aaron Bentley
Add unshelve tests
313
    def from_args(klass, shelf_id=None, action='apply', directory='.'):
0.16.98 by Aaron Bentley
Update docs and prompting
314
        """Create an unshelver from commandline arguments.
315
316
        :param shelf_id: Integer id of the shelf, as a string.
317
        :param action: action to perform.  May be 'apply', 'dry-run',
318
            'delete'.
319
        :param directory: The directory to unshelve changes into.
320
        """
0.16.94 by Aaron Bentley
Add unshelve tests
321
        tree, path = workingtree.WorkingTree.open_containing(directory)
0.16.40 by Aaron Bentley
Update for ShelfManager API changes
322
        manager = tree.get_shelf_manager()
0.16.52 by Aaron Bentley
Allow user-specified shelves
323
        if shelf_id is not None:
3990.2.4 by Daniel Watkins
Don't stack trace with an invalid shelf id.
324
            try:
325
                shelf_id = int(shelf_id)
326
            except ValueError:
327
                raise errors.InvalidShelfId(shelf_id)
0.16.52 by Aaron Bentley
Allow user-specified shelves
328
        else:
329
            shelf_id = manager.last_shelf()
330
            if shelf_id is None:
331
                raise errors.BzrCommandError('No changes are shelved.')
0.16.54 by Aaron Bentley
Inform user about shelf ids.
332
            trace.note('Unshelving changes with id "%d".' % shelf_id)
0.16.64 by Aaron Bentley
Implement dry-run option for Unshelve
333
        apply_changes = True
334
        delete_shelf = True
0.16.65 by Aaron Bentley
Implement unshelve --delete
335
        read_shelf = True
336
        if action == 'dry-run':
0.16.64 by Aaron Bentley
Implement dry-run option for Unshelve
337
            apply_changes = False
338
            delete_shelf = False
0.16.65 by Aaron Bentley
Implement unshelve --delete
339
        if action == 'delete-only':
340
            apply_changes = False
341
            read_shelf = False
342
        return klass(tree, manager, shelf_id, apply_changes, delete_shelf,
343
                     read_shelf)
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
344
0.16.94 by Aaron Bentley
Add unshelve tests
345
    def __init__(self, tree, manager, shelf_id, apply_changes=True,
346
                 delete_shelf=True, read_shelf=True):
0.16.98 by Aaron Bentley
Update docs and prompting
347
        """Constructor.
348
349
        :param tree: The working tree to unshelve into.
350
        :param manager: The ShelveManager containing the shelved changes.
351
        :param shelf_id:
352
        :param apply_changes: If True, apply the shelved changes to the
353
            working tree.
354
        :param delete_shelf: If True, delete the changes from the shelf.
355
        :param read_shelf: If True, read the changes from the shelf.
356
        """
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
357
        self.tree = tree
0.16.98 by Aaron Bentley
Update docs and prompting
358
        manager = tree.get_shelf_manager()
0.16.13 by Aaron Bentley
Appy shelve-management updates to shelver
359
        self.manager = manager
360
        self.shelf_id = shelf_id
0.16.64 by Aaron Bentley
Implement dry-run option for Unshelve
361
        self.apply_changes = apply_changes
362
        self.delete_shelf = delete_shelf
0.16.65 by Aaron Bentley
Implement unshelve --delete
363
        self.read_shelf = read_shelf
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
364
365
    def run(self):
0.16.98 by Aaron Bentley
Update docs and prompting
366
        """Perform the unshelving operation."""
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
367
        self.tree.lock_write()
0.16.37 by Aaron Bentley
Use cleanups list to reduce nested try blocks
368
        cleanups = [self.tree.unlock]
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
369
        try:
0.16.65 by Aaron Bentley
Implement unshelve --delete
370
            if self.read_shelf:
371
                unshelver = self.manager.get_unshelver(self.shelf_id)
372
                cleanups.append(unshelver.finalize)
373
                if unshelver.message is not None:
374
                    trace.note('Message: %s' % unshelver.message)
375
                change_reporter = delta._ChangeReporter()
1551.21.7 by Aaron Bentley
Fix progress warning
376
                task = ui.ui_factory.nested_progress_bar()
377
                try:
378
                    merger = unshelver.make_merger(task)
379
                    merger.change_reporter = change_reporter
380
                    if self.apply_changes:
0.16.65 by Aaron Bentley
Implement unshelve --delete
381
                        merger.do_merge()
1551.21.7 by Aaron Bentley
Fix progress warning
382
                    else:
383
                        self.show_changes(merger)
384
                finally:
385
                    task.finished()
0.16.64 by Aaron Bentley
Implement dry-run option for Unshelve
386
            if self.delete_shelf:
387
                self.manager.delete_shelf(self.shelf_id)
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
388
        finally:
0.16.37 by Aaron Bentley
Use cleanups list to reduce nested try blocks
389
            for cleanup in reversed(cleanups):
390
                cleanup()
0.16.64 by Aaron Bentley
Implement dry-run option for Unshelve
391
392
    def show_changes(self, merger):
0.16.98 by Aaron Bentley
Update docs and prompting
393
        """Show the changes that this operation specifies."""
0.16.64 by Aaron Bentley
Implement dry-run option for Unshelve
394
        tree_merger = merger.make_merger()
395
        # This implicitly shows the changes via the reporter, so we're done...
396
        tt = tree_merger.make_preview_transform()
397
        tt.finalize()