/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.16.1 by Aaron Bentley
Begin implementing UI
1
# Copyright (C) 2008 Aaron Bentley <aaron@aaronbentley.com>
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
15
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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.25 by Aaron Bentley
Show selected changes before shelving
34
    workingtree)
0.16.79 by Aaron Bentley
Remove dependencies on bzrtools
35
try:
36
    from bzrlib.plugins.bzrtools import colordiff
37
except ImportError:
38
    colordiff = None
0.16.1 by Aaron Bentley
Begin implementing UI
39
40
41
class Shelver(object):
42
0.16.23 by Aaron Bentley
Improve prompting
43
    def __init__(self, work_tree, target_tree, path, auto=False,
0.16.57 by Aaron Bentley
Expose messages in the UI
44
                 auto_apply=False, file_list=None, message=None):
0.16.1 by Aaron Bentley
Begin implementing UI
45
        self.work_tree = work_tree
46
        self.target_tree = target_tree
47
        self.path = path
48
        self.diff_file = StringIO()
0.16.5 by Aaron Bentley
Get text shelving working
49
        self.text_differ = diff.DiffText(self.target_tree, self.work_tree,
0.16.1 by Aaron Bentley
Begin implementing UI
50
                                         self.diff_file)
0.16.79 by Aaron Bentley
Remove dependencies on bzrtools
51
        if colordiff is not None:
52
            self.diff_writer = colordiff.DiffWriter(sys.stdout, False)
53
        else:
54
            self.diff_writer = sys.stdout
0.16.40 by Aaron Bentley
Update for ShelfManager API changes
55
        self.manager = work_tree.get_shelf_manager()
0.16.15 by Aaron Bentley
Implement auto mode
56
        self.auto = auto
0.16.23 by Aaron Bentley
Improve prompting
57
        self.auto_apply = auto_apply
0.16.47 by Aaron Bentley
Support selecting files to shelve
58
        self.file_list = file_list
0.16.57 by Aaron Bentley
Expose messages in the UI
59
        self.message = message
0.16.1 by Aaron Bentley
Begin implementing UI
60
61
    @classmethod
0.16.57 by Aaron Bentley
Expose messages in the UI
62
    def from_args(klass, revision=None, all=False, file_list=None,
63
                  message=None):
0.16.1 by Aaron Bentley
Begin implementing UI
64
        tree, path = workingtree.WorkingTree.open_containing('.')
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
65
        target_tree = builtins._get_one_revision_tree('shelf2', revision,
66
            tree.branch, tree)
0.16.57 by Aaron Bentley
Expose messages in the UI
67
        return klass(tree, target_tree, path, all, all, file_list, message)
0.16.1 by Aaron Bentley
Begin implementing UI
68
69
    def run(self):
0.16.47 by Aaron Bentley
Support selecting files to shelve
70
        creator = shelf.ShelfCreator(self.work_tree, self.target_tree,
71
                                     self.file_list)
0.16.5 by Aaron Bentley
Get text shelving working
72
        self.tempdir = tempfile.mkdtemp()
0.16.22 by Aaron Bentley
Only prompt when there are changes to shelve.
73
        changes_shelved = 0
0.16.1 by Aaron Bentley
Begin implementing UI
74
        try:
0.16.5 by Aaron Bentley
Get text shelving working
75
            for change in creator:
76
                if change[0] == 'modify text':
0.16.72 by Aaron Bentley
Allow shelving binary changes
77
                    try:
78
                        changes_shelved += self.handle_modify_text(creator,
79
                                                                   change[1])
80
                    except errors.BinaryFile:
81
                        if self.prompt_bool('Shelve binary changes?'):
82
                            changes_shelved += 1
83
                            creator.shelve_content_change(change[1])
0.16.16 by Aaron Bentley
Allow shelving renames and creation
84
                if change[0] == 'add file':
0.16.36 by Aaron Bentley
Better prompts on add/delete
85
                    if self.prompt_bool('Shelve adding file "%s"?'
86
                                        % change[3]):
0.16.16 by Aaron Bentley
Allow shelving renames and creation
87
                        creator.shelve_creation(change[1])
0.16.22 by Aaron Bentley
Only prompt when there are changes to shelve.
88
                        changes_shelved += 1
0.16.19 by Aaron Bentley
Implement shelving deletion
89
                if change[0] == 'delete file':
0.16.36 by Aaron Bentley
Better prompts on add/delete
90
                    if self.prompt_bool('Shelve removing file "%s"? '
91
                                        % change[3]):
0.16.19 by Aaron Bentley
Implement shelving deletion
92
                        creator.shelve_deletion(change[1])
0.16.22 by Aaron Bentley
Only prompt when there are changes to shelve.
93
                        changes_shelved += 1
0.16.72 by Aaron Bentley
Allow shelving binary changes
94
                if change[0] == 'change kind':
95
                    if self.prompt_bool('Shelve changing "%s" from %s to %s? '
96
                                        % (change[4], change[2], change[3])):
97
                        creator.shelve_content_change(change[1])
