/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
0.5.58 by John Arbash Meinel
Fixed a bug in the case that there are no revision committed yet.
11
from bzrlib.errors import BzrCommandError
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
12
0.5.5 by John Arbash Meinel
Updated to now include the diffs
13
try:
14
    set
15
except NameError:
16
    from sets import Set as set
17
0.5.1 by John Arbash Meinel
Just an initial working step.
18
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.
19
    """Fake a Revision object for the working tree.
20
    
21
    This is for the future, to support changesets against the working tree.
22
    """
0.5.1 by John Arbash Meinel
Just an initial working step.
23
    from bzrlib.revision import Revision
24
    import time
25
    from bzrlib.osutils import local_time_offset, \
26
            username
27
28
    precursor = branch.last_patch()
29
    precursor_sha1 = branch.get_revision_sha1(precursor)
30
31
    return Revision(timestamp=time.time(),
32
            timezone=local_time_offset(),
33
            committer=username(),
34
            precursor=precursor,
35
            precursor_sha1=precursor_sha1)
36
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
37
def _get_revision_set(branch):
38
    """Get the set of all revisions that are in the ancestry
39
    of this branch.
40
    """
41
    this_revs = set()
42
    to_search = [branch.last_patch()]
43
44
    while len(to_search) > 0:
45
        rev_id = to_search.pop(0)
46
        if rev_id in this_revs:
47
            continue
48
        this_revs.add(rev_id)
49
        rev = branch.get_revision(rev_id)
50
        for parent in rev.parents:
51
            if parent.revision_id not in this_revs:
52
                to_search.append(parent.revision_id)
53
    return this_revs
54
55
def _find_best_base(branch, other_rev_id, other_branch=None):
56
    """Find the best base revision based on ancestry.
57
    All revisions should already be pulled into the local tree.
58
    """
59
    this_revs = _get_revision_set(branch)
60
61
    # This does a breadth first search through history, looking for
62
    # something which matches
63
    checked = set()
64
    to_check = [other_rev_id]
65
    while len(to_check) > 0:
66
        # Removing the '0' would make this depth-first search
67
        rev_id = to_check.pop(0)
68
        if rev_id in checked:
69
            continue
70
        checked.add(rev_id)
71
        if rev_id in this_revs:
72
            return rev_id
73
74
        if rev_id in branch.revision_store:
75
            rev = branch.get_revision(rev_id)
76
        elif (other_branch is not None 
77
                and rev_id in other_branch.revision_store):
78
            rev = other_branch.get_revision(rev_id)
79
        else:
80
            # Should we just continue here?
81
            warning('Could not find revision for rev: {%s}'
82
                    % rev_id)
83
            continue
84
85
86
        for parent in rev.parents:
87
            if parent.revision_id not in checked:
88
                to_check.append(parent.revision_id)
89
90
    return None
91
92
def _create_ancestry_to_rev(branch, ancestor_rev_id, this_rev_id):
93
    """Return a listing of revisions, which traces back from this_rev_id
94
    all the way back to the ancestor_rev_id.
95
    """
96
    # This is an optimization, when both target and base
97
    # exist in the revision history, we should already have
98
    # a valid listing of revision ancestry.
99
    rh = branch.revision_history()
100
    if ancestor_rev_id in rh and this_rev_id in rh:
101
        ancestor_idx = rh.index(ancestor_rev_id)
102
        this_rev_idx = rh.index(this_rev_id)
103
        if ancestor_idx > this_rev_idx:
104
            raise BzrCommandError('Revision {%s} is a child not an ancestor'
105
                    ' of {%s}' % (ancestor_rev_id, this_rev_id))
106
        rh_list = rh[ancestor_idx:this_rev_idx+1]
107
        rh_list.reverse()
108
        # return rh_list
109
110
    # I considered using depth-first search, as it is a little
111
    # bit less resource intensive, and it should favor generating
112
    # paths that are the same as revision_history
113
    # but since breadth-first-search is generally used
114
    # we will use that
115
    # 
116
    # WARNING: In the presence of merges, there are cases where
117
    # breadth first search will return a very different path
118
    # than revision_history or depth first search. Imaging the following:
119
    #
120
    # rh: A -> B -> C -> D -> E -> F
121
    #     |                        ^
122
    #     |                        |
123
    #     +--> Z ------------------+
124
    #
125
    # In this case, Starting with F, looking for A will return
126
    # A-F for a revision_history search, but breadth-first will
127
    # return A,Z,F since it is a much shorter path, and with
128
    # F merging Z, it looks like a shortcut.
129
    #
130
    # But since A-F seems to be the more "correct" history
131
    # for F, we might consider that revision_history should always
