/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.5.1 by John Arbash Meinel
Just an initial working step.
1
#!/usr/bin/env python
2
"""\
3
Just some work for generating a changeset.
4
"""
5
6
import bzrlib, bzrlib.errors
7
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
8
import common
9
10
from bzrlib.inventory import ROOT_ID
11
0.5.5 by John Arbash Meinel
Updated to now include the diffs
12
try:
13
    set
14
except NameError:
15
    from sets import Set as set
16
0.5.1 by John Arbash Meinel
Just an initial working step.
17
def _get_trees(branch, revisions):
18
    """Get the old and new trees based on revision.
19
    """
0.5.18 by John Arbash Meinel
Some minor fixups
20
    from bzrlib.tree import EmptyTree
0.5.1 by John Arbash Meinel
Just an initial working step.
21
    if revisions[0] is None:
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
22
        if hasattr(branch, 'get_root_id'): # Watch out for trees with labeled ROOT ids
23
            old_tree = EmptyTree(branch.get_root_id) 
24
        else:
25
            old_tree = EmptyTree()
0.5.1 by John Arbash Meinel
Just an initial working step.
26
    else:
27
        old_tree = branch.revision_tree(revisions[0])
28
29
    if revisions[1] is None:
0.5.27 by John Arbash Meinel
Now capable of generating rollup changesets.
30
        raise BzrCommandError('Cannot form a bzr changeset with no committed revisions')
0.5.1 by John Arbash Meinel
Just an initial working step.
31
    else:
32
        new_tree = branch.revision_tree(revisions[1])
33
    return old_tree, new_tree
34
35
def _fake_working_revision(branch):
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
36
    """Fake a Revision object for the working tree.
37
    
38
    This is for the future, to support changesets against the working tree.
39
    """
0.5.1 by John Arbash Meinel
Just an initial working step.
40
    from bzrlib.revision import Revision
41
    import time
42
    from bzrlib.osutils import local_time_offset, \
43
            username
44
45
    precursor = branch.last_patch()
46
    precursor_sha1 = branch.get_revision_sha1(precursor)
47
48
    return Revision(timestamp=time.time(),
49
            timezone=local_time_offset(),
50
            committer=username(),
51
            precursor=precursor,
52
            precursor_sha1=precursor_sha1)
53
54
55
class MetaInfoHeader(object):
56
    """Maintain all of the header information about this
57
    changeset.
58
    """
59
0.5.5 by John Arbash Meinel
Updated to now include the diffs
60
    def __init__(self, branch, revisions, delta,
0.5.11 by John Arbash Meinel
Working on properly representing renames.
61
            full_remove=True, full_rename=False,
0.5.5 by John Arbash Meinel
Updated to now include the diffs
62
            external_diff_options = None,
63
            new_tree=None, old_tree=None,
64
            old_label = '', new_label = ''):
65
        """
66
        :param full_remove: Include the full-text for a delete
67
        :param full_rename: Include an add+delete patch for a rename
0.5.25 by John Arbash Meinel
Added some work to allow rollup revisions, and handling multiple parents.
68
0.5.5 by John Arbash Meinel
Updated to now include the diffs
69
        """
0.5.1 by John Arbash Meinel
Just an initial working step.
70
        self.branch = branch
71
        self.delta = delta
0.5.5 by John Arbash Meinel
Updated to now include the diffs
72
        self.full_remove=full_remove
73
        self.full_rename=full_rename
74
        self.external_diff_options = external_diff_options
75
        self.old_label = old_label
76
        self.new_label = new_label
77
        self.old_tree = old_tree
78
        self.new_tree = new_tree
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
79
        self.to_file = None
80
        self.revno = None
81
        self.precursor_revno = None
82
83
        self._get_revision_list(revisions)
0.5.1 by John Arbash Meinel
Just an initial working step.
84
85
    def _get_revision_list(self, revisions):
86
        """This generates the list of all revisions from->to.
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
87
0.5.27 by John Arbash Meinel
Now capable of generating rollup changesets.
88
        This is for having a rollup changeset.
0.5.1 by John Arbash Meinel
Just an initial working step.
89
        """
