mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-03 16:41:26 +01:00
fix(fuse): list a new file once while its create lands (B164)
A listing from Drive overlays what is still queued for the folder. A create Drive has made but whose answer is on its way, or which the drain is still reading back, was in both: Drive's node under its new uid and the queue's stand-in, under one name. A node queued in the folder now holds its name there.
This commit is contained in:
1 parent
b37d5e7928
commit
ce2bc0ac84
5 files changed
+80
-4
No files matched your search
@@ -6496,11 +6496,17 @@ fn node_visible(node: &Node, folder_uid: &NodeUid, hidden: &HashSet<NodeUid>) ->
|
||||
/// Lay what is queued for a folder over Drive's listing of it, from
|
||||
/// `Db::queued_children`: a node a queued rename moved away is dropped, and a
|
||||
/// node a queued create, mkdir or rename put there is listed as the DB has it.
|
||||
///
|
||||
/// That node holds its name here: a create Drive already has but whose answer
|
||||
/// is still on its way, or which the drain is still reading back, is listed by
|
||||
/// Drive under its new uid and by the queue under its stand-in. Both were
|
||||
/// listed, and a 128-file folder listed 129 (`docs/BUGS.md` B164).
|
||||
fn overlay_queued(nodes: &mut Vec<Node>, queued: Vec<Node>, gone: &HashSet<String>) {
|
||||
let here: HashSet<String> = queued.iter().map(|node| node.uid.to_string()).collect();
|
||||
let names: HashSet<&str> = queued.iter().map(|node| node.name.as_str()).collect();
|
||||
nodes.retain(|node| {
|
||||
let uid = node.uid.to_string();
|
||||
!gone.contains(&uid) && !here.contains(&uid)
|
||||
!gone.contains(&uid) && !here.contains(&uid) && !names.contains(node.name.as_str())
|
||||
});
|
||||
nodes.extend(queued);
|
||||
}
|
||||
|
||||
@@ -554,6 +554,47 @@ mod tests {
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "mounts FUSE: run with `cargo test -p pdfs-fuse sim:: -- --ignored`"]
|
||||
fn a_create_drive_lists_before_it_is_read_back_is_listed_once() {
|
||||
// The feed reported a new file while the drain still read it back, so
|
||||
// the folder was listed from Drive again, and the file came twice: as
|
||||
// Drive's node and as the queued create's stand-in. A 128-file folder
|
||||
// listed 129 (B164).
|
||||
let drive = FakeDrive::new();
|
||||
let dir = scratch("listed-before-retired");
|
||||
let daemon = Daemon::start(&dir, drive.client(1, Faults::lan())).unwrap();
|
||||
let mnt = daemon.mountpoint.clone();
|
||||
std::fs::create_dir(mnt.join("x")).unwrap();
|
||||
assert!(wait_until(Duration::from_secs(30), || {
|
||||
daemon.pending().is_ok_and(|items| items.is_empty()) && drive.lookup("x").is_some()
|
||||
}));
|
||||
|
||||
let create = daemon.client.hold_reply_to_next_create();
|
||||
std::fs::write(mnt.join("x/c.bin"), b"abc").unwrap();
|
||||
assert!(wait_until(Duration::from_secs(30), || create.reached()));
|
||||
let uid = drive.lookup("x/c.bin").unwrap();
|
||||
let read_back = daemon.client.hold_next_read(&uid);
|
||||
drop(create);
|
||||
assert!(wait_until(Duration::from_secs(30), || read_back.reached()));
|
||||
// Long enough for the next event poll to bring the file's event.
|
||||
std::thread::sleep(crate::POLL_INTERVAL + Duration::from_secs(3));
|
||||
|
||||
let names: Vec<_> = std::fs::read_dir(mnt.join("x"))
|
||||
.unwrap()
|
||||
.map(|e| e.unwrap().file_name())
|
||||
.collect();
|
||||
drop(read_back);
|
||||
assert_eq!(names, ["c.bin"]);
|
||||
assert!(wait_until(Duration::from_secs(30), || {
|
||||
daemon.pending().is_ok_and(|items| items.is_empty())
|
||||
}));
|
||||
assert_eq!(std::fs::read(mnt.join("x/c.bin")).unwrap(), b"abc");
|
||||
|
||||
assert!(matches!(daemon.stop(), Ok(MountOutcome::Shutdown)));
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "mounts FUSE: run with `cargo test -p pdfs-fuse sim:: -- --ignored`"]
|
||||
fn a_folder_made_again_while_the_old_one_is_trashed_is_a_new_folder() {
|
||||
|
||||
Reference in new issue
Block a user