/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.8.1 by John Arbash Meinel
Creating a plugin to ease generating version information from a tree.
1
# Copyright (C) 2005 Canonical Ltd
2
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""\
18
Routines for extracting all version information from a bzr branch.
19
"""
20
21
import time
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
22
import pprint
23
0.8.3 by John Arbash Meinel
Playing around with some formats
24
from StringIO import StringIO
0.8.1 by John Arbash Meinel
Creating a plugin to ease generating version information from a tree.
25
0.8.3 by John Arbash Meinel
Playing around with some formats
26
from bzrlib.errors import NoWorkingTree
27
from bzrlib.log import show_log, log_formatter
0.8.1 by John Arbash Meinel
Creating a plugin to ease generating version information from a tree.
28
from bzrlib.rio import RioReader, RioWriter, Stanza
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
29
from bzrlib.osutils import local_time_offset, format_date
30
31
32
def get_file_revisions(branch, check=False):
33
    """Get the last changed revision for all files.
34
35
    :param branch: The branch we are checking.
36
    :param check: See if there are uncommitted changes.
37
    :return: ({file_path => last changed revision}, Tree_is_clean)
0.8.1 by John Arbash Meinel
Creating a plugin to ease generating version information from a tree.
38
    """
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
39
    clean = True
40
    file_revisions = {}
41
    basis_tree = branch.basis_tree()
42
    for path, ie in basis_tree.inventory.iter_entries():
43
        file_revisions[path] = ie.revision
44
45
    if not check:
46
        # Without checking, the tree looks clean
47
        return file_revisions, clean
0.8.1 by John Arbash Meinel
Creating a plugin to ease generating version information from a tree.
48
    try:
49
        new_tree = branch.working_tree()
50
    except NoWorkingTree:
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
51
        # Without a working tree, everything is clean
52
        return file_revisions, clean
53
54
    from bzrlib.diff import compare_trees
55
    delta = compare_trees(basis_tree, new_tree, want_unchanged=False)
56
57
    # Using a 2-pass algorithm for renames. This is because you might have
58
    # renamed something out of the way, and then created a new file
59
    # in which case we would rather see the new marker
60
    # Or you might have removed the target, and then renamed
61
    # in which case we would rather see the renamed marker
62
    for old_path, new_path, file_id, kind, text_mod, meta_mod in delta.renamed:
63
        clean = False
64
        file_revisions[old_path] = u'renamed to %s' % (new_path,)
65
    for path, file_id, kind in delta.removed:
66
        clean = False
67
        file_revisions[path] = 'removed'
68
    for path, file_id, kind in delta.added:
69
        clean = False
70
        file_revisions[path] = 'new'
71
    for old_path, new_path, file_id, kind, text_mod, meta_mod in delta.renamed:
72
        clean = False
73
        file_revisions[new_path] = u'renamed from %s' % (old_path,)
74
    for path, file_id, kind, text_mod, meta_mod in delta.modified:
75
        clean = False
76
        file_revisions[path] = 'modified'
77
0.8.1 by John Arbash Meinel
Creating a plugin to ease generating version information from a tree.
78
    for info in new_tree.list_files():
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
79
        path, status = info[0:2]
80
        if status == '?':
81
            file_revisions[path] = 'unversioned'
82
            clean = False
83
84
    return file_revisions, clean
0.8.3 by John Arbash Meinel
Playing around with some formats
85
86
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
87
# This contains a map of format id => formatter
88
# None is considered the default formatter
0.8.3 by John Arbash Meinel
Playing around with some formats
89
version_formats = {}
0.8.1 by John Arbash Meinel
Creating a plugin to ease generating version information from a tree.
90
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
91
def create_date_str(timestamp=None, offset=None):
92
    """Just a wrapper around format_date to provide the right format.
93
    
94
    We don't want to use '%a' in the time string, because it is locale
95
    dependant. We also want to force timezone original, and show_offset
96
97
    Without parameters this function yields the current date in the local
98
    time zone.
