/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.12.12 by Aaron Bentley
Implement shelf creator
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
0.12.13 by Aaron Bentley
Implement shelving content
18
from cStringIO import StringIO
19
0.14.19 by Aaron Bentley
Convert bzrlib import to split-line
20
from bzrlib import (
0.15.15 by Aaron Bentley
Merge prepare-shelf into unshelve
21
    errors,
22
    merge,
0.14.19 by Aaron Bentley
Convert bzrlib import to split-line
23
    merge3,
24
    osutils,
25
    pack,
26
    transform,
0.15.15 by Aaron Bentley
Merge prepare-shelf into unshelve
27
    ui,
0.12.47 by Aaron Bentley
Merge unshelve into shelf-manager
28
    workingtree
0.14.19 by Aaron Bentley
Convert bzrlib import to split-line
29
)
0.12.19 by Aaron Bentley
Add support for writing shelves
30
31
from bzrlib.plugins.shelf2 import serialize_transform
0.12.12 by Aaron Bentley
Implement shelf creator
32
33
34
class ShelfCreator(object):
35
0.16.47 by Aaron Bentley
Support selecting files to shelve
36
    def __init__(self, work_tree, target_tree, file_list):
0.12.12 by Aaron Bentley
Implement shelf creator
37
        self.work_tree = work_tree
38
        self.work_transform = transform.TreeTransform(work_tree)
0.14.1 by Aaron Bentley
Use explicit target in ShelfCreator
39
        self.target_tree = target_tree
40
        self.shelf_transform = transform.TransformPreview(self.target_tree)
0.12.12 by Aaron Bentley
Implement shelf creator
41
        self.renames = {}
0.14.2 by Aaron Bentley
Somewhat clean up shelving
42
        self.creation = {}
0.14.4 by Aaron Bentley
Implement shelving deletion
43
        self.deletion = {}
0.16.47 by Aaron Bentley
Support selecting files to shelve
44
        self.iter_changes = work_tree.iter_changes(self.target_tree,
45
                                                   specific_files=file_list)
0.12.12 by Aaron Bentley
Implement shelf creator
46
47
    def __iter__(self):
48
        for (file_id, paths, changed, versioned, parents, names, kind,
49
             executable) in self.iter_changes:
0.12.14 by Aaron Bentley
Add shelving of created files
50
            if kind[0] is None or versioned[0] == False:
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
51
                self.creation[file_id] = (kind[1], names[1], parents[1],
52
                                          versioned)
0.14.13 by Aaron Bentley
Provide path and kind when deletes/adds are detected.
53
                yield ('add file', file_id, kind[1], paths[1])
0.14.4 by Aaron Bentley
Implement shelving deletion
54
            elif kind[1] is None or versioned[0] == False:
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
55
                self.deletion[file_id] = (kind[0], names[0], parents[0],
56
                                          versioned)
0.14.13 by Aaron Bentley
Provide path and kind when deletes/adds are detected.
57
                yield ('delete file', file_id, kind[0], paths[0])
0.12.14 by Aaron Bentley
Add shelving of created files
58
            else:
59
                if names[0] != names[1] or parents[0] != parents[1]:
60
                    self.renames[file_id] = (names, parents)
61
                    yield ('rename', file_id) + paths
62
                if changed:
63
                    yield ('modify text', file_id)
0.12.12 by Aaron Bentley
Implement shelf creator
64
65
    def shelve_rename(self, file_id):
66
        names, parents = self.renames[file_id]
67
        w_trans_id = self.work_transform.trans_id_file_id(file_id)
68
        work_parent = self.work_transform.trans_id_file_id(parents[0])
69
        self.work_transform.adjust_path(names[0], work_parent, w_trans_id)
70
71
        s_trans_id = self.shelf_transform.trans_id_file_id(file_id)
72
        shelf_parent = self.shelf_transform.trans_id_file_id(parents[1])
73
        self.shelf_transform.adjust_path(names[1], shelf_parent, s_trans_id)
74
0.14.14 by Aaron Bentley
Change shelf_text to shelve_lines
75
    def shelve_lines(self, file_id, new_lines):
0.12.13 by Aaron Bentley
Implement shelving content
76
        w_trans_id = self.work_transform.trans_id_file_id(file_id)
77
        self.work_transform.delete_contents(w_trans_id)
78
        self.work_transform.create_file(new_lines, w_trans_id)
79
80
        s_trans_id = self.shelf_transform.trans_id_file_id(file_id)
81
        self.shelf_transform.delete_contents(s_trans_id)
82
        inverse_lines = self._inverse_lines(new_lines, file_id)
83
        self.shelf_transform.create_file(inverse_lines, s_trans_id)
84
0.14.2 by Aaron Bentley
Somewhat clean up shelving
85
    def shelve_creation(self, file_id):
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
86
        kind, name, parent, versioned = self.creation[file_id]
