##// END OF EJS Templates
acl: use absolute_import...
Gregory Szorc -
r28089:a1163ee2 default
parent child Browse files
Show More
@@ -1,321 +1,329
1 # acl.py - changeset access control for mercurial
1 # acl.py - changeset access control for mercurial
2 #
2 #
3 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
3 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.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 '''hooks for controlling repository access
8 '''hooks for controlling repository access
9
9
10 This hook makes it possible to allow or deny write access to given
10 This hook makes it possible to allow or deny write access to given
11 branches and paths of a repository when receiving incoming changesets
11 branches and paths of a repository when receiving incoming changesets
12 via pretxnchangegroup and pretxncommit.
12 via pretxnchangegroup and pretxncommit.
13
13
14 The authorization is matched based on the local user name on the
14 The authorization is matched based on the local user name on the
15 system where the hook runs, and not the committer of the original
15 system where the hook runs, and not the committer of the original
16 changeset (since the latter is merely informative).
16 changeset (since the latter is merely informative).
17
17
18 The acl hook is best used along with a restricted shell like hgsh,
18 The acl hook is best used along with a restricted shell like hgsh,
19 preventing authenticating users from doing anything other than pushing
19 preventing authenticating users from doing anything other than pushing
20 or pulling. The hook is not safe to use if users have interactive
20 or pulling. The hook is not safe to use if users have interactive
21 shell access, as they can then disable the hook. Nor is it safe if
21 shell access, as they can then disable the hook. Nor is it safe if
22 remote users share an account, because then there is no way to
22 remote users share an account, because then there is no way to
23 distinguish them.
23 distinguish them.
24
24
25 The order in which access checks are performed is:
25 The order in which access checks are performed is:
26
26
27 1) Deny list for branches (section ``acl.deny.branches``)
27 1) Deny list for branches (section ``acl.deny.branches``)
28 2) Allow list for branches (section ``acl.allow.branches``)
28 2) Allow list for branches (section ``acl.allow.branches``)
29 3) Deny list for paths (section ``acl.deny``)
29 3) Deny list for paths (section ``acl.deny``)
30 4) Allow list for paths (section ``acl.allow``)
30 4) Allow list for paths (section ``acl.allow``)
31
31
32 The allow and deny sections take key-value pairs.
32 The allow and deny sections take key-value pairs.
33
33
34 Branch-based Access Control
34 Branch-based Access Control
35 ---------------------------
35 ---------------------------
36
36
37 Use the ``acl.deny.branches`` and ``acl.allow.branches`` sections to
37 Use the ``acl.deny.branches`` and ``acl.allow.branches`` sections to
38 have branch-based access control. Keys in these sections can be
38 have branch-based access control. Keys in these sections can be
39 either:
39 either:
40
40
41 - a branch name, or
41 - a branch name, or
42 - an asterisk, to match any branch;
42 - an asterisk, to match any branch;
43
43
44 The corresponding values can be either:
44 The corresponding values can be either:
45
45
46 - a comma-separated list containing users and groups, or
46 - a comma-separated list containing users and groups, or
47 - an asterisk, to match anyone;
47 - an asterisk, to match anyone;
48
48
49 You can add the "!" prefix to a user or group name to invert the sense
49 You can add the "!" prefix to a user or group name to invert the sense
50 of the match.
50 of the match.
51
51
52 Path-based Access Control
52 Path-based Access Control
53 -------------------------
53 -------------------------
54
54
55 Use the ``acl.deny`` and ``acl.allow`` sections to have path-based
55 Use the ``acl.deny`` and ``acl.allow`` sections to have path-based
56 access control. Keys in these sections accept a subtree pattern (with
56 access control. Keys in these sections accept a subtree pattern (with
57 a glob syntax by default). The corresponding values follow the same
57 a glob syntax by default). The corresponding values follow the same
58 syntax as the other sections above.
58 syntax as the other sections above.
59
59
60 Groups
60 Groups
61 ------
61 ------
62
62
63 Group names must be prefixed with an ``@`` symbol. Specifying a group
63 Group names must be prefixed with an ``@`` symbol. Specifying a group
64 name has the same effect as specifying all the users in that group.
64 name has the same effect as specifying all the users in that group.
65
65
66 You can define group members in the ``acl.groups`` section.
66 You can define group members in the ``acl.groups`` section.
67 If a group name is not defined there, and Mercurial is running under
67 If a group name is not defined there, and Mercurial is running under
68 a Unix-like system, the list of users will be taken from the OS.
68 a Unix-like system, the list of users will be taken from the OS.
69 Otherwise, an exception will be raised.
69 Otherwise, an exception will be raised.
70
70
71 Example Configuration
71 Example Configuration
72 ---------------------
72 ---------------------
73
73
74 ::
74 ::
75
75
76 [hooks]
76 [hooks]
77
77
78 # Use this if you want to check access restrictions at commit time
78 # Use this if you want to check access restrictions at commit time
79 pretxncommit.acl = python:hgext.acl.hook
79 pretxncommit.acl = python:hgext.acl.hook
80
80
81 # Use this if you want to check access restrictions for pull, push,
81 # Use this if you want to check access restrictions for pull, push,
82 # bundle and serve.
82 # bundle and serve.
83 pretxnchangegroup.acl = python:hgext.acl.hook
83 pretxnchangegroup.acl = python:hgext.acl.hook
84
84
85 [acl]
85 [acl]
86 # Allow or deny access for incoming changes only if their source is
86 # Allow or deny access for incoming changes only if their source is
87 # listed here, let them pass otherwise. Source is "serve" for all
87 # listed here, let them pass otherwise. Source is "serve" for all
88 # remote access (http or ssh), "push", "pull" or "bundle" when the
88 # remote access (http or ssh), "push", "pull" or "bundle" when the
89 # related commands are run locally.
89 # related commands are run locally.
90 # Default: serve
90 # Default: serve
91 sources = serve
91 sources = serve
92
92
93 [acl.deny.branches]
93 [acl.deny.branches]
94
94
95 # Everyone is denied to the frozen branch:
95 # Everyone is denied to the frozen branch:
96 frozen-branch = *
96 frozen-branch = *
97
97
98 # A bad user is denied on all branches:
98 # A bad user is denied on all branches:
99 * = bad-user
99 * = bad-user
100
100
101 [acl.allow.branches]
101 [acl.allow.branches]
102
102
103 # A few users are allowed on branch-a:
103 # A few users are allowed on branch-a:
104 branch-a = user-1, user-2, user-3
104 branch-a = user-1, user-2, user-3
105
105
106 # Only one user is allowed on branch-b:
106 # Only one user is allowed on branch-b:
107 branch-b = user-1
107 branch-b = user-1
108
108
109 # The super user is allowed on any branch:
109 # The super user is allowed on any branch:
110 * = super-user
110 * = super-user
111
111
112 # Everyone is allowed on branch-for-tests:
112 # Everyone is allowed on branch-for-tests:
113 branch-for-tests = *
113 branch-for-tests = *
114
114
115 [acl.deny]
115 [acl.deny]
116 # This list is checked first. If a match is found, acl.allow is not
116 # This list is checked first. If a match is found, acl.allow is not
117 # checked. All users are granted access if acl.deny is not present.
117 # checked. All users are granted access if acl.deny is not present.
118 # Format for both lists: glob pattern = user, ..., @group, ...
118 # Format for both lists: glob pattern = user, ..., @group, ...
119
119
120 # To match everyone, use an asterisk for the user:
120 # To match everyone, use an asterisk for the user:
121 # my/glob/pattern = *
121 # my/glob/pattern = *
122
122
123 # user6 will not have write access to any file:
123 # user6 will not have write access to any file:
124 ** = user6
124 ** = user6
125
125
126 # Group "hg-denied" will not have write access to any file:
126 # Group "hg-denied" will not have write access to any file:
127 ** = @hg-denied
127 ** = @hg-denied
128
128
129 # Nobody will be able to change "DONT-TOUCH-THIS.txt", despite
129 # Nobody will be able to change "DONT-TOUCH-THIS.txt", despite
130 # everyone being able to change all other files. See below.
130 # everyone being able to change all other files. See below.
131 src/main/resources/DONT-TOUCH-THIS.txt = *
131 src/main/resources/DONT-TOUCH-THIS.txt = *
132
132
133 [acl.allow]
133 [acl.allow]
134 # if acl.allow is not present, all users are allowed by default
134 # if acl.allow is not present, all users are allowed by default
135 # empty acl.allow = no users allowed
135 # empty acl.allow = no users allowed
136
136
137 # User "doc_writer" has write access to any file under the "docs"
137 # User "doc_writer" has write access to any file under the "docs"
138 # folder:
138 # folder:
139 docs/** = doc_writer
139 docs/** = doc_writer
140
140
141 # User "jack" and group "designers" have write access to any file
141 # User "jack" and group "designers" have write access to any file
142 # under the "images" folder:
142 # under the "images" folder:
143 images/** = jack, @designers
143 images/** = jack, @designers
144
144
145 # Everyone (except for "user6" and "@hg-denied" - see acl.deny above)
145 # Everyone (except for "user6" and "@hg-denied" - see acl.deny above)
146 # will have write access to any file under the "resources" folder
146 # will have write access to any file under the "resources" folder
147 # (except for 1 file. See acl.deny):
147 # (except for 1 file. See acl.deny):
148 src/main/resources/** = *
148 src/main/resources/** = *
149
149
150 .hgtags = release_engineer
150 .hgtags = release_engineer
151
151
152 Examples using the "!" prefix
152 Examples using the "!" prefix
153 .............................
153 .............................
154
154
155 Suppose there's a branch that only a given user (or group) should be able to
155 Suppose there's a branch that only a given user (or group) should be able to
156 push to, and you don't want to restrict access to any other branch that may
156 push to, and you don't want to restrict access to any other branch that may
157 be created.
157 be created.
158
158
159 The "!" prefix allows you to prevent anyone except a given user or group to
159 The "!" prefix allows you to prevent anyone except a given user or group to
160 push changesets in a given branch or path.
160 push changesets in a given branch or path.
161
161
162 In the examples below, we will:
162 In the examples below, we will:
163 1) Deny access to branch "ring" to anyone but user "gollum"
163 1) Deny access to branch "ring" to anyone but user "gollum"
164 2) Deny access to branch "lake" to anyone but members of the group "hobbit"
164 2) Deny access to branch "lake" to anyone but members of the group "hobbit"
165 3) Deny access to a file to anyone but user "gollum"
165 3) Deny access to a file to anyone but user "gollum"
166
166
167 ::
167 ::
168
168
169 [acl.allow.branches]
169 [acl.allow.branches]
170 # Empty
170 # Empty
171
171
172 [acl.deny.branches]
172 [acl.deny.branches]
173
173
174 # 1) only 'gollum' can commit to branch 'ring';
174 # 1) only 'gollum' can commit to branch 'ring';
175 # 'gollum' and anyone else can still commit to any other branch.
175 # 'gollum' and anyone else can still commit to any other branch.
176 ring = !gollum
176 ring = !gollum
177
177
178 # 2) only members of the group 'hobbit' can commit to branch 'lake';
178 # 2) only members of the group 'hobbit' can commit to branch 'lake';
179 # 'hobbit' members and anyone else can still commit to any other branch.
179 # 'hobbit' members and anyone else can still commit to any other branch.
180 lake = !@hobbit
180 lake = !@hobbit
181
181
182 # You can also deny access based on file paths:
182 # You can also deny access based on file paths:
183
183
184 [acl.allow]
184 [acl.allow]
185 # Empty
185 # Empty
186
186
187 [acl.deny]
187 [acl.deny]
188 # 3) only 'gollum' can change the file below;
188 # 3) only 'gollum' can change the file below;
189 # 'gollum' and anyone else can still change any other file.
189 # 'gollum' and anyone else can still change any other file.
190 /misty/mountains/cave/ring = !gollum
190 /misty/mountains/cave/ring = !gollum
191
191
192 '''
192 '''
193
193
194 from __future__ import absolute_import
195
196 import getpass
197 import urllib
198
194 from mercurial.i18n import _
199 from mercurial.i18n import _
195 from mercurial import util, match, error
200 from mercurial import (
196 import getpass, urllib
201 error,
202 match,
203 util,
204 )
197
205
198 # Note for extension authors: ONLY specify testedwith = 'internal' for
206 # Note for extension authors: ONLY specify testedwith = 'internal' for
199 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
207 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
200 # be specifying the version(s) of Mercurial they are tested with, or
208 # be specifying the version(s) of Mercurial they are tested with, or
201 # leave the attribute unspecified.
209 # leave the attribute unspecified.
202 testedwith = 'internal'
210 testedwith = 'internal'
203
211
204 def _getusers(ui, group):
212 def _getusers(ui, group):
205
213
206 # First, try to use group definition from section [acl.groups]
214 # First, try to use group definition from section [acl.groups]
207 hgrcusers = ui.configlist('acl.groups', group)
215 hgrcusers = ui.configlist('acl.groups', group)
208 if hgrcusers:
216 if hgrcusers:
209 return hgrcusers
217 return hgrcusers
210
218
211 ui.debug('acl: "%s" not defined in [acl.groups]\n' % group)
219 ui.debug('acl: "%s" not defined in [acl.groups]\n' % group)
212 # If no users found in group definition, get users from OS-level group
220 # If no users found in group definition, get users from OS-level group
213 try:
221 try:
214 return util.groupmembers(group)
222 return util.groupmembers(group)
215 except KeyError:
223 except KeyError:
216 raise error.Abort(_("group '%s' is undefined") % group)
224 raise error.Abort(_("group '%s' is undefined") % group)
217
225
218 def _usermatch(ui, user, usersorgroups):
226 def _usermatch(ui, user, usersorgroups):
219
227
220 if usersorgroups == '*':
228 if usersorgroups == '*':
221 return True
229 return True
222
230
223 for ug in usersorgroups.replace(',', ' ').split():
231 for ug in usersorgroups.replace(',', ' ').split():
224
232
225 if ug.startswith('!'):
233 if ug.startswith('!'):
226 # Test for excluded user or group. Format:
234 # Test for excluded user or group. Format:
227 # if ug is a user name: !username
235 # if ug is a user name: !username
228 # if ug is a group name: !@groupname
236 # if ug is a group name: !@groupname
229 ug = ug[1:]
237 ug = ug[1:]
230 if not ug.startswith('@') and user != ug \
238 if not ug.startswith('@') and user != ug \
231 or ug.startswith('@') and user not in _getusers(ui, ug[1:]):
239 or ug.startswith('@') and user not in _getusers(ui, ug[1:]):
232 return True
240 return True
233
241
234 # Test for user or group. Format:
242 # Test for user or group. Format:
235 # if ug is a user name: username
243 # if ug is a user name: username
236 # if ug is a group name: @groupname
244 # if ug is a group name: @groupname
237 elif user == ug \
245 elif user == ug \
238 or ug.startswith('@') and user in _getusers(ui, ug[1:]):
246 or ug.startswith('@') and user in _getusers(ui, ug[1:]):
239 return True
247 return True
240
248
241 return False
249 return False
242
250
243 def buildmatch(ui, repo, user, key):
251 def buildmatch(ui, repo, user, key):
244 '''return tuple of (match function, list enabled).'''
252 '''return tuple of (match function, list enabled).'''
245 if not ui.has_section(key):
253 if not ui.has_section(key):
246 ui.debug('acl: %s not enabled\n' % key)
254 ui.debug('acl: %s not enabled\n' % key)
247 return None
255 return None
248
256
249 pats = [pat for pat, users in ui.configitems(key)
257 pats = [pat for pat, users in ui.configitems(key)
250 if _usermatch(ui, user, users)]
258 if _usermatch(ui, user, users)]
251 ui.debug('acl: %s enabled, %d entries for user %s\n' %
259 ui.debug('acl: %s enabled, %d entries for user %s\n' %
252 (key, len(pats), user))
260 (key, len(pats), user))
253
261
254 # Branch-based ACL
262 # Branch-based ACL
255 if not repo:
263 if not repo:
256 if pats:
264 if pats:
257 # If there's an asterisk (meaning "any branch"), always return True;
265 # If there's an asterisk (meaning "any branch"), always return True;
258 # Otherwise, test if b is in pats
266 # Otherwise, test if b is in pats
259 if '*' in pats:
267 if '*' in pats:
260 return util.always
268 return util.always
261 return lambda b: b in pats
269 return lambda b: b in pats
262 return util.never
270 return util.never
263
271
264 # Path-based ACL
272 # Path-based ACL
265 if pats:
273 if pats:
266 return match.match(repo.root, '', pats)
274 return match.match(repo.root, '', pats)
267 return util.never
275 return util.never
268
276
269 def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
277 def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
270 if hooktype not in ['pretxnchangegroup', 'pretxncommit']:
278 if hooktype not in ['pretxnchangegroup', 'pretxncommit']:
271 raise error.Abort(_('config error - hook type "%s" cannot stop '
279 raise error.Abort(_('config error - hook type "%s" cannot stop '
272 'incoming changesets nor commits') % hooktype)
280 'incoming changesets nor commits') % hooktype)
273 if (hooktype == 'pretxnchangegroup' and
281 if (hooktype == 'pretxnchangegroup' and
274 source not in ui.config('acl', 'sources', 'serve').split()):
282 source not in ui.config('acl', 'sources', 'serve').split()):
275 ui.debug('acl: changes have source "%s" - skipping\n' % source)
283 ui.debug('acl: changes have source "%s" - skipping\n' % source)
276 return
284 return
277
285
278 user = None
286 user = None
279 if source == 'serve' and 'url' in kwargs:
287 if source == 'serve' and 'url' in kwargs:
280 url = kwargs['url'].split(':')
288 url = kwargs['url'].split(':')
281 if url[0] == 'remote' and url[1].startswith('http'):
289 if url[0] == 'remote' and url[1].startswith('http'):
282 user = urllib.unquote(url[3])
290 user = urllib.unquote(url[3])
283
291
284 if user is None:
292 if user is None:
285 user = getpass.getuser()
293 user = getpass.getuser()
286
294
287 ui.debug('acl: checking access for user "%s"\n' % user)
295 ui.debug('acl: checking access for user "%s"\n' % user)
288
296
289 # deprecated config: acl.config
297 # deprecated config: acl.config
290 cfg = ui.config('acl', 'config')
298 cfg = ui.config('acl', 'config')
291 if cfg:
299 if cfg:
292 ui.readconfig(cfg, sections=['acl.groups', 'acl.allow.branches',
300 ui.readconfig(cfg, sections=['acl.groups', 'acl.allow.branches',
293 'acl.deny.branches', 'acl.allow', 'acl.deny'])
301 'acl.deny.branches', 'acl.allow', 'acl.deny'])
294
302
295 allowbranches = buildmatch(ui, None, user, 'acl.allow.branches')
303 allowbranches = buildmatch(ui, None, user, 'acl.allow.branches')
296 denybranches = buildmatch(ui, None, user, 'acl.deny.branches')
304 denybranches = buildmatch(ui, None, user, 'acl.deny.branches')
297 allow = buildmatch(ui, repo, user, 'acl.allow')
305 allow = buildmatch(ui, repo, user, 'acl.allow')
298 deny = buildmatch(ui, repo, user, 'acl.deny')
306 deny = buildmatch(ui, repo, user, 'acl.deny')
299
307
300 for rev in xrange(repo[node], len(repo)):
308 for rev in xrange(repo[node], len(repo)):
301 ctx = repo[rev]
309 ctx = repo[rev]
302 branch = ctx.branch()
310 branch = ctx.branch()
303 if denybranches and denybranches(branch):
311 if denybranches and denybranches(branch):
304 raise error.Abort(_('acl: user "%s" denied on branch "%s"'
312 raise error.Abort(_('acl: user "%s" denied on branch "%s"'
305 ' (changeset "%s")')
313 ' (changeset "%s")')
306 % (user, branch, ctx))
314 % (user, branch, ctx))
307 if allowbranches and not allowbranches(branch):
315 if allowbranches and not allowbranches(branch):
308 raise error.Abort(_('acl: user "%s" not allowed on branch "%s"'
316 raise error.Abort(_('acl: user "%s" not allowed on branch "%s"'
309 ' (changeset "%s")')
317 ' (changeset "%s")')
310 % (user, branch, ctx))
318 % (user, branch, ctx))
311 ui.debug('acl: branch access granted: "%s" on branch "%s"\n'
319 ui.debug('acl: branch access granted: "%s" on branch "%s"\n'
312 % (ctx, branch))
320 % (ctx, branch))
313
321
314 for f in ctx.files():
322 for f in ctx.files():
315 if deny and deny(f):
323 if deny and deny(f):
316 raise error.Abort(_('acl: user "%s" denied on "%s"'
324 raise error.Abort(_('acl: user "%s" denied on "%s"'
317 ' (changeset "%s")') % (user, f, ctx))
325 ' (changeset "%s")') % (user, f, ctx))
318 if allow and not allow(f):
326 if allow and not allow(f):
319 raise error.Abort(_('acl: user "%s" not allowed on "%s"'
327 raise error.Abort(_('acl: user "%s" not allowed on "%s"'
320 ' (changeset "%s")') % (user, f, ctx))
328 ' (changeset "%s")') % (user, f, ctx))
321 ui.debug('acl: path access granted: "%s"\n' % ctx)
329 ui.debug('acl: path access granted: "%s"\n' % ctx)
@@ -1,181 +1,180
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
36 hgext/blackbox.py not using absolute_import
35 hgext/blackbox.py not using absolute_import
37 hgext/bugzilla.py not using absolute_import
36 hgext/bugzilla.py not using absolute_import
38 hgext/censor.py not using absolute_import
37 hgext/censor.py not using absolute_import
39 hgext/children.py not using absolute_import
38 hgext/children.py not using absolute_import
40 hgext/churn.py not using absolute_import
39 hgext/churn.py not using absolute_import
41 hgext/clonebundles.py not using absolute_import
40 hgext/clonebundles.py not using absolute_import
42 hgext/color.py not using absolute_import
41 hgext/color.py not using absolute_import
43 hgext/convert/__init__.py not using absolute_import
42 hgext/convert/__init__.py not using absolute_import
44 hgext/convert/bzr.py not using absolute_import
43 hgext/convert/bzr.py not using absolute_import
45 hgext/convert/common.py not using absolute_import
44 hgext/convert/common.py not using absolute_import
46 hgext/convert/convcmd.py not using absolute_import
45 hgext/convert/convcmd.py not using absolute_import
47 hgext/convert/cvs.py not using absolute_import
46 hgext/convert/cvs.py not using absolute_import
48 hgext/convert/cvsps.py not using absolute_import
47 hgext/convert/cvsps.py not using absolute_import
49 hgext/convert/darcs.py not using absolute_import
48 hgext/convert/darcs.py not using absolute_import
50 hgext/convert/filemap.py not using absolute_import
49 hgext/convert/filemap.py not using absolute_import
51 hgext/convert/git.py not using absolute_import
50 hgext/convert/git.py not using absolute_import
52 hgext/convert/gnuarch.py not using absolute_import
51 hgext/convert/gnuarch.py not using absolute_import
53 hgext/convert/hg.py not using absolute_import
52 hgext/convert/hg.py not using absolute_import
54 hgext/convert/monotone.py not using absolute_import
53 hgext/convert/monotone.py not using absolute_import
55 hgext/convert/p4.py not using absolute_import
54 hgext/convert/p4.py not using absolute_import
56 hgext/convert/subversion.py not using absolute_import
55 hgext/convert/subversion.py not using absolute_import
57 hgext/convert/transport.py not using absolute_import
56 hgext/convert/transport.py not using absolute_import
58 hgext/eol.py not using absolute_import
57 hgext/eol.py not using absolute_import
59 hgext/extdiff.py not using absolute_import
58 hgext/extdiff.py not using absolute_import
60 hgext/factotum.py not using absolute_import
59 hgext/factotum.py not using absolute_import
61 hgext/fetch.py not using absolute_import
60 hgext/fetch.py not using absolute_import
62 hgext/gpg.py not using absolute_import
61 hgext/gpg.py not using absolute_import
63 hgext/graphlog.py not using absolute_import
62 hgext/graphlog.py not using absolute_import
64 hgext/hgcia.py not using absolute_import
63 hgext/hgcia.py not using absolute_import
65 hgext/hgk.py not using absolute_import
64 hgext/hgk.py not using absolute_import
66 hgext/highlight/__init__.py not using absolute_import
65 hgext/highlight/__init__.py not using absolute_import
67 hgext/highlight/highlight.py not using absolute_import
66 hgext/highlight/highlight.py not using absolute_import
68 hgext/histedit.py not using absolute_import
67 hgext/histedit.py not using absolute_import
69 hgext/keyword.py not using absolute_import
68 hgext/keyword.py not using absolute_import
70 hgext/largefiles/__init__.py not using absolute_import
69 hgext/largefiles/__init__.py not using absolute_import
71 hgext/largefiles/basestore.py not using absolute_import
70 hgext/largefiles/basestore.py not using absolute_import
72 hgext/largefiles/lfcommands.py not using absolute_import
71 hgext/largefiles/lfcommands.py not using absolute_import
73 hgext/largefiles/lfutil.py not using absolute_import
72 hgext/largefiles/lfutil.py not using absolute_import
74 hgext/largefiles/localstore.py not using absolute_import
73 hgext/largefiles/localstore.py not using absolute_import
75 hgext/largefiles/overrides.py not using absolute_import
74 hgext/largefiles/overrides.py not using absolute_import
76 hgext/largefiles/proto.py not using absolute_import
75 hgext/largefiles/proto.py not using absolute_import
77 hgext/largefiles/remotestore.py not using absolute_import
76 hgext/largefiles/remotestore.py not using absolute_import
78 hgext/largefiles/reposetup.py not using absolute_import
77 hgext/largefiles/reposetup.py not using absolute_import
79 hgext/largefiles/uisetup.py not using absolute_import
78 hgext/largefiles/uisetup.py not using absolute_import
80 hgext/largefiles/wirestore.py not using absolute_import
79 hgext/largefiles/wirestore.py not using absolute_import
81 hgext/mq.py not using absolute_import
80 hgext/mq.py not using absolute_import
82 hgext/notify.py not using absolute_import
81 hgext/notify.py not using absolute_import
83 hgext/pager.py not using absolute_import
82 hgext/pager.py not using absolute_import
84 hgext/patchbomb.py not using absolute_import
83 hgext/patchbomb.py not using absolute_import
85 hgext/purge.py not using absolute_import
84 hgext/purge.py not using absolute_import
86 hgext/rebase.py not using absolute_import
85 hgext/rebase.py not using absolute_import
87 hgext/record.py not using absolute_import
86 hgext/record.py not using absolute_import
88 hgext/relink.py not using absolute_import
87 hgext/relink.py not using absolute_import
89 hgext/schemes.py not using absolute_import
88 hgext/schemes.py not using absolute_import
90 hgext/share.py not using absolute_import
89 hgext/share.py not using absolute_import
91 hgext/shelve.py not using absolute_import
90 hgext/shelve.py not using absolute_import
92 hgext/strip.py not using absolute_import
91 hgext/strip.py not using absolute_import
93 hgext/transplant.py not using absolute_import
92 hgext/transplant.py not using absolute_import
94 hgext/win32mbcs.py not using absolute_import
93 hgext/win32mbcs.py not using absolute_import
95 hgext/win32text.py not using absolute_import
94 hgext/win32text.py not using absolute_import
96 hgext/zeroconf/Zeroconf.py not using absolute_import
95 hgext/zeroconf/Zeroconf.py not using absolute_import
97 hgext/zeroconf/Zeroconf.py requires print_function
96 hgext/zeroconf/Zeroconf.py requires print_function
98 hgext/zeroconf/__init__.py not using absolute_import
97 hgext/zeroconf/__init__.py not using absolute_import
99 i18n/check-translation.py not using absolute_import
98 i18n/check-translation.py not using absolute_import
100 i18n/polib.py not using absolute_import
99 i18n/polib.py not using absolute_import
101 mercurial/cmdutil.py not using absolute_import
100 mercurial/cmdutil.py not using absolute_import
102 mercurial/commands.py not using absolute_import
101 mercurial/commands.py not using absolute_import
103 setup.py not using absolute_import
102 setup.py not using absolute_import
104 tests/filterpyflakes.py requires print_function
103 tests/filterpyflakes.py requires print_function
105 tests/generate-working-copy-states.py requires print_function
104 tests/generate-working-copy-states.py requires print_function
106 tests/get-with-headers.py requires print_function
105 tests/get-with-headers.py requires print_function
107 tests/heredoctest.py requires print_function
106 tests/heredoctest.py requires print_function
108 tests/hypothesishelpers.py not using absolute_import
107 tests/hypothesishelpers.py not using absolute_import
109 tests/hypothesishelpers.py requires print_function
108 tests/hypothesishelpers.py requires print_function
110 tests/killdaemons.py not using absolute_import
109 tests/killdaemons.py not using absolute_import
111 tests/md5sum.py not using absolute_import
110 tests/md5sum.py not using absolute_import
112 tests/mockblackbox.py not using absolute_import
111 tests/mockblackbox.py not using absolute_import
113 tests/printenv.py not using absolute_import
112 tests/printenv.py not using absolute_import
114 tests/readlink.py not using absolute_import
113 tests/readlink.py not using absolute_import
115 tests/readlink.py requires print_function
114 tests/readlink.py requires print_function
116 tests/revlog-formatv0.py not using absolute_import
115 tests/revlog-formatv0.py not using absolute_import
117 tests/run-tests.py not using absolute_import
116 tests/run-tests.py not using absolute_import
118 tests/seq.py not using absolute_import
117 tests/seq.py not using absolute_import
119 tests/seq.py requires print_function
118 tests/seq.py requires print_function
120 tests/silenttestrunner.py not using absolute_import
119 tests/silenttestrunner.py not using absolute_import
121 tests/silenttestrunner.py requires print_function
120 tests/silenttestrunner.py requires print_function
122 tests/sitecustomize.py not using absolute_import
121 tests/sitecustomize.py not using absolute_import
123 tests/svn-safe-append.py not using absolute_import
122 tests/svn-safe-append.py not using absolute_import
124 tests/svnxml.py not using absolute_import
123 tests/svnxml.py not using absolute_import
125 tests/test-ancestor.py requires print_function
124 tests/test-ancestor.py requires print_function
126 tests/test-atomictempfile.py not using absolute_import
125 tests/test-atomictempfile.py not using absolute_import
127 tests/test-batching.py not using absolute_import
126 tests/test-batching.py not using absolute_import
128 tests/test-batching.py requires print_function
127 tests/test-batching.py requires print_function
129 tests/test-bdiff.py not using absolute_import
128 tests/test-bdiff.py not using absolute_import
130 tests/test-bdiff.py requires print_function
129 tests/test-bdiff.py requires print_function
131 tests/test-context.py not using absolute_import
130 tests/test-context.py not using absolute_import
132 tests/test-context.py requires print_function
131 tests/test-context.py requires print_function
133 tests/test-demandimport.py not using absolute_import
132 tests/test-demandimport.py not using absolute_import
134 tests/test-demandimport.py requires print_function
133 tests/test-demandimport.py requires print_function
135 tests/test-dispatch.py not using absolute_import
134 tests/test-dispatch.py not using absolute_import
136 tests/test-dispatch.py requires print_function
135 tests/test-dispatch.py requires print_function
137 tests/test-doctest.py not using absolute_import
136 tests/test-doctest.py not using absolute_import
138 tests/test-duplicateoptions.py not using absolute_import
137 tests/test-duplicateoptions.py not using absolute_import
139 tests/test-duplicateoptions.py requires print_function
138 tests/test-duplicateoptions.py requires print_function
140 tests/test-filecache.py not using absolute_import
139 tests/test-filecache.py not using absolute_import
141 tests/test-filecache.py requires print_function
140 tests/test-filecache.py requires print_function
142 tests/test-filelog.py not using absolute_import
141 tests/test-filelog.py not using absolute_import
143 tests/test-filelog.py requires print_function
142 tests/test-filelog.py requires print_function
144 tests/test-hg-parseurl.py not using absolute_import
143 tests/test-hg-parseurl.py not using absolute_import
145 tests/test-hg-parseurl.py requires print_function
144 tests/test-hg-parseurl.py requires print_function
146 tests/test-hgweb-auth.py not using absolute_import
145 tests/test-hgweb-auth.py not using absolute_import
147 tests/test-hgweb-auth.py requires print_function
146 tests/test-hgweb-auth.py requires print_function
148 tests/test-hgwebdir-paths.py not using absolute_import
147 tests/test-hgwebdir-paths.py not using absolute_import
149 tests/test-hybridencode.py not using absolute_import
148 tests/test-hybridencode.py not using absolute_import
150 tests/test-hybridencode.py requires print_function
149 tests/test-hybridencode.py requires print_function
151 tests/test-lrucachedict.py not using absolute_import
150 tests/test-lrucachedict.py not using absolute_import
152 tests/test-lrucachedict.py requires print_function
151 tests/test-lrucachedict.py requires print_function
153 tests/test-manifest.py not using absolute_import
152 tests/test-manifest.py not using absolute_import
154 tests/test-minirst.py not using absolute_import
153 tests/test-minirst.py not using absolute_import
155 tests/test-minirst.py requires print_function
154 tests/test-minirst.py requires print_function
156 tests/test-parseindex2.py not using absolute_import
155 tests/test-parseindex2.py not using absolute_import
157 tests/test-parseindex2.py requires print_function
156 tests/test-parseindex2.py requires print_function
158 tests/test-pathencode.py not using absolute_import
157 tests/test-pathencode.py not using absolute_import
159 tests/test-pathencode.py requires print_function
158 tests/test-pathencode.py requires print_function
160 tests/test-propertycache.py not using absolute_import
159 tests/test-propertycache.py not using absolute_import
161 tests/test-propertycache.py requires print_function
160 tests/test-propertycache.py requires print_function
162 tests/test-revlog-ancestry.py not using absolute_import
161 tests/test-revlog-ancestry.py not using absolute_import
163 tests/test-revlog-ancestry.py requires print_function
162 tests/test-revlog-ancestry.py requires print_function
164 tests/test-run-tests.py not using absolute_import
163 tests/test-run-tests.py not using absolute_import
165 tests/test-simplemerge.py not using absolute_import
164 tests/test-simplemerge.py not using absolute_import
166 tests/test-status-inprocess.py not using absolute_import
165 tests/test-status-inprocess.py not using absolute_import
167 tests/test-status-inprocess.py requires print_function
166 tests/test-status-inprocess.py requires print_function
168 tests/test-symlink-os-yes-fs-no.py not using absolute_import
167 tests/test-symlink-os-yes-fs-no.py not using absolute_import
169 tests/test-trusted.py not using absolute_import
168 tests/test-trusted.py not using absolute_import
170 tests/test-trusted.py requires print_function
169 tests/test-trusted.py requires print_function
171 tests/test-ui-color.py not using absolute_import
170 tests/test-ui-color.py not using absolute_import
172 tests/test-ui-color.py requires print_function
171 tests/test-ui-color.py requires print_function
173 tests/test-ui-config.py not using absolute_import
172 tests/test-ui-config.py not using absolute_import
174 tests/test-ui-config.py requires print_function
173 tests/test-ui-config.py requires print_function
175 tests/test-ui-verbosity.py not using absolute_import
174 tests/test-ui-verbosity.py not using absolute_import
176 tests/test-ui-verbosity.py requires print_function
175 tests/test-ui-verbosity.py requires print_function
177 tests/test-url.py not using absolute_import
176 tests/test-url.py not using absolute_import
178 tests/test-url.py requires print_function
177 tests/test-url.py requires print_function
179 tests/test-walkrepo.py requires print_function
178 tests/test-walkrepo.py requires print_function
180 tests/test-wireproto.py requires print_function
179 tests/test-wireproto.py requires print_function
181 tests/tinyproxy.py requires print_function
180 tests/tinyproxy.py requires print_function
General Comments 0
You need to be logged in to leave comments. Login now