/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
1
# (C) 2005 Canonical Development Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
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
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
17
"""Serializer factory for reading and writing bundles.
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
18
"""
19
1185.82.96 by Aaron Bentley
Got first binary test passing
20
import base64
21
from StringIO import StringIO
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
22
import re
23
24
import bzrlib.errors as errors
1185.82.96 by Aaron Bentley
Got first binary test passing
25
from bzrlib.diff import internal_diff
1185.82.58 by Aaron Bentley
Handle empty branches properly
26
from bzrlib.revision import NULL_REVISION
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
27
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
28
# New bundles should try to use this header format
29
BUNDLE_HEADER = '# Bazaar revision bundle v'
1907.2.2 by Hermann Kraus
Detect wrong eol markers.
30
BUNDLE_HEADER_RE = re.compile(
31
    r'^# Bazaar revision bundle v(?P<version>\d+[\w.]*)(?P<lineending>\r?)\n$')
32
CHANGESET_OLD_HEADER_RE = re.compile(
33
    r'^# Bazaar-NG changeset v(?P<version>\d+[\w.]*)(?P<lineending>\r?)\n$')
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
34
35
1793.3.16 by John Arbash Meinel
Add tests to ensure that we gracefully handle opening and trailing non-bundle text.
36
_serializers = {}
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
37
38
39
def _get_filename(f):
40
    if hasattr(f, 'name'):
41
        return f.name
42
    return '<unknown>'
43
44
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
45
def read_bundle(f):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
46
    """Read in a bundle from a filelike object.
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
47
48
    :param f: A file-like object
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
49
    :return: A list of Bundle objects
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
50
    """
51
    version = None
52
    for line in f:
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
53
        m = BUNDLE_HEADER_RE.match(line)
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
54
        if m:
1907.2.2 by Hermann Kraus
Detect wrong eol markers.
55
            if m.group('lineending') != '':
56
                raise errors.UnsupportedEOLMarker()
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
57
            version = m.group('version')
58
            break
1793.2.7 by Aaron Bentley
Fix reporting of malformed, (especially, crlf) bundles
59
        elif line.startswith(BUNDLE_HEADER):
1907.2.1 by Hermann Kraus
Convert bundle errors from Exception to BzrNewError.
60
            raise errors.MalformedHeader(
61
                'Extra characters after version number')
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
62
        m = CHANGESET_OLD_HEADER_RE.match(line)
63
        if m:
64
            version = m.group('version')
1907.2.1 by Hermann Kraus
Convert bundle errors from Exception to BzrNewError.
65
            raise errors.BundleNotSupported(version, 
66
                'old format bundles not supported')
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
67
68
    if version is None:
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
69
        raise errors.NotABundle('Did not find an opening header')
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
70
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
71
    # Now we have a version, to figure out how to read the bundle 
1963.2.1 by Robey Pointer
remove usage of has_key()
72
    if version not in _serializers:
1907.2.1 by Hermann Kraus
Convert bundle errors from Exception to BzrNewError.
73
        raise errors.BundleNotSupported(version, 
74
            'version not listed in known versions')
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
75
76
    serializer = _serializers[version](version)
77
78
    return serializer.read(f)
79
80
1185.82.74 by Aaron Bentley
Allow custom base for any revision
81
def write(source, revision_ids, f, version=None, forced_bases={}):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
82
    """Serialize a list of bundles to a filelike object.
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
83
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
84
    :param source: A source for revision information
85
    :param revision_ids: The list of revision ids to serialize
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
86
    :param f: The file to output to
87
    :param version: [optional] target serialization version
88
    """
89
1963.2.1 by Robey Pointer
remove usage of has_key()
90
    if version not in _serializers:
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
91
        raise errors.BundleNotSupported(version, 'unknown bundle format')
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
92
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
93
    serializer = _serializers[version](version)
1927.1.1 by John Arbash Meinel
Lock the repository more often
94
    source.lock_read()
95
    try:
96
        return serializer.write(source, revision_ids, forced_bases, f)
97
    finally:
98
        source.unlock()
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
99
100
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
101
def write_bundle(repository, revision_id, base_revision_id, out):
1185.82.53 by Aaron Bentley
Factored out write_changeset to select revisions
102
    """"""
1927.1.1 by John Arbash Meinel
Lock the repository more often
103
    repository.lock_read()
104
    try:
105
        return _write_bundle(repository, revision_id, base_revision_id, out)
106
    finally:
107
        repository.unlock()
