From 78615d88973a6263cd974fa64890cf58b16e79ce Mon Sep 17 00:00:00 2001 From: Stefan Hacker Date: Thu, 23 Apr 2026 22:56:58 +0200 Subject: [PATCH] fix(cloud-files): Existierende normale Dateien vor Placeholder-Erstellung loeschen Wenn der Client vorher aktiv war und dann deaktiviert wurde (oder hart beendet), wandelt CfUnregisterSyncRoot alle Platzhalter in normale Dateien um. Beim erneuten Aktivieren versuchte populate_placeholders einen neuen Platzhalter anzulegen, was aber mit ERROR_FILE_EXISTS scheiterte - der Fehler wurde zudem nur per eprintln geloggt und verschluckt. Ergebnis: die Datei blieb eine ganz normale Datei (kein Platzhalter, kein Wolken-Icon). Spaeter fragt CfDehydratePlaceholder dann mit HRESULT 0x80070178 "Die Datei ist keine Clouddatei", und "Speicher freigeben" funktioniert nicht. Jetzt prueft populate_placeholders vor jedem Create, ob die Datei schon existiert und KEIN Platzhalter ist. Wenn ja: loeschen, dann neu als Platzhalter anlegen. Erfolge und Fehler gehen beide ins .minicloud-cloudfiles.log, damit man das Ergebnis prueft. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src-tauri/src/cloud_files/windows.rs | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/clients/desktop/src-tauri/src/cloud_files/windows.rs b/clients/desktop/src-tauri/src/cloud_files/windows.rs index 4e16c44..d397a61 100644 --- a/clients/desktop/src-tauri/src/cloud_files/windows.rs +++ b/clients/desktop/src-tauri/src/cloud_files/windows.rs @@ -432,18 +432,37 @@ pub fn populate_placeholders( std::fs::create_dir_all(&p).ok(); } - // Dann Dateien als Platzhalter + // Dann Dateien als Platzhalter. Existierende "normale" Dateien + // (z.B. nach vorherigem CfUnregisterSyncRoot) vorher loeschen, + // weil CfCreatePlaceholders sonst mit ERROR_FILE_EXISTS scheitert + // und die Datei nie zum Platzhalter wird -> spaeter koennte man + // sie nicht mehr dehydrieren (0x80070178 "keine Clouddatei"). for e in entries.iter().filter(|e| !e.is_folder) { let rel = rel_path(e, &by_id); + let full = mount_point.join(&rel); let parent = rel .parent() .map(|p| mount_point.join(p)) .unwrap_or_else(|| mount_point.clone()); let identity = e.id.to_string(); - if let Err(err) = - create_placeholder(&parent, &e.name, e.size, &e.modified_at, identity.as_bytes()) - { - eprintln!("placeholder {}: {}", e.name, err); + + if full.exists() && !is_cfapi_placeholder(&full) { + log_msg(mount_point, &format!( + "deleting non-placeholder {} to recreate", + full.display() + )); + if let Err(err) = std::fs::remove_file(&full) { + log_err(mount_point, &format!( + "remove {} failed: {err}", full.display() + )); + } + } + + match create_placeholder(&parent, &e.name, e.size, &e.modified_at, identity.as_bytes()) { + Ok(()) => log_msg(mount_point, &format!("placeholder created: {}", full.display())), + Err(err) => log_err(mount_point, &format!( + "placeholder {} FAILED: {err}", full.display() + )), } } Ok(())