/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 
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
72
    if not _serializers.has_key(version):
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
90
    if not _serializers.has_key(version):
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)
1185.82.74 by Aaron Bentley
Allow custom base for any revision
94
    return serializer.write(source, revision_ids, forced_bases, f) 
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
95
96
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
97
def write_bundle(repository, revision_id, base_revision_id, out):
1185.82.53 by Aaron Bentley
Factored out write_changeset to select revisions
98
    """"""
1185.82.58 by Aaron Bentley
Handle empty branches properly
99
    if base_revision_id is NULL_REVISION:
100
        base_revision_id = None
1185.82.53 by Aaron Bentley
Factored out write_changeset to select revisions
101
    base_ancestry = set(repository.get_ancestry(base_revision_id))
102
    revision_ids = [r for r in repository.get_ancestry(revision_id) if r
103
                    not in base_ancestry]
104
    revision_ids = list(reversed(revision_ids))
1185.82.74 by Aaron Bentley
Allow custom base for any revision
105
    write(repository, revision_ids, out, 
106
          forced_bases = {revision_id:base_revision_id})
1185.82.53 by Aaron Bentley
Factored out write_changeset to select revisions
107
    return revision_ids
108
109
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
110
def format_highres_date(t, offset=0):
111
    """Format a date, such that it includes higher precision in the
112
    seconds field.
113
114
    :param t:   The local time in fractional seconds since the epoch
115
    :type t: float
116
    :param offset:  The timezone offset in integer seconds
117
    :type offset: int
118
119
    Example: format_highres_date(time.time(), -time.timezone)
120
    this will return a date stamp for right now,
121
    formatted for the local timezone.
122
123
    >>> from bzrlib.osutils import format_date
124
    >>> format_date(1120153132.350850105, 0)
125
    'Thu 2005-06-30 17:38:52 +0000'
126
    >>> format_highres_date(1120153132.350850105, 0)
127
    'Thu 2005-06-30 17:38:52.350850105 +0000'
128
    >>> format_date(1120153132.350850105, -5*3600)
129
    'Thu 2005-06-30 12:38:52 -0500'
130
    >>> format_highres_date(1120153132.350850105, -5*3600)
131
    'Thu 2005-06-30 12:38:52.350850105 -0500'
132
    >>> format_highres_date(1120153132.350850105, 7200)
133
    'Thu 2005-06-30 19:38:52.350850105 +0200'
1793.3.7 by John Arbash Meinel
Properly handle non-hour timezone offsets.
134
    >>> format_highres_date(1152428738.867522, 19800)
135
    'Sun 2006-07-09 12:35:38.867522001 +0530'
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
136
    """
137
    import time
138
    assert isinstance(t, float)
139
    
140
    # This has to be formatted for "original" date, so that the
141
    # revision XML entry will be reproduced faithfully.
142
    if offset == None:
143
        offset = 0
144
    tt = time.gmtime(t + offset)
145
146
    return (time.strftime("%a %Y-%m-%d %H:%M:%S", tt)
147
            + ('%.9f' % (t - int(t)))[1:] # Get the high-res seconds, but ignore the 0
148
            + ' %+03d%02d' % (offset / 3600, (offset / 60) % 60))
149
150
151
def unpack_highres_date(date):
152
    """This takes the high-resolution date stamp, and
153
    converts it back into the tuple (timestamp, timezone)
154
    Where timestamp is in real UTC since epoch seconds, and timezone is an integer
155
    number of seconds offset.
156
157
    :param date: A date formated by format_highres_date
158
    :type date: string
159
160
    >>> import time, random
161
    >>> unpack_highres_date('Thu 2005-06-30 12:38:52.350850105 -0500')
162
    (1120153132.3508501, -18000)
163
    >>> unpack_highres_date('Thu 2005-06-30 17:38:52.350850105 +0000')
164
    (1120153132.3508501, 0)
165
    >>> unpack_highres_date('Thu 2005-06-30 19:38:52.350850105 +0200')
166
    (1120153132.3508501, 7200)
1793.3.7 by John Arbash Meinel
Properly handle non-hour timezone offsets.
167
    >>> unpack_highres_date('Sun 2006-07-09 12:35:38.867522001 +0530')
168
    (1152428738.867522, 19800)
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
169
    >>> from bzrlib.osutils import local_time_offset
170
    >>> t = time.time()
171
    >>> o = local_time_offset()
172
    >>> t2, o2 = unpack_highres_date(format_highres_date(t, o))
173
    >>> t == t2
174
    True
175
    >>> o == o2
176
    True
177
    >>> t -= 24*3600*365*2 # Start 2 years ago
178
    >>> o = -12*3600
179
    >>> for count in xrange(500):
180
    ...   t += random.random()*24*3600*30
181
    ...   o = ((o/3600 + 13) % 25 - 12)*3600 # Add 1 wrap around from [-12, 12]
182
    ...   date = format_highres_date(t, o)
183
    ...   t2, o2 = unpack_highres_date(date)
184
    ...   if t != t2 or o != o2:
185
    ...      print 'Failed on date %r, %s,%s diff:%s' % (date, t, o, t2-t)
186
    ...      break
187
188
    """
