mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-04 00:47:00 +01:00
fix(fuse,core): list and resolve conflict copies in synced folders, log each once (B99)
The conflict sweep flagged divergent copies anywhere in the tree but kept its dedupe set in memory, so every daemon start logged them again. The conflict listing only covered My Files, so copies in on-demand sync folders were never listed, and the Activity page showed them as resolved while they were still on disk. List copies in synced folders by their absolute local path, route resolves to the mount that serves them, flag only what the listing can show, and consult the activity log before flagging a copy again.
This commit is contained in:
1 parent
912acc760a
commit
e6cb52339d
8 files changed
+171
-21
No files matched your search
@@ -429,10 +429,12 @@ pub enum Request {
|
||||
/// Retry a backed-off queued op now instead of waiting out its backoff;
|
||||
/// every failed op when `id` is `None`. Replies with [`Response::Ok`].
|
||||
RetryPendingOp { id: Option<i64> },
|
||||
/// List the `(sync-conflict …)` copies under My Files. Replies with
|
||||
/// List the `(sync-conflict …)` copies under My Files and in synced
|
||||
/// folders. Replies with
|
||||
/// [`Response::Conflicts`].
|
||||
ListConflicts,
|
||||
/// Resolve one conflict copy (`path` mountpoint-relative or absolute).
|
||||
/// Resolve one conflict copy (`path` mountpoint-relative, or absolute for a
|
||||
/// copy in a synced folder).
|
||||
/// Everything removed goes to the Proton trash. Replies with
|
||||
/// [`Response::Ok`].
|
||||
ResolveConflict { path: String, keep: ConflictKeep },
|
||||
@@ -701,9 +703,10 @@ pub struct DeviceInfo {
|
||||
/// [`Response::Conflicts`]).
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct ConflictInfo {
|
||||
/// Mountpoint-relative path of the copy.
|
||||
/// Mountpoint-relative path of the copy, or its absolute local path when it
|
||||
/// sits in a synced folder.
|
||||
pub path: String,
|
||||
/// Mountpoint-relative path of the file it is a copy of.
|
||||
/// Path of the file it is a copy of, in the same form as `path`.
|
||||
pub original_path: String,
|
||||
/// False when the original is gone and only the copy is left.
|
||||
pub original_exists: bool,
|
||||
|
||||
@@ -29,6 +29,17 @@ impl Db {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Whether the kept log already holds an entry of `kind` for `target`. Lets
|
||||
/// the daemon report something once across restarts rather than once per
|
||||
/// run, without keeping a second table in step with the log.
|
||||
pub fn activity_has(&self, kind: ActivityKind, target: &str) -> Result<bool> {
|
||||
let kind = serde_json::to_string(&kind)?;
|
||||
let conn = self.read();
|
||||
let mut stmt =
|
||||
conn.prepare("SELECT 1 FROM activity WHERE kind = ?1 AND target = ?2 LIMIT 1")?;
|
||||
Ok(stmt.exists(params![kind, target])?)
|
||||
}
|
||||
|
||||
/// The most recent activity, newest first, capped at `limit` entries. Rows
|
||||
/// whose stored `kind` no longer parses (written by an older build) are
|
||||
/// skipped rather than failing the whole read.
|
||||
|
||||
@@ -1414,6 +1414,29 @@ fn activity_reads_back_newest_first() {
|
||||
assert_eq!(db.activity_list(1).unwrap().len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn activity_has_finds_only_matching_kind_and_target() {
|
||||
let db = Db::open_in_memory().unwrap();
|
||||
db.activity_add(&activity(
|
||||
"a (sync-conflict 1).txt",
|
||||
ActivityKind::Conflict,
|
||||
false,
|
||||
))
|
||||
.unwrap();
|
||||
db.activity_add(&activity("b.txt", ActivityKind::Upload, true))
|
||||
.unwrap();
|
||||
|
||||
assert!(
|
||||
db.activity_has(ActivityKind::Conflict, "a (sync-conflict 1).txt")
|
||||
.unwrap()
|
||||
);
|
||||
assert!(
|
||||
!db.activity_has(ActivityKind::Upload, "a (sync-conflict 1).txt")
|
||||
.unwrap()
|
||||
);
|
||||
assert!(!db.activity_has(ActivityKind::Conflict, "b.txt").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn activity_prunes_to_the_keep_limit() {
|
||||
let db = Db::open_in_memory().unwrap();
|
||||
|
||||
Reference in new issue
Block a user