Show More
@@ -1,73 +1,101 b'' | |||||
1 | # changelog.py - changelog class for mercurial |
|
1 | # changelog.py - changelog class for mercurial | |
2 | # |
|
2 | # | |
3 | # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com> |
|
3 | # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com> | |
4 | # |
|
4 | # | |
5 | # This software may be used and distributed according to the terms |
|
5 | # This software may be used and distributed according to the terms | |
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from revlog import * |
|
8 | from revlog import * | |
9 | from i18n import gettext as _ |
|
9 | from i18n import gettext as _ | |
10 | from demandload import demandload |
|
10 | from demandload import demandload | |
11 | demandload(globals(), "os time util") |
|
11 | demandload(globals(), "os time util") | |
12 |
|
12 | |||
13 | def _string_escape(text): |
|
13 | def _string_escape(text): | |
14 | """ |
|
14 | """ | |
15 | >>> d = {'nl': chr(10), 'bs': chr(92), 'cr': chr(13), 'nul': chr(0)} |
|
15 | >>> d = {'nl': chr(10), 'bs': chr(92), 'cr': chr(13), 'nul': chr(0)} | |
16 | >>> s = "ab%(nl)scd%(bs)s%(bs)sn%(nul)sab%(cr)scd%(bs)s%(nl)s" % d |
|
16 | >>> s = "ab%(nl)scd%(bs)s%(bs)sn%(nul)sab%(cr)scd%(bs)s%(nl)s" % d | |
17 | >>> s |
|
17 | >>> s | |
18 | 'ab\\ncd\\\\\\\\n\\x00ab\\rcd\\\\\\n' |
|
18 | 'ab\\ncd\\\\\\\\n\\x00ab\\rcd\\\\\\n' | |
19 | >>> res = _string_escape(s) |
|
19 | >>> res = _string_escape(s) | |
20 | >>> s == _string_unescape(res) |
|
20 | >>> s == _string_unescape(res) | |
21 | True |
|
21 | True | |
22 | """ |
|
22 | """ | |
23 | # subset of the string_escape codec |
|
23 | # subset of the string_escape codec | |
24 | text = text.replace('\\', '\\\\').replace('\n', '\\n').replace('\r', '\\r') |
|
24 | text = text.replace('\\', '\\\\').replace('\n', '\\n').replace('\r', '\\r') | |
25 | return text.replace('\0', '\\0') |
|
25 | return text.replace('\0', '\\0') | |
26 |
|
26 | |||
27 | def _string_unescape(text): |
|
27 | def _string_unescape(text): | |
28 | return text.decode('string_escape') |
|
28 | return text.decode('string_escape') | |
29 |
|
29 | |||
30 | class changelog(revlog): |
|
30 | class changelog(revlog): | |
31 | def __init__(self, opener, defversion=REVLOGV0): |
|
31 | def __init__(self, opener, defversion=REVLOGV0): | |
32 | revlog.__init__(self, opener, "00changelog.i", "00changelog.d", |
|
32 | revlog.__init__(self, opener, "00changelog.i", "00changelog.d", | |
33 | defversion) |
|
33 | defversion) | |
34 |
|
34 | |||
|
35 | def decode_extra(self, text): | |||
|
36 | extra = {} | |||
|
37 | for l in text.split('\0'): | |||
|
38 | if not l: | |||
|
39 | continue | |||
|
40 | k, v = _string_unescape(l).split(':', 1) | |||
|
41 | extra[k] = v | |||
|
42 | return extra | |||
|
43 | ||||
|
44 | def encode_extra(self, d): | |||
|
45 | items = [_string_escape(":".join(t)) for t in d.iteritems()] | |||
|
46 | return "\0".join(items) | |||
|
47 | ||||
35 | def extract(self, text): |
|
48 | def extract(self, text): | |
36 | """ |
|
49 | """ | |
37 | format used: |
|
50 | format used: | |
38 | nodeid\n : manifest node in ascii |
|
51 | nodeid\n : manifest node in ascii | |
39 | user\n : user, no \n or \r allowed |
|
52 | user\n : user, no \n or \r allowed | |
40 | time tz\n : date (time is int or float, timezone is int) |
|
53 | time tz extra\n : date (time is int or float, timezone is int) | |
41 | files\n\n : files modified by the cset, no \n or \r allowed |
|
54 | : extra is metadatas, encoded and separated by '\0' | |
42 | (.*) : comment (free text, ideally utf-8) |
|
55 | : older versions ignore it | |
|
56 | files\n\n : files modified by the cset, no \n or \r allowed | |||
|
57 | (.*) : comment (free text, ideally utf-8) | |||
|
58 | ||||
|
59 | changelog v0 doesn't use extra | |||
43 | """ |
|
60 | """ | |
44 | if not text: |
|
61 | if not text: | |
45 | return (nullid, "", (0, 0), [], "") |
|
62 | return (nullid, "", (0, 0), [], "") | |
46 | last = text.index("\n\n") |
|
63 | last = text.index("\n\n") | |
47 | desc = text[last + 2:] |
|
64 | desc = text[last + 2:] | |
48 |
l = text[:last].split |
|
65 | l = text[:last].split('\n') | |
49 | manifest = bin(l[0]) |
|
66 | manifest = bin(l[0]) | |
50 | user = l[1] |
|
67 | user = l[1] | |
51 | date = l[2].split(' ') |
|
68 | ||
52 | time = float(date.pop(0)) |
|
69 | extra_data = l[2].split(' ', 2) | |
53 | try: |
|
70 | if len(extra_data) != 3: | |
54 | # various tools did silly things with the time zone field. |
|
71 | time = float(extra_data.pop(0)) | |
55 | timezone = int(date[0]) |
|
72 | try: | |
56 | except: |
|
73 | # various tools did silly things with the time zone field. | |
57 | timezone = 0 |
|
74 | timezone = int(extra_data[0]) | |
|
75 | except: | |||
|
76 | timezone = 0 | |||
|
77 | extra = {} | |||
|
78 | else: | |||
|
79 | time, timezone, extra = extra_data | |||
|
80 | time, timezone = float(time), int(timezone) | |||
|
81 | extra = self.decode_extra(extra) | |||
58 | files = l[3:] |
|
82 | files = l[3:] | |
59 | return (manifest, user, (time, timezone), files, desc) |
|
83 | return (manifest, user, (time, timezone), files, desc, extra) | |
60 |
|
84 | |||
61 | def read(self, node): |
|
85 | def read(self, node): | |
62 | return self.extract(self.revision(node)) |
|
86 | return self.extract(self.revision(node)) | |
63 |
|
87 | |||
64 | def add(self, manifest, list, desc, transaction, p1=None, p2=None, |
|
88 | def add(self, manifest, list, desc, transaction, p1=None, p2=None, | |
65 | user=None, date=None): |
|
89 | user=None, date=None, extra={}): | |
|
90 | ||||
66 | if date: |
|
91 | if date: | |
67 | parseddate = "%d %d" % util.parsedate(date) |
|
92 | parseddate = "%d %d" % util.parsedate(date) | |
68 | else: |
|
93 | else: | |
69 | parseddate = "%d %d" % util.makedate() |
|
94 | parseddate = "%d %d" % util.makedate() | |
|
95 | if extra: | |||
|
96 | extra = self.encode_extra(extra) | |||
|
97 | parseddate = "%s %s" % (parseddate, extra) | |||
70 | list.sort() |
|
98 | list.sort() | |
71 | l = [hex(manifest), user, parseddate] + list + ["", desc] |
|
99 | l = [hex(manifest), user, parseddate] + list + ["", desc] | |
72 | text = "\n".join(l) |
|
100 | text = "\n".join(l) | |
73 | return self.addrevision(text, transaction, self.count(), p1, p2) |
|
101 | return self.addrevision(text, transaction, self.count(), p1, p2) |
General Comments 0
You need to be logged in to leave comments.
Login now