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