132
    # be consulted first, and if not found there, to use breadth
133
    # first search.
134
    checked_rev_ids = set()
135
136
    cur_trails = [[this_rev_id]]
137
    
138
    while len(cur_trails) > 0:
139
        cur_trail = cur_trails.pop(0)
140
        cur_rev_id = cur_trail[-1]
141
        if cur_rev_id in checked_rev_ids:
142
            continue
143
        checked_rev_ids.add(cur_rev_id)
144
145
        if cur_rev_id == ancestor_rev_id:
146
            return cur_trail
147
148
        if rev_id in branch.revision_store:
149
            rev = branch.get_revision(rev_id)
150
        else:
151
            # Should we just continue here?
152
            warning('Could not find revision for rev: {%s}, unable to'
153
                    ' trace ancestry.' % rev_id)
154
            continue
155
156
        for parent in rev.parents:
157
            if parent.revision_id not in checked:
158
                to_check.append(cur_trail + [parent.revision_id])
159
160
    raise BzrCommandError('Revision id {%s} not an ancestor of {%s}'
161
            % (ancestor_rev_id, this_rev_id))
0.5.1 by John Arbash Meinel
Just an initial working step.
162
163
class MetaInfoHeader(object):
164
    """Maintain all of the header information about this
165
    changeset.
166
    """
167
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
168
    def __init__(self,
169
            base_branch, base_rev_id, base_tree,
170
            target_branch, target_rev_id, target_tree,
171
            delta,
172
            starting_rev_id=None,
173
            full_remove=False, full_rename=False,
174
            base_label = 'BASE', target_label = 'TARGET'):
0.5.5 by John Arbash Meinel
Updated to now include the diffs
175
        """
176
        :param full_remove: Include the full-text for a delete
177
        :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.
178
0.5.5 by John Arbash Meinel
Updated to now include the diffs
179
        """
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
180
        self.base_branch = base_branch
181
        self.base_rev_id = base_rev_id
182
        self.base_tree = base_tree
183
184
        self.target_branch = target_branch
185
        self.target_rev_id = target_rev_id
186
        self.target_tree = target_tree
187
0.5.1 by John Arbash Meinel
Just an initial working step.
188
        self.delta = delta
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
189
190
        self.starting_rev_id = starting_rev_id
191
0.5.5 by John Arbash Meinel
Updated to now include the diffs
192
        self.full_remove=full_remove
193
        self.full_rename=full_rename
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
194
195
        self.base_label = base_label
0.5.5 by John Arbash Meinel
Updated to now include the diffs
196
        self.new_label = new_label
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
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
        self.to_file = None
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
199
        #self.revno = None
200
        #self.parent_revno = None
201
202
        # These are entries in the header.
203
        # They will be repeated in the footer,
204
        # only if they have changed
205
        self.date = None
206
        self.committer = None
207
        self.message = 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.
208
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
209
        self._get_revision_list()
0.5.1 by John Arbash Meinel
Just an initial working step.
210
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
211
    def _get_revision_list(self):
0.5.1 by John Arbash Meinel
Just an initial working step.
212
        """This generates the list of all revisions from->to.
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
213
        It fills out the internal self.revision_list with Revision
214
        entries which should be in the changeset.
0.5.1 by John Arbash Meinel
Just an initial working step.
215
        """
216
        for revno, rev in enumerate(rh):
217
            if rev == revisions[0]:
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
218
                base_revno = revno
0.5.1 by John Arbash Meinel
Just an initial working step.
219
            if rev == revisions[1]:
220
                new_revno = revno
221
0.5.3 by John Arbash Meinel
Added a couple more bits
222
        self.revision_list = []
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
223
        if base_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.
224
            self.base_revision = None # Effectively the EmptyTree()
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
225
            base_revno = -1
