/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
0.5.81 by John Arbash Meinel
Cleaning up from pychecker.
6
import bzrlib
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
7
import os
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
9
from bzrlib.inventory import ROOT_ID
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
10
from bzrlib.errors import BzrCommandError, NotAncestor
0.5.74 by John Arbash Meinel
Fixed handling when base does not exist in local tree, and workaround for older revisions without precursor sha hashes.
11
from bzrlib.trace import warning, mutter
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
12
from collections import deque
13
from bzrlib.revision import (common_ancestor, MultipleRevisionSources,
14
                             get_intervening_revisions)
15
from bzrlib.diff import internal_diff
0.5.5 by John Arbash Meinel
Updated to now include the diffs
16
0.5.1 by John Arbash Meinel
Just an initial working step.
17
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.
18
    """Fake a Revision object for the working tree.
19
    
20
    This is for the future, to support changesets against the working tree.
21
    """
0.5.1 by John Arbash Meinel
Just an initial working step.
22
    from bzrlib.revision import Revision
23
    import time
24
    from bzrlib.osutils import local_time_offset, \
25
            username
26
27
    precursor = branch.last_patch()
28
    precursor_sha1 = branch.get_revision_sha1(precursor)
29
30
    return Revision(timestamp=time.time(),
31
            timezone=local_time_offset(),
32
            committer=username(),
33
            precursor=precursor,
34
            precursor_sha1=precursor_sha1)
35
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.
36
def _create_ancestry_to_rev(branch, ancestor_rev_id, this_rev_id):
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
37
    """Return a listing of revisions, tracing from this_rev_id to ancestor_rev_id.
38
39
    This attempts to use branch.revision_history() as much as possible. 
40
    Because for changesets, that is generally what you want to show.
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.
41
    """
42
    # This is an optimization, when both target and base
43
    # exist in the revision history, we should already have
44
    # a valid listing of revision ancestry.
45
    rh = branch.revision_history()
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
46
    rh_set = set(rh)
47
48
    ancestry = set(branch.get_ancestry(this_rev_id))
49
    if ancestor_rev_id not in ancestry:
50
        raise NotAncestor(this_rev_id, ancestor_rev_id)
51
    # First, if ancestor_rev_id is None, then
52
    # we just need to trace back to the revision history
53
    # and then return the rest
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
54
    if ancestor_rev_id is None:
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
55
        if this_rev_id in rh_set:
56
            rh = rh[:rh.index(this_rev_id)+1]
57
            rh.reverse()
58
            rh.append(None)
59
            return rh
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
60
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
61
    if ancestor_rev_id in rh_set and this_rev_id in rh_set:
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.
62
        ancestor_idx = rh.index(ancestor_rev_id)
63
        this_rev_idx = rh.index(this_rev_id)
64
        if ancestor_idx > this_rev_idx:
65
            raise BzrCommandError('Revision {%s} is a child not an ancestor'
66
                    ' of {%s}' % (ancestor_rev_id, this_rev_id))
67
        rh_list = rh[ancestor_idx:this_rev_idx+1]
68
        rh_list.reverse()
69
        # return rh_list
70
71
    # I considered using depth-first search, as it is a little
72
    # bit less resource intensive, and it should favor generating
73
    # paths that are the same as revision_history
74
    # but since breadth-first-search is generally used
75
    # we will use that
76
    # 
77
    # WARNING: In the presence of merges, there are cases where
78
    # breadth first search will return a very different path
79
    # than revision_history or depth first search. Imaging the following:
80
    #
81
    # rh: A -> B -> C -> D -> E -> F
82
    #     |                        ^
83
    #     |                        |
84
    #     +--> Z ------------------+
85
    #
86
    # In this case, Starting with F, looking for A will return
87
    # A-F for a revision_history search, but breadth-first will
88
    # return A,Z,F since it is a much shorter path, and with
89
    # F merging Z, it looks like a shortcut.
