from bup import _helpers, path, midx, bloom, xstat
from bup.helpers import (Sha1, add_error, chunkyreader, debug1, debug2,
+ fdatasync,
hostname, log, merge_iter, mmap_read, mmap_readwrite,
progress, qprogress, unlink, username, userfullname,
utc_offset_str)
"""Writes Git objects inside a pack file."""
def __init__(self, objcache_maker=_make_objcache, compression_level=1):
self.file = None
+ self.parentfd = None
self.count = 0
self.outbytes = 0
self.filename = None
def _open(self):
if not self.file:
- (fd,name) = tempfile.mkstemp(suffix='.pack', dir=repo('objects'))
+ objdir = dir=repo('objects')
+ fd, name = tempfile.mkstemp(suffix='.pack', dir=objdir)
try:
self.file = os.fdopen(fd, 'w+b')
except:
os.close(fd)
raise
+ try:
+ self.parentfd = os.open(objdir, os.O_RDONLY)
+ except:
+ f = self.file
+ self.file = None
+ f.close()
+ raise
assert(name.endswith('.pack'))
self.filename = name[:-5]
self.file.write('PACK\0\0\0\2\0\0\0\0')
"""Remove the pack file from disk."""
f = self.file
if f:
- self.idx = None
+ pfd = self.parentfd
self.file = None
+ self.parentfd = None
+ self.idx = None
try:
- os.unlink(self.filename + '.pack')
+ try:
+ os.unlink(self.filename + '.pack')
+ finally:
+ f.close()
finally:
- f.close()
+ if pfd is not None:
+ os.close(pfd)
def _end(self, run_midx=True):
f = self.file
sum.update(b)
packbin = sum.digest()
f.write(packbin)
+ fdatasync(f.fileno())
finally:
f.close()
os.unlink(self.filename + '.map')
os.rename(self.filename + '.pack', nameprefix + '.pack')
os.rename(self.filename + '.idx', nameprefix + '.idx')
+ try:
+ fdatasync(self.parentfd)
+ finally:
+ os.close(self.parentfd)
if run_midx:
auto_midx(repo('objects/pack'))
idx_f = open(filename, 'w+b')
try:
idx_f.truncate(index_len)
+ fdatasync(idx_f.fileno())
idx_map = mmap_readwrite(idx_f, close=False)
try:
count = _helpers.write_idx(filename, idx_map, idx, self.count)
assert(count == self.count)
+ idx_map.flush()
finally:
idx_map.close()
finally:
for b in chunkyreader(idx_f):
idx_sum.update(b)
idx_f.write(idx_sum.digest())
+ fdatasync(idx_f.fileno())
return namebase
finally:
idx_f.close()