87
        version = not versioned[0]
0.14.4 by Aaron Bentley
Implement shelving deletion
88
        self._shelve_creation(self.work_tree, file_id, self.work_transform,
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
89
                              self.shelf_transform, kind, name, parent,
90
                              version)
0.14.4 by Aaron Bentley
Implement shelving deletion
91
92
    def shelve_deletion(self, file_id):
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
93
        kind, name, parent, versioned = self.deletion[file_id]
94
        existing_path = self.target_tree.id2path(file_id)
95
        if not self.work_tree.has_filename(existing_path):
96
            existing_path = None
97
        version = not versioned[1]
0.14.4 by Aaron Bentley
Implement shelving deletion
98
        self._shelve_creation(self.target_tree, file_id, self.shelf_transform,
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
99
                              self.work_transform, kind, name, parent,
100
                              version, existing_path=existing_path)
0.14.4 by Aaron Bentley
Implement shelving deletion
101
102
    def _shelve_creation(self, tree, file_id, from_transform, to_transform,
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
103
                         kind, name, parent, version, existing_path=None):
0.14.4 by Aaron Bentley
Implement shelving deletion
104
        w_trans_id = from_transform.trans_id_file_id(file_id)
0.14.12 by Aaron Bentley
Handle new dangling ids
105
        if parent is not None and kind is not None:
0.14.4 by Aaron Bentley
Implement shelving deletion
106
            from_transform.delete_contents(w_trans_id)
107
        from_transform.unversion_file(w_trans_id)
108
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
109
        if existing_path is not None:
110
            s_trans_id = to_transform.trans_id_tree_path(existing_path)
111
        else:
112
            s_trans_id = to_transform.trans_id_file_id(file_id)
0.14.4 by Aaron Bentley
Implement shelving deletion
113
        if parent is not None:
114
            s_parent_id = to_transform.trans_id_file_id(parent)
0.14.9 by Aaron Bentley
Shelve deleted files properly
115
            to_transform.adjust_path(name, s_parent_id, s_trans_id)
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
116
            if existing_path is None:
0.14.18 by Aaron Bentley
Simplify creating files
117
                if kind is None:
0.14.12 by Aaron Bentley
Handle new dangling ids
118
                    to_transform.create_file('', s_trans_id)
0.14.18 by Aaron Bentley
Simplify creating files
119
                else:
120
                    transform.create_from_tree(to_transform, s_trans_id,
121
                                               tree, file_id)
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
122
        if version:
123
            to_transform.version_file(file_id, s_trans_id)
0.12.14 by Aaron Bentley
Add shelving of created files
124
0.14.4 by Aaron Bentley
Implement shelving deletion
125
    def read_tree_lines(self, tree, file_id):
0.14.17 by Aaron Bentley
Use safer line-splitting
126
        return osutils.split_lines(tree.get_file_text(file_id))
0.12.14 by Aaron Bentley
Add shelving of created files
127
128
    def _inverse_lines(self, new_lines, file_id):
129
        """Produce a version with only those changes removed from new_lines."""
0.14.1 by Aaron Bentley
Use explicit target in ShelfCreator
130
        target_lines = self.target_tree.get_file_lines(file_id)
0.14.5 by Aaron Bentley
Fix call to read_tree_lines
131
        work_lines = self.read_tree_lines(self.work_tree, file_id)
0.14.1 by Aaron Bentley
Use explicit target in ShelfCreator
132
        return merge3.Merge3(new_lines, target_lines, work_lines).merge_lines()
0.12.13 by Aaron Bentley
Implement shelving content
133
0.12.12 by Aaron Bentley
Implement shelf creator
134
    def finalize(self):
135
        self.work_transform.finalize()
136
        self.shelf_transform.finalize()
0.12.13 by Aaron Bentley
Implement shelving content
137
138
    def transform(self):
139
        self.work_transform.apply()
0.12.19 by Aaron Bentley
Add support for writing shelves
140
141
    def make_shelf_filename(self):
142
        transport = self.work_tree.bzrdir.root_transport.clone('.shelf2')
143
        transport.ensure_base()
144
        return transport.local_abspath('01')
145
0.12.28 by Aaron Bentley
Update for shelf manager
146
    def write_shelf(self, shelf_file):
0.12.24 by Aaron Bentley
Get unshelve using merge codepath, not applying transform directly
147
        transform.resolve_conflicts(self.shelf_transform)
0.12.28 by Aaron Bentley
Update for shelf manager
148
        serializer = pack.ContainerSerialiser()
149
        shelf_file.write(serializer.begin())
150
        shelf_file.write(serializer.bytes_record(
151
            self.target_tree.get_revision_id(), (('revision-id',),)))
152
        for bytes in serialize_transform.serialize(
153
            self.shelf_transform, serializer):
154
            shelf_file.write(bytes)
155
        shelf_file.write(serializer.end())
