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