mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-03 16:41:26 +01:00
fix(core): a folder listed just as its create lands is listed from the database (B177)
This commit is contained in:
1 parent
4f141c78ca
commit
0f3c06f982
5 files changed
+75
-5
No files matched your search
@@ -533,9 +533,10 @@ impl Db {
|
||||
/// re-enumerates from the remote on next access.
|
||||
pub fn set_listed(&self, uid: &NodeUid, listed: bool) -> Result<()> {
|
||||
let conn = self.conn.lock();
|
||||
let (key, uid) = row_key(&uid.to_string());
|
||||
conn.execute(
|
||||
"UPDATE nodes SET listed = ?2 WHERE uid = ?1",
|
||||
params![uid.to_string(), listed as i64],
|
||||
&format!("UPDATE nodes SET listed = ?2 WHERE {key} = ?1"),
|
||||
params![uid, listed as i64],
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -694,10 +695,11 @@ impl Db {
|
||||
/// server head, so changes made while unmounted are still applied (P2).
|
||||
pub fn children_if_listed(&self, parent: &NodeUid) -> Result<Option<Vec<Node>>> {
|
||||
let conn = self.read();
|
||||
let (key, folder) = row_key(&parent.to_string());
|
||||
let listed: Option<i64> = conn
|
||||
.query_row(
|
||||
"SELECT listed FROM nodes WHERE uid = ?1",
|
||||
params![parent.to_string()],
|
||||
&format!("SELECT listed FROM nodes WHERE {key} = ?1"),
|
||||
params![folder],
|
||||
|r| r.get(0),
|
||||
)
|
||||
.optional()?;
|
||||
@@ -792,6 +794,17 @@ pub(super) fn node_lid(conn: &rusqlite::Connection, uid: &str) -> Result<Option<
|
||||
Ok(row.optional()?)
|
||||
}
|
||||
|
||||
/// The column and value that find `uid`'s own row. A stand-in is found by its
|
||||
/// local id: a create that lands gives the row the uid Drive made before the
|
||||
/// tree has it, and the tree asks by the stand-in until then (`docs/BUGS.md`
|
||||
/// B177).
|
||||
fn row_key(uid: &str) -> (&'static str, Value) {
|
||||
match local_lid(uid) {
|
||||
Some(lid) => ("lid", Value::Integer(lid)),
|
||||
None => ("uid", Value::Text(uid.to_owned())),
|
||||
}
|
||||
}
|
||||
|
||||
/// The column and value a row names `parent` by: its local id when it has a
|
||||
/// row, which the children keep when it lands, or its uid when it has none,
|
||||
/// as a device folder's root does.
|
||||
|
||||
@@ -3282,6 +3282,37 @@ fn a_stand_in_keeps_its_access_once_its_create_has_landed() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_stand_in_folder_stays_listed_once_its_create_has_landed() {
|
||||
let db = Db::open_in_memory().unwrap();
|
||||
db.upsert_node(&folder("parent", None, "My Files")).unwrap();
|
||||
let parent = uid("parent").to_string();
|
||||
let lid = db.add_local_row(&parent, "dir", true, 1).unwrap();
|
||||
let local = local_uid(lid);
|
||||
let stand_in = NodeUid::new(VolumeId::from("local"), LinkId::from(lid.to_string()));
|
||||
let mut node = folder("new", Some("parent"), "dir");
|
||||
node.uid = stand_in.clone();
|
||||
db.upsert_node(&node).unwrap();
|
||||
db.set_listed(&stand_in, true).unwrap();
|
||||
let real = uid("real").to_string();
|
||||
let (id, _) = db
|
||||
.enqueue_op(&op_on(OP_MKDIR, &local, Some(&parent)))
|
||||
.unwrap();
|
||||
db.claim_next_due_op(1).unwrap().unwrap();
|
||||
db.finish_create(id, None, &landing(&local, &real, &parent, "dir"), |_| None)
|
||||
.unwrap();
|
||||
|
||||
// The tree still names the folder by its stand-in for a moment; a listing
|
||||
// asked by it must not go to Drive, which has never heard of it.
|
||||
assert!(
|
||||
db.children_if_listed(&stand_in)
|
||||
.unwrap()
|
||||
.is_some_and(|kids| kids.is_empty())
|
||||
);
|
||||
db.set_listed(&stand_in, false).unwrap();
|
||||
assert!(db.children_if_listed(&uid("real")).unwrap().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_node_queued_under_both_its_uids_is_sent_one_op_at_a_time() {
|
||||
let db = Db::open_in_memory().unwrap();
|
||||
|
||||
Reference in new issue
Block a user