Mercurial > hg
annotate mercurial/filelog.py @ 25127:2b9cda9040f7
hg-ssh: reject push earlier (on pretxnopen)
We now have a lock triggered for any transaction. We use it to ensure no-read
are made in read-only mode. We need more that just "no changegroup is added",
since bundle2 allows for more than just changegroup to be exchanged. We still
protect pushkey as it may write data without opening a transaction.
author | Pierre-Yves David <pierre-yves.david@fb.com> |
---|---|
date | Sun, 10 May 2015 04:39:11 -0700 |
parents | 4bfe9f2d9761 |
children | 34bd1a5eef5b |
rev | line source |
---|---|
1089 | 1 # filelog.py - file history class for mercurial |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
2 # |
4635
63b9d2deed48
Updated copyright notices and add "and others" to "hg version"
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4258
diff
changeset
|
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
4 # |
8225
46293a0c7e9f
updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents:
7634
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
10263 | 6 # GNU General Public License version 2 or any later version. |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
7 |
24255
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
8 import error, mdiff, revlog |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
9 import re, struct |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
10 |
14074
e8271159c8c2
filelog: extract metadata parsing and packing
Sune Foldager <cryo@cyanite.org>
parents:
13240
diff
changeset
|
11 _mdre = re.compile('\1\n') |
22421
30a610424eff
filelog: make parsemeta a public module function, to be used by censor module
Mike Edgar <adgar@google.com>
parents:
22420
diff
changeset
|
12 def parsemeta(text): |
14074
e8271159c8c2
filelog: extract metadata parsing and packing
Sune Foldager <cryo@cyanite.org>
parents:
13240
diff
changeset
|
13 """return (metadatadict, keylist, metadatasize)""" |
e8271159c8c2
filelog: extract metadata parsing and packing
Sune Foldager <cryo@cyanite.org>
parents:
13240
diff
changeset
|
14 # text can be buffer, so we can't use .startswith or .index |
e8271159c8c2
filelog: extract metadata parsing and packing
Sune Foldager <cryo@cyanite.org>
parents:
13240
diff
changeset
|
15 if text[:2] != '\1\n': |
22422
75bb7c702317
filelog: parsemeta stops returning unused key list
Mike Edgar <adgar@google.com>
parents:
22421
diff
changeset
|
16 return None, None |
14074
e8271159c8c2
filelog: extract metadata parsing and packing
Sune Foldager <cryo@cyanite.org>
parents:
13240
diff
changeset
|
17 s = _mdre.search(text, 2).start() |
e8271159c8c2
filelog: extract metadata parsing and packing
Sune Foldager <cryo@cyanite.org>
parents:
13240
diff
changeset
|
18 mtext = text[2:s] |
e8271159c8c2
filelog: extract metadata parsing and packing
Sune Foldager <cryo@cyanite.org>
parents:
13240
diff
changeset
|
19 meta = {} |
e8271159c8c2
filelog: extract metadata parsing and packing
Sune Foldager <cryo@cyanite.org>
parents:
13240
diff
changeset
|
20 for l in mtext.splitlines(): |
13240
e5060aa22043
filelog: move metadata parsing to a helper function
Matt Mackall <mpm@selenic.com>
parents:
11541
diff
changeset
|
21 k, v = l.split(": ", 1) |
14074
e8271159c8c2
filelog: extract metadata parsing and packing
Sune Foldager <cryo@cyanite.org>
parents:
13240
diff
changeset
|
22 meta[k] = v |
22422
75bb7c702317
filelog: parsemeta stops returning unused key list
Mike Edgar <adgar@google.com>
parents:
22421
diff
changeset
|
23 return meta, (s + 2) |
14074
e8271159c8c2
filelog: extract metadata parsing and packing
Sune Foldager <cryo@cyanite.org>
parents:
13240
diff
changeset
|
24 |
22420
4669e26747c3
filelog: make packmeta a public module function, to be used by censor
Mike Edgar <adgar@google.com>
parents:
19148
diff
changeset
|
25 def packmeta(meta, text): |
4669e26747c3
filelog: make packmeta a public module function, to be used by censor
Mike Edgar <adgar@google.com>
parents:
19148
diff
changeset
|
26 keys = sorted(meta.iterkeys()) |
4669e26747c3
filelog: make packmeta a public module function, to be used by censor
Mike Edgar <adgar@google.com>
parents:
19148
diff
changeset
|
27 metatext = "".join("%s: %s\n" % (k, meta[k]) for k in keys) |
4669e26747c3
filelog: make packmeta a public module function, to be used by censor
Mike Edgar <adgar@google.com>
parents:
19148
diff
changeset
|
28 return "\1\n%s\1\n%s" % (metatext, text) |
13240
e5060aa22043
filelog: move metadata parsing to a helper function
Matt Mackall <mpm@selenic.com>
parents:
11541
diff
changeset
|
29 |
22596
27e2317efe89
filelog: raise CensoredNodeError when hash checks fail with censor metadata
Mike Edgar <adgar@google.com>
parents:
22422
diff
changeset
|
30 def _censoredtext(text): |
27e2317efe89
filelog: raise CensoredNodeError when hash checks fail with censor metadata
Mike Edgar <adgar@google.com>
parents:
22422
diff
changeset
|
31 m, offs = parsemeta(text) |
24117
9cfd7c4f22f5
filelog: allow censored files to contain padding data
Mike Edgar <adgar@google.com>
parents:
24003
diff
changeset
|
32 return m and "censored" in m |
22596
27e2317efe89
filelog: raise CensoredNodeError when hash checks fail with censor metadata
Mike Edgar <adgar@google.com>
parents:
22422
diff
changeset
|
33 |
7634
14a4337a9b9b
revlog: kill from-style imports
Matt Mackall <mpm@selenic.com>
parents:
7622
diff
changeset
|
34 class filelog(revlog.revlog): |
4258
b11a2fb59cf5
revlog: simplify revlog version handling
Matt Mackall <mpm@selenic.com>
parents:
4257
diff
changeset
|
35 def __init__(self, opener, path): |
19148
3bda242bf244
filelog: use super() for calling base functions
Durham Goode <durham@fb.com>
parents:
14287
diff
changeset
|
36 super(filelog, self).__init__(opener, |
8531
810387f59696
filelog encoding: move the encoding/decoding into store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
8225
diff
changeset
|
37 "/".join(("data", path + ".i"))) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
38 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
39 def read(self, node): |
360 | 40 t = self.revision(node) |
686
d7d68d27ebe5
Reapply startswith() changes that got lost with stale edit
Matt Mackall <mpm@selenic.com>
parents:
681
diff
changeset
|
41 if not t.startswith('\1\n'): |
360 | 42 return t |
2579
0875cda033fd
use __contains__, index or split instead of str.find
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
2470
diff
changeset
|
43 s = t.index('\1\n', 2) |
10282
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
44 return t[s + 2:] |
360 | 45 |
46 def add(self, text, meta, transaction, link, p1=None, p2=None): | |
686
d7d68d27ebe5
Reapply startswith() changes that got lost with stale edit
Matt Mackall <mpm@selenic.com>
parents:
681
diff
changeset
|
47 if meta or text.startswith('\1\n'): |
22420
4669e26747c3
filelog: make packmeta a public module function, to be used by censor
Mike Edgar <adgar@google.com>
parents:
19148
diff
changeset
|
48 text = packmeta(meta, text) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
49 return self.addrevision(text, transaction, link, p1, p2) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
50 |
1116 | 51 def renamed(self, node): |
7634
14a4337a9b9b
revlog: kill from-style imports
Matt Mackall <mpm@selenic.com>
parents:
7622
diff
changeset
|
52 if self.parents(node)[0] != revlog.nullid: |
1116 | 53 return False |
13240
e5060aa22043
filelog: move metadata parsing to a helper function
Matt Mackall <mpm@selenic.com>
parents:
11541
diff
changeset
|
54 t = self.revision(node) |
22421
30a610424eff
filelog: make parsemeta a public module function, to be used by censor module
Mike Edgar <adgar@google.com>
parents:
22420
diff
changeset
|
55 m = parsemeta(t)[0] |
5915
d0576d065993
Prefer i in d over d.has_key(i)
Christian Ebert <blacktrash@gmx.net>
parents:
4635
diff
changeset
|
56 if m and "copy" in m: |
7634
14a4337a9b9b
revlog: kill from-style imports
Matt Mackall <mpm@selenic.com>
parents:
7622
diff
changeset
|
57 return (m["copy"], revlog.bin(m["copyrev"])) |
1116 | 58 return False |
59 | |
2898
db397c38005d
merge: use file size stored in revlog index
Matt Mackall <mpm@selenic.com>
parents:
2895
diff
changeset
|
60 def size(self, rev): |
db397c38005d
merge: use file size stored in revlog index
Matt Mackall <mpm@selenic.com>
parents:
2895
diff
changeset
|
61 """return the size of a given revision""" |
db397c38005d
merge: use file size stored in revlog index
Matt Mackall <mpm@selenic.com>
parents:
2895
diff
changeset
|
62 |
db397c38005d
merge: use file size stored in revlog index
Matt Mackall <mpm@selenic.com>
parents:
2895
diff
changeset
|
63 # for revisions with renames, we have to go the slow way |
db397c38005d
merge: use file size stored in revlog index
Matt Mackall <mpm@selenic.com>
parents:
2895
diff
changeset
|
64 node = self.node(rev) |
db397c38005d
merge: use file size stored in revlog index
Matt Mackall <mpm@selenic.com>
parents:
2895
diff
changeset
|
65 if self.renamed(node): |
db397c38005d
merge: use file size stored in revlog index
Matt Mackall <mpm@selenic.com>
parents:
2895
diff
changeset
|
66 return len(self.read(node)) |
24118
76f6ae06ddf5
revlog: add "iscensored()" to revlog public API
Mike Edgar <adgar@google.com>
parents:
24117
diff
changeset
|
67 if self.iscensored(rev): |
22597
58ec36686f0e
filelog: censored files compare against empty data, have 0 size
Mike Edgar <adgar@google.com>
parents:
22596
diff
changeset
|
68 return 0 |
2898
db397c38005d
merge: use file size stored in revlog index
Matt Mackall <mpm@selenic.com>
parents:
2895
diff
changeset
|
69 |
11540
2370e270a29a
filelog: test behaviour for data starting with "\1\n"
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
11539
diff
changeset
|
70 # XXX if self.read(node).startswith("\1\n"), this returns (size+4) |
19148
3bda242bf244
filelog: use super() for calling base functions
Durham Goode <durham@fb.com>
parents:
14287
diff
changeset
|
71 return super(filelog, self).size(rev) |
2898
db397c38005d
merge: use file size stored in revlog index
Matt Mackall <mpm@selenic.com>
parents:
2895
diff
changeset
|
72 |
2887
05257fd28591
filelog: add hash-based comparisons
Matt Mackall <mpm@selenic.com>
parents:
2859
diff
changeset
|
73 def cmp(self, node, text): |
11539
a463e3c50212
cmp: document the fact that we return True if content is different
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10706
diff
changeset
|
74 """compare text with a given file revision |
a463e3c50212
cmp: document the fact that we return True if content is different
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10706
diff
changeset
|
75 |
a463e3c50212
cmp: document the fact that we return True if content is different
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10706
diff
changeset
|
76 returns True if text is different than what is stored. |
a463e3c50212
cmp: document the fact that we return True if content is different
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10706
diff
changeset
|
77 """ |
2887
05257fd28591
filelog: add hash-based comparisons
Matt Mackall <mpm@selenic.com>
parents:
2859
diff
changeset
|
78 |
11541
ab9fa7a85dd9
filelog: cmp: don't read data if hashes are identical (issue2273)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
11540
diff
changeset
|
79 t = text |
ab9fa7a85dd9
filelog: cmp: don't read data if hashes are identical (issue2273)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
11540
diff
changeset
|
80 if text.startswith('\1\n'): |
ab9fa7a85dd9
filelog: cmp: don't read data if hashes are identical (issue2273)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
11540
diff
changeset
|
81 t = '\1\n\1\n' + text |
ab9fa7a85dd9
filelog: cmp: don't read data if hashes are identical (issue2273)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
11540
diff
changeset
|
82 |
19148
3bda242bf244
filelog: use super() for calling base functions
Durham Goode <durham@fb.com>
parents:
14287
diff
changeset
|
83 samehashes = not super(filelog, self).cmp(node, t) |
11541
ab9fa7a85dd9
filelog: cmp: don't read data if hashes are identical (issue2273)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
11540
diff
changeset
|
84 if samehashes: |
ab9fa7a85dd9
filelog: cmp: don't read data if hashes are identical (issue2273)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
11540
diff
changeset
|
85 return False |
ab9fa7a85dd9
filelog: cmp: don't read data if hashes are identical (issue2273)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
11540
diff
changeset
|
86 |
22597
58ec36686f0e
filelog: censored files compare against empty data, have 0 size
Mike Edgar <adgar@google.com>
parents:
22596
diff
changeset
|
87 # censored files compare against the empty file |
24118
76f6ae06ddf5
revlog: add "iscensored()" to revlog public API
Mike Edgar <adgar@google.com>
parents:
24117
diff
changeset
|
88 if self.iscensored(self.rev(node)): |
22597
58ec36686f0e
filelog: censored files compare against empty data, have 0 size
Mike Edgar <adgar@google.com>
parents:
22596
diff
changeset
|
89 return text != '' |
58ec36686f0e
filelog: censored files compare against empty data, have 0 size
Mike Edgar <adgar@google.com>
parents:
22596
diff
changeset
|
90 |
11541
ab9fa7a85dd9
filelog: cmp: don't read data if hashes are identical (issue2273)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
11540
diff
changeset
|
91 # renaming a file produces a different hash, even if the data |
ab9fa7a85dd9
filelog: cmp: don't read data if hashes are identical (issue2273)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
11540
diff
changeset
|
92 # remains unchanged. Check if it's the case (slow): |
ab9fa7a85dd9
filelog: cmp: don't read data if hashes are identical (issue2273)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
11540
diff
changeset
|
93 if self.renamed(node): |
2887
05257fd28591
filelog: add hash-based comparisons
Matt Mackall <mpm@selenic.com>
parents:
2859
diff
changeset
|
94 t2 = self.read(node) |
2895
21631c2c09a5
filelog.cmp: return 0 for equality
Matt Mackall <mpm@selenic.com>
parents:
2890
diff
changeset
|
95 return t2 != text |
2887
05257fd28591
filelog: add hash-based comparisons
Matt Mackall <mpm@selenic.com>
parents:
2859
diff
changeset
|
96 |
11541
ab9fa7a85dd9
filelog: cmp: don't read data if hashes are identical (issue2273)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
11540
diff
changeset
|
97 return True |
14287
7c231754a621
filelog: add file function to open other filelogs
Sune Foldager <cryo@cyanite.org>
parents:
14074
diff
changeset
|
98 |
22596
27e2317efe89
filelog: raise CensoredNodeError when hash checks fail with censor metadata
Mike Edgar <adgar@google.com>
parents:
22422
diff
changeset
|
99 def checkhash(self, text, p1, p2, node, rev=None): |
27e2317efe89
filelog: raise CensoredNodeError when hash checks fail with censor metadata
Mike Edgar <adgar@google.com>
parents:
22422
diff
changeset
|
100 try: |
27e2317efe89
filelog: raise CensoredNodeError when hash checks fail with censor metadata
Mike Edgar <adgar@google.com>
parents:
22422
diff
changeset
|
101 super(filelog, self).checkhash(text, p1, p2, node, rev=rev) |
27e2317efe89
filelog: raise CensoredNodeError when hash checks fail with censor metadata
Mike Edgar <adgar@google.com>
parents:
22422
diff
changeset
|
102 except error.RevlogError: |
27e2317efe89
filelog: raise CensoredNodeError when hash checks fail with censor metadata
Mike Edgar <adgar@google.com>
parents:
22422
diff
changeset
|
103 if _censoredtext(text): |
24190
903c7e8c97ad
changegroup: emit full-replacement deltas if either revision is censored
Mike Edgar <adgar@google.com>
parents:
24118
diff
changeset
|
104 raise error.CensoredNodeError(self.indexfile, node, text) |
22596
27e2317efe89
filelog: raise CensoredNodeError when hash checks fail with censor metadata
Mike Edgar <adgar@google.com>
parents:
22422
diff
changeset
|
105 raise |
27e2317efe89
filelog: raise CensoredNodeError when hash checks fail with censor metadata
Mike Edgar <adgar@google.com>
parents:
22422
diff
changeset
|
106 |
24118
76f6ae06ddf5
revlog: add "iscensored()" to revlog public API
Mike Edgar <adgar@google.com>
parents:
24117
diff
changeset
|
107 def iscensored(self, rev): |
22597
58ec36686f0e
filelog: censored files compare against empty data, have 0 size
Mike Edgar <adgar@google.com>
parents:
22596
diff
changeset
|
108 """Check if a file revision is censored.""" |
23858
22a979d1ae56
filelog: use censored revlog flag bit to quickly check if a node is censored
Mike Edgar <adgar@google.com>
parents:
22597
diff
changeset
|
109 return self.flags(rev) & revlog.REVIDX_ISCENSORED |
24255
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
110 |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
111 def _peek_iscensored(self, baserev, delta, flush): |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
112 """Quickly check if a delta produces a censored revision.""" |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
113 # Fragile heuristic: unless new file meta keys are added alphabetically |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
114 # preceding "censored", all censored revisions are prefixed by |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
115 # "\1\ncensored:". A delta producing such a censored revision must be a |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
116 # full-replacement delta, so we inspect the first and only patch in the |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
117 # delta for this prefix. |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
118 hlen = struct.calcsize(">lll") |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
119 if len(delta) <= hlen: |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
120 return False |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
121 |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
122 oldlen = self.rawsize(baserev) |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
123 newlen = len(delta) - hlen |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
124 if delta[:hlen] != mdiff.replacediffheader(oldlen, newlen): |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
125 return False |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
126 |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
127 add = "\1\ncensored:" |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
128 addlen = len(add) |
4bfe9f2d9761
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit
Mike Edgar <adgar@google.com>
parents:
24190
diff
changeset
|
129 return newlen >= addlen and delta[hlen:hlen + addlen] == add |