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