3
Common entries, like strings, etc, for the changeset reading + writing code.
8
header_str = 'Bazaar-NG changeset v'
13
header_str + '.'.join([str(v) for v in version]),
17
def canonicalize_revision(branch, revnos):
18
"""Turn some sort of revision information into a single
19
set of from-to revision ids.
21
A revision id can be None if there is no associated revison.
23
:param revnos: A list of revisions to lookup, should be at most 2 long
26
# If only 1 entry is given, then we assume we want just the
27
# changeset between that entry and it's base (we assume parents[0])
30
elif len(revnos) == 1:
31
revnos = [None, revnos[0]]
34
new = branch.last_patch()
36
new = branch.lookup_revision(revnos[1])
41
oldrev = branch.get_revision(new)
42
if len(oldrev.parents) == 0:
45
old = oldrev.parents[0].revision_id
47
old = branch.lookup_revision(revnos[0])
51
class ChangesetTree(object):
52
"""This class is designed to take a base tree, and re-create
53
a final tree based on the information contained within a
57
def __init__(self, branch, changeset_info):
58
"""Initialize this ChangesetTree.
60
:param branch: This is where information will be acquired
62
:param changeset_info: Information about a given changeset,
63
so that we can identify the base,
64
and other information.
67
self.changeset_info = changeset_info
71
def _build_tree(self):
72
"""Build the final description of the tree, based on
73
the changeset_info object.
75
self.base_tree = self.branch.revision_tree(self.changeset_info.base)
78
"""Take a unicode string, and make sure to escape it for
81
Note: It can be either a normal, or a unicode string
83
>>> encode(u'abcdefg')
85
>>> encode(u'a b\\tc\\nd\\\\e')
87
>>> encode('a b\\tc\\nd\\e')
89
>>> encode(u'\\u1234\\u0020')
98
return s.encode('utf-8')
101
"""Undo the encode operation, returning a unicode string.
103
>>> decode('abcdefg')
105
>>> decode('a b\\tc\\nd\\\\e')
107
>>> decode('\\xe1\\x88\\xb4 ')
109
>>> for s in ('test', 'strings'):
110
... if decode(encode(s)) != s:
111
... print 'Failed: %r' % s # There should be no failures
114
return s.decode('utf-8')
116
def format_highres_date(t, offset=0):
117
"""Format a date, such that it includes higher precision in the
120
:param t: The local time in fractional seconds since the epoch
122
:param offset: The timezone offset in integer seconds
125
Example: format_highres_date(time.time(), -time.timezone)
126
this will return a date stamp for right now,
127
formatted for the local timezone.
129
>>> from bzrlib.osutils import format_date
130
>>> format_date(1120153132.350850105, 0)
131
'Thu 2005-06-30 17:38:52 +0000'
132
>>> format_highres_date(1120153132.350850105, 0)
133
'Thu 2005-06-30 17:38:52.350850105 +0000'
134
>>> format_date(1120153132.350850105, -5*3600)
135
'Thu 2005-06-30 12:38:52 -0500'
136
>>> format_highres_date(1120153132.350850105, -5*3600)
137
'Thu 2005-06-30 12:38:52.350850105 -0500'
138
>>> format_highres_date(1120153132.350850105, 7200)
139
'Thu 2005-06-30 19:38:52.350850105 +0200'
142
assert isinstance(t, float)
144
# This has to be formatted for "original" date, so that the
145
# revision XML entry will be reproduced faithfully.
148
tt = time.gmtime(t + offset)
150
return (time.strftime("%a %Y-%m-%d %H:%M:%S", tt)
151
+ ('%.9f' % (t - int(t)))[1:] # Get the high-res seconds, but ignore the 0
152
+ ' %+03d%02d' % (offset / 3600, (offset / 60) % 60))
154
def unpack_highres_date(date):
155
"""This takes the high-resolution date stamp, and
156
converts it back into the tuple (timestamp, timezone)
157
Where timestamp is in real UTC since epoch seconds, and timezone is an integer
158
number of seconds offset.
160
:param date: A date formated by format_highres_date
163
>>> import time, random
164
>>> unpack_highres_date('Thu 2005-06-30 12:38:52.350850105 -0500')
165
(1120153132.3508501, -18000)
166
>>> unpack_highres_date('Thu 2005-06-30 17:38:52.350850105 +0000')
167
(1120153132.3508501, 0)
168
>>> unpack_highres_date('Thu 2005-06-30 19:38:52.350850105 +0200')
169
(1120153132.3508501, 7200)
170
>>> from bzrlib.osutils import local_time_offset
172
>>> o = local_time_offset()
173
>>> t2, o2 = unpack_highres_date(format_highres_date(t, o))
178
>>> t -= 24*3600*365*2 # Start 2 years ago
180
>>> for count in xrange(500):
181
... t += random.random()*24*3600*30
182
... o = ((o/3600 + 13) % 25 - 12)*3600 # Add 1 wrap around from [-12, 12]
183
... date = format_highres_date(t, o)
184
... t2, o2 = unpack_highres_date(date)
185
... if t != t2 or o != o2:
186
... print 'Failed on date %r, %s,%s diff:%s' % (date, t, o, t2-t)
190
import time, calendar
191
# Up until the first period is a datestamp that is generated
192
# as normal from time.strftime, so use time.strptime to
194
dot_loc = date.find('.')
196
raise ValueError('Date string does not contain high-precision seconds: %r' % date)
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)
201
offset = int(offset / 100) * 3600 + offset % 100
203
# time.mktime returns localtime, but calendar.timegm returns UTC time
204
timestamp = calendar.timegm(base_time)
206
# Add back in the fractional seconds
207
timestamp += fract_seconds
208
return (timestamp, offset)
210
if __name__ == '__main__':