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