/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
1
#!/usr/bin/env python
2
"""\
3
Common entries, like strings, etc, for the changeset reading + writing code.
4
"""
5
0.5.57 by John Arbash Meinel
Simplified the header, only output base if it is not the expected one.
6
header_str = 'Bazaar-NG changeset v'
0.5.7 by John Arbash Meinel
Added a bunch more information about changesets. Can now read back in all of the meta information.
7
version = (0, 0, 5)
8
9
def get_header():
10
    return [
11
        header_str + '.'.join([str(v) for v in version]),
12
        ''
13
    ]
14
0.5.36 by John Arbash Meinel
Updated so that read_changeset is able to parse the output
15
def canonicalize_revision(branch, revnos):
16
    """Turn some sort of revision information into a single
17
    set of from-to revision ids.
18
19
    A revision id can be None if there is no associated revison.
20
21
    :param revnos:  A list of revisions to lookup, should be at most 2 long
22
    :return: (old, new)
23
    """
24
    # If only 1 entry is given, then we assume we want just the
25
    # changeset between that entry and it's base (we assume parents[0])
26
    if len(revnos) == 0:
27
        revnos = [None, None]
28
    elif len(revnos) == 1:
29
        revnos = [None, revnos[0]]
30
31
    if revnos[1] is None:
32
        new = branch.last_patch()
33
    else:
34
        new = branch.lookup_revision(revnos[1])
35
    if revnos[0] is None:
36
        old = branch.get_revision(new).parents[0].revision_id
37
    else:
38
        old = branch.lookup_revision(revnos[0])
39
40
    return old, new
41
0.5.39 by John Arbash Meinel
(broken) Working on changing the processing to use a ChangesetTree.
42
class ChangesetTree(object):
43
    """This class is designed to take a base tree, and re-create
44
    a final tree based on the information contained within a
45
    changeset.
46
    """
47
48
    def __init__(self, branch, changeset_info):
49
        """Initialize this ChangesetTree.
50
51
        :param branch:  This is where information will be acquired
52
                        and updated.
53
        :param changeset_info:  Information about a given changeset,
54
                                so that we can identify the base,
55
                                and other information.
56
        """
57
        self.branch = branch
58
        self.changeset_info = changeset_info
59
60
        self._build_tree()
61
62
    def _build_tree(self):
63
        """Build the final description of the tree, based on
64
        the changeset_info object.
65
        """
0.5.40 by John Arbash Meinel
Added some highres formatting of datestamps.
66
        self.base_tree = self.branch.revision_tree(self.changeset_info.base)
0.5.39 by John Arbash Meinel
(broken) Working on changing the processing to use a ChangesetTree.
67
        
0.5.55 by John Arbash Meinel
Lots of updates. Using a minimized annotations for changesets.
68
def guess_text_id(tree, file_id, rev_id, modified=True):
69
    """This returns the estimated text_id for a given file.
70
    The idea is that in general the text_id should be the id last
71
    revision which modified the file.
72
73
    :param tree: This should be the base tree for a changeset, since that
74
                 is all the target has for guessing.
75
    :param file_id: The file id to guess the text_id for.
76
    :param rev_id: The target revision id
77
    :param modified: Was the file modified between base and target?
78
    """
79
    from bzrlib.errors import BzrError
80
    if modified:
81
        # If the file was modified in an intermediate stage
82
        # (not in the final target), this won't be correct
83
        # but it is our best guess.
84
        # TODO: In the current code, text-ids are randomly generated
85
        # using the filename as the base. In the future they will
86
        # probably follow this format.
87
        return file_id + '-' + rev_id
88
    # The file was not actually modified in this changeset
89
    # so the text_id should be equal to it's previous value
90
    if not file_id in tree.inventory:
91
        raise BzrError('Unable to generate text_id for file_id {%s}'
92
            ', file does not exist in tree.' % file_id)
93
    # This is the last known text_id for this file
94
    # so assume that it is being used.
95
    text_id = tree.inventory[file_id].text_id
96
97
def encode(s):
98
    """Take a unicode string, and make sure to escape it for
99
    use in a changeset.
100
101
    Note: It can be either a normal, or a unicode string
102
103
    >>> encode(u'abcdefg')
104
    'abcdefg'
105
    >>> encode(u'a b\tc\\nd\\\\e')
106
    'a b\\\\tc\\\\nd\\\\e'
107
    >>> encode('a b\tc\\nd\\e')
108
    'a b\\\\tc\\\\nd\\\\e'
109
    >>> encode(u'\\u1234\\u0020')
110
    '\\\\u1234 '
111
    >>> encode('abcdefg')
112
    'abcdefg'
113
    >>> encode(u'')
114
    ''
115
    >>> encode('')
116
    ''
117
    """
118
    return s.encode('unicode_escape')
119
120
def decode(s):
121
    """Undo the encode operation, returning a unicode string.
122
123
    >>> decode('abcdefg')
124
    u'abcdefg'
125
    >>> decode('a b\\\\tc\\\\nd\\\\e')
126
    u'a b\tc\\nd\\\\e'
127
    >>> decode('\\\\u1234\\\\u0020')
128
    u'\\u1234 '
129
    >>> for s in ('test', 'strings'):
130
    ...   if decode(encode(s)) != s:
131
    ...     print 'Failed: %r' % s # There should be no failures
132
133
    """
134
    return s.decode('unicode_escape')