189
    import time, calendar
190
    # Up until the first period is a datestamp that is generated
191
    # as normal from time.strftime, so use time.strptime to
192
    # parse it
193
    dot_loc = date.find('.')
194
    if dot_loc == -1:
1907.2.1 by Hermann Kraus
Convert bundle errors from Exception to BzrNewError.
195
        raise ValueError(
196
            'Date string does not contain high-precision seconds: %r' % date)
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
197
    base_time = time.strptime(date[:dot_loc], "%a %Y-%m-%d %H:%M:%S")
198
    fract_seconds, offset = date[dot_loc:].split()
199
    fract_seconds = float(fract_seconds)
1793.3.11 by John Arbash Meinel
Cleanup unpack_highres_date from Aaron's suggestions.
200
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
201
    offset = int(offset)
1793.3.11 by John Arbash Meinel
Cleanup unpack_highres_date from Aaron's suggestions.
202
203
    hours = int(offset / 100)
204
    minutes = (offset % 100)
205
    seconds_offset = (hours * 3600) + (minutes * 60)
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
206
    
207
    # time.mktime returns localtime, but calendar.timegm returns UTC time
208
    timestamp = calendar.timegm(base_time)
1793.3.11 by John Arbash Meinel
Cleanup unpack_highres_date from Aaron's suggestions.
209
    timestamp -= seconds_offset
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
210
    # Add back in the fractional seconds
211
    timestamp += fract_seconds
1793.3.11 by John Arbash Meinel
Cleanup unpack_highres_date from Aaron's suggestions.
212
    return (timestamp, seconds_offset)
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
213
214
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
215
class BundleSerializer(object):
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
216
    """The base class for Serializers.
217
218
    Common functionality should be included here.
219
    """
220
    def __init__(self, version):
221
        self.version = version
222
223
    def read(self, f):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
224
        """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.
225
226
        :param f: The file to read from
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
227
        :return: A list of bundle trees
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
228
        """
229
        raise NotImplementedError
230
1185.82.74 by Aaron Bentley
Allow custom base for any revision
231
    def write(self, source, revision_ids, forced_bases, f):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
232
        """Write the bundle to the supplied file.
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
233
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
234
        :param source: A source for revision information
235
        :param revision_ids: The list of revision ids to serialize
1185.82.74 by Aaron Bentley
Allow custom base for any revision
236
        :param forced_bases: A dict of revision -> base that overrides default
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
237
        :param f: The file to output to
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
238
        """
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
239
        raise NotImplementedError
240
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
241
242
def register(version, klass, overwrite=False):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
243
    """Register a BundleSerializer version.
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
244
245
    :param version: The version associated with this format
246
    :param klass: The class to instantiate, which must take a version argument
247
    """
248
    global _serializers
249
    if overwrite:
250
        _serializers[version] = klass
251
        return
252
253
    if not _serializers.has_key(version):
254
        _serializers[version] = klass
255
256
257
def register_lazy(version, module, classname, overwrite=False):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
258
    """Register lazy-loaded bundle serializer.
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
259
260
    :param version: The version associated with this reader
261
    :param module: String indicating what module should be loaded
262
    :param classname: Name of the class that will be instantiated
263
    :param overwrite: Should this version override a default
264
    """
265
    def _loader(version):
266
        mod = __import__(module, globals(), locals(), [classname])
267
        klass = getattr(mod, classname)
268
        return klass(version)
1185.82.4 by John Arbash Meinel
Created output format, slightly simplified code
269
    register(version, _loader, overwrite=overwrite)
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
270
271
1185.82.96 by Aaron Bentley
Got first binary test passing
272
def binary_diff(old_filename, old_lines, new_filename, new_lines, to_file):
273
    temp = StringIO()
274
    internal_diff(old_filename, old_lines, new_filename, new_lines, temp,
275
                  allow_binary=True)
276
    temp.seek(0)
277
    base64.encode(temp, to_file)
278
    to_file.write('\n')
279
1551.7.3 by Aaron Bentley
Fix strict testaments, as_sha1
280
register_lazy('0.8', 'bzrlib.bundle.serializer.v08', 'BundleSerializerV08')
281
register_lazy(None, 'bzrlib.bundle.serializer.v08', 'BundleSerializerV08')
1185.82.3 by John Arbash Meinel
Working on creating a factor for serializing changesets.
282