~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to gen_changeset.py

  • Committer: John Arbash Meinel
  • Date: 2005-06-19 22:39:03 UTC
  • mto: (0.5.85) (1185.82.1 bzr-w-changeset)
  • mto: This revision was merged to the branch mainline in revision 1738.
  • Revision ID: john@arbash-meinel.com-20050619223903-b85a522a84697931
Added a bunch more information about changesets. Can now read back in all of the meta information.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 
6
6
import bzrlib, bzrlib.errors
7
7
 
 
8
import common
 
9
 
 
10
from bzrlib.inventory import ROOT_ID
 
11
 
8
12
try:
9
13
    set
10
14
except NameError:
11
15
    from sets import Set as set
12
16
 
13
 
def _canonicalize_revision(branch, revision=None):
 
17
def _canonicalize_revision(branch, revno):
14
18
    """Turn some sort of revision information into a single
15
19
    set of from-to revision ids.
16
20
 
20
24
    """
21
25
    # This is a little clumsy because revision parsing may return
22
26
    # a single entry, or a list
23
 
    if revision is None:
24
 
        old, new = None, None
25
 
    elif isinstance(revision, (list, tuple)):
26
 
        if len(revision) == 0:
27
 
            old, new = None, None
28
 
        elif len(revision) == 1:
29
 
            old = revision[0]
30
 
            new = None
31
 
        elif len(revision) == 2:
32
 
            old = revision[0]
33
 
            new = revision[1]
34
 
        else:
35
 
            raise bzrlib.errors.BzrCommandError('revision can be'
36
 
                    ' at most 2 entries.')
37
 
    else:
38
 
        old = revision
39
 
        new = None
40
 
 
41
 
    if new is not None:
42
 
        new = branch.lookup_revision(new)
43
 
    if old is None:
44
 
        old = branch.last_patch()
45
 
    else:
46
 
        old = branch.lookup_revision(old)
 
27
    if revno is None:
 
28
        new = branch.last_patch()
 
29
    else:
 
30
        new = branch.lookup_revision(revno)
 
31
 
 
32
    if new is None:
 
33
        raise BzrCommandError('Cannot generate a changset with no commits in tree.')
 
34
 
 
35
    old = branch.get_revision(new).precursor
47
36
 
48
37
    return old, new
49
38
 
51
40
    """Get the old and new trees based on revision.
52
41
    """
53
42
    if revisions[0] is None:
54
 
        old_tree = branch.basis_tree()
 
43
        if hasattr(branch, 'get_root_id'): # Watch out for trees with labeled ROOT ids
 
44
            old_tree = EmptyTree(branch.get_root_id) 
 
45
        else:
 
46
            old_tree = EmptyTree()
55
47
    else:
56
48
        old_tree = branch.revision_tree(revisions[0])
57
49
 
58
50
    if revisions[1] is None:
 
51
        # This is for the future, once we support rollup revisions
 
52
        # Or working tree revisions
59
53
        new_tree = branch.working_tree()
60
54
    else:
61
55
        new_tree = branch.revision_tree(revisions[1])
62
56
    return old_tree, new_tree
63
57
 
64
58
def _fake_working_revision(branch):
65
 
    """Fake a Revision object for the working tree."""
 
59
    """Fake a Revision object for the working tree.
 
60
    
 
61
    This is for the future, to support changesets against the working tree.
 
62
    """
66
63
    from bzrlib.revision import Revision
67
64
    import time
68
65
    from bzrlib.osutils import local_time_offset, \
94
91
        """
95
92
        self.branch = branch
96
93
        self.delta = delta
97
 
        self._get_revision_list(revisions)
98
94
        self.full_remove=full_remove
99
95
        self.full_rename=full_rename
100
96
        self.external_diff_options = external_diff_options
102
98
        self.new_label = new_label
103
99
        self.old_tree = old_tree
104
100
        self.new_tree = new_tree
 
101
        self.to_file = None
 
102
        self.revno = None
 
103
        self.precursor_revno = None
 
104
 
 
105
        self._get_revision_list(revisions)
105
106
 
106
107
    def _get_revision_list(self, revisions):
107
108
        """This generates the list of all revisions from->to.
 
109
 
 
110
        This is for the future, when we support having a rollup changeset.
 
111
        For now, the list should only be one long.
