##// END OF EJS Templates
filelog: fix parsemeta docstring...
Jun Wu -
r32124:8ac7ac71 default
parent child Browse files
Show More
@@ -1,137 +1,137 b''
1 # filelog.py - file history class for mercurial
1 # filelog.py - file history class for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import re
10 import re
11 import struct
11 import struct
12
12
13 from . import (
13 from . import (
14 error,
14 error,
15 mdiff,
15 mdiff,
16 revlog,
16 revlog,
17 )
17 )
18
18
19 _mdre = re.compile('\1\n')
19 _mdre = re.compile('\1\n')
20 def parsemeta(text):
20 def parsemeta(text):
21 """return (metadatadict, keylist, metadatasize)"""
21 """return (metadatadict, metadatasize)"""
22 # text can be buffer, so we can't use .startswith or .index
22 # text can be buffer, so we can't use .startswith or .index
23 if text[:2] != '\1\n':
23 if text[:2] != '\1\n':
24 return None, None
24 return None, None
25 s = _mdre.search(text, 2).start()
25 s = _mdre.search(text, 2).start()
26 mtext = text[2:s]
26 mtext = text[2:s]
27 meta = {}
27 meta = {}
28 for l in mtext.splitlines():
28 for l in mtext.splitlines():
29 k, v = l.split(": ", 1)
29 k, v = l.split(": ", 1)
30 meta[k] = v
30 meta[k] = v
31 return meta, (s + 2)
31 return meta, (s + 2)
32
32
33 def packmeta(meta, text):
33 def packmeta(meta, text):
34 keys = sorted(meta.iterkeys())
34 keys = sorted(meta.iterkeys())
35 metatext = "".join("%s: %s\n" % (k, meta[k]) for k in keys)
35 metatext = "".join("%s: %s\n" % (k, meta[k]) for k in keys)
36 return "\1\n%s\1\n%s" % (metatext, text)
36 return "\1\n%s\1\n%s" % (metatext, text)
37
37
38 def _censoredtext(text):
38 def _censoredtext(text):
39 m, offs = parsemeta(text)
39 m, offs = parsemeta(text)
40 return m and "censored" in m
40 return m and "censored" in m
41
41
42 class filelog(revlog.revlog):
42 class filelog(revlog.revlog):
43 def __init__(self, opener, path):
43 def __init__(self, opener, path):
44 super(filelog, self).__init__(opener,
44 super(filelog, self).__init__(opener,
45 "/".join(("data", path + ".i")))
45 "/".join(("data", path + ".i")))
46
46
47 def read(self, node):
47 def read(self, node):
48 t = self.revision(node)
48 t = self.revision(node)
49 if not t.startswith('\1\n'):
49 if not t.startswith('\1\n'):
50 return t
50 return t
51 s = t.index('\1\n', 2)
51 s = t.index('\1\n', 2)
52 return t[s + 2:]
52 return t[s + 2:]
53
53
54 def add(self, text, meta, transaction, link, p1=None, p2=None):
54 def add(self, text, meta, transaction, link, p1=None, p2=None):
55 if meta or text.startswith('\1\n'):
55 if meta or text.startswith('\1\n'):
56 text = packmeta(meta, text)
56 text = packmeta(meta, text)
57 return self.addrevision(text, transaction, link, p1, p2)
57 return self.addrevision(text, transaction, link, p1, p2)
58
58
59 def renamed(self, node):
59 def renamed(self, node):
60 if self.parents(node)[0] != revlog.nullid:
60 if self.parents(node)[0] != revlog.nullid:
61 return False
61 return False
62 t = self.revision(node)
62 t = self.revision(node)
63 m = parsemeta(t)[0]
63 m = parsemeta(t)[0]
64 if m and "copy" in m:
64 if m and "copy" in m:
65 return (m["copy"], revlog.bin(m["copyrev"]))
65 return (m["copy"], revlog.bin(m["copyrev"]))
66 return False
66 return False
67
67
68 def size(self, rev):
68 def size(self, rev):
69 """return the size of a given revision"""
69 """return the size of a given revision"""
70
70
71 # for revisions with renames, we have to go the slow way
71 # for revisions with renames, we have to go the slow way
72 node = self.node(rev)
72 node = self.node(rev)
73 if self.renamed(node):
73 if self.renamed(node):
74 return len(self.read(node))
74 return len(self.read(node))
75 if self.iscensored(rev):
75 if self.iscensored(rev):
76 return 0
76 return 0
77
77
78 # XXX if self.read(node).startswith("\1\n"), this returns (size+4)
78 # XXX if self.read(node).startswith("\1\n"), this returns (size+4)
79 return super(filelog, self).size(rev)
79 return super(filelog, self).size(rev)
80
80
81 def cmp(self, node, text):
81 def cmp(self, node, text):
82 """compare text with a given file revision
82 """compare text with a given file revision
83
83
84 returns True if text is different than what is stored.
84 returns True if text is different than what is stored.
85 """
85 """
86
86
87 t = text
87 t = text
88 if text.startswith('\1\n'):
88 if text.startswith('\1\n'):
89 t = '\1\n\1\n' + text
89 t = '\1\n\1\n' + text
90
90
91 samehashes = not super(filelog, self).cmp(node, t)
91 samehashes = not super(filelog, self).cmp(node, t)
92 if samehashes:
92 if samehashes:
93 return False
93 return False
94
94
95 # censored files compare against the empty file
95 # censored files compare against the empty file
96 if self.iscensored(self.rev(node)):
96 if self.iscensored(self.rev(node)):
97 return text != ''
97 return text != ''
98
98
99 # renaming a file produces a different hash, even if the data
99 # renaming a file produces a different hash, even if the data
100 # remains unchanged. Check if it's the case (slow):
100 # remains unchanged. Check if it's the case (slow):
101 if self.renamed(node):
101 if self.renamed(node):
102 t2 = self.read(node)
102 t2 = self.read(node)
103 return t2 != text
103 return t2 != text
104
104
105 return True
105 return True
106
106
107 def checkhash(self, text, node, p1=None, p2=None, rev=None):
107 def checkhash(self, text, node, p1=None, p2=None, rev=None):
108 try:
108 try:
109 super(filelog, self).checkhash(text, node, p1=p1, p2=p2, rev=rev)
109 super(filelog, self).checkhash(text, node, p1=p1, p2=p2, rev=rev)
110 except error.RevlogError:
110 except error.RevlogError:
111 if _censoredtext(text):
111 if _censoredtext(text):
112 raise error.CensoredNodeError(self.indexfile, node, text)
112 raise error.CensoredNodeError(self.indexfile, node, text)
113 raise
113 raise
114
114
115 def iscensored(self, rev):
115 def iscensored(self, rev):
116 """Check if a file revision is censored."""
116 """Check if a file revision is censored."""
117 return self.flags(rev) & revlog.REVIDX_ISCENSORED
117 return self.flags(rev) & revlog.REVIDX_ISCENSORED
118
118
119 def _peek_iscensored(self, baserev, delta, flush):
119 def _peek_iscensored(self, baserev, delta, flush):
120 """Quickly check if a delta produces a censored revision."""
120 """Quickly check if a delta produces a censored revision."""
121 # Fragile heuristic: unless new file meta keys are added alphabetically
121 # Fragile heuristic: unless new file meta keys are added alphabetically
122 # preceding "censored", all censored revisions are prefixed by
122 # preceding "censored", all censored revisions are prefixed by
123 # "\1\ncensored:". A delta producing such a censored revision must be a
123 # "\1\ncensored:". A delta producing such a censored revision must be a
124 # full-replacement delta, so we inspect the first and only patch in the
124 # full-replacement delta, so we inspect the first and only patch in the
125 # delta for this prefix.
125 # delta for this prefix.
126 hlen = struct.calcsize(">lll")
126 hlen = struct.calcsize(">lll")
127 if len(delta) <= hlen:
127 if len(delta) <= hlen:
128 return False
128 return False
129
129
130 oldlen = self.rawsize(baserev)
130 oldlen = self.rawsize(baserev)
131 newlen = len(delta) - hlen
131 newlen = len(delta) - hlen
132 if delta[:hlen] != mdiff.replacediffheader(oldlen, newlen):
132 if delta[:hlen] != mdiff.replacediffheader(oldlen, newlen):
133 return False
133 return False
134
134
135 add = "\1\ncensored:"
135 add = "\1\ncensored:"
136 addlen = len(add)
136 addlen = len(add)
137 return newlen >= addlen and delta[hlen:hlen + addlen] == add
137 return newlen >= addlen and delta[hlen:hlen + addlen] == add
General Comments 0
You need to be logged in to leave comments. Login now