~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
4595.13.2 by Alexander Belchenko
[cherrypick revno 4650 from bzr.dev] Fix shelve on windows. (Robert Collins, #305006)
152
        The returned shelver wil have a work_tree that is locked and should
153
        be unlocked.
154
0.16.97 by Aaron Bentley
Turn diff_file and text_differ into instance variables.
155
        :param revision: RevisionSpec of the revision to compare to.
156
        :param all: If True, shelve all changes without prompting.
157
        :param file_list: If supplied, only files in this list may be  shelved.
158
        :param message: The message to associate with the shelved changes.
159
        :param directory: The directory containing the working tree.
4100.3.1 by Aaron Bentley
Implement shelve --destroy
160
        :param destroy: Change the working tree without storing the shelved
161
            changes.
0.16.97 by Aaron Bentley
Turn diff_file and text_differ into instance variables.
162
        """
0.16.94 by Aaron Bentley
Add unshelve tests
163
        tree, path = workingtree.WorkingTree.open_containing(directory)
4595.13.2 by Alexander Belchenko
[cherrypick revno 4650 from bzr.dev] Fix shelve on windows. (Robert Collins, #305006)
164
        # Ensure that tree is locked for the lifetime of target_tree, as
165
        # target tree may be reading from the same dirstate.
166
        tree.lock_tree_write()
167
        try:
168
            target_tree = builtins._get_one_revision_tree('shelf2', revision,
169
                tree.branch, tree)
170
            files = builtins.safe_relpath_files(tree, file_list)
171
        except:
172
            tree.unlock()
173
            raise
4100.3.1 by Aaron Bentley
Implement shelve --destroy
174
        return klass(tree, target_tree, diff_writer, all, all, files, message,
175
                     destroy)
0.16.1 by Aaron Bentley
Begin implementing UI
176
177
    def run(self):
0.16.97 by Aaron Bentley
Turn diff_file and text_differ into instance variables.
178
        """Interactively shelve the changes."""
0.16.47 by Aaron Bentley
Support selecting files to shelve
179
        creator = shelf.ShelfCreator(self.work_tree, self.target_tree,
180
                                     self.file_list)
0.16.5 by Aaron Bentley
Get text shelving working
181
        self.tempdir = tempfile.mkdtemp()
0.16.22 by Aaron Bentley
Only prompt when there are changes to shelve.
182
        changes_shelved = 0
0.16.1 by Aaron Bentley
Begin implementing UI
183
        try:
0.16.86 by Aaron Bentley
Switch to iter_shelvable
184
            for change in creator.iter_shelvable():
0.16.5 by Aaron Bentley
Get text shelving working
185
                if change[0] == 'modify text':
0.16.72 by Aaron Bentley
Allow shelving binary changes
186
                    try:
187
                        changes_shelved += self.handle_modify_text(creator,
188
                                                                   change[1])
189
                    except errors.BinaryFile:
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
190
                        if self.prompt_bool(self.reporter.vocab['binary']):
0.16.72 by Aaron Bentley
Allow shelving binary changes
191
                            changes_shelved += 1
192
                            creator.shelve_content_change(change[1])
4526.6.1 by Aaron Bentley
Reverse the way changes are described by Shelver.
193
                else:
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
194
                    if self.prompt_bool(self.reporter.prompt_change(change)):
4526.6.1 by Aaron Bentley
Reverse the way changes are described by Shelver.
195
                        creator.shelve_change(change)
4119.5.1 by James Westby
Shelve can now shelve changes to a symlink's target.
196
                        changes_shelved += 1
0.16.22 by Aaron Bentley
Only prompt when there are changes to shelve.
197
            if changes_shelved > 0:
4459.4.1 by Aaron Bentley
Provide control over switch and shelver messaging.
198
                self.reporter.selected_changes(creator.work_transform)
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
199
                if (self.auto_apply or self.prompt_bool(
200
                    self.reporter.vocab['final'] % changes_shelved)):
4100.3.1 by Aaron Bentley
Implement shelve --destroy
201
                    if self.destroy:
202
                        creator.transform()
4526.6.4 by Aaron Bentley
Remove changes_destroyed message.
203
                        self.reporter.changes_destroyed()
4100.3.1 by Aaron Bentley
Implement shelve --destroy
204
                    else:
205
                        shelf_id = self.manager.shelve_changes(creator,
206
                                                               self.message)
4459.4.1 by Aaron Bentley
Provide control over switch and shelver messaging.
207
                        self.reporter.shelved_id(shelf_id)
0.16.22 by Aaron Bentley
Only prompt when there are changes to shelve.
208
            else:
4459.4.1 by Aaron Bentley
Provide control over switch and shelver messaging.
209
                self.reporter.no_changes()
0.16.1 by Aaron Bentley
Begin implementing UI
210
        finally:
0.16.5 by Aaron Bentley
Get text shelving working
211
            shutil.rmtree(self.tempdir)
0.16.1 by Aaron Bentley
Begin implementing UI
212
            creator.finalize()
213
4526.6.2 by Aaron Bentley
Fix display of diffs for apply mode
214
    def get_parsed_patch(self, file_id, invert=False):
0.16.98 by Aaron Bentley
Update docs and prompting
215
        """Return a parsed version of a file's patch.
216
217
        :param file_id: The id of the file to generate a patch for.
4526.7.2 by Aaron Bentley
Update docs.
218
        :param invert: If True, provide an inverted patch (insertions displayed
219
            as removals, removals displayed as insertions).
0.16.98 by Aaron Bentley
Update docs and prompting
220
        :return: A patches.Patch.
221
        """
0.16.97 by Aaron Bentley
Turn diff_file and text_differ into instance variables.
222
        diff_file = StringIO()
4526.6.2 by Aaron Bentley
Fix display of diffs for apply mode
223
        if invert:
224
            old_tree = self.work_tree
225
            new_tree = self.target_tree
226
        else:
227
            old_tree = self.target_tree
228
            new_tree = self.work_tree
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
229
        old_path = old_tree.id2path(file_id)
230
        new_path = new_tree.id2path(file_id)
4526.6.2 by Aaron Bentley
Fix display of diffs for apply mode
231
        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.
232
        patch = text_differ.diff(file_id, old_path, new_path, 'file', 'file')
233
        diff_file.seek(0)
234
        return patches.parse_patch(diff_file)
0.16.1 by Aaron Bentley
Begin implementing UI
235
0.16.89 by Aaron Bentley
Add tests for Shelver
236
    def prompt(self, message):
0.16.98 by Aaron Bentley
Update docs and prompting
237
        """Prompt the user for a character.
238
239
        :param message: The message to prompt a user with.
240
        :return: A character.
241
        """
0.16.89 by Aaron Bentley
Add tests for Shelver
242
        sys.stdout.write(message)
243
        char = osutils.getchar()
244
        sys.stdout.write("\r" + ' ' * len(message) + '\r')
245
        sys.stdout.flush()
246
        return char
247
3990.4.3 by Daniel Watkins
Added help option to shelve prompt.
248
    def prompt_bool(self, question, long=False):
0.16.98 by Aaron Bentley
Update docs and prompting
249
        """Prompt the user with a yes/no question.
250
0.16.102 by Aaron Bentley
Minor updates
251
        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
252
        may also raise UserAbort.
0.16.98 by Aaron Bentley
Update docs and prompting
253
        :param question: The question to ask the user.
254
        :return: True or False
255
        """
256
        if self.auto:
0.16.23 by Aaron Bentley
Improve prompting
257
            return True
3990.4.3 by Daniel Watkins
Added help option to shelve prompt.
258
        if long:
259
            prompt = ' [(y)es, (N)o, (f)inish, or (q)uit]'
260
        else:
261
            prompt = ' [yNfq?]'
262
        char = self.prompt(question + prompt)
0.16.23 by Aaron Bentley
Improve prompting
263
        if char == 'y':
264
            return True
265
        elif char == 'f':
266
            self.auto = True
267
            return True
3990.4.3 by Daniel Watkins
Added help option to shelve prompt.
268
        elif char == '?':
269
            return self.prompt_bool(question, long=True)
0.16.24 by Aaron Bentley
Regularize prompts
270
        if char == 'q':
0.16.103 by Aaron Bentley
raise UserAbort instead of doing sys.exit
271
            raise errors.UserAbort()
0.16.23 by Aaron Bentley
Improve prompting
272
        else:
273
            return False
0.16.1 by Aaron Bentley
Begin implementing UI
274
0.16.5 by Aaron Bentley
Get text shelving working
275
    def handle_modify_text(self, creator, file_id):
0.16.98 by Aaron Bentley
Update docs and prompting
276
        """Provide diff hunk selection for modified text.
277
4526.7.2 by Aaron Bentley
Update docs.
278
        If self.reporter.invert_diff is True, the diff is inverted so that
279
        insertions are displayed as removals and vice versa.
280
0.16.98 by Aaron Bentley
Update docs and prompting
281
        :param creator: a ShelfCreator
282
        :param file_id: The id of the file to shelve.
283
        :return: number of shelved hunks.
284
        """
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
285
        if self.reporter.invert_diff:
4526.6.2 by Aaron Bentley
Fix display of diffs for apply mode
286
            target_lines = self.work_tree.get_file_lines(file_id)
287
        else:
288
            target_lines = self.target_tree.get_file_lines(file_id)
0.16.102 by Aaron Bentley
Minor updates
289
        textfile.check_text_lines(self.work_tree.get_file_lines(file_id))
0.16.72 by Aaron Bentley
Allow shelving binary changes
290
        textfile.check_text_lines(target_lines)
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
291
        parsed = self.get_parsed_patch(file_id, self.reporter.invert_diff)
0.16.43 by Aaron Bentley
Reduce API friction.
292
        final_hunks = []
0.16.15 by Aaron Bentley
Implement auto mode
293
        if not self.auto:
0.16.41 by Aaron Bentley
Implement shelving with internal patch
294
            offset = 0
0.16.61 by Aaron Bentley
Show file name when shelving
295
            self.diff_writer.write(parsed.get_header())
0.16.15 by Aaron Bentley
Implement auto mode
296
            for hunk in parsed.hunks:
297
                self.diff_writer.write(str(hunk))
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
298
                selected = self.prompt_bool(self.reporter.vocab['hunk'])
299
                if not self.reporter.invert_diff:
4526.6.2 by Aaron Bentley
Fix display of diffs for apply mode
300
                    selected = (not selected)
301
                if selected:
0.16.41 by Aaron Bentley
Implement shelving with internal patch
302
                    hunk.mod_pos += offset
0.16.43 by Aaron Bentley
Reduce API friction.
303
                    final_hunks.append(hunk)
0.16.41 by Aaron Bentley
Implement shelving with internal patch
304
                else:
305
                    offset -= (hunk.mod_range - hunk.orig_range)
0.16.68 by Aaron Bentley
Avoid having escape codes affect the wrong text.
306
        sys.stdout.flush()
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
307
        if not self.reporter.invert_diff and (
308
            len(parsed.hunks) == len(final_hunks)):
4526.6.2 by Aaron Bentley
Fix display of diffs for apply mode
309
            return 0
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
310
        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
311
            return 0
0.16.43 by Aaron Bentley
Reduce API friction.
312
        patched = patches.iter_patched_from_hunks(target_lines, final_hunks)
0.16.45 by Aaron Bentley
switch to shelve_lines
313
        creator.shelve_lines(file_id, list(patched))
4526.7.1 by Aaron Bentley
Make vocabulary part of reporter.
314
        if self.reporter.invert_diff:
4526.6.2 by Aaron Bentley
Fix display of diffs for apply mode
315
            return len(final_hunks)
0.16.43 by Aaron Bentley
Reduce API friction.
316
        return len(parsed.hunks) - len(final_hunks)
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
317
318
319
class Unshelver(object):
0.16.98 by Aaron Bentley
Update docs and prompting
320
    """Unshelve changes into a working tree."""
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
321
322
    @classmethod
0.16.94 by Aaron Bentley
Add unshelve tests
323
    def from_args(klass, shelf_id=None, action='apply', directory='.'):
0.16.98 by Aaron Bentley
Update docs and prompting
324
        """Create an unshelver from commandline arguments.
325
4595.13.2 by Alexander Belchenko
[cherrypick revno 4650 from bzr.dev] Fix shelve on windows. (Robert Collins, #305006)
326
        The returned shelver wil have a tree that is locked and should
327
        be unlocked.
328
0.16.98 by Aaron Bentley
Update docs and prompting
329
        :param shelf_id: Integer id of the shelf, as a string.
330
        :param action: action to perform.  May be 'apply', 'dry-run',
331
            'delete'.
332
        :param directory: The directory to unshelve changes into.
333
        """
0.16.94 by Aaron Bentley
Add unshelve tests
334
        tree, path = workingtree.WorkingTree.open_containing(directory)
4595.13.2 by Alexander Belchenko
[cherrypick revno 4650 from bzr.dev] Fix shelve on windows. (Robert Collins, #305006)
335
        tree.lock_tree_write()
336
        try:
337
            manager = tree.get_shelf_manager()
338
            if shelf_id is not None:
339
                try:
340
                    shelf_id = int(shelf_id)
341
                except ValueError:
342
                    raise errors.InvalidShelfId(shelf_id)
343
            else:
344
                shelf_id = manager.last_shelf()
345
                if shelf_id is None:
346
                    raise errors.BzrCommandError('No changes are shelved.')
347
                trace.note('Unshelving changes with id "%d".' % shelf_id)
348
            apply_changes = True
349
            delete_shelf = True
350
            read_shelf = True
351
            if action == 'dry-run':
352
                apply_changes = False
353
                delete_shelf = False
354
            if action == 'delete-only':
355
                apply_changes = False
356
                read_shelf = False
357
        except:
358
            tree.unlock()
359
            raise
0.16.65 by Aaron Bentley
Implement unshelve --delete
360
        return klass(tree, manager, shelf_id, apply_changes, delete_shelf,
361
                     read_shelf)
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
362
0.16.94 by Aaron Bentley
Add unshelve tests
363
    def __init__(self, tree, manager, shelf_id, apply_changes=True,
364
                 delete_shelf=True, read_shelf=True):
0.16.98 by Aaron Bentley
Update docs and prompting
365
        """Constructor.
366
367
        :param tree: The working tree to unshelve into.
368
        :param manager: The ShelveManager containing the shelved changes.
369
        :param shelf_id:
370
        :param apply_changes: If True, apply the shelved changes to the
371
            working tree.
372
        :param delete_shelf: If True, delete the changes from the shelf.
373
        :param read_shelf: If True, read the changes from the shelf.
374
        """
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
375
        self.tree = tree
0.16.98 by Aaron Bentley
Update docs and prompting
376
        manager = tree.get_shelf_manager()
0.16.13 by Aaron Bentley
Appy shelve-management updates to shelver
377
        self.manager = manager
378
        self.shelf_id = shelf_id
0.16.64 by Aaron Bentley
Implement dry-run option for Unshelve
379
        self.apply_changes = apply_changes
380
        self.delete_shelf = delete_shelf
0.16.65 by Aaron Bentley
Implement unshelve --delete
381
        self.read_shelf = read_shelf
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
382
383
    def run(self):
0.16.98 by Aaron Bentley
Update docs and prompting
384
        """Perform the unshelving operation."""
4595.13.2 by Alexander Belchenko
[cherrypick revno 4650 from bzr.dev] Fix shelve on windows. (Robert Collins, #305006)
385
        self.tree.lock_tree_write()
0.16.37 by Aaron Bentley
Use cleanups list to reduce nested try blocks
386
        cleanups = [self.tree.unlock]
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
387
        try:
0.16.65 by Aaron Bentley
Implement unshelve --delete
388
            if self.read_shelf:
389
                unshelver = self.manager.get_unshelver(self.shelf_id)
390
                cleanups.append(unshelver.finalize)
391
                if unshelver.message is not None:
392
                    trace.note('Message: %s' % unshelver.message)
393
                change_reporter = delta._ChangeReporter()
1551.21.7 by Aaron Bentley
Fix progress warning
394
                task = ui.ui_factory.nested_progress_bar()
395
                try:
396
                    merger = unshelver.make_merger(task)
397
                    merger.change_reporter = change_reporter
398
                    if self.apply_changes:
0.16.65 by Aaron Bentley
Implement unshelve --delete
399
                        merger.do_merge()
1551.21.7 by Aaron Bentley
Fix progress warning
400
                    else:
401
                        self.show_changes(merger)
402
                finally:
403
                    task.finished()
0.16.64 by Aaron Bentley
Implement dry-run option for Unshelve
404
            if self.delete_shelf:
405
                self.manager.delete_shelf(self.shelf_id)
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
406
        finally:
0.16.37 by Aaron Bentley
Use cleanups list to reduce nested try blocks
407
            for cleanup in reversed(cleanups):
408
                cleanup()
0.16.64 by Aaron Bentley
Implement dry-run option for Unshelve
409
410
    def show_changes(self, merger):
0.16.98 by Aaron Bentley
Update docs and prompting
411
        """Show the changes that this operation specifies."""
0.16.64 by Aaron Bentley
Implement dry-run option for Unshelve
412
        tree_merger = merger.make_merger()
413
        # This implicitly shows the changes via the reporter, so we're done...
414
        tt = tree_merger.make_preview_transform()
415
        tt.finalize()