108
112
        """
109
113
        old_revno = None
110
114
        new_revno = None
117
121
 
118
122
        self.revision_list = []
119
123
        if old_revno is None:
120
 
            self.base_revision = None
121
 
            old_revno = 1
 
124
            self.base_revision = None # Effectively the EmptyTree()
 
125
            old_revno = 0
122
126
        else:
123
127
            self.base_revision = self.branch.get_revision(rh[old_revno])
124
 
        if new_revno is not None:
125
 
            for rev_id in rh[old_revno+1:new_revno+1]:
126
 
                self.revision_list.append(self.branch.get_revision(rev_id))
127
 
        else:
 
128
        if new_revno is None:
 
129
            # For the future, when we support working tree changesets.
128
130
            for rev_id in rh[old_revno+1:]:
129
131
                self.revision_list.append(self.branch.get_revision(rev_id))
130
132
            self.revision_list.append(_fake_working_revision(self.branch))
 
133
        else:
 
134
            for rev_id in rh[old_revno+1:new_revno+1]:
 
135
                self.revision_list.append(self.branch.get_revision(rev_id))
 
136
        self.precursor_revno = old_revno
 
137
        self.revno = new_revno
 
138
 
 
139
    def _write(self, txt, key=None):
 
140
        if key:
 
141
            self.to_file.write('# ' + key + ': ' + txt + '\n')
 
142
        else:
 
143
            self.to_file.write('# ' + txt + '\n')
131
144
 
132
145
    def write_meta_info(self, to_file):
133
146
        """Write out the meta-info portion to the supplied file.
135
148
        :param to_file: Write out the meta information to the supplied
136
149
                        file
137
150
        """
138
 
        from bzrlib.osutils import username
139
 
        def write(txt, key=None):
140
 
            if key:
141
 
                to_file.write('# ' + key + ': ' + txt + '\n')
142
 
            else:
143
 
                to_file.write('# ' + txt + '\n')
144
 
 
145
 
        write('Bazaar-NG (bzr) changeset v0.0.5')
146
 
        write('This changeset can be applied with bzr apply-changeset')
 
151
        self.to_file = to_file
 
152
 
 
153
        self._write_header()
 
154
        self._write_diffs()
 
155
        self._write_footer()
 
156
 
 
157
    def _write_header(self):
 
158
        """Write the stuff that comes before the patches."""
 
159
        from bzrlib.osutils import username, format_date
 
160
        write = self._write
 
161
 
 
162
        for line in common.get_header():
 
163
            write(line)
 
164
 
 
165
        # This grabs the current username, what we really want is the
 
166
        # username from the actual patches.
 
167
        #write(username(), key='committer')
 
168
        assert len(self.revision_list) == 1
 
169
        rev = self.revision_list[0]
 
170
        write(rev.committer, key='committer')
 
171
        write(format_date(rev.timestamp, offset=rev.timezone), key='date')
 
172
        write(str(self.revno), key='revno')
 
173
        write(rev.revision_id, key='revision')
 
174
 
 
175
        if self.base_revision:
 
176
            write(self.base_revision.revision_id, key='precursor')
 
177
            write(str(self.precursor_revno), key='precursor revno')
 
178
 
 
179
 
147
180
        write('')
148
 
 
149
 
        write(username(), key='committer')
150
 
 
 
181
        self.to_file.write('\n')
 
182
 
 
183
    def _write_footer(self):
 
184
        """Write the stuff that comes after the patches.
 
185
 
 
186
        This is meant to be more meta-information, which people probably don't want
 
187
        to read, but which is required for proper bzr operation.
 