90
        old_revno = None
91
        new_revno = None
92
        rh = self.branch.revision_history()
93
        for revno, rev in enumerate(rh):
94
            if rev == revisions[0]:
95
                old_revno = revno
96
            if rev == revisions[1]:
97
                new_revno = revno
98
0.5.3 by John Arbash Meinel
Added a couple more bits
99
        self.revision_list = []
0.5.1 by John Arbash Meinel
Just an initial working step.
100
        if old_revno is None:
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
101
            self.base_revision = None # Effectively the EmptyTree()
0.5.18 by John Arbash Meinel
Some minor fixups
102
            old_revno = -1
0.5.3 by John Arbash Meinel
Added a couple more bits
103
        else:
104
            self.base_revision = self.branch.get_revision(rh[old_revno])
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
105
        if new_revno is None:
106
            # For the future, when we support working tree changesets.
0.5.3 by John Arbash Meinel
Added a couple more bits
107
            for rev_id in rh[old_revno+1:]:
0.5.1 by John Arbash Meinel
Just an initial working step.
108
                self.revision_list.append(self.branch.get_revision(rev_id))
109
            self.revision_list.append(_fake_working_revision(self.branch))
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
110
        else:
111
            for rev_id in rh[old_revno+1:new_revno+1]:
112
                self.revision_list.append(self.branch.get_revision(rev_id))
0.5.34 by John Arbash Meinel
Fixed a bogus offset issue with revision numbers.
113
        self.precursor_revno = old_revno+1
114
        self.revno = new_revno+1
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
115
116
    def _write(self, txt, key=None):
117
        if key:
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
118
            self.to_file.write('# %s: %s\n' % (key, txt))
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
119
        else:
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
120
            self.to_file.write('# %s\n' % (txt,))
0.5.1 by John Arbash Meinel
Just an initial working step.
121
122
    def write_meta_info(self, to_file):
0.5.5 by John Arbash Meinel
Updated to now include the diffs
123
        """Write out the meta-info portion to the supplied file.
124
125
        :param to_file: Write out the meta information to the supplied
126
                        file
127
        """
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
128
        self.to_file = to_file
129
130
        self._write_header()
131
        self._write_diffs()
132
        self._write_footer()
133
134
    def _write_header(self):
135
        """Write the stuff that comes before the patches."""
136
        from bzrlib.osutils import username, format_date
137
        write = self._write
138
139
        for line in common.get_header():
140
            write(line)
141
0.5.27 by John Arbash Meinel
Now capable of generating rollup changesets.
142
        # Print out the basic information about the 'target' revision
143
        rev = self.revision_list[-1]
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
144
        write(rev.committer, key='committer')
145
        write(format_date(rev.timestamp, offset=rev.timezone), key='date')
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
146
        if rev.message:
147
            self.to_file.write('# message:\n')
148
            for line in rev.message.split('\n'):
149
                self.to_file.write('#    %s\n' % line)
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
150
0.5.4 by John Arbash Meinel
Added printout of file ids, need directory ids
151
        write('')
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
152
        self.to_file.write('\n')
153
154
    def _write_footer(self):
155
        """Write the stuff that comes after the patches.
156
157
        This is meant to be more meta-information, which people probably don't want
158
        to read, but which is required for proper bzr operation.
159
        """
160
        write = self._write
161
162
        write('BEGIN BZR FOOTER')
163
0.5.36 by John Arbash Meinel
Updated so that read_changeset is able to parse the output
164
        # Base revision is the revision this changeset is against
0.5.3 by John Arbash Meinel
Added a couple more bits
165
        if self.base_revision:
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
166
            rev_id = self.base_revision.revision_id
0.5.39 by John Arbash Meinel
(broken) Working on changing the processing to use a ChangesetTree.
167
            write(rev_id, key='base')
168
            write(self.branch.get_revision_sha1(rev_id), key='base sha1')
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
169
0.5.25 by John Arbash Meinel
Added some work to allow rollup revisions, and handling multiple parents.
170
        self._write_revisions()
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
171
0.5.38 by John Arbash Meinel
Working on updating the information to be minimalistic
172
        #self._write_ids()
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
173
174
        write('END BZR FOOTER')