108
109
110
def _write_bundle(repository, revision_id, base_revision_id, out):
1185.82.58 by Aaron Bentley
Handle empty branches properly
111
    if base_revision_id is NULL_REVISION:
112
        base_revision_id = None
1185.82.53 by Aaron Bentley
Factored out write_changeset to select revisions
113
    base_ancestry = set(repository.get_ancestry(base_revision_id))
114
    revision_ids = [r for r in repository.get_ancestry(revision_id) if r
115
                    not in base_ancestry]
116
    revision_ids = list(reversed(revision_ids))
1185.82.74 by Aaron Bentley
Allow custom base for any revision
117
    write(repository, revision_ids, out, 
118
          forced_bases = {revision_id:base_revision_id})
1185.82.53 by Aaron Bentley
Factored out write_changeset to select revisions
119
    return revision_ids
120
121
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
122
def format_highres_date(t, offset=0):
123
    """Format a date, such that it includes higher precision in the
124
    seconds field.
125
126
    :param t:   The local time in fractional seconds since the epoch
127
    :type t: float
128
    :param offset:  The timezone offset in integer seconds
129
    :type offset: int
130
131
    Example: format_highres_date(time.time(), -time.timezone)
132
    this will return a date stamp for right now,
133
    formatted for the local timezone.
134
135
    >>> from bzrlib.osutils import format_date
136
    >>> format_date(1120153132.350850105, 0)
137
    'Thu 2005-06-30 17:38:52 +0000'
138
    >>> format_highres_date(1120153132.350850105, 0)
139
    'Thu 2005-06-30 17:38:52.350850105 +0000'
140
    >>> format_date(1120153132.350850105, -5*3600)
141
    'Thu 2005-06-30 12:38:52 -0500'
142
    >>> format_highres_date(1120153132.350850105, -5*3600)
143
    'Thu 2005-06-30 12:38:52.350850105 -0500'
144
    >>> format_highres_date(1120153132.350850105, 7200)
145
    'Thu 2005-06-30 19:38:52.350850105 +0200'
1793.3.7 by John Arbash Meinel
Properly handle non-hour timezone offsets.
146
    >>> format_highres_date(1152428738.867522, 19800)
147
    'Sun 2006-07-09 12:35:38.867522001 +0530'
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
148
    """
149
    import time
150
    assert isinstance(t, float)
151
    
152
    # This has to be formatted for "original" date, so that the
153
    # revision XML entry will be reproduced faithfully.
154
    if offset == None:
155
        offset = 0
156
    tt = time.gmtime(t + offset)
157
158
    return (time.strftime("%a %Y-%m-%d %H:%M:%S", tt)
159
            + ('%.9f' % (t - int(t)))[1:] # Get the high-res seconds, but ignore the 0
160
            + ' %+03d%02d' % (offset / 3600, (offset / 60) % 60))
161
162
163
def unpack_highres_date(date):
164
    """This takes the high-resolution date stamp, and
165
    converts it back into the tuple (timestamp, timezone)
166
    Where timestamp is in real UTC since epoch seconds, and timezone is an integer
167
    number of seconds offset.
168
169
    :param date: A date formated by format_highres_date
170
    :type date: string
171
172
    >>> import time, random
173
    >>> unpack_highres_date('Thu 2005-06-30 12:38:52.350850105 -0500')
174
    (1120153132.3508501, -18000)
175
    >>> unpack_highres_date('Thu 2005-06-30 17:38:52.350850105 +0000')
176
    (1120153132.3508501, 0)
177
    >>> unpack_highres_date('Thu 2005-06-30 19:38:52.350850105 +0200')
178
    (1120153132.3508501, 7200)
1793.3.7 by John Arbash Meinel
Properly handle non-hour timezone offsets.
179
    >>> unpack_highres_date('Sun 2006-07-09 12:35:38.867522001 +0530')
180
    (1152428738.867522, 19800)
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
181
    >>> from bzrlib.osutils import local_time_offset
182
    >>> t = time.time()
183
    >>> o = local_time_offset()
184
    >>> t2, o2 = unpack_highres_date(format_highres_date(t, o))
185
    >>> t == t2
186
    True
187
    >>> o == o2
188
    True
189
    >>> t -= 24*3600*365*2 # Start 2 years ago
190
    >>> o = -12*3600
191
    >>> for count in xrange(500):
192
    ...   t += random.random()*24*3600*30
193
    ...   o = ((o/3600 + 13) % 25 - 12)*3600 # Add 1 wrap around from [-12, 12]
194
    ...   date = format_highres_date(t, o)
195
    ...   t2, o2 = unpack_highres_date(date)
196
    ...   if t != t2 or o != o2:
197
    ...      print 'Failed on date %r, %s,%s diff:%s' % (date, t, o, t2-t)
198
    ...      break
199
200
    """
