Show More
@@ -7,27 +7,20 | |||||
7 |
|
7 | |||
8 | from __future__ import absolute_import |
|
8 | from __future__ import absolute_import | |
9 |
|
9 | |||
10 | import struct |
|
|||
11 |
|
||||
12 | from .thirdparty.zope import ( |
|
10 | from .thirdparty.zope import ( | |
13 | interface as zi, |
|
11 | interface as zi, | |
14 | ) |
|
12 | ) | |
15 | from . import ( |
|
13 | from . import ( | |
16 | error, |
|
|||
17 | mdiff, |
|
|||
18 | repository, |
|
14 | repository, | |
19 | revlog, |
|
15 | revlog, | |
20 | ) |
|
16 | ) | |
21 |
|
17 | |||
22 | def _censoredtext(text): |
|
|||
23 | m, offs = revlog.parsemeta(text) |
|
|||
24 | return m and "censored" in m |
|
|||
25 |
|
||||
26 | @zi.implementer(repository.ifilestorage) |
|
18 | @zi.implementer(repository.ifilestorage) | |
27 | class filelog(revlog.revlog): |
|
19 | class filelog(revlog.revlog): | |
28 | def __init__(self, opener, path): |
|
20 | def __init__(self, opener, path): | |
29 | super(filelog, self).__init__(opener, |
|
21 | super(filelog, self).__init__(opener, | |
30 |
"/".join(("data", path + ".i")) |
|
22 | "/".join(("data", path + ".i")), | |
|
23 | censorable=True) | |||
31 | # full name of the user visible file, relative to the repository root |
|
24 | # full name of the user visible file, relative to the repository root | |
32 | self.filename = path |
|
25 | self.filename = path | |
33 |
|
26 | |||
@@ -90,35 +83,3 class filelog(revlog.revlog): | |||||
90 | return t2 != text |
|
83 | return t2 != text | |
91 |
|
84 | |||
92 | return True |
|
85 | return True | |
93 |
|
||||
94 | def checkhash(self, text, node, p1=None, p2=None, rev=None): |
|
|||
95 | try: |
|
|||
96 | super(filelog, self).checkhash(text, node, p1=p1, p2=p2, rev=rev) |
|
|||
97 | except error.RevlogError: |
|
|||
98 | if _censoredtext(text): |
|
|||
99 | raise error.CensoredNodeError(self.indexfile, node, text) |
|
|||
100 | raise |
|
|||
101 |
|
||||
102 | def iscensored(self, rev): |
|
|||
103 | """Check if a file revision is censored.""" |
|
|||
104 | return self.flags(rev) & revlog.REVIDX_ISCENSORED |
|
|||
105 |
|
||||
106 | def _peek_iscensored(self, baserev, delta, flush): |
|
|||
107 | """Quickly check if a delta produces a censored revision.""" |
|
|||
108 | # Fragile heuristic: unless new file meta keys are added alphabetically |
|
|||
109 | # preceding "censored", all censored revisions are prefixed by |
|
|||
110 | # "\1\ncensored:". A delta producing such a censored revision must be a |
|
|||
111 | # full-replacement delta, so we inspect the first and only patch in the |
|
|||
112 | # delta for this prefix. |
|
|||
113 | hlen = struct.calcsize(">lll") |
|
|||
114 | if len(delta) <= hlen: |
|
|||
115 | return False |
|
|||
116 |
|
||||
117 | oldlen = self.rawsize(baserev) |
|
|||
118 | newlen = len(delta) - hlen |
|
|||
119 | if delta[:hlen] != mdiff.replacediffheader(oldlen, newlen): |
|
|||
120 | return False |
|
|||
121 |
|
||||
122 | add = "\1\ncensored:" |
|
|||
123 | addlen = len(add) |
|
|||
124 | return newlen >= addlen and delta[hlen:hlen + addlen] == add |
|
@@ -117,6 +117,10 def packmeta(meta, text): | |||||
117 | metatext = "".join("%s: %s\n" % (k, meta[k]) for k in keys) |
|
117 | metatext = "".join("%s: %s\n" % (k, meta[k]) for k in keys) | |
118 | return "\1\n%s\1\n%s" % (metatext, text) |
|
118 | return "\1\n%s\1\n%s" % (metatext, text) | |
119 |
|
119 | |||
|
120 | def _censoredtext(text): | |||
|
121 | m, offs = parsemeta(text) | |||
|
122 | return m and "censored" in m | |||
|
123 | ||||
120 | def addflagprocessor(flag, processor): |
|
124 | def addflagprocessor(flag, processor): | |
121 | """Register a flag processor on a revision data flag. |
|
125 | """Register a flag processor on a revision data flag. | |
122 |
|
126 | |||
@@ -574,9 +578,11 class revlog(object): | |||||
574 | If mmaplargeindex is True, and an mmapindexthreshold is set, the |
|
578 | If mmaplargeindex is True, and an mmapindexthreshold is set, the | |
575 | index will be mmapped rather than read if it is larger than the |
|
579 | index will be mmapped rather than read if it is larger than the | |
576 | configured threshold. |
|
580 | configured threshold. | |
|
581 | ||||
|
582 | If censorable is True, the revlog can have censored revisions. | |||
577 | """ |
|
583 | """ | |
578 | def __init__(self, opener, indexfile, datafile=None, checkambig=False, |
|
584 | def __init__(self, opener, indexfile, datafile=None, checkambig=False, | |
579 | mmaplargeindex=False): |
|
585 | mmaplargeindex=False, censorable=False): | |
580 | """ |
|
586 | """ | |
581 | create a revlog object |
|
587 | create a revlog object | |
582 |
|
588 | |||
@@ -589,6 +595,7 class revlog(object): | |||||
589 | # When True, indexfile is opened with checkambig=True at writing, to |
|
595 | # When True, indexfile is opened with checkambig=True at writing, to | |
590 | # avoid file stat ambiguity. |
|
596 | # avoid file stat ambiguity. | |
591 | self._checkambig = checkambig |
|
597 | self._checkambig = checkambig | |
|
598 | self._censorable = censorable | |||
592 | # 3-tuple of (node, rev, text) for a raw revision. |
|
599 | # 3-tuple of (node, rev, text) for a raw revision. | |
593 | self._cache = None |
|
600 | self._cache = None | |
594 | # Maps rev to chain base rev. |
|
601 | # Maps rev to chain base rev. | |
@@ -1867,6 +1874,7 class revlog(object): | |||||
1867 | Available as a function so that subclasses can extend hash mismatch |
|
1874 | Available as a function so that subclasses can extend hash mismatch | |
1868 | behaviors as needed. |
|
1875 | behaviors as needed. | |
1869 | """ |
|
1876 | """ | |
|
1877 | try: | |||
1870 | if p1 is None and p2 is None: |
|
1878 | if p1 is None and p2 is None: | |
1871 | p1, p2 = self.parents(node) |
|
1879 | p1, p2 = self.parents(node) | |
1872 | if node != self.hash(text, p1, p2): |
|
1880 | if node != self.hash(text, p1, p2): | |
@@ -1875,6 +1883,10 class revlog(object): | |||||
1875 | revornode = templatefilters.short(hex(node)) |
|
1883 | revornode = templatefilters.short(hex(node)) | |
1876 | raise RevlogError(_("integrity check failed on %s:%s") |
|
1884 | raise RevlogError(_("integrity check failed on %s:%s") | |
1877 | % (self.indexfile, pycompat.bytestr(revornode))) |
|
1885 | % (self.indexfile, pycompat.bytestr(revornode))) | |
|
1886 | except RevlogError: | |||
|
1887 | if self._censorable and _censoredtext(text): | |||
|
1888 | raise error.CensoredNodeError(self.indexfile, node, text) | |||
|
1889 | raise | |||
1878 |
|
1890 | |||
1879 | def _enforceinlinesize(self, tr, fp=None): |
|
1891 | def _enforceinlinesize(self, tr, fp=None): | |
1880 | """Check if the revlog is too big for inline and convert if so. |
|
1892 | """Check if the revlog is too big for inline and convert if so. | |
@@ -2300,12 +2312,34 class revlog(object): | |||||
2300 |
|
2312 | |||
2301 | def iscensored(self, rev): |
|
2313 | def iscensored(self, rev): | |
2302 | """Check if a file revision is censored.""" |
|
2314 | """Check if a file revision is censored.""" | |
|
2315 | if not self._censorable: | |||
2303 | return False |
|
2316 | return False | |
2304 |
|
2317 | |||
|
2318 | return self.flags(rev) & REVIDX_ISCENSORED | |||
|
2319 | ||||
2305 | def _peek_iscensored(self, baserev, delta, flush): |
|
2320 | def _peek_iscensored(self, baserev, delta, flush): | |
2306 | """Quickly check if a delta produces a censored revision.""" |
|
2321 | """Quickly check if a delta produces a censored revision.""" | |
|
2322 | if not self._censorable: | |||
2307 | return False |
|
2323 | return False | |
2308 |
|
2324 | |||
|
2325 | # Fragile heuristic: unless new file meta keys are added alphabetically | |||
|
2326 | # preceding "censored", all censored revisions are prefixed by | |||
|
2327 | # "\1\ncensored:". A delta producing such a censored revision must be a | |||
|
2328 | # full-replacement delta, so we inspect the first and only patch in the | |||
|
2329 | # delta for this prefix. | |||
|
2330 | hlen = struct.calcsize(">lll") | |||
|
2331 | if len(delta) <= hlen: | |||
|
2332 | return False | |||
|
2333 | ||||
|
2334 | oldlen = self.rawsize(baserev) | |||
|
2335 | newlen = len(delta) - hlen | |||
|
2336 | if delta[:hlen] != mdiff.replacediffheader(oldlen, newlen): | |||
|
2337 | return False | |||
|
2338 | ||||
|
2339 | add = "\1\ncensored:" | |||
|
2340 | addlen = len(add) | |||
|
2341 | return newlen >= addlen and delta[hlen:hlen + addlen] == add | |||
|
2342 | ||||
2309 | def getstrippoint(self, minlink): |
|
2343 | def getstrippoint(self, minlink): | |
2310 | """find the minimum rev that must be stripped to strip the linkrev |
|
2344 | """find the minimum rev that must be stripped to strip the linkrev | |
2311 |
|
2345 |
General Comments 0
You need to be logged in to leave comments.
Login now