188
        """
 
189
        write = self._write
 
190
 
 
191
        write('BEGIN BZR FOOTER')
 
192
 
 
193
        assert len(self.revision_list) == 1 # We only handle single revision entries
 
194
        write(self.branch.get_revision_sha1(self.revision_list[0].revision_id), key='revision sha1')
151
195
        if self.base_revision:
152
 
            write(self.base_revision.revision_id, key='precursor')
153
 
 
 
196
            write(self.branch.get_revision_sha1(self.base_revision.revision_id), 'precursor sha1')
 
197
 
 
198
        self._write_ids()
 
199
 
 
200
        write('END BZR FOOTER')
 
201
 
 
202
    def _write_revisions(self):
 
203
        """Not used. Used for writing multiple revisions."""
154
204
        first = True
155
205
        for rev in self.revision_list:
156
206
            if rev.revision_id is not None:
157
207
                if first:
158
 
                    write(rev.revision_id, key='revisions')
 
208
                    self._write('revisions:')
159
209
                    first = False
160
 
                else:
161
 
                    write(' '*11 + rev.revision_id)
162
 
 
163
 
        self._write_diffs(to_file)
164
 
        self._write_ids(to_file)
165
 
 
166
 
    def _write_ids(self, to_file):
167
 
        seen_ids = set(['TREE_ROOT'])
 
210
                self._write(' '*4 + rev.revision_id + '\t' + self.branch.get_revision_sha1(rev.revision_id))
 
211
 
 
212
 
 
213
    def _write_ids(self):
 
214
        if hasattr(self.branch, 'get_root_id'):
 
215
            root_id = self.branch.get_root_id()
 
216
        else:
 
217
            root_id = ROOT_ID
 
218
        seen_ids = set([root_id])
168
219
        need_ids = set()
169
220
 
 
221
        to_file = self.to_file
 
222
 
170
223
        def _write_entry(file_id, path=None):
171
224
            if file_id in self.new_tree.inventory:
172
225
                ie = self.new_tree.inventory[file_id]
194
247
            def __call__(self, info):
195
248
                if self.first:
196
249
                    self.first = False
197
 
                    to_file.write('# %s ids: ' % self.kind)
198
 
                else:
199
 
                    to_file.write('#')
200
 
                    to_file.write(' ' * (len(self.kind) + 7))
 
250
                    to_file.write('# %s ids:\n' % self.kind)
 
251
                to_file.write('#    ')
201
252
                _write_entry(info[1], info[0])
202
253
 
203
254
        def _write_all(kind):
210
261
                    writer(info)
211
262
            for info in self.delta.renamed:
212
263
                if info[3] == kind:
213
 
                    writer(info[1:2])
 
264
                    writer(info[1:3])
214
265
            for info in self.delta.modified:
215
266
                if info[2] == kind:
216
267
                    writer(info)
217
268
 
 
269
        self._write(root_id, key='tree root id')
 
270
 
218
271
        _write_all('file')
219
272
        _write_all('directory')
220
273
 
225
278
                continue
226
279
            seen_ids.add(file_id)
227
280
            if first:
228
 
                to_file.write('# parent ids: ')
 
281
                self.to_file.write('# parent ids: ')
229
282
                first = False
230
283
            else:
231
284
                to_file.write('#             ')
232
285
            _write_entry(file_id)
233
286
 
234
287
 
235
 
    def _write_diffs(self, to_file):
 
288
    def _write_diffs(self):
236
289
        """Write out the specific diffs"""
237
290
        from bzrlib.diff import internal_diff, external_diff
238
291
        DEVNULL = '/dev/null'
246
299
            diff_file = internal_diff
247
300
 
248
301
        for path, file_id, kind in self.delta.removed:
249
 
            print >>to_file, '*** removed %s %r' % (kind, path)
 
302
            print >>self.to_file, '*** removed %s %r' % (kind, path)
250
303
            if kind == 'file' and self.full_remove:
251
304
                diff_file(self.old_label + path,
252
305
                          self.old_tree.get_file(file_id).readlines(),
253
306
                          DEVNULL, 
254
307
                          [],
255
 
                          to_file)
 
308
                          self.to_file)
256
309
    
257
310
        for path, file_id, kind in self.delta.added:
258
 
            print >>to_file, '*** added %s %r' % (kind, path)
 
311
            print >>self.to_file, '*** added %s %r' % (kind, path)
259
312
            if kind == 'file':
260
313
                diff_file(DEVNULL,
261
314
                          [],
262
315
                          self.new_label + path,
263
316
                          self.new_tree.get_file(file_id).readlines(),
264
 
                          to_file)
 
317
                          self.to_file)
265
318
    
266
319
        for old_path, new_path, file_id, kind, text_modified in self.delta.renamed:
267
 
            print >>to_file, '*** renamed %s %r => %r' % (kind, old_path, new_path)
 
320
            print >>self.to_file, '*** renamed %s %r => %r' % (kind, old_path, new_path)
268
321
            if self.full_rename and kind == 'file':
269
322
                diff_file(self.old_label + old_path,
270
323
                          self.old_tree.get_file(file_id).readlines(),
271
324
                          DEVNULL, 
272
325
                          [],
273
 
                          to_file)
 
326
                          self.to_file)
274
327
                diff_file(DEVNULL,
275
328
                          [],
276
329
                          self.new_label + new_path,
277
330
                          self.new_tree.get_file(file_id).readlines(),
278
 
                          to_file)
 
331
                          self.to_file)
279
332
            elif text_modified:
280
333
                    diff_file(self.old_label + old_path,
281
334
                              self.old_tree.get_file(file_id).readlines(),
282
335
                              self.new_label + new_path,
283
336
                              self.new_tree.get_file(file_id).readlines(),
284
 
                              to_file)
 
337
                              self.to_file)
285
338
    
286
339
        for path, file_id, kind in self.delta.modified:
287
 
            print >>to_file, '*** modified %s %r' % (kind, path)
 
340
            print >>self.to_file, '*** modified %s %r' % (kind, path)
288
341
            if kind == 'file':
289
342
                diff_file(self.old_label + path,
290
343
                          self.old_tree.get_file(file_id).readlines(),
291
344
                          self.new_label + path,
292
345
                          self.new_tree.get_file(file_id).readlines(),
293
 
                          to_file)
 
346
                          self.to_file)
294
347
 
295
348
def show_changeset(branch, revision=None, specific_files=None,
296
349
        external_diff_options=None, to_file=None,