175
176
    def _write_revisions(self):
177
        """Not used. Used for writing multiple revisions."""
0.5.3 by John Arbash Meinel
Added a couple more bits
178
        for rev in self.revision_list:
0.5.25 by John Arbash Meinel
Added some work to allow rollup revisions, and handling multiple parents.
179
            rev_id = rev.revision_id
180
            self.to_file.write('# revision: %s\n' % rev_id)
181
            self.to_file.write('#    sha1: %s\n' % 
182
                self.branch.get_revision_sha1(rev_id))
183
            self.to_file.write('#    committer: %s\n' % rev.committer)
184
            self.to_file.write('#    timestamp: %.9f\n' % rev.timestamp)
0.5.35 by John Arbash Meinel
Timezone doesn't need 9 digits of precision.
185
            self.to_file.write('#    timezone: %s\n' % rev.timezone)
0.5.25 by John Arbash Meinel
Added some work to allow rollup revisions, and handling multiple parents.
186
            self.to_file.write('#    inventory id: %s\n' % rev.inventory_id)
187
            self.to_file.write('#    inventory sha1: %s\n' % rev.inventory_sha1)
188
            self.to_file.write('#    parents:\n')
189
            for parent in rev.parents:
0.5.36 by John Arbash Meinel
Updated so that read_changeset is able to parse the output
190
                self.to_file.write('#       %s\t%s\n' % (
0.5.25 by John Arbash Meinel
Added some work to allow rollup revisions, and handling multiple parents.
191
                    parent.revision_id,
192
                    parent.revision_sha1))
0.5.26 by John Arbash Meinel
Adding the commit message for each revision.
193
            self.to_file.write('#    message:\n')
194
            for line in rev.message.split('\n'):
0.5.36 by John Arbash Meinel
Updated so that read_changeset is able to parse the output
195
                self.to_file.write('#       %s\n' % line)
0.5.25 by John Arbash Meinel
Added some work to allow rollup revisions, and handling multiple parents.
196
197
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
198
    def _write_ids(self):
199
        if hasattr(self.branch, 'get_root_id'):
200
            root_id = self.branch.get_root_id()
201
        else:
202
            root_id = ROOT_ID
0.5.15 by John Arbash Meinel
Created an apply-changeset function, and modified output for better parsing.
203
204
        old_ids = set()
205
        new_ids = set()
206
207
        for path, file_id, kind in self.delta.removed:
208
            old_ids.add(file_id)
209
        for path, file_id, kind in self.delta.added:
210
            new_ids.add(file_id)
211
        for old_path, new_path, file_id, kind, text_modified in self.delta.renamed:
212
            old_ids.add(file_id)
213
            new_ids.add(file_id)
214
        for path, file_id, kind in self.delta.modified:
215
            new_ids.add(file_id)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
216
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
217
        self._write(root_id, key='tree root id')
218
0.5.15 by John Arbash Meinel
Created an apply-changeset function, and modified output for better parsing.
219
        def write_ids(tree, id_set, name):
220
            if len(id_set) > 0:
221
                self.to_file.write('# %s ids:\n' % name)
222
            seen_ids = set([root_id])
223
            while len(id_set) > 0:
224
                file_id = id_set.pop()
225
                if file_id in seen_ids:
226
                    continue
227
                seen_ids.add(file_id)
228
                ie = tree.inventory[file_id]
229
                if ie.parent_id not in seen_ids:
230
                    id_set.add(ie.parent_id)
231
                path = tree.inventory.id2path(file_id)
232
                self.to_file.write('#    %s\t%s\t%s\n'
0.5.25 by John Arbash Meinel
Added some work to allow rollup revisions, and handling multiple parents.
233
                        % (path, file_id,
234
                            ie.parent_id))
0.5.15 by John Arbash Meinel
Created an apply-changeset function, and modified output for better parsing.
235
        write_ids(self.new_tree, new_ids, 'file')
236
        write_ids(self.old_tree, old_ids, 'old file')
0.5.5 by John Arbash Meinel
Updated to now include the diffs
237
0.5.38 by John Arbash Meinel
Working on updating the information to be minimalistic
238
    def _write_text_ids(self):
