From 138aaeeff20746f6dd9a0854912327284729d99e Mon Sep 17 00:00:00 2001 From: "Nathan-J. Hirschauer" Date: Tue, 17 Oct 2023 00:04:40 +0200 Subject: [PATCH] Do not re-populate directory structure from disk on pending entry change When updating a dentry (e.g., adding a new file), the parent directory will be re-read from disk on lazy-loading. This causes the pending change to be reverted, leading to missing newly added files. To fix this, the directory entries __dirs list will only be populated once. --- CHANGELOG.rst | 1 + pyfatfs/FATDirectoryEntry.py | 3 +-- tests/test_PyFatFS.py | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 999d980..cd4aa2e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -29,6 +29,7 @@ Changed - Introduce ``lazy_load`` parameter to allow restoring previous behavior - `PR #32 `_: Fix tree iteration on non-lazy load by `@zurcher `_ / `@Microsoft `_ - `PR #33 `_: Fix missing parent directory entry link on lazy-load by `@zurcher `_ / `@Microsoft `_ + - `PR #33 `_: Do not re-populate directory structure from disk on pending entry change by `@zurcher `_ / `@Microsoft `_ Removed ~~~~~~~ diff --git a/pyfatfs/FATDirectoryEntry.py b/pyfatfs/FATDirectoryEntry.py index e55ff0a..a346eca 100644 --- a/pyfatfs/FATDirectoryEntry.py +++ b/pyfatfs/FATDirectoryEntry.py @@ -378,6 +378,7 @@ def __populate_dirs(self): self.__dirs = self.__fs.parse_dir_entries_in_cluster_chain(clus) for dir_entry in self.__dirs: dir_entry._add_parent(self) + self.__lazy_load = False def _get_entries_raw(self): """Get a full list of entries in current directory.""" @@ -497,8 +498,6 @@ def remove_dir_entry(self, name): **NOTE:** This will also remove special entries such as ».«, »..« and volume labels! """ - self._verify_is_directory() - self.__populate_dirs() # Iterate all entries for dir_entry in self._get_entries_raw(): sn = dir_entry.get_short_name() diff --git a/tests/test_PyFatFS.py b/tests/test_PyFatFS.py index 043844c..de7fc18 100644 --- a/tests/test_PyFatFS.py +++ b/tests/test_PyFatFS.py @@ -77,6 +77,26 @@ def test_lazy_load_dentry_parent_update(self): assert foo_dentry.get_full_path() == "foo" assert foobar_dentry.get_full_path() == "foo/bar" + def test_update_dentry_no_repopulate(self): + """#33: Verify that update_dentry doesn't re-read entries from disk. + + This is only problematic in case of lazy-loading, where + directory entries can be dynamically loaded, even when there + is a pending directory entry change; ultimately overwriting + the pending change. + """ + fs, in_memory_fs = _make_fs(self.FAT_TYPE, lazy_load=True) + fs.makedirs("/foo") + fs.touch("/foo/bar") + assert fs.listdir("/foo") == ['bar'] + + in_memory_fs.seek(0) + fs = PyFatBytesIOFS(BytesIO(in_memory_fs.read()), + encoding='UTF-8', lazy_load=True) + fs.touch("/foo/baz") + fs.remove("/foo/bar") + assert fs.listdir("/foo") == ['baz'] + def test_lazy_vs_nonlazy_tree(self): """Compare directory tree between lazy and non-lazy loading.""" fs1, in_memory_fs = _make_fs(self.FAT_TYPE, lazy_load=False)