/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.36 by John Arbash Meinel
Updated so that read_changeset is able to parse the output
166
            write(self.base_revision.revision_id, key='base')
167
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
168
            rev_id = self.base_revision.revision_id
169
            write(self.branch.get_revision_sha1(rev_id),
0.5.25 by John Arbash Meinel
Added some work to allow rollup revisions, and handling multiple parents.
170
                    key='base sha1')
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
171
0.5.25 by John Arbash Meinel
Added some work to allow rollup revisions, and handling multiple parents.
172
        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.
173
0.5.38 by John Arbash Meinel
Working on updating the information to be minimalistic
174
        #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.
175
176
        write('END BZR FOOTER')
177
178
    def _write_revisions(self):
179
        """Not used. Used for writing multiple revisions."""
0.5.3 by John Arbash Meinel
Added a couple more bits
180
        for rev in self.revision_list:
0.5.25 by John Arbash Meinel
Added some work to allow rollup revisions, and handling multiple parents.
181
            rev_id = rev.revision_id
182
            self.to_file.write('# revision: %s\n' % rev_id)
183
            self.to_file.write('#    sha1: %s\n' % 
184
                self.branch.get_revision_sha1(rev_id))
185
            self.to_file.write('#    committer: %s\n' % rev.committer)
186
            self.to_file.write('#    timestamp: %.9f\n' % rev.timestamp)
0.5.35 by John Arbash Meinel
Timezone doesn't need 9 digits of precision.
187
            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.
188
            self.to_file.write('#    inventory id: %s\n' % rev.inventory_id)
189
            self.to_file.write('#    inventory sha1: %s\n' % rev.inventory_sha1)
190
            self.to_file.write('#    parents:\n')
191
            for parent in rev.parents:
0.5.36 by John Arbash Meinel
Updated so that read_changeset is able to parse the output
192
                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.
193
                    parent.revision_id,
194
                    parent.revision_sha1))
0.5.26 by John Arbash Meinel
Adding the commit message for each revision.
195
            self.to_file.write('#    message:\n')
196
            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
197
                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.
198
199
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
200
    def _write_ids(self):
201
        if hasattr(self.branch, 'get_root_id'):
202
            root_id = self.branch.get_root_id()
203
        else:
204
            root_id = ROOT_ID
0.5.15 by John Arbash Meinel
Created an apply-changeset function, and modified output for better parsing.
205
206
        old_ids = set()
207
        new_ids = set()
208
209
        for path, file_id, kind in self.delta.removed:
210
            old_ids.add(file_id)
211
        for path, file_id, kind in self.delta.added:
212
            new_ids.add(file_id)
213
        for old_path, new_path, file_id, kind, text_modified in self.delta.renamed:
214
            old_ids.add(file_id)
215
            new_ids.add(file_id)
216
        for path, file_id, kind in self.delta.modified:
217
            new_ids.add(file_id)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
218
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
219
        self._write(root_id, key='tree root id')
220
0.5.15 by John Arbash Meinel
Created an apply-changeset function, and modified output for better parsing.
221
        def write_ids(tree, id_set, name):
222
            if len(id_set) > 0:
223
                self.to_file.write('# %s ids:\n' % name)
224
            seen_ids = set([root_id])
225
            while len(id_set) > 0:
226
                file_id = id_set.pop()
227
                if file_id in seen_ids:
228
                    continue
229
                seen_ids.add(file_id)
230
                ie = tree.inventory[file_id]
231
                if ie.parent_id not in seen_ids:
232
                    id_set.add(ie.parent_id)
233
                path = tree.inventory.id2path(file_id)
234
                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.
235
                        % (path, file_id,
236
                            ie.parent_id))
0.5.15 by John Arbash Meinel
Created an apply-changeset function, and modified output for better parsing.
237
        write_ids(self.new_tree, new_ids, 'file')
238
        write_ids(self.old_tree, old_ids, 'old file')
0.5.5 by John Arbash Meinel
Updated to now include the diffs
239
0.5.38 by John Arbash Meinel
Working on updating the information to be minimalistic
240
    def _write_text_ids(self):
241
        pass
242
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
243
    def _write_diffs(self):
0.5.5 by John Arbash Meinel
Updated to now include the diffs
244
        """Write out the specific diffs"""
245
        from bzrlib.diff import internal_diff, external_diff
246
        DEVNULL = '/dev/null'
247
248
        if self.external_diff_options:
249
            assert isinstance(self.external_diff_options, basestring)
250
            opts = self.external_diff_options.split()
251
            def diff_file(olab, olines, nlab, nlines, to_file):
252
                external_diff(olab, olines, nlab, nlines, to_file, opts)
253
        else:
254
            diff_file = internal_diff
255
256
        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.
257
            print >>self.to_file, '*** removed %s %r' % (kind, path)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
258
            if kind == 'file' and self.full_remove:
259
                diff_file(self.old_label + path,
260
                          self.old_tree.get_file(file_id).readlines(),
261
                          DEVNULL, 
262
                          [],
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
263
                          self.to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
264
    
265
        for path, file_id, kind in self.delta.added:
0.5.38 by John Arbash Meinel
Working on updating the information to be minimalistic
266
            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
267
            if kind == 'file':
268
                diff_file(DEVNULL,
269
                          [],
270
                          self.new_label + path,
271
                          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.
272
                          self.to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
273
    
274
        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.
275
            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
276
            if self.full_rename and kind == 'file':
277
                diff_file(self.old_label + old_path,
278
                          self.old_tree.get_file(file_id).readlines(),
279
                          DEVNULL, 
280
                          [],
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
281
                          self.to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
282
                diff_file(DEVNULL,
283
                          [],
284
                          self.new_label + new_path,
285
                          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.
286
                          self.to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
287
            elif text_modified:
288
                    diff_file(self.old_label + old_path,
289
                              self.old_tree.get_file(file_id).readlines(),
290
                              self.new_label + new_path,
291
                              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.
292
                              self.to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
293
    
294
        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.
295
            print >>self.to_file, '*** modified %s %r' % (kind, path)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
296
            if kind == 'file':
297
                diff_file(self.old_label + path,
298
                          self.old_tree.get_file(file_id).readlines(),
299
                          self.new_label + path,
300
                          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.
301
                          self.to_file)
0.5.1 by John Arbash Meinel
Just an initial working step.
302
0.5.27 by John Arbash Meinel
Now capable of generating rollup changesets.
303
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.
304
    from bzrlib.diff import compare_trees
305
306
    if to_file is None:
307
        import sys
308
        to_file = sys.stdout
0.5.36 by John Arbash Meinel
Updated so that read_changeset is able to parse the output
309
    revisions = common.canonicalize_revision(branch, revisions)
0.5.1 by John Arbash Meinel
Just an initial working step.
310
311
    old_tree, new_tree = _get_trees(branch, revisions)
312
0.5.27 by John Arbash Meinel
Now capable of generating rollup changesets.
313
    delta = compare_trees(old_tree, new_tree, want_unchanged=False)
0.5.1 by John Arbash Meinel
Just an initial working step.
314
0.5.5 by John Arbash Meinel
Updated to now include the diffs
315
    meta = MetaInfoHeader(branch, revisions, delta,
316
            old_tree=old_tree, new_tree=new_tree)
0.5.1 by John Arbash Meinel
Just an initial working step.
317
    meta.write_meta_info(to_file)
318