##// END OF EJS Templates
narrow: assume addflagprocessor will always exist on revlog module...
Augie Fackler -
r36100:9772ef9f default
parent child Browse files
Show More
@@ -1,162 +1,161 b''
1 # narrowrevlog.py - revlog storing irrelevant nodes as "ellipsis" nodes
1 # narrowrevlog.py - revlog storing irrelevant nodes as "ellipsis" nodes
2 #
2 #
3 # Copyright 2017 Google, Inc.
3 # Copyright 2017 Google, Inc.
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 from mercurial import (
10 from mercurial import (
11 manifest,
11 manifest,
12 revlog,
12 revlog,
13 util,
13 util,
14 )
14 )
15
15
16 ELLIPSIS_NODE_FLAG = 1 << 14
16 ELLIPSIS_NODE_FLAG = 1 << 14
17 revlog.REVIDX_KNOWN_FLAGS |= ELLIPSIS_NODE_FLAG
17 revlog.REVIDX_KNOWN_FLAGS |= ELLIPSIS_NODE_FLAG
18 if ELLIPSIS_NODE_FLAG not in revlog.REVIDX_FLAGS_ORDER:
18 if ELLIPSIS_NODE_FLAG not in revlog.REVIDX_FLAGS_ORDER:
19 revlog.REVIDX_FLAGS_ORDER.append(ELLIPSIS_NODE_FLAG)
19 revlog.REVIDX_FLAGS_ORDER.append(ELLIPSIS_NODE_FLAG)
20
20
21 def readtransform(self, text):
21 def readtransform(self, text):
22 return text, False
22 return text, False
23
23
24 def writetransform(self, text):
24 def writetransform(self, text):
25 return text, False
25 return text, False
26
26
27 def rawtransform(self, text):
27 def rawtransform(self, text):
28 return False
28 return False
29
29
30 if util.safehasattr(revlog, 'addflagprocessor'):
30 revlog.addflagprocessor(ELLIPSIS_NODE_FLAG,
31 revlog.addflagprocessor(ELLIPSIS_NODE_FLAG,
31 (readtransform, writetransform, rawtransform))
32 (readtransform, writetransform, rawtransform))
33
32
34 def setup():
33 def setup():
35 # We just wanted to add the flag processor, which is done at module
34 # We just wanted to add the flag processor, which is done at module
36 # load time.
35 # load time.
37 pass
36 pass
38
37
39 class excludeddir(manifest.treemanifest):
38 class excludeddir(manifest.treemanifest):
40 def __init__(self, dir, node):
39 def __init__(self, dir, node):
41 super(excludeddir, self).__init__(dir)
40 super(excludeddir, self).__init__(dir)
42 self._node = node
41 self._node = node
43 # Add an empty file, which will be included by iterators and such,
42 # Add an empty file, which will be included by iterators and such,
44 # appearing as the directory itself (i.e. something like "dir/")
43 # appearing as the directory itself (i.e. something like "dir/")
45 self._files[''] = node
44 self._files[''] = node
46 self._flags[''] = 't'
45 self._flags[''] = 't'
47
46
48 # Manifests outside the narrowspec should never be modified, so avoid
47 # Manifests outside the narrowspec should never be modified, so avoid
49 # copying. This makes a noticeable difference when there are very many
48 # copying. This makes a noticeable difference when there are very many
50 # directories outside the narrowspec. Also, it makes sense for the copy to
49 # directories outside the narrowspec. Also, it makes sense for the copy to
51 # be of the same type as the original, which would not happen with the
50 # be of the same type as the original, which would not happen with the
52 # super type's copy().
51 # super type's copy().
53 def copy(self):
52 def copy(self):
54 return self
53 return self
55
54
56 class excludeddirmanifestctx(manifest.treemanifestctx):
55 class excludeddirmanifestctx(manifest.treemanifestctx):
57 def __init__(self, dir, node):
56 def __init__(self, dir, node):
58 self._dir = dir
57 self._dir = dir
59 self._node = node
58 self._node = node
60
59
61 def read(self):
60 def read(self):
62 return excludeddir(self._dir, self._node)
61 return excludeddir(self._dir, self._node)
63
62
64 def write(self, *args):
63 def write(self, *args):
65 raise AssertionError('Attempt to write manifest from excluded dir %s' %
64 raise AssertionError('Attempt to write manifest from excluded dir %s' %
66 self._dir)
65 self._dir)
67
66
68 class excludedmanifestrevlog(manifest.manifestrevlog):
67 class excludedmanifestrevlog(manifest.manifestrevlog):
69 def __init__(self, dir):
68 def __init__(self, dir):
70 self._dir = dir
69 self._dir = dir
71
70
72 def __len__(self):
71 def __len__(self):
73 raise AssertionError('Attempt to get length of excluded dir %s' %
72 raise AssertionError('Attempt to get length of excluded dir %s' %
74 self._dir)
73 self._dir)
75
74
76 def rev(self, node):
75 def rev(self, node):
77 raise AssertionError('Attempt to get rev from excluded dir %s' %
76 raise AssertionError('Attempt to get rev from excluded dir %s' %
78 self._dir)
77 self._dir)
79
78
80 def linkrev(self, node):
79 def linkrev(self, node):
81 raise AssertionError('Attempt to get linkrev from excluded dir %s' %
80 raise AssertionError('Attempt to get linkrev from excluded dir %s' %
82 self._dir)
81 self._dir)
83
82
84 def node(self, rev):
83 def node(self, rev):
85 raise AssertionError('Attempt to get node from excluded dir %s' %
84 raise AssertionError('Attempt to get node from excluded dir %s' %
86 self._dir)
85 self._dir)
87
86
88 def add(self, *args, **kwargs):
87 def add(self, *args, **kwargs):
89 # We should never write entries in dirlogs outside the narrow clone.
88 # We should never write entries in dirlogs outside the narrow clone.
90 # However, the method still gets called from writesubtree() in
89 # However, the method still gets called from writesubtree() in
91 # _addtree(), so we need to handle it. We should possibly make that
90 # _addtree(), so we need to handle it. We should possibly make that
92 # avoid calling add() with a clean manifest (_dirty is always False
91 # avoid calling add() with a clean manifest (_dirty is always False
93 # in excludeddir instances).
92 # in excludeddir instances).
94 pass
93 pass
95
94
96 def makenarrowmanifestrevlog(mfrevlog, repo):
95 def makenarrowmanifestrevlog(mfrevlog, repo):
97 if util.safehasattr(mfrevlog, '_narrowed'):
96 if util.safehasattr(mfrevlog, '_narrowed'):
98 return
97 return
99
98
100 class narrowmanifestrevlog(mfrevlog.__class__):
99 class narrowmanifestrevlog(mfrevlog.__class__):
101 # This function is called via debug{revlog,index,data}, but also during
100 # This function is called via debug{revlog,index,data}, but also during
102 # at least some push operations. This will be used to wrap/exclude the
101 # at least some push operations. This will be used to wrap/exclude the
103 # child directories when using treemanifests.
102 # child directories when using treemanifests.
104 def dirlog(self, dir):
103 def dirlog(self, dir):
105 if dir and not dir.endswith('/'):
104 if dir and not dir.endswith('/'):
106 dir = dir + '/'
105 dir = dir + '/'
107 if not repo.narrowmatch().visitdir(dir[:-1] or '.'):
106 if not repo.narrowmatch().visitdir(dir[:-1] or '.'):
108 return excludedmanifestrevlog(dir)
107 return excludedmanifestrevlog(dir)
109 result = super(narrowmanifestrevlog, self).dirlog(dir)
108 result = super(narrowmanifestrevlog, self).dirlog(dir)
110 makenarrowmanifestrevlog(result, repo)
109 makenarrowmanifestrevlog(result, repo)
111 return result
110 return result
112
111
113 mfrevlog.__class__ = narrowmanifestrevlog
112 mfrevlog.__class__ = narrowmanifestrevlog
114 mfrevlog._narrowed = True
113 mfrevlog._narrowed = True
115
114
116 def makenarrowmanifestlog(mfl, repo):
115 def makenarrowmanifestlog(mfl, repo):
117 class narrowmanifestlog(mfl.__class__):
116 class narrowmanifestlog(mfl.__class__):
118 def get(self, dir, node, verify=True):
117 def get(self, dir, node, verify=True):
119 if not repo.narrowmatch().visitdir(dir[:-1] or '.'):
118 if not repo.narrowmatch().visitdir(dir[:-1] or '.'):
120 return excludeddirmanifestctx(dir, node)
119 return excludeddirmanifestctx(dir, node)
121 return super(narrowmanifestlog, self).get(dir, node, verify=verify)
120 return super(narrowmanifestlog, self).get(dir, node, verify=verify)
122 mfl.__class__ = narrowmanifestlog
121 mfl.__class__ = narrowmanifestlog
123
122
124 def makenarrowfilelog(fl, narrowmatch):
123 def makenarrowfilelog(fl, narrowmatch):
125 class narrowfilelog(fl.__class__):
124 class narrowfilelog(fl.__class__):
126 def renamed(self, node):
125 def renamed(self, node):
127 m = super(narrowfilelog, self).renamed(node)
126 m = super(narrowfilelog, self).renamed(node)
128 if m and not narrowmatch(m[0]):
127 if m and not narrowmatch(m[0]):
129 return None
128 return None
130 return m
129 return m
131
130
132 def size(self, rev):
131 def size(self, rev):
133 # We take advantage of the fact that remotefilelog
132 # We take advantage of the fact that remotefilelog
134 # lacks a node() method to just skip the
133 # lacks a node() method to just skip the
135 # rename-checking logic when on remotefilelog. This
134 # rename-checking logic when on remotefilelog. This
136 # might be incorrect on other non-revlog-based storage
135 # might be incorrect on other non-revlog-based storage
137 # engines, but for now this seems to be fine.
136 # engines, but for now this seems to be fine.
138 if util.safehasattr(self, 'node'):
137 if util.safehasattr(self, 'node'):
139 node = self.node(rev)
138 node = self.node(rev)
140 # Because renamed() is overridden above to
139 # Because renamed() is overridden above to
141 # sometimes return None even if there is metadata
140 # sometimes return None even if there is metadata
142 # in the revlog, size can be incorrect for
141 # in the revlog, size can be incorrect for
143 # copies/renames, so we need to make sure we call
142 # copies/renames, so we need to make sure we call
144 # the super class's implementation of renamed()
143 # the super class's implementation of renamed()
145 # for the purpose of size calculation.
144 # for the purpose of size calculation.
146 if super(narrowfilelog, self).renamed(node):
145 if super(narrowfilelog, self).renamed(node):
147 return len(self.read(node))
146 return len(self.read(node))
148 return super(narrowfilelog, self).size(rev)
147 return super(narrowfilelog, self).size(rev)
149
148
150 def cmp(self, node, text):
149 def cmp(self, node, text):
151 different = super(narrowfilelog, self).cmp(node, text)
150 different = super(narrowfilelog, self).cmp(node, text)
152 if different:
151 if different:
153 # Similar to size() above, if the file was copied from
152 # Similar to size() above, if the file was copied from
154 # a file outside the narrowspec, the super class's
153 # a file outside the narrowspec, the super class's
155 # would have returned True because we tricked it into
154 # would have returned True because we tricked it into
156 # thinking that the file was not renamed.
155 # thinking that the file was not renamed.
157 if super(narrowfilelog, self).renamed(node):
156 if super(narrowfilelog, self).renamed(node):
158 t2 = self.read(node)
157 t2 = self.read(node)
159 return t2 != text
158 return t2 != text
160 return different
159 return different
161
160
162 fl.__class__ = narrowfilelog
161 fl.__class__ = narrowfilelog
General Comments 0
You need to be logged in to leave comments. Login now