fix: Sync vergleicht Timestamps - Server-Aenderungen nicht ueberschreiben
Problem: Wenn eine Datei auf dem Server geaendert wurde, hat der Client sie trotzdem mit der lokalen (alten) Version ueberschrieben. Der Sync hat nur Checksums verglichen aber nicht geprueft wer neuer ist. Fix: Bei unterschiedlichen Checksums wird jetzt der Timestamp verglichen: - Server neuer (updated_at > lokales modified) -> Download vom Server - Lokal neuer (modified > Server updated_at) -> Upload zum Server - Log zeigt "Server->Lokal" oder "Lokal->Server" statt nur "Aktualisiert" Betrifft alle drei Sync-Methoden: - sync_virtual (Offline-markierte Dateien) - sync_upload_new (Virtual Mode Upload) - sync_full_upload (Full Sync Upload) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
11fd11aa45
commit
4673423e2f
|
|
@ -98,17 +98,35 @@ impl SyncEngine {
|
|||
} else {
|
||||
// Check if real file exists (manually downloaded or offline-marked)
|
||||
if local_path.exists() {
|
||||
// Real file exists - check if it's been modified
|
||||
let local_hash = compute_file_hash(&local_path);
|
||||
if local_hash != entry.checksum.as_deref().unwrap_or("") {
|
||||
// Local file changed - upload it
|
||||
if !entry.locked.unwrap_or(false) {
|
||||
match self.api.upload_file(&local_path, entry.id.into()).await {
|
||||
Ok(_) => log.push(format!("Hochgeladen: {}", entry.name)),
|
||||
Err(e) => log.push(format!("Upload-Fehler {}: {}", entry.name, e)),
|
||||
let server_hash = entry.checksum.as_deref().unwrap_or("");
|
||||
if local_hash != server_hash {
|
||||
if entry.locked.unwrap_or(false) {
|
||||
log.push(format!("Zurueckgehalten (gesperrt): {}", entry.name));
|
||||
continue;
|
||||
}
|
||||
// Who is newer?
|
||||
let local_modified = std::fs::metadata(&local_path)
|
||||
.and_then(|m| m.modified()).ok();
|
||||
let server_modified = entry.updated_at.as_deref()
|
||||
.and_then(|s| chrono::DateTime::parse_from_rfc3339(s).ok())
|
||||
.map(|dt| std::time::SystemTime::from(dt));
|
||||
|
||||
let server_is_newer = match (local_modified, server_modified) {
|
||||
(Some(lt), Some(st)) => st > lt,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if server_is_newer {
|
||||
match self.api.download_file(entry.id, &local_path).await {
|
||||
Ok(_) => log.push(format!("Server->Lokal: {}", entry.name)),
|
||||
Err(e) => log.push(format!("Download-Fehler {}: {}", entry.name, e)),
|
||||
}
|
||||
} else {
|
||||
log.push(format!("Zurueckgehalten (gesperrt): {}", entry.name));
|
||||
match self.api.upload_file(&local_path, None).await {
|
||||
Ok(_) => log.push(format!("Lokal->Server: {}", entry.name)),
|
||||
Err(e) => log.push(format!("Upload-Fehler {}: {}", entry.name, e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
|
@ -198,16 +216,41 @@ impl SyncEngine {
|
|||
} else {
|
||||
// Existing file: check if changed (checksum compare)
|
||||
if let Some(se) = server_entries.iter().find(|e| e.name == name) {
|
||||
if !se.locked.unwrap_or(false) {
|
||||
let local_hash = compute_file_hash(&path);
|
||||
if local_hash != se.checksum.as_deref().unwrap_or("") {
|
||||
if se.locked.unwrap_or(false) {
|
||||
log.push(format!("Zurueckgehalten (gesperrt): {}", name));
|
||||
continue;
|
||||
}
|
||||
|
||||
let local_hash = compute_file_hash(&path);
|
||||
let server_hash = se.checksum.as_deref().unwrap_or("");
|
||||
|
||||
if local_hash != server_hash {
|
||||
// Hashes differ - who is newer?
|
||||
let local_modified = std::fs::metadata(&path)
|
||||
.and_then(|m| m.modified())
|
||||
.ok();
|
||||
let server_modified = se.updated_at.as_deref()
|
||||
.and_then(|s| chrono::DateTime::parse_from_rfc3339(s).ok())
|
||||
.map(|dt| std::time::SystemTime::from(dt));
|
||||
|
||||
let server_is_newer = match (local_modified, server_modified) {
|
||||
(Some(local_t), Some(server_t)) => server_t > local_t,
|
||||
_ => false, // if we can't compare, don't overwrite server
|
||||
};
|
||||
|
||||
if server_is_newer {
|
||||
// Server is newer -> download
|
||||
match self.api.download_file(se.id, &path).await {
|
||||
Ok(_) => log.push(format!("Server->Lokal: {}", name)),
|
||||
Err(e) => log.push(format!("Download-Fehler {}: {}", name, e)),
|
||||
}
|
||||
} else {
|
||||
// Local is newer -> upload
|
||||
match self.api.upload_file(&path, parent_id).await {
|
||||
Ok(_) => log.push(format!("Aktualisiert: {}", name)),
|
||||
Ok(_) => log.push(format!("Lokal->Server: {}", name)),
|
||||
Err(e) => log.push(format!("Upload-Fehler {}: {}", name, e)),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.push(format!("Zurueckgehalten (gesperrt): {}", name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -289,17 +332,40 @@ impl SyncEngine {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
let needs_upload = if let Some(se) = server_names.get(&name) {
|
||||
if let Some(se) = server_names.get(&name) {
|
||||
if se.locked.unwrap_or(false) {
|
||||
log.push(format!("Zurueckgehalten (gesperrt): {}", name));
|
||||
continue;
|
||||
}
|
||||
compute_file_hash(&path) != se.checksum.as_deref().unwrap_or("")
|
||||
} else {
|
||||
true
|
||||
};
|
||||
let local_hash = compute_file_hash(&path);
|
||||
let server_hash = se.checksum.as_deref().unwrap_or("");
|
||||
if local_hash != server_hash {
|
||||
// Who is newer?
|
||||
let local_modified = std::fs::metadata(&path)
|
||||
.and_then(|m| m.modified()).ok();
|
||||
let server_modified = se.updated_at.as_deref()
|
||||
.and_then(|s| chrono::DateTime::parse_from_rfc3339(s).ok())
|
||||
.map(|dt| std::time::SystemTime::from(dt));
|
||||
|
||||
if needs_upload {
|
||||
let server_is_newer = match (local_modified, server_modified) {
|
||||
(Some(lt), Some(st)) => st > lt,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if server_is_newer {
|
||||
match self.api.download_file(se.id, &path).await {
|
||||
Ok(_) => log.push(format!("Server->Lokal: {}", name)),
|
||||
Err(e) => log.push(format!("Download-Fehler {}: {}", name, e)),
|
||||
}
|
||||
} else {
|
||||
match self.api.upload_file(&path, parent_id).await {
|
||||
Ok(_) => log.push(format!("Lokal->Server: {}", name)),
|
||||
Err(e) => log.push(format!("Upload-Fehler {}: {}", name, e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// New file, not on server
|
||||
match self.api.upload_file(&path, parent_id).await {
|
||||
Ok(_) => log.push(format!("Hochgeladen: {}", name)),
|
||||
Err(e) => log.push(format!("Upload-Fehler {}: {}", name, e)),
|
||||
|
|
|
|||
Loading…
Reference in New Issue