/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.12.14 by Aaron Bentley
Add shelving of created files
43
                yield ('add file', file_id, kind[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.4 by Aaron Bentley
Implement shelving deletion
47
                yield ('delete file', file_id)
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
        versioned = list(reversed(versioned))
89
        existing_path = self.target_tree.id2path(file_id)
90
        if not self.work_tree.has_filename(existing_path):
91
            existing_path = None
92
        version = not versioned[1]
0.14.4 by Aaron Bentley
Implement shelving deletion
93
        self._shelve_creation(self.target_tree, file_id, self.shelf_transform,
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
94
                              self.work_transform, kind, name, parent,
95
                              version, existing_path=existing_path)
0.14.4 by Aaron Bentley
Implement shelving deletion
96
97
    def _shelve_creation(self, tree, file_id, from_transform, to_transform,
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
98
                         kind, name, parent, version, existing_path=None):
0.14.4 by Aaron Bentley
Implement shelving deletion
99
        w_trans_id = from_transform.trans_id_file_id(file_id)
100
        if parent is not None:
101
            from_transform.delete_contents(w_trans_id)
102
        from_transform.unversion_file(w_trans_id)
103
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
104
        if existing_path is not None:
105
            s_trans_id = to_transform.trans_id_tree_path(existing_path)
106
        else:
107
            s_trans_id = to_transform.trans_id_file_id(file_id)
0.14.4 by Aaron Bentley
Implement shelving deletion
108
        if parent is not None:
109
            s_parent_id = to_transform.trans_id_file_id(parent)
0.14.9 by Aaron Bentley
Shelve deleted files properly
110
            to_transform.adjust_path(name, s_parent_id, s_trans_id)
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
111
            if existing_path is None:
112
                if kind == 'file':
113
                    lines = self.read_tree_lines(tree, file_id)
114
                    to_transform.create_file(lines, s_trans_id)
115
                elif kind == 'directory':
116
                    to_transform.create_directory(s_trans_id)
117
                elif kind == 'symlink':
118
                    target = tree.get_symlink_target(file_id)
119
                    to_transform.create_symlink(target, s_trans_id)
120
        if version:
121
            to_transform.version_file(file_id, s_trans_id)
0.12.14 by Aaron Bentley
Add shelving of created files
122
0.14.4 by Aaron Bentley
Implement shelving deletion
123
    def read_tree_lines(self, tree, file_id):
124
        tree_file = tree.get_file(file_id)
0.12.13 by Aaron Bentley
Implement shelving content
125
        try:
0.12.14 by Aaron Bentley
Add shelving of created files
126
            return tree_file.readlines()
0.12.13 by Aaron Bentley
Implement shelving content
127
        finally:
128
            tree_file.close()
0.12.14 by Aaron Bentley
Add shelving of created files
129
130
    def _inverse_lines(self, new_lines, file_id):
131
        """Produce a version with only those changes removed from new_lines."""
0.14.1 by Aaron Bentley
Use explicit target in ShelfCreator
132
        target_lines = self.target_tree.get_file_lines(file_id)
0.14.5 by Aaron Bentley
Fix call to read_tree_lines
133
        work_lines = self.read_tree_lines(self.work_tree, file_id)
0.14.1 by Aaron Bentley
Use explicit target in ShelfCreator
134
        return merge3.Merge3(new_lines, target_lines, work_lines).merge_lines()
0.12.13 by Aaron Bentley
Implement shelving content
135
0.12.12 by Aaron Bentley
Implement shelf creator
136
    def finalize(self):
137
        self.work_transform.finalize()
138
        self.shelf_transform.finalize()
0.12.13 by Aaron Bentley
Implement shelving content
139
140
    def transform(self):
141
        self.work_transform.apply()
0.12.19 by Aaron Bentley
Add support for writing shelves
142
143
    def make_shelf_filename(self):
144
        transport = self.work_tree.bzrdir.root_transport.clone('.shelf2')
145
        transport.ensure_base()
146
        return transport.local_abspath('01')
147
0.12.28 by Aaron Bentley
Update for shelf manager
148
    def write_shelf(self, shelf_file):
0.12.24 by Aaron Bentley
Get unshelve using merge codepath, not applying transform directly
149
        transform.resolve_conflicts(self.shelf_transform)
0.12.28 by Aaron Bentley
Update for shelf manager
150
        serializer = pack.ContainerSerialiser()
151
        shelf_file.write(serializer.begin())
152
        shelf_file.write(serializer.bytes_record(
153
            self.target_tree.get_revision_id(), (('revision-id',),)))
154
        for bytes in serialize_transform.serialize(
155
            self.shelf_transform, serializer):
156
            shelf_file.write(bytes)
157
        shelf_file.write(serializer.end())
0.12.21 by Aaron Bentley
Add failing test of unshelver
158
159
160
class Unshelver(object):
161
162
    def __init__(self, tree, base_tree, transform):
163
        self.tree = tree
0.12.24 by Aaron Bentley
Get unshelve using merge codepath, not applying transform directly
164
        self.base_tree = base_tree
0.12.21 by Aaron Bentley
Add failing test of unshelver
165
        self.transform = transform
166
167
    @classmethod
0.12.28 by Aaron Bentley
Update for shelf manager
168
    def from_tree_and_shelf(klass, tree, shelf_file):
0.12.21 by Aaron Bentley
Add failing test of unshelver
169
        parser = pack.ContainerPushParser()
0.12.28 by Aaron Bentley
Update for shelf manager
170
        parser.accept_bytes(shelf_file.read())
0.12.24 by Aaron Bentley
Get unshelve using merge codepath, not applying transform directly
171
        tt = transform.TransformPreview(tree)
0.12.21 by Aaron Bentley
Add failing test of unshelver
172
        records = iter(parser.read_pending_records())
0.12.26 by Aaron Bentley
Use correct base for shelving
173
        names, base_revision_id = records.next()
0.12.21 by Aaron Bentley
Add failing test of unshelver
174
        serialize_transform.deserialize(tt, records)
0.12.26 by Aaron Bentley
Use correct base for shelving
175
        try:
176
            base_tree = tree.revision_tree(base_revision_id)
177
        except errors.NoSuchRevisionInTree:
178
            base_tree = tree.branch.repository.revision_tree(base_revision_id)
179
        return klass(tree, base_tree, tt)
0.12.21 by Aaron Bentley
Add failing test of unshelver
180
181
    def unshelve(self):
0.12.25 by Aaron Bentley
Update to use new from_uncommitted API
182
        pb = ui.ui_factory.nested_progress_bar()
183
        try:
184
            target_tree = self.transform.get_preview_tree()
185
            merger = merge.Merger.from_uncommitted(self.tree, target_tree, pb,
186
                                                   self.base_tree)
187
            merger.merge_type = merge.Merge3Merger
188
            merger.do_merge()
189
        finally:
190
            pb.finished()
191
192
    def finalize(self):
193
        self.transform.finalize()
0.12.27 by Aaron Bentley
Implement shelf manager
194
195
196
class ShelfManager(object):
197
198
    def __init__(self, transport):
199
        self.transport = transport.clone('.shelf2')
200
        self.transport.ensure_base()
201
202
    @classmethod
203
    def for_tree(klass, tree):
204
        return klass(tree.bzrdir.root_transport)
205
206
    def new_shelf(self):
207
        last_shelf = self.last_shelf()
208
        if last_shelf is None:
209
            next_shelf = 1
210
        else:
211
            next_shelf = last_shelf + 1
212
        shelf_file = open(self.transport.local_abspath(str(next_shelf)), 'wb')
213
        return next_shelf, shelf_file
214
215
    def read_shelf(self, shelf_id):
216
        return open(self.transport.local_abspath(str(shelf_id)), 'rb')
217
218
    def delete_shelf(self, shelf_id):
219
        self.transport.delete(str(shelf_id))
220
221
    def active_shelves(self):
222
        return [int(f) for f in self.transport.list_dir('.')]
223
224
    def last_shelf(self):
225
        active = self.active_shelves()
226
        if len(active) > 0:
227
            return max(active)
228
        else:
229
            return None