/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/changeset/old/common.py

  • Committer: John Arbash Meinel
  • Date: 2005-11-19 04:22:51 UTC
  • mto: (1185.82.108 w-changeset)
  • mto: This revision was merged to the branch mainline in revision 1738.
  • Revision ID: john@arbash-meinel.com-20051119042251-aaa8514b7d68c29f
Working on creating a factor for serializing changesets.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
"""\
 
3
Common entries, like strings, etc, for the changeset reading + writing code.
 
4
"""
 
5
 
 
6
import bzrlib
 
7
 
 
8
header_str = 'Bazaar-NG changeset v'
 
9
version = (0, 1, 0)
 
10
 
 
11
def get_header():
 
12
    return [
 
13
        header_str + '.'.join([str(v) for v in version]),
 
14
        ''
 
15
    ]
 
16
 
 
17
def canonicalize_revision(branch, revnos):
 
18
    """Turn some sort of revision information into a single
 
19
    set of from-to revision ids.
 
20
 
 
21
    A revision id can be None if there is no associated revison.
 
22
 
 
23
    :param revnos:  A list of revisions to lookup, should be at most 2 long
 
24
    :return: (old, new)
 
25
    """
 
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])
 
28
    if len(revnos) == 0:
 
29
        revnos = [None, None]
 
30
    elif len(revnos) == 1:
 
31
        revnos = [None, revnos[0]]
 
32
 
 
33
    if revnos[1] is None:
 
34
        new = branch.last_patch()
 
35
    else:
 
36
        new = branch.lookup_revision(revnos[1])
 
37
    if revnos[0] is None:
 
38
        if new is None:
 
39
            old = None
 
40
        else:
 
41
            oldrev = branch.get_revision(new)
 
42
            if len(oldrev.parents) == 0:
 
43
                old = None
 
44
            else:
 
45
                old = oldrev.parents[0].revision_id
 
46
    else:
 
47
        old = branch.lookup_revision(revnos[0])
 
48
 
 
49
    return old, new
 
50
 
 
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
 
54
    changeset.
 
55
    """
 
56
 
 
57
    def __init__(self, branch, changeset_info):
 
58
        """Initialize this ChangesetTree.
 
59
 
 
60
        :param branch:  This is where information will be acquired
 
61
                        and updated.
 
62
        :param changeset_info:  Information about a given changeset,
 
63
                                so that we can identify the base,
 
64
                                and other information.
 
65
        """
 
66
        self.branch = branch
 
67
        self.changeset_info = changeset_info
 
68
 
 
69
        self._build_tree()
 
70
 
 
71
    def _build_tree(self):
 
72
        """Build the final description of the tree, based on
 
73
        the changeset_info object.
 
74
        """
 
75
        self.base_tree = self.branch.revision_tree(self.changeset_info.base)
 
76
        
 
77
def encode(s):
 
78
    """Take a unicode string, and make sure to escape it for
 
79
    use in a changeset.
 
80
 
 
81
    Note: It can be either a normal, or a unicode string
 
82
 
 
83
    >>> encode(u'abcdefg')
 
84
    'abcdefg'
 
85
    >>> encode(u'a b\\tc\\nd\\\\e')
 
86
    'a b\\tc\\nd\\\\e'
 
87
    >>> encode('a b\\tc\\nd\\e')
 
88
    'a b\\tc\\nd\\\\e'
 
89
    >>> encode(u'\\u1234\\u0020')
 
90
    '\\xe1\\x88\\xb4 '
 
91
    >>> encode('abcdefg')
 
92
    'abcdefg'
 
93
    >>> encode(u'')
 
94
    ''
 
95
    >>> encode('')
 
96
    ''
 
97
    """
 
98
    return s.encode('utf-8')
 
99
 
 
100
def decode(s):
 
101
    """Undo the encode operation, returning a unicode string.
 
102
 
 
103
    >>> decode('abcdefg')
 
104
    u'abcdefg'
 
105
    >>> decode('a b\\tc\\nd\\\\e')
 
106
    u'a b\\tc\\nd\\\\e'
 
107
    >>> decode('\\xe1\\x88\\xb4 ')
 
108
    u'\\u1234 '
 
109
    >>> for s in ('test', 'strings'):
 
110
    ...   if decode(encode(s)) != s:
 
111
    ...     print 'Failed: %r' % s # There should be no failures
 
112
 
 
113
    """
 
114
    return s.decode('utf-8')
 
115
 
 
116
def format_highres_date(t, offset=0):
 
117
    """Format a date, such that it includes higher precision in the
 
118
    seconds field.
 
119
 
 
120
    :param t:   The local time in fractional seconds since the epoch
 
121
    :type t: float
 
122
    :param offset:  The timezone offset in integer seconds
 
123
    :type offset: int
 
124
 
 
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.
 
128
 
 
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'
 
140
    """
 
141
    import time
 
142
    assert isinstance(t, float)
 
143
    
 
144
    # This has to be formatted for "original" date, so that the
 
145
    # revision XML entry will be reproduced faithfully.
 
146
    if offset == None:
 
147
        offset = 0
 
148
    tt = time.gmtime(t + offset)
 
149
 
 
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))
 
153
 
 
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.
 
159
 
 
160
    :param date: A date formated by format_highres_date
 
161
    :type date: string
 
162
 
 
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
 
171
    >>> t = time.time()
 
172
    >>> o = local_time_offset()
 
173
    >>> t2, o2 = unpack_highres_date(format_highres_date(t, o))
 
174
    >>> t == t2
 
175
    True
 
176
    >>> o == o2
 
177
    True
 
178
    >>> t -= 24*3600*365*2 # Start 2 years ago
 
179
    >>> o = -12*3600
 
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)
 
187
    ...      break
 
188
 
 
189
    """
 
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
 
193
    # parse it
 
194
    dot_loc = date.find('.')
 
195
    if dot_loc == -1:
 
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)
 
200
    offset = int(offset)
 
201
    offset = int(offset / 100) * 3600 + offset % 100
 
202
    
 
203
    # time.mktime returns localtime, but calendar.timegm returns UTC time
 
204
    timestamp = calendar.timegm(base_time)
 
205
    timestamp -= offset
 
206
    # Add back in the fractional seconds
 
207
    timestamp += fract_seconds
 
208
    return (timestamp, offset)
 
209
 
 
210
if __name__ == '__main__':
 
211
    import doctest
 
212
    doctest.testmod()
 
213