201
    import time, calendar
202
    # Up until the first period is a datestamp that is generated
203
    # as normal from time.strftime, so use time.strptime to
204
    # parse it
205
    dot_loc = date.find('.')
206
    if dot_loc == -1:
1907.2.1 by Hermann Kraus
Convert bundle errors from Exception to BzrNewError.
207
        raise ValueError(
208
            'Date string does not contain high-precision seconds: %r' % date)
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
209
    base_time = time.strptime(date[:dot_loc], "%a %Y-%m-%d %H:%M:%S")
210
    fract_seconds, offset = date[dot_loc:].split()
211
    fract_seconds = float(fract_seconds)
1793.3.11 by John Arbash Meinel
Cleanup unpack_highres_date from Aaron's suggestions.
212
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
213
    offset = int(offset)
1793.3.11 by John Arbash Meinel
Cleanup unpack_highres_date from Aaron's suggestions.
214
215
    hours = int(offset / 100)
216
    minutes = (offset % 100)
217
    seconds_offset = (hours * 3600) + (minutes * 60)
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
218
    
219
    # time.mktime returns localtime, but calendar.timegm returns UTC time
220
    timestamp = calendar.timegm(base_time)
1793.3.11 by John Arbash Meinel
Cleanup unpack_highres_date from Aaron's suggestions.
221
    timestamp -= seconds_offset
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
222
    # Add back in the fractional seconds
223
    timestamp += fract_seconds
1793.3.11 by John Arbash Meinel
Cleanup unpack_highres_date from Aaron's suggestions.
224
    return (timestamp, seconds_offset)
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
225
226
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
227
class BundleSerializer(object):
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
228
    """The base class for Serializers.
229
230
    Common functionality should be included here.
231
    """
232
    def __init__(self, version):
233
        self.version = version
234
235
    def read(self, f):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
236
        """Read the rest of the bundles from the supplied file.
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
237
238
        :param f: The file to read from
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
239
        :return: A list of bundle trees
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
240
        """
241
        raise NotImplementedError
242
1185.82.74 by Aaron Bentley
Allow custom base for any revision
243
    def write(self, source, revision_ids, forced_bases, f):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
244
        """Write the bundle to the supplied file.
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
245
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
246
        :param source: A source for revision information
247
        :param revision_ids: The list of revision ids to serialize
1185.82.74 by Aaron Bentley
Allow custom base for any revision
248
        :param forced_bases: A dict of revision -> base that overrides default
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
249
        :param f: The file to output to
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
250
        """
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
251
        raise NotImplementedError
252
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
253
254
def register(version, klass, overwrite=False):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
255
    """Register a BundleSerializer version.
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
256
257
    :param version: The version associated with this format
258
    :param klass: The class to instantiate, which must take a version argument
259
    """
260
    global _serializers
261
    if overwrite:
262
        _serializers[version] = klass
263
        return
264
1963.2.1 by Robey Pointer
remove usage of has_key()
265
    if version not in _serializers:
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
266
        _serializers[version] = klass
267
268
269
def register_lazy(version, module, classname, overwrite=False):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
270
    """Register lazy-loaded bundle serializer.
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
271
272
    :param version: The version associated with this reader
273
    :param module: String indicating what module should be loaded
274
    :param classname: Name of the class that will be instantiated
275
    :param overwrite: Should this version override a default
276
    """
277
    def _loader(version):
278
        mod = __import__(module, globals(), locals(), [classname])
279
        klass = getattr(mod, classname)
280
        return klass(version)
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
281
    register(version, _loader, overwrite=overwrite)
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
282
283
1185.82.96 by Aaron Bentley
Got first binary test passing
284
def binary_diff(old_filename, old_lines, new_filename, new_lines, to_file):
285
    temp = StringIO()
286
    internal_diff(old_filename, old_lines, new_filename, new_lines, temp,
287
                  allow_binary=True)
288
    temp.seek(0)
289
    base64.encode(temp, to_file)
290
    to_file.write('\n')
291
1551.7.3 by Aaron Bentley
Fix strict testaments, as_sha1
292
register_lazy('0.8', 'bzrlib.bundle.serializer.v08', 'BundleSerializerV08')
293
register_lazy(None, 'bzrlib.bundle.serializer.v08', 'BundleSerializerV08')
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
294