135
0.5.39 by John Arbash Meinel
(broken) Working on changing the processing to use a ChangesetTree.
136
def format_highres_date(t, offset=0):
137
    """Format a date, such that it includes higher precision in the
138
    seconds field.
139
0.5.40 by John Arbash Meinel
Added some highres formatting of datestamps.
140
    :param t:   The local time in fractional seconds since the epoch
0.5.39 by John Arbash Meinel
(broken) Working on changing the processing to use a ChangesetTree.
141
    :type t: float
142
    :param offset:  The timezone offset in integer seconds
143
    :type offset: int
144
0.5.40 by John Arbash Meinel
Added some highres formatting of datestamps.
145
    Example: format_highres_date(time.time(), -time.timezone)
146
    this will return a date stamp for right now,
147
    formatted for the local timezone.
148
0.5.39 by John Arbash Meinel
(broken) Working on changing the processing to use a ChangesetTree.
149
    >>> from bzrlib.osutils import format_date
150
    >>> format_date(1120153132.350850105, 0)
151
    'Thu 2005-06-30 17:38:52 +0000'
152
    >>> format_highres_date(1120153132.350850105, 0)
153
    'Thu 2005-06-30 17:38:52.350850105 +0000'
154
    >>> format_date(1120153132.350850105, -5*3600)
155
    'Thu 2005-06-30 12:38:52 -0500'
156
    >>> format_highres_date(1120153132.350850105, -5*3600)
157
    'Thu 2005-06-30 12:38:52.350850105 -0500'
0.5.40 by John Arbash Meinel
Added some highres formatting of datestamps.
158
    >>> format_highres_date(1120153132.350850105, 7200)
159
    'Thu 2005-06-30 19:38:52.350850105 +0200'
0.5.39 by John Arbash Meinel
(broken) Working on changing the processing to use a ChangesetTree.
160
    """
161
    import time
162
    assert isinstance(t, float)
163
    
164
    # This has to be formatted for "original" date, so that the
165
    # revision XML entry will be reproduced faithfully.
166
    if offset == None:
167
        offset = 0
168
    tt = time.gmtime(t + offset)
169
170
    return (time.strftime("%a %Y-%m-%d %H:%M:%S", tt)
171
            + ('%.9f' % (t - int(t)))[1:] # Get the high-res seconds, but ignore the 0
172
            + ' %+03d%02d' % (offset / 3600, (offset / 60) % 60))
173
174
def unpack_highres_date(date):
175
    """This takes the high-resolution date stamp, and
176
    converts it back into the tuple (timestamp, timezone)
177
    Where timestamp is in real seconds, and timezone is an integer
178
    number of seconds offset.
179
180
    :param date: A date formated by format_highres_date
181
    :type date: string
182
0.5.40 by John Arbash Meinel
Added some highres formatting of datestamps.
183
    >>> import time, random
184
    >>> unpack_highres_date('Thu 2005-06-30 12:38:52.350850105 -0500')
185
    (1120153132.3508501, -18000)
186
    >>> unpack_highres_date('Thu 2005-06-30 17:38:52.350850105 +0000')
187
    (1120153132.3508501, 0)
188
    >>> unpack_highres_date('Thu 2005-06-30 19:38:52.350850105 +0200')
189
    (1120153132.3508501, 7200)
190
    >>> from bzrlib.osutils import local_time_offset
191
    >>> t = time.time()
192
    >>> o = local_time_offset()
193
    >>> t2, o2 = unpack_highres_date(format_highres_date(t, o))
194
    >>> t == t2
195
    True
196
    >>> o == o2
197
    True
198
    >>> for count in xrange(500):
199
    ...   t += random.random()*24*3600*365*2 - 24*3600*364 # Random time within +/- 1 year
200
    ...   o = random.randint(-12,12)*3600 # Random timezone
201
    ...   date = format_highres_date(t, o)
202
    ...   t2, o2 = unpack_highres_date(date)
203
    ...   if t != t2 or o != o2:
204
    ...      print 'Failed on date %r, %s,%s diff:%s' % (date, t, o, t2-t)
205
0.5.39 by John Arbash Meinel
(broken) Working on changing the processing to use a ChangesetTree.
206
    """
0.5.40 by John Arbash Meinel
Added some highres formatting of datestamps.
207
    #from bzrlib.errors import BzrError
208
    from bzrlib.osutils import local_time_offset
209
    import time
210
    # Up until the first period is a datestamp that is generated
211
    # as normal from time.strftime, so use time.strptime to
212
    # parse it
213
    dot_loc = date.find('.')
214
    if dot_loc == -1:
215
        raise ValueError('Date string does not contain high-precision seconds: %r' % date)
216
    base_time = time.strptime(date[:dot_loc], "%a %Y-%m-%d %H:%M:%S")
217
    fract_seconds, offset = date[dot_loc:].split()
218
    fract_seconds = float(fract_seconds)
219
    offset = int(offset)
220
    offset = int(offset / 100) * 3600 + offset % 100
221
    
222
    # mktime returns the a local timestamp, not the timestamp based
223
    # on the offset given in the file, so we need to adjust based
224
    # on what the local offset is, and then re-adjust based on
225
    # offset read
226
    timestamp = time.mktime(base_time)
227
    timestamp += local_time_offset(timestamp) - offset
228
    # Add back in the fractional seconds
229
    timestamp += fract_seconds
230
    return (timestamp, offset)
0.5.39 by John Arbash Meinel
(broken) Working on changing the processing to use a ChangesetTree.
231
232
if __name__ == '__main__':
233
    import doctest
234
    doctest.testmod()
0.5.40 by John Arbash Meinel
Added some highres formatting of datestamps.
235