98
                        changes_shelved += 1
0.16.16 by Aaron Bentley
Allow shelving renames and creation
99
                if change[0] == 'rename':
0.16.23 by Aaron Bentley
Improve prompting
100
                    if self.prompt_bool('Shelve renaming %s => %s?' %
101
                                   change[2:]):
0.16.16 by Aaron Bentley
Allow shelving renames and creation
102
                        creator.shelve_rename(change[1])
0.16.22 by Aaron Bentley
Only prompt when there are changes to shelve.
103
                        changes_shelved += 1
104
            if changes_shelved > 0:
0.16.60 by Aaron Bentley
Clean up I/O handling
105
                trace.note("Selected changes:")
0.16.25 by Aaron Bentley
Show selected changes before shelving
106
                changes = creator.work_transform.iter_changes()
0.16.60 by Aaron Bentley
Clean up I/O handling
107
                reporter = delta._ChangeReporter()
0.16.25 by Aaron Bentley
Show selected changes before shelving
108
                delta.report_changes(changes, reporter)
0.16.24 by Aaron Bentley
Regularize prompts
109
                if (self.prompt_bool('Shelve %d change(s)?' %
0.16.23 by Aaron Bentley
Improve prompting
110
                    changes_shelved, auto=self.auto_apply)):
0.16.57 by Aaron Bentley
Expose messages in the UI
111
                    shelf_id = self.manager.shelve_changes(creator,
112
                                                           self.message)
0.16.54 by Aaron Bentley
Inform user about shelf ids.
113
                    trace.note('Changes shelved with id "%d".' % shelf_id)
0.16.22 by Aaron Bentley
Only prompt when there are changes to shelve.
114
            else:
0.16.60 by Aaron Bentley
Clean up I/O handling
115
                trace.warning('No changes to shelve.')
0.16.1 by Aaron Bentley
Begin implementing UI
116
        finally:
0.16.5 by Aaron Bentley
Get text shelving working
117
            shutil.rmtree(self.tempdir)
0.16.1 by Aaron Bentley
Begin implementing UI
118
            creator.finalize()
119
120
    def get_parsed_patch(self, file_id):
121
        old_path = self.work_tree.id2path(file_id)
122
        new_path = self.target_tree.id2path(file_id)
123
        try:
124
            patch = self.text_differ.diff(file_id, old_path, new_path, 'file',
125
                                          'file')
126
            self.diff_file.seek(0)
127
            return patches.parse_patch(self.diff_file)
128
        finally:
129
            self.diff_file.truncate(0)
130
0.16.23 by Aaron Bentley
Improve prompting
131
    def prompt_bool(self, question, auto=None):
0.16.44 by Aaron Bentley
Fix bogosity
132
        if auto is None:
0.16.23 by Aaron Bentley
Improve prompting
133
            auto = self.auto
134
        if auto:
135
            return True
0.16.26 by Aaron Bentley
Restore fancy prompting
136
        message = question + ' [yNfq]'
0.16.60 by Aaron Bentley
Clean up I/O handling
137
        sys.stdout.write(message)
0.16.79 by Aaron Bentley
Remove dependencies on bzrtools
138
        char = osutils.getchar()
0.16.60 by Aaron Bentley
Clean up I/O handling
139
        sys.stdout.write("\r" + ' ' * len(message) + '\r')
140
        sys.stdout.flush()
0.16.23 by Aaron Bentley
Improve prompting
141
        if char == 'y':
142
            return True
143
        elif char == 'f':
144
            self.auto = True
145
            return True
0.16.24 by Aaron Bentley
Regularize prompts
146
        if char == 'q':
147
            sys.exit(0)
0.16.23 by Aaron Bentley
Improve prompting
148
        else:
149
            return False
0.16.1 by Aaron Bentley
Begin implementing UI
150
0.16.5 by Aaron Bentley
Get text shelving working
151
    def handle_modify_text(self, creator, file_id):
0.16.72 by Aaron Bentley
Allow shelving binary changes
152
        target_lines = self.target_tree.get_file_lines(file_id)
153
        work_file = self.work_tree.get_file(file_id)
154
        try:
155
            textfile.text_file(work_file)
156
        finally:
157
            work_file.close()
158
        textfile.check_text_lines(target_lines)
0.16.1 by Aaron Bentley
Begin implementing UI
159
        parsed = self.get_parsed_patch(file_id)
0.16.43 by Aaron Bentley
Reduce API friction.
160
        final_hunks = []
0.16.15 by Aaron Bentley
Implement auto mode
161
        if not self.auto:
0.16.41 by Aaron Bentley
Implement shelving with internal patch
162
            offset = 0
0.16.61 by Aaron Bentley
Show file name when shelving
163
            self.diff_writer.write(parsed.get_header())
0.16.15 by Aaron Bentley
Implement auto mode
164
            for hunk in parsed.hunks:
165
                self.diff_writer.write(str(hunk))
0.16.24 by Aaron Bentley
Regularize prompts
166
                if not self.prompt_bool('Shelve?'):