99
    """
100
    if timestamp is None and offset is None:
101
        timestamp = time.time()
102
        offset = local_time_offset()
103
    return format_date(timestamp, offset, date_fmt='%Y-%m-%d %H:%M:%S',
104
                       timezone='original', show_offset=True)
105
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
106
0.8.2 by John Arbash Meinel
Have working rio output
107
def generate_rio_version(branch, to_file,
0.8.1 by John Arbash Meinel
Creating a plugin to ease generating version information from a tree.
108
        check_for_clean=False,
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
109
        include_revision_history=False,
110
        include_file_revisions=False):
0.8.1 by John Arbash Meinel
Creating a plugin to ease generating version information from a tree.
111
    """Create the version file for this project.
112
113
    :param branch: The branch to write information about
114
    :param to_file: The file to write the information
115
    :param check_for_clean: If true, check if the branch is clean.
116
        This can be expensive for large trees. This is also only
117
        valid for branches with working trees.
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
118
    :param include_revision_history: Write out the list of revisions, and
119
        the commit message associated with each
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
120
    :param include_file_revisions: Write out the set of last changed revision
121
        for each file.
0.8.1 by John Arbash Meinel
Creating a plugin to ease generating version information from a tree.
122
    """
123
    info = Stanza()
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
124
    info.add('build-date', create_date_str())
0.8.2 by John Arbash Meinel
Have working rio output
125
    info.add('revno', str(branch.revno()))
0.8.3 by John Arbash Meinel
Playing around with some formats
126
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
127
    last_rev_id = branch.last_revision()
128
    if last_rev_id is not None:
129
        info.add('revision_id', last_rev_id)
130
        rev = branch.get_revision(last_rev_id)
131
        info.add('date', create_date_str(rev.timestamp, rev.timezone))
0.8.3 by John Arbash Meinel
Playing around with some formats
132
0.8.2 by John Arbash Meinel
Have working rio output
133
    if branch.nick is not None:
134
        info.add('branch_nick', branch.nick)
0.8.3 by John Arbash Meinel
Playing around with some formats
135
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
136
    file_revisions = {}
137
    clean = True
138
    if check_for_clean or include_file_revisions:
139
        file_revisions, clean = get_file_revisions(branch, check=check_for_clean)
140
0.8.1 by John Arbash Meinel
Creating a plugin to ease generating version information from a tree.
141
    if check_for_clean:
0.8.3 by John Arbash Meinel
Playing around with some formats
142
        if clean:
143
            info.add('clean', 'True')
144
        else:
0.8.2 by John Arbash Meinel
Have working rio output
145
            info.add('clean', 'False')
0.8.3 by John Arbash Meinel
Playing around with some formats
146
147
    if include_revision_history:
148
        revs = branch.revision_history()
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
149
        log = Stanza()
150
        for rev_id in revs:
151
            rev = branch.get_revision(rev_id)
0.8.6 by John Arbash Meinel
Updated the blackbox tests.
152
            log.add('id', rev_id)
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
153
            log.add('message', rev.message)
154
        sio = StringIO()
155
        log_writer = RioWriter(to_file=sio)
156
        log_writer.write_stanza(log)
157
        info.add('revisions', sio.getvalue())
0.8.3 by John Arbash Meinel
Playing around with some formats
158
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
159
    if include_file_revisions:
160
        files = Stanza()
161
        for path in sorted(file_revisions.keys()):
162
            files.add('path', path)
163
            files.add('revision', file_revisions[path])
164
        sio = StringIO()
165
        file_writer = RioWriter(to_file=sio)
166
        file_writer.write_stanza(files)
167
        info.add('file-revisions', sio.getvalue())
168
0.8.2 by John Arbash Meinel
Have working rio output
169
    writer = RioWriter(to_file=to_file)
170
    writer.write_stanza(info)
0.8.1 by John Arbash Meinel
Creating a plugin to ease generating version information from a tree.
171
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
172
0.8.3 by John Arbash Meinel
Playing around with some formats
173
version_formats['rio'] = generate_rio_version
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
174
# Default format is rio
0.8.3 by John Arbash Meinel
Playing around with some formats
175
version_formats[None] = generate_rio_version
176
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
177
178
# Header and footer for the python format
179
_py_version_header = '''#!/usr/bin/env python
0.8.3 by John Arbash Meinel
Playing around with some formats
180
"""\\
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
181
This file is automatically generated by generate_version_info
0.8.3 by John Arbash Meinel
Playing around with some formats
182
It uses the current working tree to determine the revision.
183
So don't edit it. :)
184
"""
185
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
186
'''
187
188
189
_py_version_footer = '''
0.8.3 by John Arbash Meinel
Playing around with some formats
190
191
if __name__ == '__main__':
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
192
    print 'revision: %(revno)d' % version_info
193
    print 'nick: %(branch_nick)s' % version_info
194
    print 'revision id: %(revision_id)s' % version_info
0.8.3 by John Arbash Meinel
Playing around with some formats
195
'''
196
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
197
0.8.3 by John Arbash Meinel
Playing around with some formats
198
def generate_python_version(branch, to_file,
199
        check_for_clean=False,
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
200
        include_revision_history=False,
201
        include_file_revisions=False):
0.8.3 by John Arbash Meinel
Playing around with some formats
202
    """Create a python version file for this project.
