Show More
@@ -1,101 +1,103 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): |
|
35 | def decode_extra(self, text): | |
36 | extra = {} |
|
36 | extra = {} | |
37 | for l in text.split('\0'): |
|
37 | for l in text.split('\0'): | |
38 | if not l: |
|
38 | if not l: | |
39 | continue |
|
39 | continue | |
40 | k, v = _string_unescape(l).split(':', 1) |
|
40 | k, v = _string_unescape(l).split(':', 1) | |
41 | extra[k] = v |
|
41 | extra[k] = v | |
42 | return extra |
|
42 | return extra | |
43 |
|
43 | |||
44 | def encode_extra(self, d): |
|
44 | def encode_extra(self, d): | |
45 | items = [_string_escape(":".join(t)) for t in d.iteritems()] |
|
45 | items = [_string_escape(":".join(t)) for t in d.iteritems()] | |
46 | return "\0".join(items) |
|
46 | return "\0".join(items) | |
47 |
|
47 | |||
48 | def extract(self, text): |
|
48 | def extract(self, text): | |
49 | """ |
|
49 | """ | |
50 | format used: |
|
50 | format used: | |
51 | nodeid\n : manifest node in ascii |
|
51 | nodeid\n : manifest node in ascii | |
52 | user\n : user, no \n or \r allowed |
|
52 | user\n : user, no \n or \r allowed | |
53 | time tz extra\n : date (time is int or float, timezone is int) |
|
53 | time tz extra\n : date (time is int or float, timezone is int) | |
54 | : extra is metadatas, encoded and separated by '\0' |
|
54 | : extra is metadatas, encoded and separated by '\0' | |
55 | : older versions ignore it |
|
55 | : older versions ignore it | |
56 | files\n\n : files modified by the cset, no \n or \r allowed |
|
56 | files\n\n : files modified by the cset, no \n or \r allowed | |
57 | (.*) : comment (free text, ideally utf-8) |
|
57 | (.*) : comment (free text, ideally utf-8) | |
58 |
|
58 | |||
59 | changelog v0 doesn't use extra |
|
59 | changelog v0 doesn't use extra | |
60 | """ |
|
60 | """ | |
61 | if not text: |
|
61 | if not text: | |
62 | return (nullid, "", (0, 0), [], "", {}) |
|
62 | return (nullid, "", (0, 0), [], "", {}) | |
63 | last = text.index("\n\n") |
|
63 | last = text.index("\n\n") | |
64 | desc = text[last + 2:] |
|
64 | desc = util.tolocal(text[last + 2:]) | |
65 | l = text[:last].split('\n') |
|
65 | l = text[:last].split('\n') | |
66 | manifest = bin(l[0]) |
|
66 | manifest = bin(l[0]) | |
67 | user = l[1] |
|
67 | user = util.tolocal(l[1]) | |
68 |
|
68 | |||
69 | extra_data = l[2].split(' ', 2) |
|
69 | extra_data = l[2].split(' ', 2) | |
70 | if len(extra_data) != 3: |
|
70 | if len(extra_data) != 3: | |
71 | time = float(extra_data.pop(0)) |
|
71 | time = float(extra_data.pop(0)) | |
72 | try: |
|
72 | try: | |
73 | # various tools did silly things with the time zone field. |
|
73 | # various tools did silly things with the time zone field. | |
74 | timezone = int(extra_data[0]) |
|
74 | timezone = int(extra_data[0]) | |
75 | except: |
|
75 | except: | |
76 | timezone = 0 |
|
76 | timezone = 0 | |
77 | extra = {} |
|
77 | extra = {} | |
78 | else: |
|
78 | else: | |
79 | time, timezone, extra = extra_data |
|
79 | time, timezone, extra = extra_data | |
80 | time, timezone = float(time), int(timezone) |
|
80 | time, timezone = float(time), int(timezone) | |
81 | extra = self.decode_extra(extra) |
|
81 | extra = self.decode_extra(extra) | |
82 | files = l[3:] |
|
82 | files = l[3:] | |
83 | return (manifest, user, (time, timezone), files, desc, extra) |
|
83 | return (manifest, user, (time, timezone), files, desc, extra) | |
84 |
|
84 | |||
85 | def read(self, node): |
|
85 | def read(self, node): | |
86 | return self.extract(self.revision(node)) |
|
86 | return self.extract(self.revision(node)) | |
87 |
|
87 | |||
88 | def add(self, manifest, list, desc, transaction, p1=None, p2=None, |
|
88 | def add(self, manifest, list, desc, transaction, p1=None, p2=None, | |
89 | user=None, date=None, extra={}): |
|
89 | user=None, date=None, extra={}): | |
90 |
|
90 | |||
|
91 | user, desc = util.fromlocal(user), util.fromlocal(desc) | |||
|
92 | ||||
91 | if date: |
|
93 | if date: | |
92 | parseddate = "%d %d" % util.parsedate(date) |
|
94 | parseddate = "%d %d" % util.parsedate(date) | |
93 | else: |
|
95 | else: | |
94 | parseddate = "%d %d" % util.makedate() |
|
96 | parseddate = "%d %d" % util.makedate() | |
95 | if extra: |
|
97 | if extra: | |
96 | extra = self.encode_extra(extra) |
|
98 | extra = self.encode_extra(extra) | |
97 | parseddate = "%s %s" % (parseddate, extra) |
|
99 | parseddate = "%s %s" % (parseddate, extra) | |
98 | list.sort() |
|
100 | list.sort() | |
99 | l = [hex(manifest), user, parseddate] + list + ["", desc] |
|
101 | l = [hex(manifest), user, parseddate] + list + ["", desc] | |
100 | text = "\n".join(l) |
|
102 | text = "\n".join(l) | |
101 | return self.addrevision(text, transaction, self.count(), p1, p2) |
|
103 | return self.addrevision(text, transaction, self.count(), p1, p2) |
General Comments 0
You need to be logged in to leave comments.
Login now