239
        pass
240
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
241
    def _write_diffs(self):
0.5.5 by John Arbash Meinel
Updated to now include the diffs
242
        """Write out the specific diffs"""
243
        from bzrlib.diff import internal_diff, external_diff
244
        DEVNULL = '/dev/null'
245
246
        if self.external_diff_options:
247
            assert isinstance(self.external_diff_options, basestring)
248
            opts = self.external_diff_options.split()
249
            def diff_file(olab, olines, nlab, nlines, to_file):
250
                external_diff(olab, olines, nlab, nlines, to_file, opts)
251
        else:
252
            diff_file = internal_diff
253
254
        for path, file_id, kind in self.delta.removed:
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
255
            print >>self.to_file, '*** removed %s %r' % (kind, path)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
256
            if kind == 'file' and self.full_remove:
257
                diff_file(self.old_label + path,
258
                          self.old_tree.get_file(file_id).readlines(),
259
                          DEVNULL, 
260
                          [],
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
261
                          self.to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
262
    
263
        for path, file_id, kind in self.delta.added:
0.5.38 by John Arbash Meinel
Working on updating the information to be minimalistic
264
            print >>self.to_file, '*** added %s %r id:%s' % (kind, path, file_id)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
265
            if kind == 'file':
266
                diff_file(DEVNULL,
267
                          [],
268
                          self.new_label + path,
269
                          self.new_tree.get_file(file_id).readlines(),
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
270
                          self.to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
271
    
272
        for old_path, new_path, file_id, kind, text_modified in self.delta.renamed:
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
273
            print >>self.to_file, '*** renamed %s %r => %r' % (kind, old_path, new_path)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
274
            if self.full_rename and kind == 'file':
275
                diff_file(self.old_label + old_path,
276
                          self.old_tree.get_file(file_id).readlines(),
277
                          DEVNULL, 
278
                          [],
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
279
                          self.to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
280
                diff_file(DEVNULL,
281
                          [],
282
                          self.new_label + new_path,
283
                          self.new_tree.get_file(file_id).readlines(),
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
284
                          self.to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
285
            elif text_modified:
286
                    diff_file(self.old_label + old_path,
287
                              self.old_tree.get_file(file_id).readlines(),
288
                              self.new_label + new_path,
289
                              self.new_tree.get_file(file_id).readlines(),
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
290
                              self.to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
291
    
292
        for path, file_id, kind in self.delta.modified:
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
293
            print >>self.to_file, '*** modified %s %r' % (kind, path)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
294
            if kind == 'file':
295
                diff_file(self.old_label + path,
296
                          self.old_tree.get_file(file_id).readlines(),
297
                          self.new_label + path,
298
                          self.new_tree.get_file(file_id).readlines(),
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
299
                          self.to_file)
0.5.1 by John Arbash Meinel
Just an initial working step.
300
0.5.27 by John Arbash Meinel
Now capable of generating rollup changesets.
301
def show_changeset(branch, revisions=None, to_file=None, include_full_diff=False):
0.5.1 by John Arbash Meinel
Just an initial working step.
302
    from bzrlib.diff import compare_trees
303
304
    if to_file is None:
305
        import sys
306
        to_file = sys.stdout
0.5.36 by John Arbash Meinel
Updated so that read_changeset is able to parse the output
307
    revisions = common.canonicalize_revision(branch, revisions)
0.5.1 by John Arbash Meinel
Just an initial working step.
308
309
    old_tree, new_tree = _get_trees(branch, revisions)
310
0.5.27 by John Arbash Meinel
Now capable of generating rollup changesets.
311
    delta = compare_trees(old_tree, new_tree, want_unchanged=False)
0.5.1 by John Arbash Meinel
Just an initial working step.
312
0.5.5 by John Arbash Meinel
Updated to now include the diffs
313
    meta = MetaInfoHeader(branch, revisions, delta,
314
            old_tree=old_tree, new_tree=new_tree)
0.5.1 by John Arbash Meinel
Just an initial working step.
315
    meta.write_meta_info(to_file)
316