0.5.3 by John Arbash Meinel
Added a couple more bits
226
        else:
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
227
            self.base_revision = self.branch.get_revision(rh[base_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.
228
        if new_revno is None:
229
            # For the future, when we support working tree changesets.
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
230
            for rev_id in rh[base_revno+1:]:
0.5.1 by John Arbash Meinel
Just an initial working step.
231
                self.revision_list.append(self.branch.get_revision(rev_id))
232
            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.
233
        else:
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
234
            for rev_id in rh[base_revno+1: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.
235
                self.revision_list.append(self.branch.get_revision(rev_id))
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
236
        #self.parent_revno = base_revno+1
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
237
        #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.
238
239
    def _write(self, txt, key=None):
240
        if key:
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
241
            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.
242
        else:
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
243
            self.to_file.write('# %s\n' % (txt,))
0.5.1 by John Arbash Meinel
Just an initial working step.
244
245
    def write_meta_info(self, to_file):
0.5.5 by John Arbash Meinel
Updated to now include the diffs
246
        """Write out the meta-info portion to the supplied file.
247
248
        :param to_file: Write out the meta information to the supplied
249
                        file
250
        """
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
251
        self.to_file = to_file
252
253
        self._write_header()
254
        self._write_diffs()
255
        self._write_footer()
256
257
    def _write_header(self):
258
        """Write the stuff that comes before the patches."""
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
259
        from bzrlib.osutils import username
260
        from common import format_highres_date
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
        write = self._write
262
263
        for line in common.get_header():
264
            write(line)
265
0.5.27 by John Arbash Meinel
Now capable of generating rollup changesets.
266
        # Print out the basic information about the 'target' revision
267
        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.
268
        write(rev.committer, key='committer')
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
269
        self.committer = rev.committer
270
        self.date = format_highres_date(rev.timestamp, offset=rev.timezone)
271
        write(self.date, key='date')
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
272
        if rev.message:
273
            self.to_file.write('# message:\n')
274
            for line in rev.message.split('\n'):
275
                self.to_file.write('#    %s\n' % line)
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
276
            self.message = rev.message
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
277
0.5.4 by John Arbash Meinel
Added printout of file ids, need directory ids
278
        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.
279
        self.to_file.write('\n')
280
281
    def _write_footer(self):
282
        """Write the stuff that comes after the patches.
283
284
        This is meant to be more meta-information, which people probably don't want
285
        to read, but which is required for proper bzr operation.
286
        """
287
        write = self._write
288
0.5.57 by John Arbash Meinel
Simplified the header, only output base if it is not the expected one.
289
        # What should we print out for an Empty base revision?
0.5.59 by John Arbash Meinel
Several fixes for handling the case where you are doing a changeset against revno=0 (Null base)
290
        if len(self.revision_list[0].parents) == 0:
291
            assumed_base = None
292
        else:
293
            assumed_base = self.revision_list[0].parents[0].revision_id
294
        if (self.base_revision is not None 
295
                and self.base_revision.revision_id != assumed_base):
0.5.57 by John Arbash Meinel
Simplified the header, only output base if it is not the expected one.
296
            base = self.base_revision.revision_id
297
            write(base, key='base')
298
            write(self.branch.get_revision_sha1(base), key='base sha1')
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
299
0.5.25 by John Arbash Meinel
Added some work to allow rollup revisions, and handling multiple parents.
300
        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.
301
302
    def _write_revisions(self):
303
        """Not used. Used for writing multiple revisions."""
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
304
        from common import format_highres_date
305
0.5.3 by John Arbash Meinel
Added a couple more bits
306
        for rev in self.revision_list:
0.5.25 by John Arbash Meinel
Added some work to allow rollup revisions, and handling multiple parents.
307
            rev_id = rev.revision_id
308
            self.to_file.write('# revision: %s\n' % rev_id)
309
            self.to_file.write('#    sha1: %s\n' % 
310
                self.branch.get_revision_sha1(rev_id))
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
311
            if rev.committer != self.committer:
312
                self.to_file.write('#    committer: %s\n' % rev.committer)
313
            date = format_highres_date(rev.timestamp, rev.timezone)
314
            if date != self.date:
315
                self.to_file.write('#    date: %s\n' % date)
316
            if rev.inventory_id != rev_id:
317
                self.to_file.write('#    inventory id: %s\n' % rev.inventory_id)
0.5.25 by John Arbash Meinel
Added some work to allow rollup revisions, and handling multiple parents.
318
            self.to_file.write('#    inventory sha1: %s\n' % rev.inventory_sha1)
0.5.59 by John Arbash Meinel
Several fixes for handling the case where you are doing a changeset against revno=0 (Null base)
319
            if len(rev.parents) > 0:
320
                self.to_file.write('#    parents:\n')
321
                for parent in rev.parents:
322
                    self.to_file.write('#       %s\t%s\n' % (
323
                        parent.revision_id,
324
                        parent.revision_sha1))
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
325
            if rev.message and rev.message != self.message:
326
                self.to_file.write('#    message:\n')
327
                for line in rev.message.split('\n'):
328
                    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.
329
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
330
    def _write_diffs(self):
0.5.5 by John Arbash Meinel
Updated to now include the diffs
331
        """Write out the specific diffs"""
332
        from bzrlib.diff import internal_diff, external_diff
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
333
        from common import encode
0.5.5 by John Arbash Meinel
Updated to now include the diffs
334
        DEVNULL = '/dev/null'
335
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
336
        diff_file = internal_diff
337
        # Get the target tree so that we can check for
338
        # Appropriate text ids.
339
        rev_id = self.revision_list[-1].revision_id
340
        tree = self.branch.revision_tree(rev_id)
341
342
343
        def get_text_id_str(file_id, modified=True):
344
            """This returns an empty string if guess_text_id == real_text_id.
345
            Otherwise it returns a string suitable for printing, indicating
346
            the file's id.
347
            """
348
            guess_id = common.guess_text_id(tree, file_id, rev_id,
349
                    modified=modified)
350
            real_id = tree.inventory[file_id].text_id
351
            if guess_id != real_id:
352
                return '\ttext-id:' + encode(real_id)
353
            else:
354
                return ''
355
0.5.5 by John Arbash Meinel
Updated to now include the diffs
356
357
        for path, file_id, kind in self.delta.removed:
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
358
            # We don't care about text ids for removed files
359
            print >>self.to_file, '*** removed %s %s' % (kind,
360
                    encode(path))
0.5.5 by John Arbash Meinel
Updated to now include the diffs
361
            if kind == 'file' and self.full_remove:
362
                diff_file(self.old_label + path,
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
363
                          self.base_tree.get_file(file_id).readlines(),
0.5.5 by John Arbash Meinel
Updated to now include the diffs
364
                          DEVNULL, 
365
                          [],
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
366
                          self.to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
367
    
368
        for path, file_id, kind in self.delta.added:
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
369
            print >>self.to_file, '*** added %s %s\tfile-id:%s%s' % (kind,
370
                    encode(path),
371
                    encode(file_id),
372
                    get_text_id_str(file_id))
0.5.5 by John Arbash Meinel
Updated to now include the diffs
373
            if kind == 'file':
374
                diff_file(DEVNULL,
375
                          [],
376
                          self.new_label + path,
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
377
                          self.target_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.
378
                          self.to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
379
    
380
        for old_path, new_path, file_id, kind, text_modified in self.delta.renamed:
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
381
            print >>self.to_file, '*** renamed %s %s\t=> %s%s' % (kind,
382
                    encode(old_path), encode(new_path),
383
                    get_text_id_str(file_id, text_modified))
0.5.5 by John Arbash Meinel
Updated to now include the diffs
384
            if self.full_rename and kind == 'file':
385
                diff_file(self.old_label + old_path,
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
386
                          self.base_tree.get_file(file_id).readlines(),
0.5.5 by John Arbash Meinel
Updated to now include the diffs
387
                          DEVNULL, 
388
                          [],
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
389
                          self.to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
390
                diff_file(DEVNULL,
391
                          [],
392
                          self.new_label + new_path,
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
393
                          self.target_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.
394
                          self.to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
395
            elif text_modified:
396
                    diff_file(self.old_label + old_path,
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
397
                              self.base_tree.get_file(file_id).readlines(),
0.5.5 by John Arbash Meinel
Updated to now include the diffs
398
                              self.new_label + new_path,
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
399
                              self.target_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.
400
                              self.to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
401
    
402
        for path, file_id, kind in self.delta.modified:
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
403
            print >>self.to_file, '*** modified %s %s%s' % (kind,
404
                    encode(path), get_text_id_str(file_id))
0.5.5 by John Arbash Meinel
Updated to now include the diffs
405
            if kind == 'file':
406
                diff_file(self.old_label + path,
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
407
                          self.base_tree.get_file(file_id).readlines(),
0.5.5 by John Arbash Meinel
Updated to now include the diffs
408
                          self.new_label + path,
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
409
                          self.target_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.
410
                          self.to_file)
0.5.1 by John Arbash Meinel
Just an initial working step.
411
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
412
def show_changeset(base_branch, base_rev_id,
413
        target_branch, target_rev_id,
414
        starting_rev_id = None,
415
        to_file=None, include_full_diff=False):
0.5.1 by John Arbash Meinel
Just an initial working step.
416
    from bzrlib.diff import compare_trees
417
418
    if to_file is None:
419
        import sys
420
        to_file = sys.stdout
0.5.68 by John Arbash Meinel
(broken), starting to change the syntax of the command to allow cset to take a base and a target.
421
    base_tree = base_branch.get_revision_tree(base_rev_id)
422
    target_tree = target_branch.get_revision_tree(target_rev_id)
423
424
    delta = compare_trees(base_tree, target_tree, want_unchanged=False)
425
426
    meta = MetaInfoHeader(base_branch, base_rev_id, base_tree,
427
            target_branch, target_rev_id, target_tree,
428
            delta,
429
            starting_rev_id=starting_rev_id,
430
            full_rename=include_full_diff, full_remove=include_full_diff)
0.5.1 by John Arbash Meinel
Just an initial working step.
431
    meta.write_meta_info(to_file)
432