90
    #
91
    # But since A-F seems to be the more "correct" history
92
    # for F, we might consider that revision_history should always
93
    # be consulted first, and if not found there, to use breadth
94
    # first search.
95
    checked_rev_ids = set()
96
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
97
    cur_trails = deque([[this_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.
98
    
99
    while len(cur_trails) > 0:
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
100
        cur_trail = cur_trails.popleft()
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.
101
        cur_rev_id = cur_trail[-1]
102
        if cur_rev_id in checked_rev_ids:
103
            continue
104
        checked_rev_ids.add(cur_rev_id)
105
106
        if cur_rev_id == ancestor_rev_id:
107
            return cur_trail
108
0.5.71 by John Arbash Meinel
Cleaning up code for latest bzr.
109
        if cur_rev_id in branch.revision_store:
110
            rev = branch.get_revision(cur_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.
111
        else:
112
            # Should we just continue here?
113
            warning('Could not find revision for rev: {%s}, unable to'
0.5.71 by John Arbash Meinel
Cleaning up code for latest bzr.
114
                    ' trace ancestry.' % cur_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.
115
            continue
116
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
117
        for p_id in rev.parent_ids:
118
            if p_id not in checked_rev_ids:
119
                cur_trails.append(cur_trail + [p_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.
120
121
    raise BzrCommandError('Revision id {%s} not an ancestor of {%s}'
122
            % (ancestor_rev_id, this_rev_id))
0.5.1 by John Arbash Meinel
Just an initial working step.
123
124
class MetaInfoHeader(object):
125
    """Maintain all of the header information about this
126
    changeset.
127
    """
128
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.
129
    def __init__(self,
130
            base_branch, base_rev_id, base_tree,
131
            target_branch, target_rev_id, target_tree,
132
            delta,
133
            starting_rev_id=None,
134
            full_remove=False, full_rename=False,
0.5.103 by John Arbash Meinel
Updated to having a changeset specific message.
135
            message=None,
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
136
            base_label = 'orig', target_label = 'mod'):
0.5.5 by John Arbash Meinel
Updated to now include the diffs
137
        """
138
        :param full_remove: Include the full-text for a delete
139
        :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.
140
0.5.5 by John Arbash Meinel
Updated to now include the diffs
141
        """
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.
142
        self.base_branch = base_branch
143
        self.base_rev_id = base_rev_id
144
        self.base_tree = base_tree
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
145
        if self.base_rev_id is not None:
146
            self.base_revision = self.base_branch.get_revision(self.base_rev_id)
147
        else:
148
            self.base_revision = None
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.
149
150
        self.target_branch = target_branch
151
        self.target_rev_id = target_rev_id
152
        self.target_tree = target_tree
153
0.5.1 by John Arbash Meinel
Just an initial working step.
154
        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.
155
156
        self.starting_rev_id = starting_rev_id
157
0.5.5 by John Arbash Meinel
Updated to now include the diffs
158
        self.full_remove=full_remove
159
        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.
160
161
        self.base_label = base_label
0.5.71 by John Arbash Meinel
Cleaning up code for latest bzr.
162
        self.target_label = target_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.
163
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
164
        self.to_file = None
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
165
        #self.revno = None
166
        #self.parent_revno = None
167
168
        # These are entries in the header.
169
        # They will be repeated in the footer,
170
        # only if they have changed
171
        self.date = None
172
        self.committer = None
0.5.103 by John Arbash Meinel
Updated to having a changeset specific message.
173
        self.message = 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.
174
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.
175
        self._get_revision_list()
0.5.1 by John Arbash Meinel
Just an initial working step.
176
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.
177
    def _get_revision_list(self):
0.5.1 by John Arbash Meinel
Just an initial working step.
178
        """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.
179
        It fills out the internal self.revision_list with Revision
180
        entries which should be in the changeset.
0.5.1 by John Arbash Meinel
Just an initial working step.
181
        """
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
182
        source = MultipleRevisionSources(self.target_branch, self.base_branch)
0.5.71 by John Arbash Meinel
Cleaning up code for latest bzr.
183
        if self.starting_rev_id is None:
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
184
            self.starting_rev_id = common_ancestor(self.target_rev_id, 
185
                self.base_rev_id, source)
186
187
        rev_id_list = get_intervening_revisions(self.starting_rev_id,
188
            self.target_rev_id, source, self.target_branch.revision_history())
189
190
        self.revision_list = [source.get_revision(rid) for rid in rev_id_list]
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
191
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
192
    def _write(self, txt, key=None, encode=True, indent=1):
193
        from common import encode as _encode
194
        if encode:
195
            def write(txt):
196
                self.to_file.write(_encode(txt))
197
        else:
198
            def write(txt):
199
                self.to_file.write(txt)
200
        if indent > 0:
201
            write('#' + (' ' * indent))
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
202
        if key:
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
203
            if txt:
204
                write('%s: %s\n' % (key, txt))
205
            else:
206
                write('%s:\n' % key)
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
207
        else:
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
208
            write('%s\n' % (txt,))
0.5.1 by John Arbash Meinel
Just an initial working step.
209
210
    def write_meta_info(self, to_file):
0.5.5 by John Arbash Meinel
Updated to now include the diffs
211
        """Write out the meta-info portion to the supplied file.
212
213
        :param to_file: Write out the meta information to the supplied
214
                        file
215
        """
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
216
        self.to_file = to_file
217
218
        self._write_header()
219
        self._write_diffs()
220
        self._write_footer()
221
222
    def _write_header(self):
223
        """Write the stuff that comes before the patches."""
0.5.81 by John Arbash Meinel
Cleaning up from pychecker.
224
        from common import format_highres_date, get_header
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
225
        write = self._write
226
0.5.81 by John Arbash Meinel
Cleaning up from pychecker.
227
        for line in get_header():
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
            write(line)
229
0.5.27 by John Arbash Meinel
Now capable of generating rollup changesets.
230
        # Print out the basic information about the 'target' revision
231
        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.
232
        write(rev.committer, key='committer')
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
233
        self.committer = rev.committer
234
        self.date = format_highres_date(rev.timestamp, offset=rev.timezone)
235
        write(self.date, key='date')
0.5.103 by John Arbash Meinel
Updated to having a changeset specific message.
236
        if self.message is None:
237
            if rev.message is not None:
238
                self.message = rev.message
239
        if self.message:
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
240
            write('', key='message')
0.5.103 by John Arbash Meinel
Updated to having a changeset specific message.
241
            for line in self.message.split('\n'):
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
242
                write(txt=line, indent=4)
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
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
244
        write('') # line with just '#'
245
        write('', indent=0) # Empty 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.
246
247
    def _write_footer(self):
248
        """Write the stuff that comes after the patches.
249
250
        This is meant to be more meta-information, which people probably don't want
251
        to read, but which is required for proper bzr operation.
252
        """
253
        write = self._write
254
0.5.57 by John Arbash Meinel
Simplified the header, only output base if it is not the expected one.
255
        # What should we print out for an Empty base revision?
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
256
        if len(self.revision_list[0].parent_ids) == 0:
0.5.59 by John Arbash Meinel
Several fixes for handling the case where you are doing a changeset against revno=0 (Null base)
257
            assumed_base = None
258
        else:
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
259
            assumed_base = self.revision_list[0].parent_ids[0]
260
0.5.59 by John Arbash Meinel
Several fixes for handling the case where you are doing a changeset against revno=0 (Null base)
261
        if (self.base_revision is not None 
262
                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.
263
            base = self.base_revision.revision_id
264
            write(base, key='base')
0.5.74 by John Arbash Meinel
Fixed handling when base does not exist in local tree, and workaround for older revisions without precursor sha hashes.
265
            write(self.base_branch.get_revision_sha1(base), key='base sha1')
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
266
0.5.25 by John Arbash Meinel
Added some work to allow rollup revisions, and handling multiple parents.
267
        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.
268
269
    def _write_revisions(self):
270
        """Not used. Used for writing multiple revisions."""
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
271
        from common import format_highres_date, encode
272
273
        write = self._write
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
274
0.5.3 by John Arbash Meinel
Added a couple more bits
275
        for rev in self.revision_list:
0.5.25 by John Arbash Meinel
Added some work to allow rollup revisions, and handling multiple parents.
276
            rev_id = rev.revision_id
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
277
            write(rev_id, key='revision')
278
            write(self.target_branch.get_revision_sha1(rev_id),
279
                    key = 'sha1', indent=4)
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
280
            if rev.committer != self.committer:
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
281
                write(rev.committer, key='committer', indent=4)
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
282
            date = format_highres_date(rev.timestamp, rev.timezone)
283
            if date != self.date:
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
284
                write(date, key='date', indent=4)
285
            write(rev.inventory_sha1, key='inventory sha1', indent=4)
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
286
            if len(rev.parent_ids) > 0:
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
287
                write(txt='', key='parents', indent=4)
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
288
                for p_id in rev.parent_ids:
289
                    p_sha1 = self.target_branch.get_revision_sha1(p_id)
0.5.74 by John Arbash Meinel
Fixed handling when base does not exist in local tree, and workaround for older revisions without precursor sha hashes.
290
                    if p_sha1 is None:
291
                        warning('Rev id {%s} parent {%s} missing sha hash.'
292
                                % (rev_id, p_id))
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
293
                        write(p_id + '\t' + p_sha1, indent=7)
294
                    else:
295
                        write(p_id, indent=7)
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
296
            if rev.message and rev.message != self.message:
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
297
                write('', key='message', indent=4)
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
298
                for line in rev.message.split('\n'):
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
299
                    write(line, indent=7)
0.5.25 by John Arbash Meinel
Added some work to allow rollup revisions, and handling multiple parents.
300
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
    def _write_diffs(self):
0.5.5 by John Arbash Meinel
Updated to now include the diffs
302
        """Write out the specific diffs"""
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
303
        def pjoin(*args):
304
            # Only forward slashes in changesets
305
            return os.path.join(*args).replace('\\', '/')
306
307
        def _maybe_diff(old_label, old_path, old_tree, file_id,
308
                        new_label, new_path, new_tree, text_modified,
309
                        kind, to_file, diff_file):
310
            if text_modified:
311
                new_entry = new_tree.inventory[file_id]
312
                old_tree.inventory[file_id].diff(diff_file,
313
                                                 pjoin(old_label, old_path), old_tree,
314
                                                 pjoin(new_label, new_path), new_entry, 
315
                                                 new_tree, to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
316
        DEVNULL = '/dev/null'
317
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
318
        diff_file = internal_diff
319
        # Get the target tree so that we can check for
320
        # Appropriate text ids.
0.5.73 by John Arbash Meinel
Some fixups for gen_changeset.
321
        rev_id = self.target_rev_id
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
322
323
        new_label = self.target_label
324
        new_tree = self.target_tree
325
326
        old_tree = self.base_tree
327
        old_label = self.base_label
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
328
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
329
        write = self._write
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
330
        to_file = self.to_file
331
332
333
        def get_rev_id_str(file_id, kind):
334
            last_changed_rev_id = new_tree.inventory[file_id].revision
335
336
            if rev_id != last_changed_rev_id:
337
                return ' // last-changed:' + last_changed_rev_id
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
338
            else:
339
                return ''
340
0.5.5 by John Arbash Meinel
Updated to now include the diffs
341
        for path, file_id, kind in self.delta.removed:
0.5.100 by John Arbash Meinel
Switching from *** to ===
342
            write('=== removed %s %s' % (kind, path), indent=0)
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
343
            if self.full_remove:
344
                old_tree.inventory[file_id].diff(diff_file, pjoin(old_label, path), old_tree,
345
                                                 DEVNULL, None, None, to_file)
0.5.5 by John Arbash Meinel
Updated to now include the diffs
346
        for path, file_id, kind in self.delta.added:
0.5.100 by John Arbash Meinel
Switching from *** to ===
347
            write('=== added %s %s // file-id:%s%s' % (kind,
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
348
                    path, file_id, get_rev_id_str(file_id, kind)),
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
349
                    indent=0)
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
350
            new_tree.inventory[file_id].diff(diff_file, pjoin(new_label, path), new_tree,
351
                                             DEVNULL, None, None, to_file, 
352
                                             reverse=True)
353
        for (old_path, new_path, file_id, kind,
354
             text_modified, meta_modified) in self.delta.renamed:
355
            # TODO: Handle meta_modified
356
            #prop_str = get_prop_change(meta_modified)
0.5.100 by John Arbash Meinel
Switching from *** to ===
357
            write('=== renamed %s %s // %s%s' % (kind,
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
358
                    old_path, new_path,
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
359
                    get_rev_id_str(file_id, kind)),
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
360
                    indent=0)
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
361
            if self.full_rename:
362
                # Looks like a delete + add
363
                old_tree.inventory[file_id].diff(diff_file, pjoin(old_label, path), old_tree,
364
                                                 DEVNULL, None, None, to_file)
365
                new_tree.inventory[file_id].diff(diff_file, pjoin(new_label, path), new_tree,
366
                                                 DEVNULL, None, None, to_file, 
367
                                                 reverse=True)
368
            else:
369
                _maybe_diff(old_label, old_path, old_tree, file_id,
370
                            new_label, new_path, new_tree,
371
                            text_modified, kind, to_file, diff_file)
372
373
        for (path, file_id, kind,
374
             text_modified, meta_modified) in self.delta.modified:
375
            # TODO: Handle meta_modified
376
            #prop_str = get_prop_change(meta_modified)
0.5.100 by John Arbash Meinel
Switching from *** to ===
377
            write('=== modified %s %s%s' % (kind,
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
378
                    path, get_rev_id_str(file_id, kind)),
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
379
                    indent=0)
0.5.112 by John Arbash Meinel
Upgrading to v5 (ignoring compatibility)
380
            _maybe_diff(old_label, path, old_tree, file_id,
381
                        new_label, path, new_tree,
382
                        text_modified, kind, to_file, diff_file)
383
 
0.5.1 by John Arbash Meinel
Just an initial working step.
384
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.
385
def show_changeset(base_branch, base_rev_id,
386
        target_branch, target_rev_id,
387
        starting_rev_id = None,
0.5.103 by John Arbash Meinel
Updated to having a changeset specific message.
388
        to_file=None, include_full_diff=False,
389
        message=None):
0.5.1 by John Arbash Meinel
Just an initial working step.
390
    from bzrlib.diff import compare_trees
391
392
    if to_file is None:
393
        import sys
394
        to_file = sys.stdout
0.5.71 by John Arbash Meinel
Cleaning up code for latest bzr.
395
    base_tree = base_branch.revision_tree(base_rev_id)
396
    target_tree = target_branch.revision_tree(target_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.
397
398
    delta = compare_trees(base_tree, target_tree, want_unchanged=False)
399
400
    meta = MetaInfoHeader(base_branch, base_rev_id, base_tree,
401
            target_branch, target_rev_id, target_tree,
402
            delta,
403
            starting_rev_id=starting_rev_id,
0.5.103 by John Arbash Meinel
Updated to having a changeset specific message.
404
            full_rename=include_full_diff, full_remove=include_full_diff,
405
            message=message)
0.5.1 by John Arbash Meinel
Just an initial working step.
406
    meta.write_meta_info(to_file)
407