##// END OF EJS Templates
py3: fix formatting of path-auditing errors
Yuya Nishihara -
r36667:d3b893ec default
parent child Browse files
Show More
@@ -1,350 +1,352
1 test-abort-checkin.t
1 test-abort-checkin.t
2 test-add.t
2 test-add.t
3 test-addremove-similar.t
3 test-addremove-similar.t
4 test-addremove.t
4 test-addremove.t
5 test-amend-subrepo.t
5 test-amend-subrepo.t
6 test-ancestor.py
6 test-ancestor.py
7 test-annotate.py
7 test-annotate.py
8 test-annotate.t
8 test-annotate.t
9 test-audit-path.t
10 test-audit-subrepo.t
9 test-automv.t
11 test-automv.t
10 test-backout.t
12 test-backout.t
11 test-backwards-remove.t
13 test-backwards-remove.t
12 test-basic.t
14 test-basic.t
13 test-bheads.t
15 test-bheads.t
14 test-bisect2.t
16 test-bisect2.t
15 test-bookmarks-current.t
17 test-bookmarks-current.t
16 test-bookmarks-merge.t
18 test-bookmarks-merge.t
17 test-bookmarks-rebase.t
19 test-bookmarks-rebase.t
18 test-bookmarks-strip.t
20 test-bookmarks-strip.t
19 test-bookmarks.t
21 test-bookmarks.t
20 test-branch-option.t
22 test-branch-option.t
21 test-branch-tag-confict.t
23 test-branch-tag-confict.t
22 test-branches.t
24 test-branches.t
23 test-bundle-phases.t
25 test-bundle-phases.t
24 test-bundle-vs-outgoing.t
26 test-bundle-vs-outgoing.t
25 test-bundle2-multiple-changegroups.t
27 test-bundle2-multiple-changegroups.t
26 test-cappedreader.py
28 test-cappedreader.py
27 test-casecollision.t
29 test-casecollision.t
28 test-cat.t
30 test-cat.t
29 test-censor.t
31 test-censor.t
30 test-changelog-exec.t
32 test-changelog-exec.t
31 test-check-commit.t
33 test-check-commit.t
32 test-check-execute.t
34 test-check-execute.t
33 test-check-module-imports.t
35 test-check-module-imports.t
34 test-check-pyflakes.t
36 test-check-pyflakes.t
35 test-check-pylint.t
37 test-check-pylint.t
36 test-check-shbang.t
38 test-check-shbang.t
37 test-children.t
39 test-children.t
38 test-clone-pull-corruption.t
40 test-clone-pull-corruption.t
39 test-clone-r.t
41 test-clone-r.t
40 test-clone-update-order.t
42 test-clone-update-order.t
41 test-command-template.t
43 test-command-template.t
42 test-commit-amend.t
44 test-commit-amend.t
43 test-commit-unresolved.t
45 test-commit-unresolved.t
44 test-commit.t
46 test-commit.t
45 test-completion.t
47 test-completion.t
46 test-conflict.t
48 test-conflict.t
47 test-confused-revert.t
49 test-confused-revert.t
48 test-contrib-check-code.t
50 test-contrib-check-code.t
49 test-contrib-check-commit.t
51 test-contrib-check-commit.t
50 test-convert-authormap.t
52 test-convert-authormap.t
51 test-convert-clonebranches.t
53 test-convert-clonebranches.t
52 test-convert-datesort.t
54 test-convert-datesort.t
53 test-convert-filemap.t
55 test-convert-filemap.t
54 test-convert-hg-sink.t
56 test-convert-hg-sink.t
55 test-convert-hg-source.t
57 test-convert-hg-source.t
56 test-convert-hg-startrev.t
58 test-convert-hg-startrev.t
57 test-copy-move-merge.t
59 test-copy-move-merge.t
58 test-copytrace-heuristics.t
60 test-copytrace-heuristics.t
59 test-debugbuilddag.t
61 test-debugbuilddag.t
60 test-debugbundle.t
62 test-debugbundle.t
61 test-debugextensions.t
63 test-debugextensions.t
62 test-debugindexdot.t
64 test-debugindexdot.t
63 test-debugrename.t
65 test-debugrename.t
64 test-diff-binary-file.t
66 test-diff-binary-file.t
65 test-diff-change.t
67 test-diff-change.t
66 test-diff-copy-depth.t
68 test-diff-copy-depth.t
67 test-diff-hashes.t
69 test-diff-hashes.t
68 test-diff-issue2761.t
70 test-diff-issue2761.t
69 test-diff-newlines.t
71 test-diff-newlines.t
70 test-diff-reverse.t
72 test-diff-reverse.t
71 test-diff-subdir.t
73 test-diff-subdir.t
72 test-diffdir.t
74 test-diffdir.t
73 test-directaccess.t
75 test-directaccess.t
74 test-dirstate-backup.t
76 test-dirstate-backup.t
75 test-dirstate-nonnormalset.t
77 test-dirstate-nonnormalset.t
76 test-doctest.py
78 test-doctest.py
77 test-double-merge.t
79 test-double-merge.t
78 test-drawdag.t
80 test-drawdag.t
79 test-duplicateoptions.py
81 test-duplicateoptions.py
80 test-empty-dir.t
82 test-empty-dir.t
81 test-empty-file.t
83 test-empty-file.t
82 test-empty-group.t
84 test-empty-group.t
83 test-empty.t
85 test-empty.t
84 test-encoding-func.py
86 test-encoding-func.py
85 test-encoding.t
87 test-encoding.t
86 test-eol-add.t
88 test-eol-add.t
87 test-eol-clone.t
89 test-eol-clone.t
88 test-eol-tag.t
90 test-eol-tag.t
89 test-eol-update.t
91 test-eol-update.t
90 test-excessive-merge.t
92 test-excessive-merge.t
91 test-exchange-obsmarkers-case-A1.t
93 test-exchange-obsmarkers-case-A1.t
92 test-exchange-obsmarkers-case-A2.t
94 test-exchange-obsmarkers-case-A2.t
93 test-exchange-obsmarkers-case-A3.t
95 test-exchange-obsmarkers-case-A3.t
94 test-exchange-obsmarkers-case-A4.t
96 test-exchange-obsmarkers-case-A4.t
95 test-exchange-obsmarkers-case-A5.t
97 test-exchange-obsmarkers-case-A5.t
96 test-exchange-obsmarkers-case-A6.t
98 test-exchange-obsmarkers-case-A6.t
97 test-exchange-obsmarkers-case-A7.t
99 test-exchange-obsmarkers-case-A7.t
98 test-exchange-obsmarkers-case-B1.t
100 test-exchange-obsmarkers-case-B1.t
99 test-exchange-obsmarkers-case-B2.t
101 test-exchange-obsmarkers-case-B2.t
100 test-exchange-obsmarkers-case-B3.t
102 test-exchange-obsmarkers-case-B3.t
101 test-exchange-obsmarkers-case-B4.t
103 test-exchange-obsmarkers-case-B4.t
102 test-exchange-obsmarkers-case-B5.t
104 test-exchange-obsmarkers-case-B5.t
103 test-exchange-obsmarkers-case-B6.t
105 test-exchange-obsmarkers-case-B6.t
104 test-exchange-obsmarkers-case-B7.t
106 test-exchange-obsmarkers-case-B7.t
105 test-exchange-obsmarkers-case-C1.t
107 test-exchange-obsmarkers-case-C1.t
106 test-exchange-obsmarkers-case-C2.t
108 test-exchange-obsmarkers-case-C2.t
107 test-exchange-obsmarkers-case-C3.t
109 test-exchange-obsmarkers-case-C3.t
108 test-exchange-obsmarkers-case-C4.t
110 test-exchange-obsmarkers-case-C4.t
109 test-exchange-obsmarkers-case-D1.t
111 test-exchange-obsmarkers-case-D1.t
110 test-exchange-obsmarkers-case-D2.t
112 test-exchange-obsmarkers-case-D2.t
111 test-exchange-obsmarkers-case-D3.t
113 test-exchange-obsmarkers-case-D3.t
112 test-exchange-obsmarkers-case-D4.t
114 test-exchange-obsmarkers-case-D4.t
113 test-execute-bit.t
115 test-execute-bit.t
114 test-extdiff.t
116 test-extdiff.t
115 test-extra-filelog-entry.t
117 test-extra-filelog-entry.t
116 test-filebranch.t
118 test-filebranch.t
117 test-fileset-generated.t
119 test-fileset-generated.t
118 test-flags.t
120 test-flags.t
119 test-generaldelta.t
121 test-generaldelta.t
120 test-getbundle.t
122 test-getbundle.t
121 test-git-export.t
123 test-git-export.t
122 test-glog-topological.t
124 test-glog-topological.t
123 test-gpg.t
125 test-gpg.t
124 test-graft.t
126 test-graft.t
125 test-hghave.t
127 test-hghave.t
126 test-hgignore.t
128 test-hgignore.t
127 test-hgk.t
129 test-hgk.t
128 test-hgweb-removed.t
130 test-hgweb-removed.t
129 test-histedit-arguments.t
131 test-histedit-arguments.t
130 test-histedit-base.t
132 test-histedit-base.t
131 test-histedit-bookmark-motion.t
133 test-histedit-bookmark-motion.t
132 test-histedit-commute.t
134 test-histedit-commute.t
133 test-histedit-drop.t
135 test-histedit-drop.t
134 test-histedit-edit.t
136 test-histedit-edit.t
135 test-histedit-fold-non-commute.t
137 test-histedit-fold-non-commute.t
136 test-histedit-fold.t
138 test-histedit-fold.t
137 test-histedit-no-change.t
139 test-histedit-no-change.t
138 test-histedit-non-commute-abort.t
140 test-histedit-non-commute-abort.t
139 test-histedit-non-commute.t
141 test-histedit-non-commute.t
140 test-histedit-obsolete.t
142 test-histedit-obsolete.t
141 test-histedit-outgoing.t
143 test-histedit-outgoing.t
142 test-histedit-templates.t
144 test-histedit-templates.t
143 test-http-branchmap.t
145 test-http-branchmap.t
144 test-http-clone-r.t
146 test-http-clone-r.t
145 test-identify.t
147 test-identify.t
146 test-imports-checker.t
148 test-imports-checker.t
147 test-inherit-mode.t
149 test-inherit-mode.t
148 test-issue1089.t
150 test-issue1089.t
149 test-issue1102.t
151 test-issue1102.t
150 test-issue1175.t
152 test-issue1175.t
151 test-issue1306.t
153 test-issue1306.t
152 test-issue1438.t
154 test-issue1438.t
153 test-issue1502.t
155 test-issue1502.t
154 test-issue1802.t
156 test-issue1802.t
155 test-issue1877.t
157 test-issue1877.t
156 test-issue1993.t
158 test-issue1993.t
157 test-issue2137.t
159 test-issue2137.t
158 test-issue3084.t
160 test-issue3084.t
159 test-issue4074.t
161 test-issue4074.t
160 test-issue522.t
162 test-issue522.t
161 test-issue586.t
163 test-issue586.t
162 test-issue612.t
164 test-issue612.t
163 test-issue619.t
165 test-issue619.t
164 test-issue672.t
166 test-issue672.t
165 test-issue842.t
167 test-issue842.t
166 test-journal-exists.t
168 test-journal-exists.t
167 test-largefiles-small-disk.t
169 test-largefiles-small-disk.t
168 test-locate.t
170 test-locate.t
169 test-lock-badness.t
171 test-lock-badness.t
170 test-logexchange.t
172 test-logexchange.t
171 test-lrucachedict.py
173 test-lrucachedict.py
172 test-mactext.t
174 test-mactext.t
173 test-manifest-merging.t
175 test-manifest-merging.t
174 test-manifest.py
176 test-manifest.py
175 test-manifest.t
177 test-manifest.t
176 test-match.py
178 test-match.py
177 test-mdiff.py
179 test-mdiff.py
178 test-merge-closedheads.t
180 test-merge-closedheads.t
179 test-merge-commit.t
181 test-merge-commit.t
180 test-merge-criss-cross.t
182 test-merge-criss-cross.t
181 test-merge-default.t
183 test-merge-default.t
182 test-merge-internal-tools-pattern.t
184 test-merge-internal-tools-pattern.t
183 test-merge-local.t
185 test-merge-local.t
184 test-merge-remove.t
186 test-merge-remove.t
185 test-merge-revert.t
187 test-merge-revert.t
186 test-merge-revert2.t
188 test-merge-revert2.t
187 test-merge-subrepos.t
189 test-merge-subrepos.t
188 test-merge-symlinks.t
190 test-merge-symlinks.t
189 test-merge-types.t
191 test-merge-types.t
190 test-merge1.t
192 test-merge1.t
191 test-merge10.t
193 test-merge10.t
192 test-merge2.t
194 test-merge2.t
193 test-merge4.t
195 test-merge4.t
194 test-merge5.t
196 test-merge5.t
195 test-merge6.t
197 test-merge6.t
196 test-merge7.t
198 test-merge7.t
197 test-merge8.t
199 test-merge8.t
198 test-merge9.t
200 test-merge9.t
199 test-mq-git.t
201 test-mq-git.t
200 test-mq-pull-from-bundle.t
202 test-mq-pull-from-bundle.t
201 test-mq-qdiff.t
203 test-mq-qdiff.t
202 test-mq-qimport-fail-cleanup.t
204 test-mq-qimport-fail-cleanup.t
203 test-mq-qqueue.t
205 test-mq-qqueue.t
204 test-mq-qrefresh.t
206 test-mq-qrefresh.t
205 test-mq-qsave.t
207 test-mq-qsave.t
206 test-narrow-clone-no-ellipsis.t
208 test-narrow-clone-no-ellipsis.t
207 test-narrow-clone-nonlinear.t
209 test-narrow-clone-nonlinear.t
208 test-narrow-clone.t
210 test-narrow-clone.t
209 test-narrow-commit.t
211 test-narrow-commit.t
210 test-narrow-copies.t
212 test-narrow-copies.t
211 test-narrow-debugrebuilddirstate.t
213 test-narrow-debugrebuilddirstate.t
212 test-narrow-exchange-merges.t
214 test-narrow-exchange-merges.t
213 test-narrow-exchange.t
215 test-narrow-exchange.t
214 test-narrow-merge.t
216 test-narrow-merge.t
215 test-narrow-patch.t
217 test-narrow-patch.t
216 test-narrow-patterns.t
218 test-narrow-patterns.t
217 test-narrow-pull.t
219 test-narrow-pull.t
218 test-narrow-rebase.t
220 test-narrow-rebase.t
219 test-narrow-shallow-merges.t
221 test-narrow-shallow-merges.t
220 test-narrow-shallow.t
222 test-narrow-shallow.t
221 test-narrow-update.t
223 test-narrow-update.t
222 test-newbranch.t
224 test-newbranch.t
223 test-obshistory.t
225 test-obshistory.t
224 test-obsmarker-template.t
226 test-obsmarker-template.t
225 test-obsmarkers-effectflag.t
227 test-obsmarkers-effectflag.t
226 test-obsolete-bundle-strip.t
228 test-obsolete-bundle-strip.t
227 test-obsolete-changeset-exchange.t
229 test-obsolete-changeset-exchange.t
228 test-obsolete-checkheads.t
230 test-obsolete-checkheads.t
229 test-obsolete-distributed.t
231 test-obsolete-distributed.t
230 test-obsolete-tag-cache.t
232 test-obsolete-tag-cache.t
231 test-parents.t
233 test-parents.t
232 test-pathconflicts-merge.t
234 test-pathconflicts-merge.t
233 test-pathconflicts-update.t
235 test-pathconflicts-update.t
234 test-pending.t
236 test-pending.t
235 test-permissions.t
237 test-permissions.t
236 test-phases.t
238 test-phases.t
237 test-pull-branch.t
239 test-pull-branch.t
238 test-pull-http.t
240 test-pull-http.t
239 test-pull-permission.t
241 test-pull-permission.t
240 test-pull-pull-corruption.t
242 test-pull-pull-corruption.t
241 test-pull-r.t
243 test-pull-r.t
242 test-pull-update.t
244 test-pull-update.t
243 test-purge.t
245 test-purge.t
244 test-push-checkheads-partial-C1.t
246 test-push-checkheads-partial-C1.t
245 test-push-checkheads-partial-C2.t
247 test-push-checkheads-partial-C2.t
246 test-push-checkheads-partial-C3.t
248 test-push-checkheads-partial-C3.t
247 test-push-checkheads-partial-C4.t
249 test-push-checkheads-partial-C4.t
248 test-push-checkheads-pruned-B1.t
250 test-push-checkheads-pruned-B1.t
249 test-push-checkheads-pruned-B2.t
251 test-push-checkheads-pruned-B2.t
250 test-push-checkheads-pruned-B3.t
252 test-push-checkheads-pruned-B3.t
251 test-push-checkheads-pruned-B4.t
253 test-push-checkheads-pruned-B4.t
252 test-push-checkheads-pruned-B5.t
254 test-push-checkheads-pruned-B5.t
253 test-push-checkheads-pruned-B6.t
255 test-push-checkheads-pruned-B6.t
254 test-push-checkheads-pruned-B7.t
256 test-push-checkheads-pruned-B7.t
255 test-push-checkheads-pruned-B8.t
257 test-push-checkheads-pruned-B8.t
256 test-push-checkheads-superceed-A1.t
258 test-push-checkheads-superceed-A1.t
257 test-push-checkheads-superceed-A2.t
259 test-push-checkheads-superceed-A2.t
258 test-push-checkheads-superceed-A3.t
260 test-push-checkheads-superceed-A3.t
259 test-push-checkheads-superceed-A4.t
261 test-push-checkheads-superceed-A4.t
260 test-push-checkheads-superceed-A5.t
262 test-push-checkheads-superceed-A5.t
261 test-push-checkheads-superceed-A6.t
263 test-push-checkheads-superceed-A6.t
262 test-push-checkheads-superceed-A7.t
264 test-push-checkheads-superceed-A7.t
263 test-push-checkheads-superceed-A8.t
265 test-push-checkheads-superceed-A8.t
264 test-push-checkheads-unpushed-D1.t
266 test-push-checkheads-unpushed-D1.t
265 test-push-checkheads-unpushed-D2.t
267 test-push-checkheads-unpushed-D2.t
266 test-push-checkheads-unpushed-D3.t
268 test-push-checkheads-unpushed-D3.t
267 test-push-checkheads-unpushed-D4.t
269 test-push-checkheads-unpushed-D4.t
268 test-push-checkheads-unpushed-D5.t
270 test-push-checkheads-unpushed-D5.t
269 test-push-checkheads-unpushed-D6.t
271 test-push-checkheads-unpushed-D6.t
270 test-push-checkheads-unpushed-D7.t
272 test-push-checkheads-unpushed-D7.t
271 test-push-http.t
273 test-push-http.t
272 test-push-warn.t
274 test-push-warn.t
273 test-pushvars.t
275 test-pushvars.t
274 test-rebase-abort.t
276 test-rebase-abort.t
275 test-rebase-base-flag.t
277 test-rebase-base-flag.t
276 test-rebase-bookmarks.t
278 test-rebase-bookmarks.t
277 test-rebase-brute-force.t
279 test-rebase-brute-force.t
278 test-rebase-cache.t
280 test-rebase-cache.t
279 test-rebase-check-restore.t
281 test-rebase-check-restore.t
280 test-rebase-collapse.t
282 test-rebase-collapse.t
281 test-rebase-dest.t
283 test-rebase-dest.t
282 test-rebase-detach.t
284 test-rebase-detach.t
283 test-rebase-emptycommit.t
285 test-rebase-emptycommit.t
284 test-rebase-inmemory.t
286 test-rebase-inmemory.t
285 test-rebase-interruptions.t
287 test-rebase-interruptions.t
286 test-rebase-issue-noparam-single-rev.t
288 test-rebase-issue-noparam-single-rev.t
287 test-rebase-legacy.t
289 test-rebase-legacy.t
288 test-rebase-named-branches.t
290 test-rebase-named-branches.t
289 test-rebase-newancestor.t
291 test-rebase-newancestor.t
290 test-rebase-obsolete.t
292 test-rebase-obsolete.t
291 test-rebase-parameters.t
293 test-rebase-parameters.t
292 test-rebase-partial.t
294 test-rebase-partial.t
293 test-rebase-pull.t
295 test-rebase-pull.t
294 test-rebase-rename.t
296 test-rebase-rename.t
295 test-rebase-scenario-global.t
297 test-rebase-scenario-global.t
296 test-rebase-templates.t
298 test-rebase-templates.t
297 test-rebase-transaction.t
299 test-rebase-transaction.t
298 test-record.t
300 test-record.t
299 test-relink.t
301 test-relink.t
300 test-remove.t
302 test-remove.t
301 test-rename-after-merge.t
303 test-rename-after-merge.t
302 test-rename-dir-merge.t
304 test-rename-dir-merge.t
303 test-rename-merge1.t
305 test-rename-merge1.t
304 test-rename.t
306 test-rename.t
305 test-repair-strip.t
307 test-repair-strip.t
306 test-repo-compengines.t
308 test-repo-compengines.t
307 test-resolve.t
309 test-resolve.t
308 test-revert-flags.t
310 test-revert-flags.t
309 test-revert-unknown.t
311 test-revert-unknown.t
310 test-revlog-ancestry.py
312 test-revlog-ancestry.py
311 test-revlog-group-emptyiter.t
313 test-revlog-group-emptyiter.t
312 test-revlog-mmapindex.t
314 test-revlog-mmapindex.t
313 test-revlog-packentry.t
315 test-revlog-packentry.t
314 test-revset-dirstate-parents.t
316 test-revset-dirstate-parents.t
315 test-revset-outgoing.t
317 test-revset-outgoing.t
316 test-run-tests.py
318 test-run-tests.py
317 test-serve.t
319 test-serve.t
318 test-share.t
320 test-share.t
319 test-show-stack.t
321 test-show-stack.t
320 test-show-work.t
322 test-show-work.t
321 test-show.t
323 test-show.t
322 test-simple-update.t
324 test-simple-update.t
323 test-single-head.t
325 test-single-head.t
324 test-sparse-clear.t
326 test-sparse-clear.t
325 test-sparse-merges.t
327 test-sparse-merges.t
326 test-sparse-requirement.t
328 test-sparse-requirement.t
327 test-sparse-verbose-json.t
329 test-sparse-verbose-json.t
328 test-ssh-clone-r.t
330 test-ssh-clone-r.t
329 test-ssh-proto.t
331 test-ssh-proto.t
330 test-sshserver.py
332 test-sshserver.py
331 test-status-rev.t
333 test-status-rev.t
332 test-status-terse.t
334 test-status-terse.t
333 test-strip-cross.t
335 test-strip-cross.t
334 test-strip.t
336 test-strip.t
335 test-unamend.t
337 test-unamend.t
336 test-uncommit.t
338 test-uncommit.t
337 test-unified-test.t
339 test-unified-test.t
338 test-unrelated-pull.t
340 test-unrelated-pull.t
339 test-up-local-change.t
341 test-up-local-change.t
340 test-update-branches.t
342 test-update-branches.t
341 test-update-dest.t
343 test-update-dest.t
342 test-update-issue1456.t
344 test-update-issue1456.t
343 test-update-names.t
345 test-update-names.t
344 test-update-reverse.t
346 test-update-reverse.t
345 test-url-rev.t
347 test-url-rev.t
346 test-username-newline.t
348 test-username-newline.t
347 test-verify.t
349 test-verify.t
348 test-websub.t
350 test-websub.t
349 test-win32text.t
351 test-win32text.t
350 test-xdg.t
352 test-xdg.t
@@ -1,263 +1,264
1 from __future__ import absolute_import
1 from __future__ import absolute_import
2
2
3 import errno
3 import errno
4 import os
4 import os
5 import posixpath
5 import posixpath
6 import stat
6 import stat
7
7
8 from .i18n import _
8 from .i18n import _
9 from . import (
9 from . import (
10 encoding,
10 encoding,
11 error,
11 error,
12 pycompat,
12 pycompat,
13 util,
13 util,
14 )
14 )
15
15
16 def _lowerclean(s):
16 def _lowerclean(s):
17 return encoding.hfsignoreclean(s.lower())
17 return encoding.hfsignoreclean(s.lower())
18
18
19 class pathauditor(object):
19 class pathauditor(object):
20 '''ensure that a filesystem path contains no banned components.
20 '''ensure that a filesystem path contains no banned components.
21 the following properties of a path are checked:
21 the following properties of a path are checked:
22
22
23 - ends with a directory separator
23 - ends with a directory separator
24 - under top-level .hg
24 - under top-level .hg
25 - starts at the root of a windows drive
25 - starts at the root of a windows drive
26 - contains ".."
26 - contains ".."
27
27
28 More check are also done about the file system states:
28 More check are also done about the file system states:
29 - traverses a symlink (e.g. a/symlink_here/b)
29 - traverses a symlink (e.g. a/symlink_here/b)
30 - inside a nested repository (a callback can be used to approve
30 - inside a nested repository (a callback can be used to approve
31 some nested repositories, e.g., subrepositories)
31 some nested repositories, e.g., subrepositories)
32
32
33 The file system checks are only done when 'realfs' is set to True (the
33 The file system checks are only done when 'realfs' is set to True (the
34 default). They should be disable then we are auditing path for operation on
34 default). They should be disable then we are auditing path for operation on
35 stored history.
35 stored history.
36
36
37 If 'cached' is set to True, audited paths and sub-directories are cached.
37 If 'cached' is set to True, audited paths and sub-directories are cached.
38 Be careful to not keep the cache of unmanaged directories for long because
38 Be careful to not keep the cache of unmanaged directories for long because
39 audited paths may be replaced with symlinks.
39 audited paths may be replaced with symlinks.
40 '''
40 '''
41
41
42 def __init__(self, root, callback=None, realfs=True, cached=False):
42 def __init__(self, root, callback=None, realfs=True, cached=False):
43 self.audited = set()
43 self.audited = set()
44 self.auditeddir = set()
44 self.auditeddir = set()
45 self.root = root
45 self.root = root
46 self._realfs = realfs
46 self._realfs = realfs
47 self._cached = cached
47 self._cached = cached
48 self.callback = callback
48 self.callback = callback
49 if os.path.lexists(root) and not util.fscasesensitive(root):
49 if os.path.lexists(root) and not util.fscasesensitive(root):
50 self.normcase = util.normcase
50 self.normcase = util.normcase
51 else:
51 else:
52 self.normcase = lambda x: x
52 self.normcase = lambda x: x
53
53
54 def __call__(self, path, mode=None):
54 def __call__(self, path, mode=None):
55 '''Check the relative path.
55 '''Check the relative path.
56 path may contain a pattern (e.g. foodir/**.txt)'''
56 path may contain a pattern (e.g. foodir/**.txt)'''
57
57
58 path = util.localpath(path)
58 path = util.localpath(path)
59 normpath = self.normcase(path)
59 normpath = self.normcase(path)
60 if normpath in self.audited:
60 if normpath in self.audited:
61 return
61 return
62 # AIX ignores "/" at end of path, others raise EISDIR.
62 # AIX ignores "/" at end of path, others raise EISDIR.
63 if util.endswithsep(path):
63 if util.endswithsep(path):
64 raise error.Abort(_("path ends in directory separator: %s") % path)
64 raise error.Abort(_("path ends in directory separator: %s") % path)
65 parts = util.splitpath(path)
65 parts = util.splitpath(path)
66 if (os.path.splitdrive(path)[0]
66 if (os.path.splitdrive(path)[0]
67 or _lowerclean(parts[0]) in ('.hg', '.hg.', '')
67 or _lowerclean(parts[0]) in ('.hg', '.hg.', '')
68 or pycompat.ospardir in parts):
68 or pycompat.ospardir in parts):
69 raise error.Abort(_("path contains illegal component: %s") % path)
69 raise error.Abort(_("path contains illegal component: %s") % path)
70 # Windows shortname aliases
70 # Windows shortname aliases
71 for p in parts:
71 for p in parts:
72 if "~" in p:
72 if "~" in p:
73 first, last = p.split("~", 1)
73 first, last = p.split("~", 1)
74 if last.isdigit() and first.upper() in ["HG", "HG8B6C"]:
74 if last.isdigit() and first.upper() in ["HG", "HG8B6C"]:
75 raise error.Abort(_("path contains illegal component: %s")
75 raise error.Abort(_("path contains illegal component: %s")
76 % path)
76 % path)
77 if '.hg' in _lowerclean(path):
77 if '.hg' in _lowerclean(path):
78 lparts = [_lowerclean(p.lower()) for p in parts]
78 lparts = [_lowerclean(p.lower()) for p in parts]
79 for p in '.hg', '.hg.':
79 for p in '.hg', '.hg.':
80 if p in lparts[1:]:
80 if p in lparts[1:]:
81 pos = lparts.index(p)
81 pos = lparts.index(p)
82 base = os.path.join(*parts[:pos])
82 base = os.path.join(*parts[:pos])
83 raise error.Abort(_("path '%s' is inside nested repo %r")
83 raise error.Abort(_("path '%s' is inside nested repo %r")
84 % (path, base))
84 % (path, pycompat.bytestr(base)))
85
85
86 normparts = util.splitpath(normpath)
86 normparts = util.splitpath(normpath)
87 assert len(parts) == len(normparts)
87 assert len(parts) == len(normparts)
88
88
89 parts.pop()
89 parts.pop()
90 normparts.pop()
90 normparts.pop()
91 prefixes = []
91 prefixes = []
92 # It's important that we check the path parts starting from the root.
92 # It's important that we check the path parts starting from the root.
93 # This means we won't accidentally traverse a symlink into some other
93 # This means we won't accidentally traverse a symlink into some other
94 # filesystem (which is potentially expensive to access).
94 # filesystem (which is potentially expensive to access).
95 for i in range(len(parts)):
95 for i in range(len(parts)):
96 prefix = pycompat.ossep.join(parts[:i + 1])
96 prefix = pycompat.ossep.join(parts[:i + 1])
97 normprefix = pycompat.ossep.join(normparts[:i + 1])
97 normprefix = pycompat.ossep.join(normparts[:i + 1])
98 if normprefix in self.auditeddir:
98 if normprefix in self.auditeddir:
99 continue
99 continue
100 if self._realfs:
100 if self._realfs:
101 self._checkfs(prefix, path)
101 self._checkfs(prefix, path)
102 prefixes.append(normprefix)
102 prefixes.append(normprefix)
103
103
104 if self._cached:
104 if self._cached:
105 self.audited.add(normpath)
105 self.audited.add(normpath)
106 # only add prefixes to the cache after checking everything: we don't
106 # only add prefixes to the cache after checking everything: we don't
107 # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
107 # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
108 self.auditeddir.update(prefixes)
108 self.auditeddir.update(prefixes)
109
109
110 def _checkfs(self, prefix, path):
110 def _checkfs(self, prefix, path):
111 """raise exception if a file system backed check fails"""
111 """raise exception if a file system backed check fails"""
112 curpath = os.path.join(self.root, prefix)
112 curpath = os.path.join(self.root, prefix)
113 try:
113 try:
114 st = os.lstat(curpath)
114 st = os.lstat(curpath)
115 except OSError as err:
115 except OSError as err:
116 # EINVAL can be raised as invalid path syntax under win32.
116 # EINVAL can be raised as invalid path syntax under win32.
117 # They must be ignored for patterns can be checked too.
117 # They must be ignored for patterns can be checked too.
118 if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
118 if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
119 raise
119 raise
120 else:
120 else:
121 if stat.S_ISLNK(st.st_mode):
121 if stat.S_ISLNK(st.st_mode):
122 msg = _('path %r traverses symbolic link %r') % (path, prefix)
122 msg = (_('path %r traverses symbolic link %r')
123 % (pycompat.bytestr(path), pycompat.bytestr(prefix)))
123 raise error.Abort(msg)
124 raise error.Abort(msg)
124 elif (stat.S_ISDIR(st.st_mode) and
125 elif (stat.S_ISDIR(st.st_mode) and
125 os.path.isdir(os.path.join(curpath, '.hg'))):
126 os.path.isdir(os.path.join(curpath, '.hg'))):
126 if not self.callback or not self.callback(curpath):
127 if not self.callback or not self.callback(curpath):
127 msg = _("path '%s' is inside nested repo %r")
128 msg = _("path '%s' is inside nested repo %r")
128 raise error.Abort(msg % (path, prefix))
129 raise error.Abort(msg % (path, pycompat.bytestr(prefix)))
129
130
130 def check(self, path):
131 def check(self, path):
131 try:
132 try:
132 self(path)
133 self(path)
133 return True
134 return True
134 except (OSError, error.Abort):
135 except (OSError, error.Abort):
135 return False
136 return False
136
137
137 def canonpath(root, cwd, myname, auditor=None):
138 def canonpath(root, cwd, myname, auditor=None):
138 '''return the canonical path of myname, given cwd and root
139 '''return the canonical path of myname, given cwd and root
139
140
140 >>> def check(root, cwd, myname):
141 >>> def check(root, cwd, myname):
141 ... a = pathauditor(root, realfs=False)
142 ... a = pathauditor(root, realfs=False)
142 ... try:
143 ... try:
143 ... return canonpath(root, cwd, myname, a)
144 ... return canonpath(root, cwd, myname, a)
144 ... except error.Abort:
145 ... except error.Abort:
145 ... return 'aborted'
146 ... return 'aborted'
146 >>> def unixonly(root, cwd, myname, expected='aborted'):
147 >>> def unixonly(root, cwd, myname, expected='aborted'):
147 ... if pycompat.iswindows:
148 ... if pycompat.iswindows:
148 ... return expected
149 ... return expected
149 ... return check(root, cwd, myname)
150 ... return check(root, cwd, myname)
150 >>> def winonly(root, cwd, myname, expected='aborted'):
151 >>> def winonly(root, cwd, myname, expected='aborted'):
151 ... if not pycompat.iswindows:
152 ... if not pycompat.iswindows:
152 ... return expected
153 ... return expected
153 ... return check(root, cwd, myname)
154 ... return check(root, cwd, myname)
154 >>> winonly(b'd:\\\\repo', b'c:\\\\dir', b'filename')
155 >>> winonly(b'd:\\\\repo', b'c:\\\\dir', b'filename')
155 'aborted'
156 'aborted'
156 >>> winonly(b'c:\\\\repo', b'c:\\\\dir', b'filename')
157 >>> winonly(b'c:\\\\repo', b'c:\\\\dir', b'filename')
157 'aborted'
158 'aborted'
158 >>> winonly(b'c:\\\\repo', b'c:\\\\', b'filename')
159 >>> winonly(b'c:\\\\repo', b'c:\\\\', b'filename')
159 'aborted'
160 'aborted'
160 >>> winonly(b'c:\\\\repo', b'c:\\\\', b'repo\\\\filename',
161 >>> winonly(b'c:\\\\repo', b'c:\\\\', b'repo\\\\filename',
161 ... b'filename')
162 ... b'filename')
162 'filename'
163 'filename'
163 >>> winonly(b'c:\\\\repo', b'c:\\\\repo', b'filename', b'filename')
164 >>> winonly(b'c:\\\\repo', b'c:\\\\repo', b'filename', b'filename')
164 'filename'
165 'filename'
165 >>> winonly(b'c:\\\\repo', b'c:\\\\repo\\\\subdir', b'filename',
166 >>> winonly(b'c:\\\\repo', b'c:\\\\repo\\\\subdir', b'filename',
166 ... b'subdir/filename')
167 ... b'subdir/filename')
167 'subdir/filename'
168 'subdir/filename'
168 >>> unixonly(b'/repo', b'/dir', b'filename')
169 >>> unixonly(b'/repo', b'/dir', b'filename')
169 'aborted'
170 'aborted'
170 >>> unixonly(b'/repo', b'/', b'filename')
171 >>> unixonly(b'/repo', b'/', b'filename')
171 'aborted'
172 'aborted'
172 >>> unixonly(b'/repo', b'/', b'repo/filename', b'filename')
173 >>> unixonly(b'/repo', b'/', b'repo/filename', b'filename')
173 'filename'
174 'filename'
174 >>> unixonly(b'/repo', b'/repo', b'filename', b'filename')
175 >>> unixonly(b'/repo', b'/repo', b'filename', b'filename')
175 'filename'
176 'filename'
176 >>> unixonly(b'/repo', b'/repo/subdir', b'filename', b'subdir/filename')
177 >>> unixonly(b'/repo', b'/repo/subdir', b'filename', b'subdir/filename')
177 'subdir/filename'
178 'subdir/filename'
178 '''
179 '''
179 if util.endswithsep(root):
180 if util.endswithsep(root):
180 rootsep = root
181 rootsep = root
181 else:
182 else:
182 rootsep = root + pycompat.ossep
183 rootsep = root + pycompat.ossep
183 name = myname
184 name = myname
184 if not os.path.isabs(name):
185 if not os.path.isabs(name):
185 name = os.path.join(root, cwd, name)
186 name = os.path.join(root, cwd, name)
186 name = os.path.normpath(name)
187 name = os.path.normpath(name)
187 if auditor is None:
188 if auditor is None:
188 auditor = pathauditor(root)
189 auditor = pathauditor(root)
189 if name != rootsep and name.startswith(rootsep):
190 if name != rootsep and name.startswith(rootsep):
190 name = name[len(rootsep):]
191 name = name[len(rootsep):]
191 auditor(name)
192 auditor(name)
192 return util.pconvert(name)
193 return util.pconvert(name)
193 elif name == root:
194 elif name == root:
194 return ''
195 return ''
195 else:
196 else:
196 # Determine whether `name' is in the hierarchy at or beneath `root',
197 # Determine whether `name' is in the hierarchy at or beneath `root',
197 # by iterating name=dirname(name) until that causes no change (can't
198 # by iterating name=dirname(name) until that causes no change (can't
198 # check name == '/', because that doesn't work on windows). The list
199 # check name == '/', because that doesn't work on windows). The list
199 # `rel' holds the reversed list of components making up the relative
200 # `rel' holds the reversed list of components making up the relative
200 # file name we want.
201 # file name we want.
201 rel = []
202 rel = []
202 while True:
203 while True:
203 try:
204 try:
204 s = util.samefile(name, root)
205 s = util.samefile(name, root)
205 except OSError:
206 except OSError:
206 s = False
207 s = False
207 if s:
208 if s:
208 if not rel:
209 if not rel:
209 # name was actually the same as root (maybe a symlink)
210 # name was actually the same as root (maybe a symlink)
210 return ''
211 return ''
211 rel.reverse()
212 rel.reverse()
212 name = os.path.join(*rel)
213 name = os.path.join(*rel)
213 auditor(name)
214 auditor(name)
214 return util.pconvert(name)
215 return util.pconvert(name)
215 dirname, basename = util.split(name)
216 dirname, basename = util.split(name)
216 rel.append(basename)
217 rel.append(basename)
217 if dirname == name:
218 if dirname == name:
218 break
219 break
219 name = dirname
220 name = dirname
220
221
221 # A common mistake is to use -R, but specify a file relative to the repo
222 # A common mistake is to use -R, but specify a file relative to the repo
222 # instead of cwd. Detect that case, and provide a hint to the user.
223 # instead of cwd. Detect that case, and provide a hint to the user.
223 hint = None
224 hint = None
224 try:
225 try:
225 if cwd != root:
226 if cwd != root:
226 canonpath(root, root, myname, auditor)
227 canonpath(root, root, myname, auditor)
227 relpath = util.pathto(root, cwd, '')
228 relpath = util.pathto(root, cwd, '')
228 if relpath[-1] == pycompat.ossep:
229 if relpath[-1] == pycompat.ossep:
229 relpath = relpath[:-1]
230 relpath = relpath[:-1]
230 hint = (_("consider using '--cwd %s'") % relpath)
231 hint = (_("consider using '--cwd %s'") % relpath)
231 except error.Abort:
232 except error.Abort:
232 pass
233 pass
233
234
234 raise error.Abort(_("%s not under root '%s'") % (myname, root),
235 raise error.Abort(_("%s not under root '%s'") % (myname, root),
235 hint=hint)
236 hint=hint)
236
237
237 def normasprefix(path):
238 def normasprefix(path):
238 '''normalize the specified path as path prefix
239 '''normalize the specified path as path prefix
239
240
240 Returned value can be used safely for "p.startswith(prefix)",
241 Returned value can be used safely for "p.startswith(prefix)",
241 "p[len(prefix):]", and so on.
242 "p[len(prefix):]", and so on.
242
243
243 For efficiency, this expects "path" argument to be already
244 For efficiency, this expects "path" argument to be already
244 normalized by "os.path.normpath", "os.path.realpath", and so on.
245 normalized by "os.path.normpath", "os.path.realpath", and so on.
245
246
246 See also issue3033 for detail about need of this function.
247 See also issue3033 for detail about need of this function.
247
248
248 >>> normasprefix(b'/foo/bar').replace(pycompat.ossep, b'/')
249 >>> normasprefix(b'/foo/bar').replace(pycompat.ossep, b'/')
249 '/foo/bar/'
250 '/foo/bar/'
250 >>> normasprefix(b'/').replace(pycompat.ossep, b'/')
251 >>> normasprefix(b'/').replace(pycompat.ossep, b'/')
251 '/'
252 '/'
252 '''
253 '''
253 d, p = os.path.splitdrive(path)
254 d, p = os.path.splitdrive(path)
254 if len(p) != len(pycompat.ossep):
255 if len(p) != len(pycompat.ossep):
255 return path + pycompat.ossep
256 return path + pycompat.ossep
256 else:
257 else:
257 return path
258 return path
258
259
259 # forward two methods from posixpath that do what we need, but we'd
260 # forward two methods from posixpath that do what we need, but we'd
260 # rather not let our internals know that we're thinking in posix terms
261 # rather not let our internals know that we're thinking in posix terms
261 # - instead we'll let them be oblivious.
262 # - instead we'll let them be oblivious.
262 join = posixpath.join
263 join = posixpath.join
263 dirname = posixpath.dirname
264 dirname = posixpath.dirname
General Comments 0
You need to be logged in to leave comments. Login now