Fixed some mtime errors, more tests
This commit is contained in:
parent
f99cffbc89
commit
14cc98d8db
0
expected_test_result/exists
Normal file
0
expected_test_result/exists
Normal file
0
expected_test_result/touch
Normal file
0
expected_test_result/touch
Normal file
1
expected_test_result/truncate
Normal file
1
expected_test_result/truncate
Normal file
|
@ -0,0 +1 @@
|
||||||
|
123456
|
27
fs.py
27
fs.py
|
@ -33,6 +33,7 @@ class FilterFS(Operations):
|
||||||
rl = os.readlink(p)
|
rl = os.readlink(p)
|
||||||
if rl.startswith('/!/'):
|
if rl.startswith('/!/'):
|
||||||
cached_output = os.path.join(self.cache, 'get', path.lstrip('/'))
|
cached_output = os.path.join(self.cache, 'get', path.lstrip('/'))
|
||||||
|
peek = os.path.join(self.cache, 'peek', path.lstrip('/'))
|
||||||
if not os.path.exists(cached_output):
|
if not os.path.exists(cached_output):
|
||||||
translator = self._parse(rl)
|
translator = self._parse(rl)
|
||||||
d = os.path.dirname(p)
|
d = os.path.dirname(p)
|
||||||
|
@ -44,6 +45,9 @@ class FilterFS(Operations):
|
||||||
self._mkparents(cached_output)
|
self._mkparents(cached_output)
|
||||||
shutil.move(os.path.join(d, translator.output_filename), cached_output)
|
shutil.move(os.path.join(d, translator.output_filename), cached_output)
|
||||||
# end hack
|
# end hack
|
||||||
|
attr = os.lstat(p)
|
||||||
|
os.utime(cached_output, (attr.st_ctime, attr.st_mtime))
|
||||||
|
os.utime(peek, (attr.st_ctime, attr.st_mtime))
|
||||||
p = cached_output
|
p = cached_output
|
||||||
return p
|
return p
|
||||||
|
|
||||||
|
@ -65,8 +69,10 @@ class FilterFS(Operations):
|
||||||
translator = self._parse(rl)
|
translator = self._parse(rl)
|
||||||
self._mkparents(peek)
|
self._mkparents(peek)
|
||||||
pathlib.Path(peek).touch()
|
pathlib.Path(peek).touch()
|
||||||
|
attr = os.lstat(p)
|
||||||
|
os.utime(peek, (attr.st_ctime, attr.st_mtime))
|
||||||
os.chmod(peek, translator.mode)
|
os.chmod(peek, translator.mode)
|
||||||
return Entity(path = peek, is_translator = True, peek = peek, source = p, size = 9999999999999999)
|
return Entity(path = peek, is_translator = True, peek = peek, source = p, size = 0)
|
||||||
return Entity(path = p, is_translator = False, peek = p, source = p, size = None)
|
return Entity(path = p, is_translator = False, peek = p, source = p, size = None)
|
||||||
|
|
||||||
# directory
|
# directory
|
||||||
|
@ -139,26 +145,28 @@ class FilterFS(Operations):
|
||||||
|
|
||||||
# other:
|
# other:
|
||||||
def mknod(self, path, mode, dev):
|
def mknod(self, path, mode, dev):
|
||||||
return os.mknod(self._get_entity(path).source, mode, dev)
|
return os.mknod(self._get_entity('mknod', path).source, mode, dev)
|
||||||
|
|
||||||
# filesystem
|
# filesystem
|
||||||
def statfs(self, path):
|
def statfs(self, path):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# symlinks
|
# symlinks
|
||||||
#def readlink(self, path):
|
def readlink(self, path):
|
||||||
# pass
|
pass
|
||||||
def symlink(self, destination, symlink_path):
|
def symlink(self, destination, symlink_path):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# file
|
# file
|
||||||
def open(self, path, flags):
|
def open(self, path, flags):
|
||||||
g = self._get("open", path)
|
print('open', path, flags)
|
||||||
print('open:', g)
|
return os.open(self._get("open", path), flags)
|
||||||
return os.open(g, flags)
|
|
||||||
def read(self, path, length, offset, file_handle):
|
def read(self, path, length, offset, file_handle):
|
||||||
|
print('read', path, length, offset, file_handle)
|
||||||
|
self._get("read", path)
|
||||||
os.lseek(file_handle, offset, os.SEEK_SET)
|
os.lseek(file_handle, offset, os.SEEK_SET)
|
||||||
return os.read(file_handle, length)
|
r = os.read(file_handle, length)
|
||||||
|
return r
|
||||||
def _assert_is_writable(self, why, path):
|
def _assert_is_writable(self, why, path):
|
||||||
# TODO: might be a bit slow for many repeated writes, but guarantees that
|
# TODO: might be a bit slow for many repeated writes, but guarantees that
|
||||||
# if a translator is created in src and a file handle was already obtained
|
# if a translator is created in src and a file handle was already obtained
|
||||||
|
@ -191,7 +199,8 @@ class FilterFS(Operations):
|
||||||
return self.flush(path, file_handle)
|
return self.flush(path, file_handle)
|
||||||
|
|
||||||
def main(source, cache, mountpoint):
|
def main(source, cache, mountpoint):
|
||||||
FUSE(FilterFS(source, cache), mountpoint, nothreads=True, foreground=True)
|
# direct_io allows us to return size 0 for non-empty files
|
||||||
|
FUSE(FilterFS(source, cache), mountpoint, nothreads=True, foreground=True, direct_io = True)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main(sys.argv[1], sys.argv[2], sys.argv[3])
|
main(sys.argv[1], sys.argv[2], sys.argv[3])
|
0
source/exists
Normal file
0
source/exists
Normal file
1
source/truncate
Normal file
1
source/truncate
Normal file
|
@ -0,0 +1 @@
|
||||||
|
1234567890
|
49
test.sh
49
test.sh
|
@ -6,17 +6,48 @@ fusermount -u test/mnt || true
|
||||||
rm test -fr
|
rm test -fr
|
||||||
mkdir test test/cache test/mnt
|
mkdir test test/cache test/mnt
|
||||||
cp -ai source test/source
|
cp -ai source test/source
|
||||||
./fs.py test/source test/cache test/mnt & pid=$!
|
|
||||||
|
find test/source -print0 | xargs -0r touch --no-dereference --date="2023-01-01 00:00Z"
|
||||||
|
find expected_test_result -print0 | xargs -0r touch --no-dereference --date="2023-01-01 00:00Z"
|
||||||
|
|
||||||
|
# TODO: are the chmod preserved by git commit + git checkout ?
|
||||||
|
|
||||||
|
./fs.py test/source test/cache test/mnt > test/fs.log & pid=$!
|
||||||
|
|
||||||
run_tests() {
|
run_tests() {
|
||||||
sleep 2 # TODO: use foreground=False instead of & pid=$!
|
# make sure any mtime errors will show up
|
||||||
touch test/mnt/touched
|
sleep 1.1
|
||||||
echo 42 > test/mnt/written
|
|
||||||
echo 'Append' >> test/mnt/append
|
# TODO: use foreground=False instead of & pid=$!
|
||||||
echo 'This is an overwrite' > test/mnt/overwrite
|
for i in `seq 20`; do
|
||||||
cp -ai test/mnt test/actual_result
|
if test -e test/mnt/exists; then
|
||||||
fusermount -u test/mnt
|
break
|
||||||
diff -r test/actual_result expected_test_result
|
else
|
||||||
|
printf '.'
|
||||||
|
sleep 0.1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
printf '\n'
|
||||||
|
|
||||||
|
echo 01; test -e test/mnt/exists
|
||||||
|
echo 02; touch --date='2023-02-02 00:00Z' test/mnt/touch && touch --date='2023-02-02 00:00Z' expected_test_result/touch
|
||||||
|
echo 03; touch --date='2023-02-02 00:00Z' test/mnt/create && touch --date='2023-02-02 00:00Z' expected_test_result/create
|
||||||
|
echo 04; echo 42 > test/mnt/create_write && touch --reference=test/mnt/create_write expected_test_result/create_write
|
||||||
|
echo 05; echo 'Append' >> test/mnt/append && touch --reference=test/mnt/append expected_test_result/append
|
||||||
|
echo 06; echo 'This is an overwrite' > test/mnt/overwrite && touch --reference=test/mnt/overwrite expected_test_result/overwrite
|
||||||
|
echo 07; truncate --size=6 test/mnt/truncate && touch --reference=test/mnt/truncate expected_test_result/truncate
|
||||||
|
echo 08; mknod -m 644 test/mnt/mknod644p p && touch --reference=test/mnt/truncate expected_test_result/mknod644p
|
||||||
|
# TODO: test that a _peek cached but not _get cached file has the correct mtime?
|
||||||
|
|
||||||
|
# reset the mtime of the modified directories
|
||||||
|
#touch --date='2023-01-01 00:00Z' test/mnt/some_dir # unmodified
|
||||||
|
touch --date='2023-01-01 00:00Z' test/mnt
|
||||||
|
|
||||||
|
echo 99; cp -ai test/mnt test/actual_result
|
||||||
|
echo uu; fusermount -u test/mnt
|
||||||
|
echo ta; tar -cf test/actual.tar -C test/actual_result/ .
|
||||||
|
echo te; tar -cf test/expected.tar -C expected_test_result/ .
|
||||||
|
echo dd; diffoscope test/actual.tar test/expected.tar
|
||||||
}
|
}
|
||||||
|
|
||||||
if run_tests; then
|
if run_tests; then
|
||||||
|
|
Loading…
Reference in New Issue
Block a user