0.12.21 by Aaron Bentley
Add failing test of unshelver
156
157
158
class Unshelver(object):
159
160
    def __init__(self, tree, base_tree, transform):
161
        self.tree = tree
0.12.24 by Aaron Bentley
Get unshelve using merge codepath, not applying transform directly
162
        self.base_tree = base_tree
0.12.21 by Aaron Bentley
Add failing test of unshelver
163
        self.transform = transform
164
165
    @classmethod
0.12.28 by Aaron Bentley
Update for shelf manager
166
    def from_tree_and_shelf(klass, tree, shelf_file):
0.12.21 by Aaron Bentley
Add failing test of unshelver
167
        parser = pack.ContainerPushParser()
0.12.28 by Aaron Bentley
Update for shelf manager
168
        parser.accept_bytes(shelf_file.read())
0.12.24 by Aaron Bentley
Get unshelve using merge codepath, not applying transform directly
169
        tt = transform.TransformPreview(tree)
0.12.21 by Aaron Bentley
Add failing test of unshelver
170
        records = iter(parser.read_pending_records())
0.12.26 by Aaron Bentley
Use correct base for shelving
171
        names, base_revision_id = records.next()
0.12.21 by Aaron Bentley
Add failing test of unshelver
172
        serialize_transform.deserialize(tt, records)
0.12.26 by Aaron Bentley
Use correct base for shelving
173
        try:
174
            base_tree = tree.revision_tree(base_revision_id)
175
        except errors.NoSuchRevisionInTree:
176
            base_tree = tree.branch.repository.revision_tree(base_revision_id)
177
        return klass(tree, base_tree, tt)
0.12.21 by Aaron Bentley
Add failing test of unshelver
178
179
    def unshelve(self):
0.12.25 by Aaron Bentley
Update to use new from_uncommitted API
180
        pb = ui.ui_factory.nested_progress_bar()
181
        try:
182
            target_tree = self.transform.get_preview_tree()
183
            merger = merge.Merger.from_uncommitted(self.tree, target_tree, pb,
184
                                                   self.base_tree)
185
            merger.merge_type = merge.Merge3Merger
186
            merger.do_merge()
187
        finally:
188
            pb.finished()
189
190
    def finalize(self):
191
        self.transform.finalize()
0.12.27 by Aaron Bentley
Implement shelf manager
192
193
194
class ShelfManager(object):
195
0.12.42 by Aaron Bentley
Get shelf from tree
196
    def __init__(self, tree, transport):
197
        self.tree = tree
0.12.41 by Aaron Bentley
Change shelf to use WT control dir for shelves
198
        self.transport = transport.clone('shelf')
0.12.27 by Aaron Bentley
Implement shelf manager
199
        self.transport.ensure_base()
200
201
    def new_shelf(self):
202
        last_shelf = self.last_shelf()
203
        if last_shelf is None:
204
            next_shelf = 1
205
        else:
206
            next_shelf = last_shelf + 1
207
        shelf_file = open(self.transport.local_abspath(str(next_shelf)), 'wb')
208
        return next_shelf, shelf_file
209
0.12.43 by Aaron Bentley
Make ShelfManager consume ShelfCreator and produce Unshelver
210
    def shelve_changes(self, creator):
211
        next_shelf, shelf_file = self.new_shelf()
212
        try:
213
            creator.write_shelf(shelf_file)
214
        finally:
215
            shelf_file.close()
0.12.44 by Aaron Bentley
Give manager responsibility for applying transform
216
        creator.transform()
0.12.43 by Aaron Bentley
Make ShelfManager consume ShelfCreator and produce Unshelver
217
        return next_shelf
218
0.12.27 by Aaron Bentley
Implement shelf manager
219
    def read_shelf(self, shelf_id):
220
        return open(self.transport.local_abspath(str(shelf_id)), 'rb')
221
0.12.43 by Aaron Bentley
Make ShelfManager consume ShelfCreator and produce Unshelver
222
    def get_unshelver(self, shelf_id):
223
        shelf_file = self.read_shelf(shelf_id)
224
        try:
225
            return Unshelver.from_tree_and_shelf(self.tree, shelf_file)
226
        finally:
227
            shelf_file.close()
228
0.12.27 by Aaron Bentley
Implement shelf manager
229
    def delete_shelf(self, shelf_id):
230
        self.transport.delete(str(shelf_id))
231
232
    def active_shelves(self):
233
        return [int(f) for f in self.transport.list_dir('.')]
234
235
    def last_shelf(self):
236
        active = self.active_shelves()
237
        if len(active) > 0:
238
            return max(active)
239
        else:
240
            return None
0.12.42 by Aaron Bentley
Get shelf from tree
241
242
243
def get_shelf_manager(self):
244
    return ShelfManager(self, self._transport)
245
246
247
workingtree.WorkingTree.get_shelf_manager = get_shelf_manager