comparison mercurial/util.py @ 2076:d007df6daf8e

Create an atomic opener that does not automatically rename on close The revlog.checkinlinesize() uses an atomic opener to replace the index file after converting it from inline to traditional .i and .d files. If this operation is interrupted, the atomic file class can overwrite a valid file with a partially written one. This patch introduces an atomic opener that does not automatically replace the destination file with the tempfile. This way an interrupted checkinlinesize() call turns into a noop.
author mason@suse.com
date Tue, 04 Apr 2006 16:38:44 -0400
parents 24c604628867
children 345107e167a0
comparison
equal deleted inserted replaced
2075:343aeefb553b 2076:d007df6daf8e
429 fp.close() 429 fp.close()
430 st = os.lstat(name) 430 st = os.lstat(name)
431 os.chmod(temp, st.st_mode) 431 os.chmod(temp, st.st_mode)
432 return temp 432 return temp
433 433
434 class atomicfile(file): 434 class atomictempfile(file):
435 """the file will only be copied on close""" 435 """the file will only be copied when rename is called"""
436 def __init__(self, name, mode, atomic=False): 436 def __init__(self, name, mode):
437 self.__name = name 437 self.__name = name
438 self.temp = mktempcopy(name) 438 self.temp = mktempcopy(name)
439 file.__init__(self, self.temp, mode) 439 file.__init__(self, self.temp, mode)
440 def close(self): 440 def rename(self):
441 if not self.closed: 441 if not self.closed:
442 file.close(self) 442 file.close(self)
443 rename(self.temp, self.__name) 443 rename(self.temp, self.__name)
444 def __del__(self): 444 def __del__(self):
445 self.close() 445 if not self.closed:
446 446 try:
447 def o(path, mode="r", text=False, atomic=False): 447 os.unlink(self.temp)
448 except: pass
449 file.close(self)
450
451 class atomicfile(atomictempfile):
452 """the file will only be copied on close"""
453 def __init__(self, name, mode):
454 atomictempfile.__init__(self, name, mode)
455 def close(self):
456 self.rename()
457 def __del__(self):
458 self.rename()
459
460 def o(path, mode="r", text=False, atomic=False, atomictemp=False):
448 if audit_p: 461 if audit_p:
449 audit_path(path) 462 audit_path(path)
450 f = os.path.join(p, path) 463 f = os.path.join(p, path)
451 464
452 if not text: 465 if not text:
460 if not os.path.isdir(d): 473 if not os.path.isdir(d):
461 os.makedirs(d) 474 os.makedirs(d)
462 else: 475 else:
463 if atomic: 476 if atomic:
464 return atomicfile(f, mode) 477 return atomicfile(f, mode)
478 elif atomictemp:
479 return atomictempfile(f, mode)
465 if nlink > 1: 480 if nlink > 1:
466 rename(mktempcopy(f), f) 481 rename(mktempcopy(f), f)
467 return file(f, mode) 482 return file(f, mode)
468 483
469 return o 484 return o