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