0.16.41 by Aaron Bentley
Implement shelving with internal patch
167
                    hunk.mod_pos += offset
0.16.43 by Aaron Bentley
Reduce API friction.
168
                    final_hunks.append(hunk)
0.16.41 by Aaron Bentley
Implement shelving with internal patch
169
                else:
170
                    offset -= (hunk.mod_range - hunk.orig_range)
0.16.68 by Aaron Bentley
Avoid having escape codes affect the wrong text.
171
        sys.stdout.flush()
0.16.62 by Aaron Bentley
Make status nicer by not shelving lines for files not being changed
172
        if len(parsed.hunks) == len(final_hunks):
173
            return 0
0.16.43 by Aaron Bentley
Reduce API friction.
174
        patched = patches.iter_patched_from_hunks(target_lines, final_hunks)
0.16.45 by Aaron Bentley
switch to shelve_lines
175
        creator.shelve_lines(file_id, list(patched))
0.16.43 by Aaron Bentley
Reduce API friction.
176
        return len(parsed.hunks) - len(final_hunks)
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
177
178
179
class Unshelver(object):
180
181
    @classmethod
0.16.65 by Aaron Bentley
Implement unshelve --delete
182
    def from_args(klass, shelf_id=None, action='apply'):
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
183
        tree, path = workingtree.WorkingTree.open_containing('.')
0.16.40 by Aaron Bentley
Update for ShelfManager API changes
184
        manager = tree.get_shelf_manager()
0.16.52 by Aaron Bentley
Allow user-specified shelves
185
        if shelf_id is not None:
186
            shelf_id = int(shelf_id)
187
        else:
188
            shelf_id = manager.last_shelf()
189
            if shelf_id is None:
190
                raise errors.BzrCommandError('No changes are shelved.')
0.16.54 by Aaron Bentley
Inform user about shelf ids.
191
            trace.note('Unshelving changes with id "%d".' % shelf_id)
0.16.64 by Aaron Bentley
Implement dry-run option for Unshelve
192
        apply_changes = True
193
        delete_shelf = True
0.16.65 by Aaron Bentley
Implement unshelve --delete
194
        read_shelf = True
195
        if action == 'dry-run':
0.16.64 by Aaron Bentley
Implement dry-run option for Unshelve
196
            apply_changes = False
197
            delete_shelf = False
0.16.65 by Aaron Bentley
Implement unshelve --delete
198
        if action == 'delete-only':
199
            apply_changes = False
200
            read_shelf = False
201
        return klass(tree, manager, shelf_id, apply_changes, delete_shelf,
202
                     read_shelf)
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
203
0.16.65 by Aaron Bentley
Implement unshelve --delete
204
    def __init__(self, tree, manager, shelf_id, apply_changes, delete_shelf,
205
                 read_shelf):
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
206
        self.tree = tree
0.16.13 by Aaron Bentley
Appy shelve-management updates to shelver
207
        self.manager = manager
208
        self.shelf_id = shelf_id
0.16.64 by Aaron Bentley
Implement dry-run option for Unshelve
209
        self.apply_changes = apply_changes
210
        self.delete_shelf = delete_shelf
0.16.65 by Aaron Bentley
Implement unshelve --delete
211
        self.read_shelf = read_shelf
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
212
213
    def run(self):
214
        self.tree.lock_write()
0.16.37 by Aaron Bentley
Use cleanups list to reduce nested try blocks
215
        cleanups = [self.tree.unlock]
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
216
        try:
0.16.65 by Aaron Bentley
Implement unshelve --delete
217
            if self.read_shelf:
218
                unshelver = self.manager.get_unshelver(self.shelf_id)
219
                cleanups.append(unshelver.finalize)
220
                if unshelver.message is not None:
221
                    trace.note('Message: %s' % unshelver.message)
222
                change_reporter = delta._ChangeReporter()
0.16.78 by Aaron Bentley
Update for name change
223
                merger = unshelver.make_merger()
0.16.65 by Aaron Bentley
Implement unshelve --delete
224
                merger.change_reporter = change_reporter
225
                if self.apply_changes:
226
                    pb = ui.ui_factory.nested_progress_bar()
227
                    try:
228
                        merger.do_merge()
229
                    finally:
230
                        pb.finished()
231
                else:
232
                    self.show_changes(merger)
0.16.64 by Aaron Bentley
Implement dry-run option for Unshelve
233
            if self.delete_shelf:
234
                self.manager.delete_shelf(self.shelf_id)
0.16.8 by Aaron Bentley
Implement unshelve2, tidy shelve2
235
        finally:
0.16.37 by Aaron Bentley
Use cleanups list to reduce nested try blocks
236
            for cleanup in reversed(cleanups):
237
                cleanup()
0.16.64 by Aaron Bentley
Implement dry-run option for Unshelve
238
239
    def show_changes(self, merger):
240
        tree_merger = merger.make_merger()
241
        # This implicitly shows the changes via the reporter, so we're done...
242
        tt = tree_merger.make_preview_transform()
243
        tt.finalize()