##// END OF EJS Templates
py3: use bytes.endswith() instead of bytes[n]
Yuya Nishihara -
r38611:21be76e0 default
parent child Browse files
Show More
@@ -1,530 +1,531 b''
1 1 test-abort-checkin.t
2 2 test-add.t
3 3 test-addremove-similar.t
4 4 test-addremove.t
5 test-alias.t
5 6 test-amend-subrepo.t
6 7 test-amend.t
7 8 test-ancestor.py
8 9 test-annotate.py
9 10 test-annotate.t
10 11 test-archive-symlinks.t
11 12 test-atomictempfile.py
12 13 test-audit-path.t
13 14 test-audit-subrepo.t
14 15 test-automv.t
15 16 test-backout.t
16 17 test-backwards-remove.t
17 18 test-basic.t
18 19 test-bheads.t
19 20 test-bisect.t
20 21 test-bisect2.t
21 22 test-bisect3.t
22 23 test-blackbox.t
23 24 test-bookmarks-current.t
24 25 test-bookmarks-merge.t
25 26 test-bookmarks-rebase.t
26 27 test-bookmarks-strip.t
27 28 test-bookmarks.t
28 29 test-branch-change.t
29 30 test-branch-option.t
30 31 test-branch-tag-confict.t
31 32 test-branches.t
32 33 test-bundle-phases.t
33 34 test-bundle-type.t
34 35 test-bundle-vs-outgoing.t
35 36 test-bundle2-multiple-changegroups.t
36 37 test-bundle2-pushback.t
37 38 test-cappedreader.py
38 39 test-casecollision.t
39 40 test-cat.t
40 41 test-cbor.py
41 42 test-censor.t
42 43 test-changelog-exec.t
43 44 test-check-commit.t
44 45 test-check-execute.t
45 46 test-check-interfaces.py
46 47 test-check-module-imports.t
47 48 test-check-pyflakes.t
48 49 test-check-pylint.t
49 50 test-check-shbang.t
50 51 test-children.t
51 52 test-clone-cgi.t
52 53 test-clone-pull-corruption.t
53 54 test-clone-r.t
54 55 test-clone-update-order.t
55 56 test-commit-amend.t
56 57 test-commit-interactive.t
57 58 test-commit-multiple.t
58 59 test-commit-unresolved.t
59 60 test-commit.t
60 61 test-committer.t
61 62 test-completion.t
62 63 test-config-env.py
63 64 test-config.t
64 65 test-conflict.t
65 66 test-confused-revert.t
66 67 test-context.py
67 68 test-contrib-check-code.t
68 69 test-contrib-check-commit.t
69 70 test-convert-authormap.t
70 71 test-convert-clonebranches.t
71 72 test-convert-cvs-branch.t
72 73 test-convert-cvs-detectmerge.t
73 74 test-convert-cvs-synthetic.t
74 75 test-convert-cvs.t
75 76 test-convert-cvsnt-mergepoints.t
76 77 test-convert-datesort.t
77 78 test-convert-filemap.t
78 79 test-convert-hg-sink.t
79 80 test-convert-hg-source.t
80 81 test-convert-hg-startrev.t
81 82 test-convert-splicemap.t
82 83 test-convert-tagsbranch-topology.t
83 84 test-copy-move-merge.t
84 85 test-copy.t
85 86 test-copytrace-heuristics.t
86 87 test-debugbuilddag.t
87 88 test-debugbundle.t
88 89 test-debugextensions.t
89 90 test-debugindexdot.t
90 91 test-debugrename.t
91 92 test-default-push.t
92 93 test-diff-antipatience.t
93 94 test-diff-binary-file.t
94 95 test-diff-change.t
95 96 test-diff-copy-depth.t
96 97 test-diff-hashes.t
97 98 test-diff-ignore-whitespace.t
98 99 test-diff-indent-heuristic.t
99 100 test-diff-issue2761.t
100 101 test-diff-newlines.t
101 102 test-diff-reverse.t
102 103 test-diff-subdir.t
103 104 test-diff-unified.t
104 105 test-diff-upgrade.t
105 106 test-diffdir.t
106 107 test-diffstat.t
107 108 test-directaccess.t
108 109 test-dirstate-backup.t
109 110 test-dirstate-nonnormalset.t
110 111 test-dirstate.t
111 112 test-dispatch.py
112 113 test-doctest.py
113 114 test-double-merge.t
114 115 test-drawdag.t
115 116 test-duplicateoptions.py
116 117 test-editor-filename.t
117 118 test-empty-dir.t
118 119 test-empty-file.t
119 120 test-empty-group.t
120 121 test-empty.t
121 122 test-encode.t
122 123 test-encoding-func.py
123 124 test-encoding.t
124 125 test-eol-add.t
125 126 test-eol-clone.t
126 127 test-eol-hook.t
127 128 test-eol-patch.t
128 129 test-eol-tag.t
129 130 test-eol-update.t
130 131 test-eol.t
131 132 test-eolfilename.t
132 133 test-excessive-merge.t
133 134 test-exchange-obsmarkers-case-A1.t
134 135 test-exchange-obsmarkers-case-A2.t
135 136 test-exchange-obsmarkers-case-A3.t
136 137 test-exchange-obsmarkers-case-A4.t
137 138 test-exchange-obsmarkers-case-A5.t
138 139 test-exchange-obsmarkers-case-A6.t
139 140 test-exchange-obsmarkers-case-A7.t
140 141 test-exchange-obsmarkers-case-B1.t
141 142 test-exchange-obsmarkers-case-B2.t
142 143 test-exchange-obsmarkers-case-B3.t
143 144 test-exchange-obsmarkers-case-B4.t
144 145 test-exchange-obsmarkers-case-B5.t
145 146 test-exchange-obsmarkers-case-B6.t
146 147 test-exchange-obsmarkers-case-B7.t
147 148 test-exchange-obsmarkers-case-C1.t
148 149 test-exchange-obsmarkers-case-C2.t
149 150 test-exchange-obsmarkers-case-C3.t
150 151 test-exchange-obsmarkers-case-C4.t
151 152 test-exchange-obsmarkers-case-D1.t
152 153 test-exchange-obsmarkers-case-D2.t
153 154 test-exchange-obsmarkers-case-D3.t
154 155 test-exchange-obsmarkers-case-D4.t
155 156 test-execute-bit.t
156 157 test-export.t
157 158 test-extdata.t
158 159 test-extdiff.t
159 160 test-extensions-afterloaded.t
160 161 test-extensions-wrapfunction.py
161 162 test-extra-filelog-entry.t
162 163 test-fetch.t
163 164 test-filebranch.t
164 165 test-filecache.py
165 166 test-filelog.py
166 167 test-fileset-generated.t
167 168 test-fileset.t
168 169 test-fix-topology.t
169 170 test-flags.t
170 171 test-generaldelta.t
171 172 test-getbundle.t
172 173 test-git-export.t
173 174 test-glog-topological.t
174 175 test-gpg.t
175 176 test-graft.t
176 177 test-hg-parseurl.py
177 178 test-hghave.t
178 179 test-hgignore.t
179 180 test-hgk.t
180 181 test-hgrc.t
181 182 test-hgweb-bundle.t
182 183 test-hgweb-descend-empties.t
183 184 test-hgweb-empty.t
184 185 test-hgweb-removed.t
185 186 test-hgwebdir-paths.py
186 187 test-hgwebdirsym.t
187 188 test-histedit-arguments.t
188 189 test-histedit-base.t
189 190 test-histedit-bookmark-motion.t
190 191 test-histedit-commute.t
191 192 test-histedit-drop.t
192 193 test-histedit-edit.t
193 194 test-histedit-fold-non-commute.t
194 195 test-histedit-fold.t
195 196 test-histedit-no-change.t
196 197 test-histedit-non-commute-abort.t
197 198 test-histedit-non-commute.t
198 199 test-histedit-obsolete.t
199 200 test-histedit-outgoing.t
200 201 test-histedit-templates.t
201 202 test-http-branchmap.t
202 203 test-http-bundle1.t
203 204 test-http-clone-r.t
204 205 test-http.t
205 206 test-hybridencode.py
206 207 test-identify.t
207 208 test-impexp-branch.t
208 209 test-import-bypass.t
209 210 test-import-eol.t
210 211 test-import-merge.t
211 212 test-import-unknown.t
212 213 test-import.t
213 214 test-imports-checker.t
214 215 test-incoming-outgoing.t
215 216 test-inherit-mode.t
216 217 test-init.t
217 218 test-issue1089.t
218 219 test-issue1102.t
219 220 test-issue1175.t
220 221 test-issue1306.t
221 222 test-issue1438.t
222 223 test-issue1502.t
223 224 test-issue1802.t
224 225 test-issue1877.t
225 226 test-issue1993.t
226 227 test-issue2137.t
227 228 test-issue3084.t
228 229 test-issue4074.t
229 230 test-issue522.t
230 231 test-issue586.t
231 232 test-issue612.t
232 233 test-issue619.t
233 234 test-issue660.t
234 235 test-issue672.t
235 236 test-issue842.t
236 237 test-journal-exists.t
237 238 test-journal-share.t
238 239 test-journal.t
239 240 test-known.t
240 241 test-largefiles-cache.t
241 242 test-largefiles-misc.t
242 243 test-largefiles-small-disk.t
243 244 test-largefiles-update.t
244 245 test-largefiles.t
245 246 test-lfs-largefiles.t
246 247 test-lfs-pointer.py
247 248 test-linerange.py
248 249 test-locate.t
249 250 test-lock-badness.t
250 251 test-log-linerange.t
251 252 test-log.t
252 253 test-logexchange.t
253 254 test-lrucachedict.py
254 255 test-mactext.t
255 256 test-mailmap.t
256 257 test-manifest-merging.t
257 258 test-manifest.py
258 259 test-manifest.t
259 260 test-match.py
260 261 test-mdiff.py
261 262 test-merge-changedelete.t
262 263 test-merge-closedheads.t
263 264 test-merge-commit.t
264 265 test-merge-criss-cross.t
265 266 test-merge-default.t
266 267 test-merge-force.t
267 268 test-merge-halt.t
268 269 test-merge-internal-tools-pattern.t
269 270 test-merge-local.t
270 271 test-merge-remove.t
271 272 test-merge-revert.t
272 273 test-merge-revert2.t
273 274 test-merge-subrepos.t
274 275 test-merge-symlinks.t
275 276 test-merge-tools.t
276 277 test-merge-types.t
277 278 test-merge1.t
278 279 test-merge10.t
279 280 test-merge2.t
280 281 test-merge4.t
281 282 test-merge5.t
282 283 test-merge6.t
283 284 test-merge7.t
284 285 test-merge8.t
285 286 test-merge9.t
286 287 test-minifileset.py
287 288 test-minirst.py
288 289 test-mq-git.t
289 290 test-mq-header-date.t
290 291 test-mq-header-from.t
291 292 test-mq-merge.t
292 293 test-mq-pull-from-bundle.t
293 294 test-mq-qclone-http.t
294 295 test-mq-qdelete.t
295 296 test-mq-qdiff.t
296 297 test-mq-qfold.t
297 298 test-mq-qgoto.t
298 299 test-mq-qimport-fail-cleanup.t
299 300 test-mq-qnew.t
300 301 test-mq-qpush-exact.t
301 302 test-mq-qqueue.t
302 303 test-mq-qrefresh-interactive.t
303 304 test-mq-qrefresh-replace-log-message.t
304 305 test-mq-qrefresh.t
305 306 test-mq-qrename.t
306 307 test-mq-qsave.t
307 308 test-mq-safety.t
308 309 test-mq-subrepo.t
309 310 test-mq-symlinks.t
310 311 test-mv-cp-st-diff.t
311 312 test-narrow-archive.t
312 313 test-narrow-clone-no-ellipsis.t
313 314 test-narrow-clone-non-narrow-server.t
314 315 test-narrow-clone-nonlinear.t
315 316 test-narrow-clone.t
316 317 test-narrow-commit.t
317 318 test-narrow-copies.t
318 319 test-narrow-debugcommands.t
319 320 test-narrow-debugrebuilddirstate.t
320 321 test-narrow-exchange-merges.t
321 322 test-narrow-exchange.t
322 323 test-narrow-expanddirstate.t
323 324 test-narrow-merge.t
324 325 test-narrow-patch.t
325 326 test-narrow-patterns.t
326 327 test-narrow-pull.t
327 328 test-narrow-rebase.t
328 329 test-narrow-shallow-merges.t
329 330 test-narrow-shallow.t
330 331 test-narrow-strip.t
331 332 test-narrow-update.t
332 333 test-narrow-widen.t
333 334 test-narrow.t
334 335 test-nested-repo.t
335 336 test-newbranch.t
336 337 test-obshistory.t
337 338 test-obsmarker-template.t
338 339 test-obsmarkers-effectflag.t
339 340 test-obsolete-bundle-strip.t
340 341 test-obsolete-changeset-exchange.t
341 342 test-obsolete-checkheads.t
342 343 test-obsolete-distributed.t
343 344 test-obsolete-divergent.t
344 345 test-obsolete-tag-cache.t
345 346 test-pager.t
346 347 test-parents.t
347 348 test-parseindex2.py
348 349 test-patch-offset.t
349 350 test-patch.t
350 351 test-pathconflicts-merge.t
351 352 test-pathconflicts-update.t
352 353 test-pathencode.py
353 354 test-pending.t
354 355 test-permissions.t
355 356 test-phases.t
356 357 test-pull-branch.t
357 358 test-pull-http.t
358 359 test-pull-permission.t
359 360 test-pull-pull-corruption.t
360 361 test-pull-r.t
361 362 test-pull-update.t
362 363 test-pull.t
363 364 test-purge.t
364 365 test-push-checkheads-partial-C1.t
365 366 test-push-checkheads-partial-C2.t
366 367 test-push-checkheads-partial-C3.t
367 368 test-push-checkheads-partial-C4.t
368 369 test-push-checkheads-pruned-B1.t
369 370 test-push-checkheads-pruned-B2.t
370 371 test-push-checkheads-pruned-B3.t
371 372 test-push-checkheads-pruned-B4.t
372 373 test-push-checkheads-pruned-B5.t
373 374 test-push-checkheads-pruned-B6.t
374 375 test-push-checkheads-pruned-B7.t
375 376 test-push-checkheads-pruned-B8.t
376 377 test-push-checkheads-superceed-A1.t
377 378 test-push-checkheads-superceed-A2.t
378 379 test-push-checkheads-superceed-A3.t
379 380 test-push-checkheads-superceed-A4.t
380 381 test-push-checkheads-superceed-A5.t
381 382 test-push-checkheads-superceed-A6.t
382 383 test-push-checkheads-superceed-A7.t
383 384 test-push-checkheads-superceed-A8.t
384 385 test-push-checkheads-unpushed-D1.t
385 386 test-push-checkheads-unpushed-D2.t
386 387 test-push-checkheads-unpushed-D3.t
387 388 test-push-checkheads-unpushed-D4.t
388 389 test-push-checkheads-unpushed-D5.t
389 390 test-push-checkheads-unpushed-D6.t
390 391 test-push-checkheads-unpushed-D7.t
391 392 test-push-http.t
392 393 test-push-warn.t
393 394 test-push.t
394 395 test-pushvars.t
395 396 test-qrecord.t
396 397 test-rebase-abort.t
397 398 test-rebase-base-flag.t
398 399 test-rebase-bookmarks.t
399 400 test-rebase-brute-force.t
400 401 test-rebase-cache.t
401 402 test-rebase-check-restore.t
402 403 test-rebase-collapse.t
403 404 test-rebase-conflicts.t
404 405 test-rebase-dest.t
405 406 test-rebase-detach.t
406 407 test-rebase-emptycommit.t
407 408 test-rebase-inmemory.t
408 409 test-rebase-interruptions.t
409 410 test-rebase-issue-noparam-single-rev.t
410 411 test-rebase-legacy.t
411 412 test-rebase-mq-skip.t
412 413 test-rebase-mq.t
413 414 test-rebase-named-branches.t
414 415 test-rebase-newancestor.t
415 416 test-rebase-obsolete.t
416 417 test-rebase-parameters.t
417 418 test-rebase-partial.t
418 419 test-rebase-pull.t
419 420 test-rebase-rename.t
420 421 test-rebase-scenario-global.t
421 422 test-rebase-templates.t
422 423 test-rebase-transaction.t
423 424 test-rebuildstate.t
424 425 test-record.t
425 426 test-relink.t
426 427 test-remove.t
427 428 test-rename-after-merge.t
428 429 test-rename-dir-merge.t
429 430 test-rename-merge1.t
430 431 test-rename.t
431 432 test-repair-strip.t
432 433 test-repo-compengines.t
433 434 test-resolve.t
434 435 test-revert-flags.t
435 436 test-revert-interactive.t
436 437 test-revert-unknown.t
437 438 test-revlog-ancestry.py
438 439 test-revlog-group-emptyiter.t
439 440 test-revlog-mmapindex.t
440 441 test-revlog-packentry.t
441 442 test-revlog-raw.py
442 443 test-revlog-v2.t
443 444 test-revset-dirstate-parents.t
444 445 test-revset-legacy-lookup.t
445 446 test-revset-outgoing.t
446 447 test-rollback.t
447 448 test-run-tests.py
448 449 test-run-tests.t
449 450 test-schemes.t
450 451 test-serve.t
451 452 test-setdiscovery.t
452 453 test-share.t
453 454 test-shelve.t
454 455 test-show-stack.t
455 456 test-show-work.t
456 457 test-show.t
457 458 test-simple-update.t
458 459 test-simplekeyvaluefile.py
459 460 test-simplemerge.py
460 461 test-single-head.t
461 462 test-sparse-clear.t
462 463 test-sparse-clone.t
463 464 test-sparse-import.t
464 465 test-sparse-merges.t
465 466 test-sparse-profiles.t
466 467 test-sparse-requirement.t
467 468 test-sparse-verbose-json.t
468 469 test-sparse.t
469 470 test-split.t
470 471 test-ssh-bundle1.t
471 472 test-ssh-clone-r.t
472 473 test-ssh-proto-unbundle.t
473 474 test-ssh-proto.t
474 475 test-ssh.t
475 476 test-sshserver.py
476 477 test-stack.t
477 478 test-status-inprocess.py
478 479 test-status-rev.t
479 480 test-status-terse.t
480 481 test-strict.t
481 482 test-strip-cross.t
482 483 test-strip.t
483 484 test-subrepo-deep-nested-change.t
484 485 test-subrepo-missing.t
485 486 test-subrepo-paths.t
486 487 test-subrepo-recursion.t
487 488 test-subrepo-relative-path.t
488 489 test-subrepo.t
489 490 test-symlink-os-yes-fs-no.py
490 491 test-symlink-placeholder.t
491 492 test-symlinks.t
492 493 test-tag.t
493 494 test-tags.t
494 495 test-template-basic.t
495 496 test-template-functions.t
496 497 test-template-keywords.t
497 498 test-template-map.t
498 499 test-transplant.t
499 500 test-treemanifest.t
500 501 test-ui-color.py
501 502 test-ui-config.py
502 503 test-ui-verbosity.py
503 504 test-unamend.t
504 505 test-unbundlehash.t
505 506 test-uncommit.t
506 507 test-unified-test.t
507 508 test-unionrepo.t
508 509 test-unrelated-pull.t
509 510 test-up-local-change.t
510 511 test-update-branches.t
511 512 test-update-dest.t
512 513 test-update-issue1456.t
513 514 test-update-names.t
514 515 test-update-reverse.t
515 516 test-upgrade-repo.t
516 517 test-url-download.t
517 518 test-url-rev.t
518 519 test-url.py
519 520 test-username-newline.t
520 521 test-verify.t
521 522 test-walk.t
522 523 test-walkrepo.py
523 524 test-websub.t
524 525 test-win32text.t
525 526 test-wireproto-clientreactor.py
526 527 test-wireproto-framing.py
527 528 test-wireproto-serverreactor.py
528 529 test-wireproto.py
529 530 test-wsgirequest.py
530 531 test-xdg.t
@@ -1,264 +1,264 b''
1 1 from __future__ import absolute_import
2 2
3 3 import errno
4 4 import os
5 5 import posixpath
6 6 import stat
7 7
8 8 from .i18n import _
9 9 from . import (
10 10 encoding,
11 11 error,
12 12 pycompat,
13 13 util,
14 14 )
15 15
16 16 def _lowerclean(s):
17 17 return encoding.hfsignoreclean(s.lower())
18 18
19 19 class pathauditor(object):
20 20 '''ensure that a filesystem path contains no banned components.
21 21 the following properties of a path are checked:
22 22
23 23 - ends with a directory separator
24 24 - under top-level .hg
25 25 - starts at the root of a windows drive
26 26 - contains ".."
27 27
28 28 More check are also done about the file system states:
29 29 - traverses a symlink (e.g. a/symlink_here/b)
30 30 - inside a nested repository (a callback can be used to approve
31 31 some nested repositories, e.g., subrepositories)
32 32
33 33 The file system checks are only done when 'realfs' is set to True (the
34 34 default). They should be disable then we are auditing path for operation on
35 35 stored history.
36 36
37 37 If 'cached' is set to True, audited paths and sub-directories are cached.
38 38 Be careful to not keep the cache of unmanaged directories for long because
39 39 audited paths may be replaced with symlinks.
40 40 '''
41 41
42 42 def __init__(self, root, callback=None, realfs=True, cached=False):
43 43 self.audited = set()
44 44 self.auditeddir = set()
45 45 self.root = root
46 46 self._realfs = realfs
47 47 self._cached = cached
48 48 self.callback = callback
49 49 if os.path.lexists(root) and not util.fscasesensitive(root):
50 50 self.normcase = util.normcase
51 51 else:
52 52 self.normcase = lambda x: x
53 53
54 54 def __call__(self, path, mode=None):
55 55 '''Check the relative path.
56 56 path may contain a pattern (e.g. foodir/**.txt)'''
57 57
58 58 path = util.localpath(path)
59 59 normpath = self.normcase(path)
60 60 if normpath in self.audited:
61 61 return
62 62 # AIX ignores "/" at end of path, others raise EISDIR.
63 63 if util.endswithsep(path):
64 64 raise error.Abort(_("path ends in directory separator: %s") % path)
65 65 parts = util.splitpath(path)
66 66 if (os.path.splitdrive(path)[0]
67 67 or _lowerclean(parts[0]) in ('.hg', '.hg.', '')
68 68 or pycompat.ospardir in parts):
69 69 raise error.Abort(_("path contains illegal component: %s") % path)
70 70 # Windows shortname aliases
71 71 for p in parts:
72 72 if "~" in p:
73 73 first, last = p.split("~", 1)
74 74 if last.isdigit() and first.upper() in ["HG", "HG8B6C"]:
75 75 raise error.Abort(_("path contains illegal component: %s")
76 76 % path)
77 77 if '.hg' in _lowerclean(path):
78 78 lparts = [_lowerclean(p.lower()) for p in parts]
79 79 for p in '.hg', '.hg.':
80 80 if p in lparts[1:]:
81 81 pos = lparts.index(p)
82 82 base = os.path.join(*parts[:pos])
83 83 raise error.Abort(_("path '%s' is inside nested repo %r")
84 84 % (path, pycompat.bytestr(base)))
85 85
86 86 normparts = util.splitpath(normpath)
87 87 assert len(parts) == len(normparts)
88 88
89 89 parts.pop()
90 90 normparts.pop()
91 91 prefixes = []
92 92 # It's important that we check the path parts starting from the root.
93 93 # This means we won't accidentally traverse a symlink into some other
94 94 # filesystem (which is potentially expensive to access).
95 95 for i in range(len(parts)):
96 96 prefix = pycompat.ossep.join(parts[:i + 1])
97 97 normprefix = pycompat.ossep.join(normparts[:i + 1])
98 98 if normprefix in self.auditeddir:
99 99 continue
100 100 if self._realfs:
101 101 self._checkfs(prefix, path)
102 102 prefixes.append(normprefix)
103 103
104 104 if self._cached:
105 105 self.audited.add(normpath)
106 106 # only add prefixes to the cache after checking everything: we don't
107 107 # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
108 108 self.auditeddir.update(prefixes)
109 109
110 110 def _checkfs(self, prefix, path):
111 111 """raise exception if a file system backed check fails"""
112 112 curpath = os.path.join(self.root, prefix)
113 113 try:
114 114 st = os.lstat(curpath)
115 115 except OSError as err:
116 116 # EINVAL can be raised as invalid path syntax under win32.
117 117 # They must be ignored for patterns can be checked too.
118 118 if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
119 119 raise
120 120 else:
121 121 if stat.S_ISLNK(st.st_mode):
122 122 msg = (_('path %r traverses symbolic link %r')
123 123 % (pycompat.bytestr(path), pycompat.bytestr(prefix)))
124 124 raise error.Abort(msg)
125 125 elif (stat.S_ISDIR(st.st_mode) and
126 126 os.path.isdir(os.path.join(curpath, '.hg'))):
127 127 if not self.callback or not self.callback(curpath):
128 128 msg = _("path '%s' is inside nested repo %r")
129 129 raise error.Abort(msg % (path, pycompat.bytestr(prefix)))
130 130
131 131 def check(self, path):
132 132 try:
133 133 self(path)
134 134 return True
135 135 except (OSError, error.Abort):
136 136 return False
137 137
138 138 def canonpath(root, cwd, myname, auditor=None):
139 139 '''return the canonical path of myname, given cwd and root
140 140
141 141 >>> def check(root, cwd, myname):
142 142 ... a = pathauditor(root, realfs=False)
143 143 ... try:
144 144 ... return canonpath(root, cwd, myname, a)
145 145 ... except error.Abort:
146 146 ... return 'aborted'
147 147 >>> def unixonly(root, cwd, myname, expected='aborted'):
148 148 ... if pycompat.iswindows:
149 149 ... return expected
150 150 ... return check(root, cwd, myname)
151 151 >>> def winonly(root, cwd, myname, expected='aborted'):
152 152 ... if not pycompat.iswindows:
153 153 ... return expected
154 154 ... return check(root, cwd, myname)
155 155 >>> winonly(b'd:\\\\repo', b'c:\\\\dir', b'filename')
156 156 'aborted'
157 157 >>> winonly(b'c:\\\\repo', b'c:\\\\dir', b'filename')
158 158 'aborted'
159 159 >>> winonly(b'c:\\\\repo', b'c:\\\\', b'filename')
160 160 'aborted'
161 161 >>> winonly(b'c:\\\\repo', b'c:\\\\', b'repo\\\\filename',
162 162 ... b'filename')
163 163 'filename'
164 164 >>> winonly(b'c:\\\\repo', b'c:\\\\repo', b'filename', b'filename')
165 165 'filename'
166 166 >>> winonly(b'c:\\\\repo', b'c:\\\\repo\\\\subdir', b'filename',
167 167 ... b'subdir/filename')
168 168 'subdir/filename'
169 169 >>> unixonly(b'/repo', b'/dir', b'filename')
170 170 'aborted'
171 171 >>> unixonly(b'/repo', b'/', b'filename')
172 172 'aborted'
173 173 >>> unixonly(b'/repo', b'/', b'repo/filename', b'filename')
174 174 'filename'
175 175 >>> unixonly(b'/repo', b'/repo', b'filename', b'filename')
176 176 'filename'
177 177 >>> unixonly(b'/repo', b'/repo/subdir', b'filename', b'subdir/filename')
178 178 'subdir/filename'
179 179 '''
180 180 if util.endswithsep(root):
181 181 rootsep = root
182 182 else:
183 183 rootsep = root + pycompat.ossep
184 184 name = myname
185 185 if not os.path.isabs(name):
186 186 name = os.path.join(root, cwd, name)
187 187 name = os.path.normpath(name)
188 188 if auditor is None:
189 189 auditor = pathauditor(root)
190 190 if name != rootsep and name.startswith(rootsep):
191 191 name = name[len(rootsep):]
192 192 auditor(name)
193 193 return util.pconvert(name)
194 194 elif name == root:
195 195 return ''
196 196 else:
197 197 # Determine whether `name' is in the hierarchy at or beneath `root',
198 198 # by iterating name=dirname(name) until that causes no change (can't
199 199 # check name == '/', because that doesn't work on windows). The list
200 200 # `rel' holds the reversed list of components making up the relative
201 201 # file name we want.
202 202 rel = []
203 203 while True:
204 204 try:
205 205 s = util.samefile(name, root)
206 206 except OSError:
207 207 s = False
208 208 if s:
209 209 if not rel:
210 210 # name was actually the same as root (maybe a symlink)
211 211 return ''
212 212 rel.reverse()
213 213 name = os.path.join(*rel)
214 214 auditor(name)
215 215 return util.pconvert(name)
216 216 dirname, basename = util.split(name)
217 217 rel.append(basename)
218 218 if dirname == name:
219 219 break
220 220 name = dirname
221 221
222 222 # A common mistake is to use -R, but specify a file relative to the repo
223 223 # instead of cwd. Detect that case, and provide a hint to the user.
224 224 hint = None
225 225 try:
226 226 if cwd != root:
227 227 canonpath(root, root, myname, auditor)
228 228 relpath = util.pathto(root, cwd, '')
229 if relpath[-1] == pycompat.ossep:
229 if relpath.endswith(pycompat.ossep):
230 230 relpath = relpath[:-1]
231 231 hint = (_("consider using '--cwd %s'") % relpath)
232 232 except error.Abort:
233 233 pass
234 234
235 235 raise error.Abort(_("%s not under root '%s'") % (myname, root),
236 236 hint=hint)
237 237
238 238 def normasprefix(path):
239 239 '''normalize the specified path as path prefix
240 240
241 241 Returned value can be used safely for "p.startswith(prefix)",
242 242 "p[len(prefix):]", and so on.
243 243
244 244 For efficiency, this expects "path" argument to be already
245 245 normalized by "os.path.normpath", "os.path.realpath", and so on.
246 246
247 247 See also issue3033 for detail about need of this function.
248 248
249 249 >>> normasprefix(b'/foo/bar').replace(pycompat.ossep, b'/')
250 250 '/foo/bar/'
251 251 >>> normasprefix(b'/').replace(pycompat.ossep, b'/')
252 252 '/'
253 253 '''
254 254 d, p = os.path.splitdrive(path)
255 255 if len(p) != len(pycompat.ossep):
256 256 return path + pycompat.ossep
257 257 else:
258 258 return path
259 259
260 260 # forward two methods from posixpath that do what we need, but we'd
261 261 # rather not let our internals know that we're thinking in posix terms
262 262 # - instead we'll let them be oblivious.
263 263 join = posixpath.join
264 264 dirname = posixpath.dirname
General Comments 0
You need to be logged in to leave comments. Login now