203
204
    :param branch: The branch to write information about
205
    :param to_file: The file to write the information
206
    :param check_for_clean: If true, check if the branch is clean.
207
        This can be expensive for large trees. This is also only
208
        valid for branches with working trees.
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
209
    :param include_revision_history: Write out the list of revisions, and
210
        the commit message associated with each
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
211
    :param include_file_revisions: Write out the set of last changed revision
212
        for each file.
0.8.3 by John Arbash Meinel
Playing around with some formats
213
    """
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
214
    # TODO: jam 20051228 The python output doesn't actually need to be
215
    #       encoded, because it should only generate ascii safe output.
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
216
    info = {'build-date':create_date_str()
0.8.3 by John Arbash Meinel
Playing around with some formats
217
              , 'revno':branch.revno()
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
218
              , 'revision_id':None
0.8.3 by John Arbash Meinel
Playing around with some formats
219
              , 'branch_nick':branch.nick
220
              , 'clean':None
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
221
              , 'date':None
0.8.3 by John Arbash Meinel
Playing around with some formats
222
    }
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
223
    revisions = []
224
225
    last_rev_id = branch.last_revision()
226
    if last_rev_id:
227
        rev = branch.get_revision(last_rev_id)
228
        info['revision_id'] = last_rev_id
229
        info['date'] = create_date_str(rev.timestamp, rev.timezone)
230
231
    file_revisions = {}
232
    clean = True
233
    if check_for_clean or include_file_revisions:
234
        file_revisions, clean = get_file_revisions(branch, check=check_for_clean)
0.8.3 by John Arbash Meinel
Playing around with some formats
235
236
    if check_for_clean:
0.8.5 by John Arbash Meinel
Adding some whitebox tests for the output of generate_version_info
237
        if clean:
0.8.3 by John Arbash Meinel
Playing around with some formats
238
            info['clean'] = True
239
        else:
240
            info['clean'] = False
241
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
242
    info_str = pprint.pformat(info)
243
    to_file.write(_py_version_header)
244
    to_file.write('version_info =')
245
    to_file.write(info_str)
246
    to_file.write('\n')
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
247
248
    if include_revision_history:
249
        revs = branch.revision_history()
250
        for rev_id in revs:
251
            rev = branch.get_revision(rev_id)
252
            revisions.append((rev_id, rev.message))
253
        revision_str = pprint.pformat(revisions)
254
        to_file.write('revisions = ')
255
        to_file.write(revision_str)
256
        to_file.write('\n')
257
    else:
258
        to_file.write('revisions = {}\n\n')
259
260
    if include_file_revisions:
261
        file_rev_str = pprint.pformat(file_revisions)
262
        to_file.write('file_revisions = ')
263
        to_file.write(file_rev_str)
264
        to_file.write('\n')
265
    else:
266
        to_file.write('file_revisions = {}\n\n')
267
0.8.4 by John Arbash Meinel
Cleaned up formats include-history always displays the log message.
268
    to_file.write(_py_version_footer)
0.8.3 by John Arbash Meinel
Playing around with some formats
269
0.8.13 by John Arbash Meinel
Including file-revisions fields, updated test suite.
270
0.8.3 by John Arbash Meinel
Playing around with some formats
271
version_formats['python'] = generate_python_version
0.8.1 by John Arbash Meinel
Creating a plugin to ease generating version information from a tree.
272