##// END OF EJS Templates
store: use absolute_import
Gregory Szorc -
r27480:50915967 default
parent child Browse files
Show More
@@ -1,542 +1,552 b''
1 # store.py - repository store handling for Mercurial
1 # store.py - repository store handling for Mercurial
2 #
2 #
3 # Copyright 2008 Matt Mackall <mpm@selenic.com>
3 # Copyright 2008 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 i18n import _
8 from __future__ import absolute_import
9 import scmutil, util, parsers, error
9
10 import os, stat, errno
10 import errno
11 import os
12 import stat
13
14 from .i18n import _
15 from . import (
16 error,
17 parsers,
18 scmutil,
19 util,
20 )
11
21
12 _sha = util.sha1
22 _sha = util.sha1
13
23
14 # This avoids a collision between a file named foo and a dir named
24 # This avoids a collision between a file named foo and a dir named
15 # foo.i or foo.d
25 # foo.i or foo.d
16 def _encodedir(path):
26 def _encodedir(path):
17 '''
27 '''
18 >>> _encodedir('data/foo.i')
28 >>> _encodedir('data/foo.i')
19 'data/foo.i'
29 'data/foo.i'
20 >>> _encodedir('data/foo.i/bla.i')
30 >>> _encodedir('data/foo.i/bla.i')
21 'data/foo.i.hg/bla.i'
31 'data/foo.i.hg/bla.i'
22 >>> _encodedir('data/foo.i.hg/bla.i')
32 >>> _encodedir('data/foo.i.hg/bla.i')
23 'data/foo.i.hg.hg/bla.i'
33 'data/foo.i.hg.hg/bla.i'
24 >>> _encodedir('data/foo.i\\ndata/foo.i/bla.i\\ndata/foo.i.hg/bla.i\\n')
34 >>> _encodedir('data/foo.i\\ndata/foo.i/bla.i\\ndata/foo.i.hg/bla.i\\n')
25 'data/foo.i\\ndata/foo.i.hg/bla.i\\ndata/foo.i.hg.hg/bla.i\\n'
35 'data/foo.i\\ndata/foo.i.hg/bla.i\\ndata/foo.i.hg.hg/bla.i\\n'
26 '''
36 '''
27 return (path
37 return (path
28 .replace(".hg/", ".hg.hg/")
38 .replace(".hg/", ".hg.hg/")
29 .replace(".i/", ".i.hg/")
39 .replace(".i/", ".i.hg/")
30 .replace(".d/", ".d.hg/"))
40 .replace(".d/", ".d.hg/"))
31
41
32 encodedir = getattr(parsers, 'encodedir', _encodedir)
42 encodedir = getattr(parsers, 'encodedir', _encodedir)
33
43
34 def decodedir(path):
44 def decodedir(path):
35 '''
45 '''
36 >>> decodedir('data/foo.i')
46 >>> decodedir('data/foo.i')
37 'data/foo.i'
47 'data/foo.i'
38 >>> decodedir('data/foo.i.hg/bla.i')
48 >>> decodedir('data/foo.i.hg/bla.i')
39 'data/foo.i/bla.i'
49 'data/foo.i/bla.i'
40 >>> decodedir('data/foo.i.hg.hg/bla.i')
50 >>> decodedir('data/foo.i.hg.hg/bla.i')
41 'data/foo.i.hg/bla.i'
51 'data/foo.i.hg/bla.i'
42 '''
52 '''
43 if ".hg/" not in path:
53 if ".hg/" not in path:
44 return path
54 return path
45 return (path
55 return (path
46 .replace(".d.hg/", ".d/")
56 .replace(".d.hg/", ".d/")
47 .replace(".i.hg/", ".i/")
57 .replace(".i.hg/", ".i/")
48 .replace(".hg.hg/", ".hg/"))
58 .replace(".hg.hg/", ".hg/"))
49
59
50 def _buildencodefun():
60 def _buildencodefun():
51 '''
61 '''
52 >>> enc, dec = _buildencodefun()
62 >>> enc, dec = _buildencodefun()
53
63
54 >>> enc('nothing/special.txt')
64 >>> enc('nothing/special.txt')
55 'nothing/special.txt'
65 'nothing/special.txt'
56 >>> dec('nothing/special.txt')
66 >>> dec('nothing/special.txt')
57 'nothing/special.txt'
67 'nothing/special.txt'
58
68
59 >>> enc('HELLO')
69 >>> enc('HELLO')
60 '_h_e_l_l_o'
70 '_h_e_l_l_o'
61 >>> dec('_h_e_l_l_o')
71 >>> dec('_h_e_l_l_o')
62 'HELLO'
72 'HELLO'
63
73
64 >>> enc('hello:world?')
74 >>> enc('hello:world?')
65 'hello~3aworld~3f'
75 'hello~3aworld~3f'
66 >>> dec('hello~3aworld~3f')
76 >>> dec('hello~3aworld~3f')
67 'hello:world?'
77 'hello:world?'
68
78
69 >>> enc('the\x07quick\xADshot')
79 >>> enc('the\x07quick\xADshot')
70 'the~07quick~adshot'
80 'the~07quick~adshot'
71 >>> dec('the~07quick~adshot')
81 >>> dec('the~07quick~adshot')
72 'the\\x07quick\\xadshot'
82 'the\\x07quick\\xadshot'
73 '''
83 '''
74 e = '_'
84 e = '_'
75 winreserved = [ord(x) for x in '\\:*?"<>|']
85 winreserved = [ord(x) for x in '\\:*?"<>|']
76 cmap = dict([(chr(x), chr(x)) for x in xrange(127)])
86 cmap = dict([(chr(x), chr(x)) for x in xrange(127)])
77 for x in (range(32) + range(126, 256) + winreserved):
87 for x in (range(32) + range(126, 256) + winreserved):
78 cmap[chr(x)] = "~%02x" % x
88 cmap[chr(x)] = "~%02x" % x
79 for x in range(ord("A"), ord("Z") + 1) + [ord(e)]:
89 for x in range(ord("A"), ord("Z") + 1) + [ord(e)]:
80 cmap[chr(x)] = e + chr(x).lower()
90 cmap[chr(x)] = e + chr(x).lower()
81 dmap = {}
91 dmap = {}
82 for k, v in cmap.iteritems():
92 for k, v in cmap.iteritems():
83 dmap[v] = k
93 dmap[v] = k
84 def decode(s):
94 def decode(s):
85 i = 0
95 i = 0
86 while i < len(s):
96 while i < len(s):
87 for l in xrange(1, 4):
97 for l in xrange(1, 4):
88 try:
98 try:
89 yield dmap[s[i:i + l]]
99 yield dmap[s[i:i + l]]
90 i += l
100 i += l
91 break
101 break
92 except KeyError:
102 except KeyError:
93 pass
103 pass
94 else:
104 else:
95 raise KeyError
105 raise KeyError
96 return (lambda s: ''.join([cmap[c] for c in s]),
106 return (lambda s: ''.join([cmap[c] for c in s]),
97 lambda s: ''.join(list(decode(s))))
107 lambda s: ''.join(list(decode(s))))
98
108
99 _encodefname, _decodefname = _buildencodefun()
109 _encodefname, _decodefname = _buildencodefun()
100
110
101 def encodefilename(s):
111 def encodefilename(s):
102 '''
112 '''
103 >>> encodefilename('foo.i/bar.d/bla.hg/hi:world?/HELLO')
113 >>> encodefilename('foo.i/bar.d/bla.hg/hi:world?/HELLO')
104 'foo.i.hg/bar.d.hg/bla.hg.hg/hi~3aworld~3f/_h_e_l_l_o'
114 'foo.i.hg/bar.d.hg/bla.hg.hg/hi~3aworld~3f/_h_e_l_l_o'
105 '''
115 '''
106 return _encodefname(encodedir(s))
116 return _encodefname(encodedir(s))
107
117
108 def decodefilename(s):
118 def decodefilename(s):
109 '''
119 '''
110 >>> decodefilename('foo.i.hg/bar.d.hg/bla.hg.hg/hi~3aworld~3f/_h_e_l_l_o')
120 >>> decodefilename('foo.i.hg/bar.d.hg/bla.hg.hg/hi~3aworld~3f/_h_e_l_l_o')
111 'foo.i/bar.d/bla.hg/hi:world?/HELLO'
121 'foo.i/bar.d/bla.hg/hi:world?/HELLO'
112 '''
122 '''
113 return decodedir(_decodefname(s))
123 return decodedir(_decodefname(s))
114
124
115 def _buildlowerencodefun():
125 def _buildlowerencodefun():
116 '''
126 '''
117 >>> f = _buildlowerencodefun()
127 >>> f = _buildlowerencodefun()
118 >>> f('nothing/special.txt')
128 >>> f('nothing/special.txt')
119 'nothing/special.txt'
129 'nothing/special.txt'
120 >>> f('HELLO')
130 >>> f('HELLO')
121 'hello'
131 'hello'
122 >>> f('hello:world?')
132 >>> f('hello:world?')
123 'hello~3aworld~3f'
133 'hello~3aworld~3f'
124 >>> f('the\x07quick\xADshot')
134 >>> f('the\x07quick\xADshot')
125 'the~07quick~adshot'
135 'the~07quick~adshot'
126 '''
136 '''
127 winreserved = [ord(x) for x in '\\:*?"<>|']
137 winreserved = [ord(x) for x in '\\:*?"<>|']
128 cmap = dict([(chr(x), chr(x)) for x in xrange(127)])
138 cmap = dict([(chr(x), chr(x)) for x in xrange(127)])
129 for x in (range(32) + range(126, 256) + winreserved):
139 for x in (range(32) + range(126, 256) + winreserved):
130 cmap[chr(x)] = "~%02x" % x
140 cmap[chr(x)] = "~%02x" % x
131 for x in range(ord("A"), ord("Z") + 1):
141 for x in range(ord("A"), ord("Z") + 1):
132 cmap[chr(x)] = chr(x).lower()
142 cmap[chr(x)] = chr(x).lower()
133 return lambda s: "".join([cmap[c] for c in s])
143 return lambda s: "".join([cmap[c] for c in s])
134
144
135 lowerencode = getattr(parsers, 'lowerencode', None) or _buildlowerencodefun()
145 lowerencode = getattr(parsers, 'lowerencode', None) or _buildlowerencodefun()
136
146
137 # Windows reserved names: con, prn, aux, nul, com1..com9, lpt1..lpt9
147 # Windows reserved names: con, prn, aux, nul, com1..com9, lpt1..lpt9
138 _winres3 = ('aux', 'con', 'prn', 'nul') # length 3
148 _winres3 = ('aux', 'con', 'prn', 'nul') # length 3
139 _winres4 = ('com', 'lpt') # length 4 (with trailing 1..9)
149 _winres4 = ('com', 'lpt') # length 4 (with trailing 1..9)
140 def _auxencode(path, dotencode):
150 def _auxencode(path, dotencode):
141 '''
151 '''
142 Encodes filenames containing names reserved by Windows or which end in
152 Encodes filenames containing names reserved by Windows or which end in
143 period or space. Does not touch other single reserved characters c.
153 period or space. Does not touch other single reserved characters c.
144 Specifically, c in '\\:*?"<>|' or ord(c) <= 31 are *not* encoded here.
154 Specifically, c in '\\:*?"<>|' or ord(c) <= 31 are *not* encoded here.
145 Additionally encodes space or period at the beginning, if dotencode is
155 Additionally encodes space or period at the beginning, if dotencode is
146 True. Parameter path is assumed to be all lowercase.
156 True. Parameter path is assumed to be all lowercase.
147 A segment only needs encoding if a reserved name appears as a
157 A segment only needs encoding if a reserved name appears as a
148 basename (e.g. "aux", "aux.foo"). A directory or file named "foo.aux"
158 basename (e.g. "aux", "aux.foo"). A directory or file named "foo.aux"
149 doesn't need encoding.
159 doesn't need encoding.
150
160
151 >>> s = '.foo/aux.txt/txt.aux/con/prn/nul/foo.'
161 >>> s = '.foo/aux.txt/txt.aux/con/prn/nul/foo.'
152 >>> _auxencode(s.split('/'), True)
162 >>> _auxencode(s.split('/'), True)
153 ['~2efoo', 'au~78.txt', 'txt.aux', 'co~6e', 'pr~6e', 'nu~6c', 'foo~2e']
163 ['~2efoo', 'au~78.txt', 'txt.aux', 'co~6e', 'pr~6e', 'nu~6c', 'foo~2e']
154 >>> s = '.com1com2/lpt9.lpt4.lpt1/conprn/com0/lpt0/foo.'
164 >>> s = '.com1com2/lpt9.lpt4.lpt1/conprn/com0/lpt0/foo.'
155 >>> _auxencode(s.split('/'), False)
165 >>> _auxencode(s.split('/'), False)
156 ['.com1com2', 'lp~749.lpt4.lpt1', 'conprn', 'com0', 'lpt0', 'foo~2e']
166 ['.com1com2', 'lp~749.lpt4.lpt1', 'conprn', 'com0', 'lpt0', 'foo~2e']
157 >>> _auxencode(['foo. '], True)
167 >>> _auxencode(['foo. '], True)
158 ['foo.~20']
168 ['foo.~20']
159 >>> _auxencode([' .foo'], True)
169 >>> _auxencode([' .foo'], True)
160 ['~20.foo']
170 ['~20.foo']
161 '''
171 '''
162 for i, n in enumerate(path):
172 for i, n in enumerate(path):
163 if not n:
173 if not n:
164 continue
174 continue
165 if dotencode and n[0] in '. ':
175 if dotencode and n[0] in '. ':
166 n = "~%02x" % ord(n[0]) + n[1:]
176 n = "~%02x" % ord(n[0]) + n[1:]
167 path[i] = n
177 path[i] = n
168 else:
178 else:
169 l = n.find('.')
179 l = n.find('.')
170 if l == -1:
180 if l == -1:
171 l = len(n)
181 l = len(n)
172 if ((l == 3 and n[:3] in _winres3) or
182 if ((l == 3 and n[:3] in _winres3) or
173 (l == 4 and n[3] <= '9' and n[3] >= '1'
183 (l == 4 and n[3] <= '9' and n[3] >= '1'
174 and n[:3] in _winres4)):
184 and n[:3] in _winres4)):
175 # encode third letter ('aux' -> 'au~78')
185 # encode third letter ('aux' -> 'au~78')
176 ec = "~%02x" % ord(n[2])
186 ec = "~%02x" % ord(n[2])
177 n = n[0:2] + ec + n[3:]
187 n = n[0:2] + ec + n[3:]
178 path[i] = n
188 path[i] = n
179 if n[-1] in '. ':
189 if n[-1] in '. ':
180 # encode last period or space ('foo...' -> 'foo..~2e')
190 # encode last period or space ('foo...' -> 'foo..~2e')
181 path[i] = n[:-1] + "~%02x" % ord(n[-1])
191 path[i] = n[:-1] + "~%02x" % ord(n[-1])
182 return path
192 return path
183
193
184 _maxstorepathlen = 120
194 _maxstorepathlen = 120
185 _dirprefixlen = 8
195 _dirprefixlen = 8
186 _maxshortdirslen = 8 * (_dirprefixlen + 1) - 4
196 _maxshortdirslen = 8 * (_dirprefixlen + 1) - 4
187
197
188 def _hashencode(path, dotencode):
198 def _hashencode(path, dotencode):
189 digest = _sha(path).hexdigest()
199 digest = _sha(path).hexdigest()
190 le = lowerencode(path[5:]).split('/') # skips prefix 'data/' or 'meta/'
200 le = lowerencode(path[5:]).split('/') # skips prefix 'data/' or 'meta/'
191 parts = _auxencode(le, dotencode)
201 parts = _auxencode(le, dotencode)
192 basename = parts[-1]
202 basename = parts[-1]
193 _root, ext = os.path.splitext(basename)
203 _root, ext = os.path.splitext(basename)
194 sdirs = []
204 sdirs = []
195 sdirslen = 0
205 sdirslen = 0
196 for p in parts[:-1]:
206 for p in parts[:-1]:
197 d = p[:_dirprefixlen]
207 d = p[:_dirprefixlen]
198 if d[-1] in '. ':
208 if d[-1] in '. ':
199 # Windows can't access dirs ending in period or space
209 # Windows can't access dirs ending in period or space
200 d = d[:-1] + '_'
210 d = d[:-1] + '_'
201 if sdirslen == 0:
211 if sdirslen == 0:
202 t = len(d)
212 t = len(d)
203 else:
213 else:
204 t = sdirslen + 1 + len(d)
214 t = sdirslen + 1 + len(d)
205 if t > _maxshortdirslen:
215 if t > _maxshortdirslen:
206 break
216 break
207 sdirs.append(d)
217 sdirs.append(d)
208 sdirslen = t
218 sdirslen = t
209 dirs = '/'.join(sdirs)
219 dirs = '/'.join(sdirs)
210 if len(dirs) > 0:
220 if len(dirs) > 0:
211 dirs += '/'
221 dirs += '/'
212 res = 'dh/' + dirs + digest + ext
222 res = 'dh/' + dirs + digest + ext
213 spaceleft = _maxstorepathlen - len(res)
223 spaceleft = _maxstorepathlen - len(res)
214 if spaceleft > 0:
224 if spaceleft > 0:
215 filler = basename[:spaceleft]
225 filler = basename[:spaceleft]
216 res = 'dh/' + dirs + filler + digest + ext
226 res = 'dh/' + dirs + filler + digest + ext
217 return res
227 return res
218
228
219 def _hybridencode(path, dotencode):
229 def _hybridencode(path, dotencode):
220 '''encodes path with a length limit
230 '''encodes path with a length limit
221
231
222 Encodes all paths that begin with 'data/', according to the following.
232 Encodes all paths that begin with 'data/', according to the following.
223
233
224 Default encoding (reversible):
234 Default encoding (reversible):
225
235
226 Encodes all uppercase letters 'X' as '_x'. All reserved or illegal
236 Encodes all uppercase letters 'X' as '_x'. All reserved or illegal
227 characters are encoded as '~xx', where xx is the two digit hex code
237 characters are encoded as '~xx', where xx is the two digit hex code
228 of the character (see encodefilename).
238 of the character (see encodefilename).
229 Relevant path components consisting of Windows reserved filenames are
239 Relevant path components consisting of Windows reserved filenames are
230 masked by encoding the third character ('aux' -> 'au~78', see _auxencode).
240 masked by encoding the third character ('aux' -> 'au~78', see _auxencode).
231
241
232 Hashed encoding (not reversible):
242 Hashed encoding (not reversible):
233
243
234 If the default-encoded path is longer than _maxstorepathlen, a
244 If the default-encoded path is longer than _maxstorepathlen, a
235 non-reversible hybrid hashing of the path is done instead.
245 non-reversible hybrid hashing of the path is done instead.
236 This encoding uses up to _dirprefixlen characters of all directory
246 This encoding uses up to _dirprefixlen characters of all directory
237 levels of the lowerencoded path, but not more levels than can fit into
247 levels of the lowerencoded path, but not more levels than can fit into
238 _maxshortdirslen.
248 _maxshortdirslen.
239 Then follows the filler followed by the sha digest of the full path.
249 Then follows the filler followed by the sha digest of the full path.
240 The filler is the beginning of the basename of the lowerencoded path
250 The filler is the beginning of the basename of the lowerencoded path
241 (the basename is everything after the last path separator). The filler
251 (the basename is everything after the last path separator). The filler
242 is as long as possible, filling in characters from the basename until
252 is as long as possible, filling in characters from the basename until
243 the encoded path has _maxstorepathlen characters (or all chars of the
253 the encoded path has _maxstorepathlen characters (or all chars of the
244 basename have been taken).
254 basename have been taken).
245 The extension (e.g. '.i' or '.d') is preserved.
255 The extension (e.g. '.i' or '.d') is preserved.
246
256
247 The string 'data/' at the beginning is replaced with 'dh/', if the hashed
257 The string 'data/' at the beginning is replaced with 'dh/', if the hashed
248 encoding was used.
258 encoding was used.
249 '''
259 '''
250 path = encodedir(path)
260 path = encodedir(path)
251 ef = _encodefname(path).split('/')
261 ef = _encodefname(path).split('/')
252 res = '/'.join(_auxencode(ef, dotencode))
262 res = '/'.join(_auxencode(ef, dotencode))
253 if len(res) > _maxstorepathlen:
263 if len(res) > _maxstorepathlen:
254 res = _hashencode(path, dotencode)
264 res = _hashencode(path, dotencode)
255 return res
265 return res
256
266
257 def _pathencode(path):
267 def _pathencode(path):
258 de = encodedir(path)
268 de = encodedir(path)
259 if len(path) > _maxstorepathlen:
269 if len(path) > _maxstorepathlen:
260 return _hashencode(de, True)
270 return _hashencode(de, True)
261 ef = _encodefname(de).split('/')
271 ef = _encodefname(de).split('/')
262 res = '/'.join(_auxencode(ef, True))
272 res = '/'.join(_auxencode(ef, True))
263 if len(res) > _maxstorepathlen:
273 if len(res) > _maxstorepathlen:
264 return _hashencode(de, True)
274 return _hashencode(de, True)
265 return res
275 return res
266
276
267 _pathencode = getattr(parsers, 'pathencode', _pathencode)
277 _pathencode = getattr(parsers, 'pathencode', _pathencode)
268
278
269 def _plainhybridencode(f):
279 def _plainhybridencode(f):
270 return _hybridencode(f, False)
280 return _hybridencode(f, False)
271
281
272 def _calcmode(vfs):
282 def _calcmode(vfs):
273 try:
283 try:
274 # files in .hg/ will be created using this mode
284 # files in .hg/ will be created using this mode
275 mode = vfs.stat().st_mode
285 mode = vfs.stat().st_mode
276 # avoid some useless chmods
286 # avoid some useless chmods
277 if (0o777 & ~util.umask) == (0o777 & mode):
287 if (0o777 & ~util.umask) == (0o777 & mode):
278 mode = None
288 mode = None
279 except OSError:
289 except OSError:
280 mode = None
290 mode = None
281 return mode
291 return mode
282
292
283 _data = ('data 00manifest.d 00manifest.i 00changelog.d 00changelog.i'
293 _data = ('data 00manifest.d 00manifest.i 00changelog.d 00changelog.i'
284 ' phaseroots obsstore')
294 ' phaseroots obsstore')
285
295
286 class basicstore(object):
296 class basicstore(object):
287 '''base class for local repository stores'''
297 '''base class for local repository stores'''
288 def __init__(self, path, vfstype):
298 def __init__(self, path, vfstype):
289 vfs = vfstype(path)
299 vfs = vfstype(path)
290 self.path = vfs.base
300 self.path = vfs.base
291 self.createmode = _calcmode(vfs)
301 self.createmode = _calcmode(vfs)
292 vfs.createmode = self.createmode
302 vfs.createmode = self.createmode
293 self.rawvfs = vfs
303 self.rawvfs = vfs
294 self.vfs = scmutil.filtervfs(vfs, encodedir)
304 self.vfs = scmutil.filtervfs(vfs, encodedir)
295 self.opener = self.vfs
305 self.opener = self.vfs
296
306
297 def join(self, f):
307 def join(self, f):
298 return self.path + '/' + encodedir(f)
308 return self.path + '/' + encodedir(f)
299
309
300 def _walk(self, relpath, recurse):
310 def _walk(self, relpath, recurse):
301 '''yields (unencoded, encoded, size)'''
311 '''yields (unencoded, encoded, size)'''
302 path = self.path
312 path = self.path
303 if relpath:
313 if relpath:
304 path += '/' + relpath
314 path += '/' + relpath
305 striplen = len(self.path) + 1
315 striplen = len(self.path) + 1
306 l = []
316 l = []
307 if self.rawvfs.isdir(path):
317 if self.rawvfs.isdir(path):
308 visit = [path]
318 visit = [path]
309 readdir = self.rawvfs.readdir
319 readdir = self.rawvfs.readdir
310 while visit:
320 while visit:
311 p = visit.pop()
321 p = visit.pop()
312 for f, kind, st in readdir(p, stat=True):
322 for f, kind, st in readdir(p, stat=True):
313 fp = p + '/' + f
323 fp = p + '/' + f
314 if kind == stat.S_IFREG and f[-2:] in ('.d', '.i'):
324 if kind == stat.S_IFREG and f[-2:] in ('.d', '.i'):
315 n = util.pconvert(fp[striplen:])
325 n = util.pconvert(fp[striplen:])
316 l.append((decodedir(n), n, st.st_size))
326 l.append((decodedir(n), n, st.st_size))
317 elif kind == stat.S_IFDIR and recurse:
327 elif kind == stat.S_IFDIR and recurse:
318 visit.append(fp)
328 visit.append(fp)
319 l.sort()
329 l.sort()
320 return l
330 return l
321
331
322 def datafiles(self):
332 def datafiles(self):
323 return self._walk('data', True)
333 return self._walk('data', True)
324
334
325 def topfiles(self):
335 def topfiles(self):
326 # yield manifest before changelog
336 # yield manifest before changelog
327 return reversed(self._walk('', False))
337 return reversed(self._walk('', False))
328
338
329 def walk(self):
339 def walk(self):
330 '''yields (unencoded, encoded, size)'''
340 '''yields (unencoded, encoded, size)'''
331 # yield data files first
341 # yield data files first
332 for x in self.datafiles():
342 for x in self.datafiles():
333 yield x
343 yield x
334 for x in self.topfiles():
344 for x in self.topfiles():
335 yield x
345 yield x
336
346
337 def copylist(self):
347 def copylist(self):
338 return ['requires'] + _data.split()
348 return ['requires'] + _data.split()
339
349
340 def write(self, tr):
350 def write(self, tr):
341 pass
351 pass
342
352
343 def invalidatecaches(self):
353 def invalidatecaches(self):
344 pass
354 pass
345
355
346 def markremoved(self, fn):
356 def markremoved(self, fn):
347 pass
357 pass
348
358
349 def __contains__(self, path):
359 def __contains__(self, path):
350 '''Checks if the store contains path'''
360 '''Checks if the store contains path'''
351 path = "/".join(("data", path))
361 path = "/".join(("data", path))
352 # file?
362 # file?
353 if self.vfs.exists(path + ".i"):
363 if self.vfs.exists(path + ".i"):
354 return True
364 return True
355 # dir?
365 # dir?
356 if not path.endswith("/"):
366 if not path.endswith("/"):
357 path = path + "/"
367 path = path + "/"
358 return self.vfs.exists(path)
368 return self.vfs.exists(path)
359
369
360 class encodedstore(basicstore):
370 class encodedstore(basicstore):
361 def __init__(self, path, vfstype):
371 def __init__(self, path, vfstype):
362 vfs = vfstype(path + '/store')
372 vfs = vfstype(path + '/store')
363 self.path = vfs.base
373 self.path = vfs.base
364 self.createmode = _calcmode(vfs)
374 self.createmode = _calcmode(vfs)
365 vfs.createmode = self.createmode
375 vfs.createmode = self.createmode
366 self.rawvfs = vfs
376 self.rawvfs = vfs
367 self.vfs = scmutil.filtervfs(vfs, encodefilename)
377 self.vfs = scmutil.filtervfs(vfs, encodefilename)
368 self.opener = self.vfs
378 self.opener = self.vfs
369
379
370 def datafiles(self):
380 def datafiles(self):
371 for a, b, size in self._walk('data', True):
381 for a, b, size in self._walk('data', True):
372 try:
382 try:
373 a = decodefilename(a)
383 a = decodefilename(a)
374 except KeyError:
384 except KeyError:
375 a = None
385 a = None
376 yield a, b, size
386 yield a, b, size
377
387
378 def join(self, f):
388 def join(self, f):
379 return self.path + '/' + encodefilename(f)
389 return self.path + '/' + encodefilename(f)
380
390
381 def copylist(self):
391 def copylist(self):
382 return (['requires', '00changelog.i'] +
392 return (['requires', '00changelog.i'] +
383 ['store/' + f for f in _data.split()])
393 ['store/' + f for f in _data.split()])
384
394
385 class fncache(object):
395 class fncache(object):
386 # the filename used to be partially encoded
396 # the filename used to be partially encoded
387 # hence the encodedir/decodedir dance
397 # hence the encodedir/decodedir dance
388 def __init__(self, vfs):
398 def __init__(self, vfs):
389 self.vfs = vfs
399 self.vfs = vfs
390 self.entries = None
400 self.entries = None
391 self._dirty = False
401 self._dirty = False
392
402
393 def _load(self):
403 def _load(self):
394 '''fill the entries from the fncache file'''
404 '''fill the entries from the fncache file'''
395 self._dirty = False
405 self._dirty = False
396 try:
406 try:
397 fp = self.vfs('fncache', mode='rb')
407 fp = self.vfs('fncache', mode='rb')
398 except IOError:
408 except IOError:
399 # skip nonexistent file
409 # skip nonexistent file
400 self.entries = set()
410 self.entries = set()
401 return
411 return
402 self.entries = set(decodedir(fp.read()).splitlines())
412 self.entries = set(decodedir(fp.read()).splitlines())
403 if '' in self.entries:
413 if '' in self.entries:
404 fp.seek(0)
414 fp.seek(0)
405 for n, line in enumerate(fp):
415 for n, line in enumerate(fp):
406 if not line.rstrip('\n'):
416 if not line.rstrip('\n'):
407 t = _('invalid entry in fncache, line %d') % (n + 1)
417 t = _('invalid entry in fncache, line %d') % (n + 1)
408 raise error.Abort(t)
418 raise error.Abort(t)
409 fp.close()
419 fp.close()
410
420
411 def write(self, tr):
421 def write(self, tr):
412 if self._dirty:
422 if self._dirty:
413 tr.addbackup('fncache')
423 tr.addbackup('fncache')
414 fp = self.vfs('fncache', mode='wb', atomictemp=True)
424 fp = self.vfs('fncache', mode='wb', atomictemp=True)
415 if self.entries:
425 if self.entries:
416 fp.write(encodedir('\n'.join(self.entries) + '\n'))
426 fp.write(encodedir('\n'.join(self.entries) + '\n'))
417 fp.close()
427 fp.close()
418 self._dirty = False
428 self._dirty = False
419
429
420 def add(self, fn):
430 def add(self, fn):
421 if self.entries is None:
431 if self.entries is None:
422 self._load()
432 self._load()
423 if fn not in self.entries:
433 if fn not in self.entries:
424 self._dirty = True
434 self._dirty = True
425 self.entries.add(fn)
435 self.entries.add(fn)
426
436
427 def remove(self, fn):
437 def remove(self, fn):
428 if self.entries is None:
438 if self.entries is None:
429 self._load()
439 self._load()
430 try:
440 try:
431 self.entries.remove(fn)
441 self.entries.remove(fn)
432 self._dirty = True
442 self._dirty = True
433 except KeyError:
443 except KeyError:
434 pass
444 pass
435
445
436 def __contains__(self, fn):
446 def __contains__(self, fn):
437 if self.entries is None:
447 if self.entries is None:
438 self._load()
448 self._load()
439 return fn in self.entries
449 return fn in self.entries
440
450
441 def __iter__(self):
451 def __iter__(self):
442 if self.entries is None:
452 if self.entries is None:
443 self._load()
453 self._load()
444 return iter(self.entries)
454 return iter(self.entries)
445
455
446 class _fncachevfs(scmutil.abstractvfs, scmutil.auditvfs):
456 class _fncachevfs(scmutil.abstractvfs, scmutil.auditvfs):
447 def __init__(self, vfs, fnc, encode):
457 def __init__(self, vfs, fnc, encode):
448 scmutil.auditvfs.__init__(self, vfs)
458 scmutil.auditvfs.__init__(self, vfs)
449 self.fncache = fnc
459 self.fncache = fnc
450 self.encode = encode
460 self.encode = encode
451
461
452 def __call__(self, path, mode='r', *args, **kw):
462 def __call__(self, path, mode='r', *args, **kw):
453 if mode not in ('r', 'rb') and path.startswith('data/'):
463 if mode not in ('r', 'rb') and path.startswith('data/'):
454 self.fncache.add(path)
464 self.fncache.add(path)
455 return self.vfs(self.encode(path), mode, *args, **kw)
465 return self.vfs(self.encode(path), mode, *args, **kw)
456
466
457 def join(self, path):
467 def join(self, path):
458 if path:
468 if path:
459 return self.vfs.join(self.encode(path))
469 return self.vfs.join(self.encode(path))
460 else:
470 else:
461 return self.vfs.join(path)
471 return self.vfs.join(path)
462
472
463 class fncachestore(basicstore):
473 class fncachestore(basicstore):
464 def __init__(self, path, vfstype, dotencode):
474 def __init__(self, path, vfstype, dotencode):
465 if dotencode:
475 if dotencode:
466 encode = _pathencode
476 encode = _pathencode
467 else:
477 else:
468 encode = _plainhybridencode
478 encode = _plainhybridencode
469 self.encode = encode
479 self.encode = encode
470 vfs = vfstype(path + '/store')
480 vfs = vfstype(path + '/store')
471 self.path = vfs.base
481 self.path = vfs.base
472 self.pathsep = self.path + '/'
482 self.pathsep = self.path + '/'
473 self.createmode = _calcmode(vfs)
483 self.createmode = _calcmode(vfs)
474 vfs.createmode = self.createmode
484 vfs.createmode = self.createmode
475 self.rawvfs = vfs
485 self.rawvfs = vfs
476 fnc = fncache(vfs)
486 fnc = fncache(vfs)
477 self.fncache = fnc
487 self.fncache = fnc
478 self.vfs = _fncachevfs(vfs, fnc, encode)
488 self.vfs = _fncachevfs(vfs, fnc, encode)
479 self.opener = self.vfs
489 self.opener = self.vfs
480
490
481 def join(self, f):
491 def join(self, f):
482 return self.pathsep + self.encode(f)
492 return self.pathsep + self.encode(f)
483
493
484 def getsize(self, path):
494 def getsize(self, path):
485 return self.rawvfs.stat(path).st_size
495 return self.rawvfs.stat(path).st_size
486
496
487 def datafiles(self):
497 def datafiles(self):
488 for f in sorted(self.fncache):
498 for f in sorted(self.fncache):
489 ef = self.encode(f)
499 ef = self.encode(f)
490 try:
500 try:
491 yield f, ef, self.getsize(ef)
501 yield f, ef, self.getsize(ef)
492 except OSError as err:
502 except OSError as err:
493 if err.errno != errno.ENOENT:
503 if err.errno != errno.ENOENT:
494 raise
504 raise
495
505
496 def copylist(self):
506 def copylist(self):
497 d = ('data dh fncache phaseroots obsstore'
507 d = ('data dh fncache phaseroots obsstore'
498 ' 00manifest.d 00manifest.i 00changelog.d 00changelog.i')
508 ' 00manifest.d 00manifest.i 00changelog.d 00changelog.i')
499 return (['requires', '00changelog.i'] +
509 return (['requires', '00changelog.i'] +
500 ['store/' + f for f in d.split()])
510 ['store/' + f for f in d.split()])
501
511
502 def write(self, tr):
512 def write(self, tr):
503 self.fncache.write(tr)
513 self.fncache.write(tr)
504
514
505 def invalidatecaches(self):
515 def invalidatecaches(self):
506 self.fncache.entries = None
516 self.fncache.entries = None
507
517
508 def markremoved(self, fn):
518 def markremoved(self, fn):
509 self.fncache.remove(fn)
519 self.fncache.remove(fn)
510
520
511 def _exists(self, f):
521 def _exists(self, f):
512 ef = self.encode(f)
522 ef = self.encode(f)
513 try:
523 try:
514 self.getsize(ef)
524 self.getsize(ef)
515 return True
525 return True
516 except OSError as err:
526 except OSError as err:
517 if err.errno != errno.ENOENT:
527 if err.errno != errno.ENOENT:
518 raise
528 raise
519 # nonexistent entry
529 # nonexistent entry
520 return False
530 return False
521
531
522 def __contains__(self, path):
532 def __contains__(self, path):
523 '''Checks if the store contains path'''
533 '''Checks if the store contains path'''
524 path = "/".join(("data", path))
534 path = "/".join(("data", path))
525 # check for files (exact match)
535 # check for files (exact match)
526 e = path + '.i'
536 e = path + '.i'
527 if e in self.fncache and self._exists(e):
537 if e in self.fncache and self._exists(e):
528 return True
538 return True
529 # now check for directories (prefix match)
539 # now check for directories (prefix match)
530 if not path.endswith('/'):
540 if not path.endswith('/'):
531 path += '/'
541 path += '/'
532 for e in self.fncache:
542 for e in self.fncache:
533 if e.startswith(path) and self._exists(e):
543 if e.startswith(path) and self._exists(e):
534 return True
544 return True
535 return False
545 return False
536
546
537 def store(requirements, path, vfstype):
547 def store(requirements, path, vfstype):
538 if 'store' in requirements:
548 if 'store' in requirements:
539 if 'fncache' in requirements:
549 if 'fncache' in requirements:
540 return fncachestore(path, vfstype, 'dotencode' in requirements)
550 return fncachestore(path, vfstype, 'dotencode' in requirements)
541 return encodedstore(path, vfstype)
551 return encodedstore(path, vfstype)
542 return basicstore(path, vfstype)
552 return basicstore(path, vfstype)
@@ -1,206 +1,205 b''
1 #require test-repo
1 #require test-repo
2
2
3 $ cd "$TESTDIR"/..
3 $ cd "$TESTDIR"/..
4
4
5 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs python contrib/check-py3-compat.py
5 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs python contrib/check-py3-compat.py
6 contrib/casesmash.py not using absolute_import
6 contrib/casesmash.py not using absolute_import
7 contrib/check-code.py not using absolute_import
7 contrib/check-code.py not using absolute_import
8 contrib/check-code.py requires print_function
8 contrib/check-code.py requires print_function
9 contrib/check-config.py not using absolute_import
9 contrib/check-config.py not using absolute_import
10 contrib/check-config.py requires print_function
10 contrib/check-config.py requires print_function
11 contrib/debugcmdserver.py not using absolute_import
11 contrib/debugcmdserver.py not using absolute_import
12 contrib/debugcmdserver.py requires print_function
12 contrib/debugcmdserver.py requires print_function
13 contrib/debugshell.py not using absolute_import
13 contrib/debugshell.py not using absolute_import
14 contrib/fixpax.py not using absolute_import
14 contrib/fixpax.py not using absolute_import
15 contrib/fixpax.py requires print_function
15 contrib/fixpax.py requires print_function
16 contrib/hgclient.py not using absolute_import
16 contrib/hgclient.py not using absolute_import
17 contrib/hgclient.py requires print_function
17 contrib/hgclient.py requires print_function
18 contrib/hgfixes/fix_bytes.py not using absolute_import
18 contrib/hgfixes/fix_bytes.py not using absolute_import
19 contrib/hgfixes/fix_bytesmod.py not using absolute_import
19 contrib/hgfixes/fix_bytesmod.py not using absolute_import
20 contrib/hgfixes/fix_leftover_imports.py not using absolute_import
20 contrib/hgfixes/fix_leftover_imports.py not using absolute_import
21 contrib/import-checker.py not using absolute_import
21 contrib/import-checker.py not using absolute_import
22 contrib/import-checker.py requires print_function
22 contrib/import-checker.py requires print_function
23 contrib/memory.py not using absolute_import
23 contrib/memory.py not using absolute_import
24 contrib/perf.py not using absolute_import
24 contrib/perf.py not using absolute_import
25 contrib/python-hook-examples.py not using absolute_import
25 contrib/python-hook-examples.py not using absolute_import
26 contrib/revsetbenchmarks.py not using absolute_import
26 contrib/revsetbenchmarks.py not using absolute_import
27 contrib/revsetbenchmarks.py requires print_function
27 contrib/revsetbenchmarks.py requires print_function
28 contrib/showstack.py not using absolute_import
28 contrib/showstack.py not using absolute_import
29 contrib/synthrepo.py not using absolute_import
29 contrib/synthrepo.py not using absolute_import
30 contrib/win32/hgwebdir_wsgi.py not using absolute_import
30 contrib/win32/hgwebdir_wsgi.py not using absolute_import
31 doc/check-seclevel.py not using absolute_import
31 doc/check-seclevel.py not using absolute_import
32 doc/gendoc.py not using absolute_import
32 doc/gendoc.py not using absolute_import
33 doc/hgmanpage.py not using absolute_import
33 doc/hgmanpage.py not using absolute_import
34 hgext/__init__.py not using absolute_import
34 hgext/__init__.py not using absolute_import
35 hgext/acl.py not using absolute_import
35 hgext/acl.py not using absolute_import
36 hgext/blackbox.py not using absolute_import
36 hgext/blackbox.py not using absolute_import
37 hgext/bugzilla.py not using absolute_import
37 hgext/bugzilla.py not using absolute_import
38 hgext/censor.py not using absolute_import
38 hgext/censor.py not using absolute_import
39 hgext/children.py not using absolute_import
39 hgext/children.py not using absolute_import
40 hgext/churn.py not using absolute_import
40 hgext/churn.py not using absolute_import
41 hgext/clonebundles.py not using absolute_import
41 hgext/clonebundles.py not using absolute_import
42 hgext/color.py not using absolute_import
42 hgext/color.py not using absolute_import
43 hgext/convert/__init__.py not using absolute_import
43 hgext/convert/__init__.py not using absolute_import
44 hgext/convert/bzr.py not using absolute_import
44 hgext/convert/bzr.py not using absolute_import
45 hgext/convert/common.py not using absolute_import
45 hgext/convert/common.py not using absolute_import
46 hgext/convert/convcmd.py not using absolute_import
46 hgext/convert/convcmd.py not using absolute_import
47 hgext/convert/cvs.py not using absolute_import
47 hgext/convert/cvs.py not using absolute_import
48 hgext/convert/cvsps.py not using absolute_import
48 hgext/convert/cvsps.py not using absolute_import
49 hgext/convert/darcs.py not using absolute_import
49 hgext/convert/darcs.py not using absolute_import
50 hgext/convert/filemap.py not using absolute_import
50 hgext/convert/filemap.py not using absolute_import
51 hgext/convert/git.py not using absolute_import
51 hgext/convert/git.py not using absolute_import
52 hgext/convert/gnuarch.py not using absolute_import
52 hgext/convert/gnuarch.py not using absolute_import
53 hgext/convert/hg.py not using absolute_import
53 hgext/convert/hg.py not using absolute_import
54 hgext/convert/monotone.py not using absolute_import
54 hgext/convert/monotone.py not using absolute_import
55 hgext/convert/p4.py not using absolute_import
55 hgext/convert/p4.py not using absolute_import
56 hgext/convert/subversion.py not using absolute_import
56 hgext/convert/subversion.py not using absolute_import
57 hgext/convert/transport.py not using absolute_import
57 hgext/convert/transport.py not using absolute_import
58 hgext/eol.py not using absolute_import
58 hgext/eol.py not using absolute_import
59 hgext/extdiff.py not using absolute_import
59 hgext/extdiff.py not using absolute_import
60 hgext/factotum.py not using absolute_import
60 hgext/factotum.py not using absolute_import
61 hgext/fetch.py not using absolute_import
61 hgext/fetch.py not using absolute_import
62 hgext/gpg.py not using absolute_import
62 hgext/gpg.py not using absolute_import
63 hgext/graphlog.py not using absolute_import
63 hgext/graphlog.py not using absolute_import
64 hgext/hgcia.py not using absolute_import
64 hgext/hgcia.py not using absolute_import
65 hgext/hgk.py not using absolute_import
65 hgext/hgk.py not using absolute_import
66 hgext/highlight/__init__.py not using absolute_import
66 hgext/highlight/__init__.py not using absolute_import
67 hgext/highlight/highlight.py not using absolute_import
67 hgext/highlight/highlight.py not using absolute_import
68 hgext/histedit.py not using absolute_import
68 hgext/histedit.py not using absolute_import
69 hgext/keyword.py not using absolute_import
69 hgext/keyword.py not using absolute_import
70 hgext/largefiles/__init__.py not using absolute_import
70 hgext/largefiles/__init__.py not using absolute_import
71 hgext/largefiles/basestore.py not using absolute_import
71 hgext/largefiles/basestore.py not using absolute_import
72 hgext/largefiles/lfcommands.py not using absolute_import
72 hgext/largefiles/lfcommands.py not using absolute_import
73 hgext/largefiles/lfutil.py not using absolute_import
73 hgext/largefiles/lfutil.py not using absolute_import
74 hgext/largefiles/localstore.py not using absolute_import
74 hgext/largefiles/localstore.py not using absolute_import
75 hgext/largefiles/overrides.py not using absolute_import
75 hgext/largefiles/overrides.py not using absolute_import
76 hgext/largefiles/proto.py not using absolute_import
76 hgext/largefiles/proto.py not using absolute_import
77 hgext/largefiles/remotestore.py not using absolute_import
77 hgext/largefiles/remotestore.py not using absolute_import
78 hgext/largefiles/reposetup.py not using absolute_import
78 hgext/largefiles/reposetup.py not using absolute_import
79 hgext/largefiles/uisetup.py not using absolute_import
79 hgext/largefiles/uisetup.py not using absolute_import
80 hgext/largefiles/wirestore.py not using absolute_import
80 hgext/largefiles/wirestore.py not using absolute_import
81 hgext/mq.py not using absolute_import
81 hgext/mq.py not using absolute_import
82 hgext/notify.py not using absolute_import
82 hgext/notify.py not using absolute_import
83 hgext/pager.py not using absolute_import
83 hgext/pager.py not using absolute_import
84 hgext/patchbomb.py not using absolute_import
84 hgext/patchbomb.py not using absolute_import
85 hgext/purge.py not using absolute_import
85 hgext/purge.py not using absolute_import
86 hgext/rebase.py not using absolute_import
86 hgext/rebase.py not using absolute_import
87 hgext/record.py not using absolute_import
87 hgext/record.py not using absolute_import
88 hgext/relink.py not using absolute_import
88 hgext/relink.py not using absolute_import
89 hgext/schemes.py not using absolute_import
89 hgext/schemes.py not using absolute_import
90 hgext/share.py not using absolute_import
90 hgext/share.py not using absolute_import
91 hgext/shelve.py not using absolute_import
91 hgext/shelve.py not using absolute_import
92 hgext/strip.py not using absolute_import
92 hgext/strip.py not using absolute_import
93 hgext/transplant.py not using absolute_import
93 hgext/transplant.py not using absolute_import
94 hgext/win32mbcs.py not using absolute_import
94 hgext/win32mbcs.py not using absolute_import
95 hgext/win32text.py not using absolute_import
95 hgext/win32text.py not using absolute_import
96 hgext/zeroconf/Zeroconf.py not using absolute_import
96 hgext/zeroconf/Zeroconf.py not using absolute_import
97 hgext/zeroconf/Zeroconf.py requires print_function
97 hgext/zeroconf/Zeroconf.py requires print_function
98 hgext/zeroconf/__init__.py not using absolute_import
98 hgext/zeroconf/__init__.py not using absolute_import
99 i18n/check-translation.py not using absolute_import
99 i18n/check-translation.py not using absolute_import
100 i18n/polib.py not using absolute_import
100 i18n/polib.py not using absolute_import
101 mercurial/byterange.py not using absolute_import
101 mercurial/byterange.py not using absolute_import
102 mercurial/cmdutil.py not using absolute_import
102 mercurial/cmdutil.py not using absolute_import
103 mercurial/commands.py not using absolute_import
103 mercurial/commands.py not using absolute_import
104 mercurial/context.py not using absolute_import
104 mercurial/context.py not using absolute_import
105 mercurial/dirstate.py not using absolute_import
105 mercurial/dirstate.py not using absolute_import
106 mercurial/dispatch.py requires print_function
106 mercurial/dispatch.py requires print_function
107 mercurial/exchange.py not using absolute_import
107 mercurial/exchange.py not using absolute_import
108 mercurial/httpclient/__init__.py not using absolute_import
108 mercurial/httpclient/__init__.py not using absolute_import
109 mercurial/httpclient/_readers.py not using absolute_import
109 mercurial/httpclient/_readers.py not using absolute_import
110 mercurial/httpclient/socketutil.py not using absolute_import
110 mercurial/httpclient/socketutil.py not using absolute_import
111 mercurial/httpconnection.py not using absolute_import
111 mercurial/httpconnection.py not using absolute_import
112 mercurial/keepalive.py not using absolute_import
112 mercurial/keepalive.py not using absolute_import
113 mercurial/keepalive.py requires print_function
113 mercurial/keepalive.py requires print_function
114 mercurial/localrepo.py not using absolute_import
114 mercurial/localrepo.py not using absolute_import
115 mercurial/lsprof.py requires print_function
115 mercurial/lsprof.py requires print_function
116 mercurial/lsprofcalltree.py not using absolute_import
116 mercurial/lsprofcalltree.py not using absolute_import
117 mercurial/lsprofcalltree.py requires print_function
117 mercurial/lsprofcalltree.py requires print_function
118 mercurial/mail.py requires print_function
118 mercurial/mail.py requires print_function
119 mercurial/manifest.py not using absolute_import
119 mercurial/manifest.py not using absolute_import
120 mercurial/mdiff.py not using absolute_import
120 mercurial/mdiff.py not using absolute_import
121 mercurial/patch.py not using absolute_import
121 mercurial/patch.py not using absolute_import
122 mercurial/pvec.py not using absolute_import
122 mercurial/pvec.py not using absolute_import
123 mercurial/py3kcompat.py not using absolute_import
123 mercurial/py3kcompat.py not using absolute_import
124 mercurial/scmposix.py not using absolute_import
124 mercurial/scmposix.py not using absolute_import
125 mercurial/scmutil.py not using absolute_import
125 mercurial/scmutil.py not using absolute_import
126 mercurial/scmwindows.py not using absolute_import
126 mercurial/scmwindows.py not using absolute_import
127 mercurial/store.py not using absolute_import
128 setup.py not using absolute_import
127 setup.py not using absolute_import
129 tests/filterpyflakes.py requires print_function
128 tests/filterpyflakes.py requires print_function
130 tests/generate-working-copy-states.py requires print_function
129 tests/generate-working-copy-states.py requires print_function
131 tests/get-with-headers.py requires print_function
130 tests/get-with-headers.py requires print_function
132 tests/heredoctest.py requires print_function
131 tests/heredoctest.py requires print_function
133 tests/hypothesishelpers.py not using absolute_import
132 tests/hypothesishelpers.py not using absolute_import
134 tests/hypothesishelpers.py requires print_function
133 tests/hypothesishelpers.py requires print_function
135 tests/killdaemons.py not using absolute_import
134 tests/killdaemons.py not using absolute_import
136 tests/md5sum.py not using absolute_import
135 tests/md5sum.py not using absolute_import
137 tests/mockblackbox.py not using absolute_import
136 tests/mockblackbox.py not using absolute_import
138 tests/printenv.py not using absolute_import
137 tests/printenv.py not using absolute_import
139 tests/readlink.py not using absolute_import
138 tests/readlink.py not using absolute_import
140 tests/readlink.py requires print_function
139 tests/readlink.py requires print_function
141 tests/revlog-formatv0.py not using absolute_import
140 tests/revlog-formatv0.py not using absolute_import
142 tests/run-tests.py not using absolute_import
141 tests/run-tests.py not using absolute_import
143 tests/seq.py not using absolute_import
142 tests/seq.py not using absolute_import
144 tests/seq.py requires print_function
143 tests/seq.py requires print_function
145 tests/silenttestrunner.py not using absolute_import
144 tests/silenttestrunner.py not using absolute_import
146 tests/silenttestrunner.py requires print_function
145 tests/silenttestrunner.py requires print_function
147 tests/sitecustomize.py not using absolute_import
146 tests/sitecustomize.py not using absolute_import
148 tests/svn-safe-append.py not using absolute_import
147 tests/svn-safe-append.py not using absolute_import
149 tests/svnxml.py not using absolute_import
148 tests/svnxml.py not using absolute_import
150 tests/test-ancestor.py requires print_function
149 tests/test-ancestor.py requires print_function
151 tests/test-atomictempfile.py not using absolute_import
150 tests/test-atomictempfile.py not using absolute_import
152 tests/test-batching.py not using absolute_import
151 tests/test-batching.py not using absolute_import
153 tests/test-batching.py requires print_function
152 tests/test-batching.py requires print_function
154 tests/test-bdiff.py not using absolute_import
153 tests/test-bdiff.py not using absolute_import
155 tests/test-bdiff.py requires print_function
154 tests/test-bdiff.py requires print_function
156 tests/test-context.py not using absolute_import
155 tests/test-context.py not using absolute_import
157 tests/test-context.py requires print_function
156 tests/test-context.py requires print_function
158 tests/test-demandimport.py not using absolute_import
157 tests/test-demandimport.py not using absolute_import
159 tests/test-demandimport.py requires print_function
158 tests/test-demandimport.py requires print_function
160 tests/test-dispatch.py not using absolute_import
159 tests/test-dispatch.py not using absolute_import
161 tests/test-dispatch.py requires print_function
160 tests/test-dispatch.py requires print_function
162 tests/test-doctest.py not using absolute_import
161 tests/test-doctest.py not using absolute_import
163 tests/test-duplicateoptions.py not using absolute_import
162 tests/test-duplicateoptions.py not using absolute_import
164 tests/test-duplicateoptions.py requires print_function
163 tests/test-duplicateoptions.py requires print_function
165 tests/test-filecache.py not using absolute_import
164 tests/test-filecache.py not using absolute_import
166 tests/test-filecache.py requires print_function
165 tests/test-filecache.py requires print_function
167 tests/test-filelog.py not using absolute_import
166 tests/test-filelog.py not using absolute_import
168 tests/test-filelog.py requires print_function
167 tests/test-filelog.py requires print_function
169 tests/test-hg-parseurl.py not using absolute_import
168 tests/test-hg-parseurl.py not using absolute_import
170 tests/test-hg-parseurl.py requires print_function
169 tests/test-hg-parseurl.py requires print_function
171 tests/test-hgweb-auth.py not using absolute_import
170 tests/test-hgweb-auth.py not using absolute_import
172 tests/test-hgweb-auth.py requires print_function
171 tests/test-hgweb-auth.py requires print_function
173 tests/test-hgwebdir-paths.py not using absolute_import
172 tests/test-hgwebdir-paths.py not using absolute_import
174 tests/test-hybridencode.py not using absolute_import
173 tests/test-hybridencode.py not using absolute_import
175 tests/test-hybridencode.py requires print_function
174 tests/test-hybridencode.py requires print_function
176 tests/test-lrucachedict.py not using absolute_import
175 tests/test-lrucachedict.py not using absolute_import
177 tests/test-lrucachedict.py requires print_function
176 tests/test-lrucachedict.py requires print_function
178 tests/test-manifest.py not using absolute_import
177 tests/test-manifest.py not using absolute_import
179 tests/test-minirst.py not using absolute_import
178 tests/test-minirst.py not using absolute_import
180 tests/test-minirst.py requires print_function
179 tests/test-minirst.py requires print_function
181 tests/test-parseindex2.py not using absolute_import
180 tests/test-parseindex2.py not using absolute_import
182 tests/test-parseindex2.py requires print_function
181 tests/test-parseindex2.py requires print_function
183 tests/test-pathencode.py not using absolute_import
182 tests/test-pathencode.py not using absolute_import
184 tests/test-pathencode.py requires print_function
183 tests/test-pathencode.py requires print_function
185 tests/test-propertycache.py not using absolute_import
184 tests/test-propertycache.py not using absolute_import
186 tests/test-propertycache.py requires print_function
185 tests/test-propertycache.py requires print_function
187 tests/test-revlog-ancestry.py not using absolute_import
186 tests/test-revlog-ancestry.py not using absolute_import
188 tests/test-revlog-ancestry.py requires print_function
187 tests/test-revlog-ancestry.py requires print_function
189 tests/test-run-tests.py not using absolute_import
188 tests/test-run-tests.py not using absolute_import
190 tests/test-simplemerge.py not using absolute_import
189 tests/test-simplemerge.py not using absolute_import
191 tests/test-status-inprocess.py not using absolute_import
190 tests/test-status-inprocess.py not using absolute_import
192 tests/test-status-inprocess.py requires print_function
191 tests/test-status-inprocess.py requires print_function
193 tests/test-symlink-os-yes-fs-no.py not using absolute_import
192 tests/test-symlink-os-yes-fs-no.py not using absolute_import
194 tests/test-trusted.py not using absolute_import
193 tests/test-trusted.py not using absolute_import
195 tests/test-trusted.py requires print_function
194 tests/test-trusted.py requires print_function
196 tests/test-ui-color.py not using absolute_import
195 tests/test-ui-color.py not using absolute_import
197 tests/test-ui-color.py requires print_function
196 tests/test-ui-color.py requires print_function
198 tests/test-ui-config.py not using absolute_import
197 tests/test-ui-config.py not using absolute_import
199 tests/test-ui-config.py requires print_function
198 tests/test-ui-config.py requires print_function
200 tests/test-ui-verbosity.py not using absolute_import
199 tests/test-ui-verbosity.py not using absolute_import
201 tests/test-ui-verbosity.py requires print_function
200 tests/test-ui-verbosity.py requires print_function
202 tests/test-url.py not using absolute_import
201 tests/test-url.py not using absolute_import
203 tests/test-url.py requires print_function
202 tests/test-url.py requires print_function
204 tests/test-walkrepo.py requires print_function
203 tests/test-walkrepo.py requires print_function
205 tests/test-wireproto.py requires print_function
204 tests/test-wireproto.py requires print_function
206 tests/tinyproxy.py requires print_function
205 tests/tinyproxy.py requires print_function
General Comments 0
You need to be logged in to leave comments. Login now