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