comparison mercurial/vfs.py @ 40796:03bca908d9fb

vfs: add option to not create parent directories implicitly In blackbox, we don't want to create a ".hg" directory by mistake. This provides a race-safe option to achieve that.
author Yuya Nishihara <yuya@tcha.org>
date Tue, 20 Nov 2018 22:31:12 +0900
parents 34f15db81cf0
children e10adebf8176
comparison
equal deleted inserted replaced
40795:e1c3a2e9df59 40796:03bca908d9fb
343 if r: 343 if r:
344 raise error.Abort("%s: %r" % (r, path)) 344 raise error.Abort("%s: %r" % (r, path))
345 self.audit(path, mode=mode) 345 self.audit(path, mode=mode)
346 346
347 def __call__(self, path, mode="r", atomictemp=False, notindexed=False, 347 def __call__(self, path, mode="r", atomictemp=False, notindexed=False,
348 backgroundclose=False, checkambig=False, auditpath=True): 348 backgroundclose=False, checkambig=False, auditpath=True,
349 makeparentdirs=True):
349 '''Open ``path`` file, which is relative to vfs root. 350 '''Open ``path`` file, which is relative to vfs root.
350 351
351 Newly created directories are marked as "not to be indexed by 352 By default, parent directories are created as needed. Newly created
352 the content indexing service", if ``notindexed`` is specified 353 directories are marked as "not to be indexed by the content indexing
353 for "write" mode access. 354 service", if ``notindexed`` is specified for "write" mode access.
355 Set ``makeparentdirs=False`` to not create directories implicitly.
354 356
355 If ``backgroundclose`` is passed, the file may be closed asynchronously. 357 If ``backgroundclose`` is passed, the file may be closed asynchronously.
356 It can only be used if the ``self.backgroundclosing()`` context manager 358 It can only be used if the ``self.backgroundclosing()`` context manager
357 is active. This should only be specified if the following criteria hold: 359 is active. This should only be specified if the following criteria hold:
358 360
387 dirname, basename = util.split(f) 389 dirname, basename = util.split(f)
388 # If basename is empty, then the path is malformed because it points 390 # If basename is empty, then the path is malformed because it points
389 # to a directory. Let the posixfile() call below raise IOError. 391 # to a directory. Let the posixfile() call below raise IOError.
390 if basename: 392 if basename:
391 if atomictemp: 393 if atomictemp:
392 util.makedirs(dirname, self.createmode, notindexed) 394 if makeparentdirs:
395 util.makedirs(dirname, self.createmode, notindexed)
393 return util.atomictempfile(f, mode, self.createmode, 396 return util.atomictempfile(f, mode, self.createmode,
394 checkambig=checkambig) 397 checkambig=checkambig)
395 try: 398 try:
396 if 'w' in mode: 399 if 'w' in mode:
397 util.unlink(f) 400 util.unlink(f)
405 nlink = 2 # force mktempcopy (issue1922) 408 nlink = 2 # force mktempcopy (issue1922)
406 except (OSError, IOError) as e: 409 except (OSError, IOError) as e:
407 if e.errno != errno.ENOENT: 410 if e.errno != errno.ENOENT:
408 raise 411 raise
409 nlink = 0 412 nlink = 0
410 util.makedirs(dirname, self.createmode, notindexed) 413 if makeparentdirs:
414 util.makedirs(dirname, self.createmode, notindexed)
411 if nlink > 0: 415 if nlink > 0:
412 if self._trustnlink is None: 416 if self._trustnlink is None:
413 self._trustnlink = nlink > 1 or util.checknlink(f) 417 self._trustnlink = nlink > 1 or util.checknlink(f)
414 if nlink > 1 or not self._trustnlink: 418 if nlink > 1 or not self._trustnlink:
415 util.rename(util.mktempcopy(f), f) 419 util.rename(util.mktempcopy(f), f)