fix(core): keep a folder's pin when the folder lands (B148)

A folder pinned before its mkdir landed kept the placeholder uid in
pins.uid, which named no node once the landing moved the row to the
real uid. The landing now moves the pin with it.
This commit is contained in:
nvrl committed 2026-10-04 04:45:47 +02:00
1 parent 9b3651e4e8
commit f029e652a1
4 files changed
+73

No files matched your search

+7
View File
@@ -733,6 +733,13 @@ pub(super) fn adopt_placeholder_row_tx(
local: &str,
real: &str,
) -> Result<()> {
// A folder pinned before it landed stays pinned: the pin keyed by the
// placeholder was dropped with it (`docs/BUGS.md` B148).
tx.execute(
"UPDATE OR IGNORE pins SET uid = ?2 WHERE uid = ?1",
params![local, real],
)?;
tx.execute("DELETE FROM pins WHERE uid = ?1", params![local])?;
// The node a row holds names its parent too, and is what a restart builds
// the tree from: a folder that landed with no write to its children after
// left them under a parent no row has (`docs/BUGS.md` B140).
+47
View File
@@ -3321,6 +3321,53 @@ fn a_landed_folder_keeps_a_row_until_the_server_copy_replaces_it() {
assert_eq!(found[0].path, "New folder/inside.txt");
}
/// B148: a folder pinned before it landed is still pinned once it has.
#[test]
fn a_folder_pinned_before_it_landed_stays_pinned() {
let db = Db::open_in_memory().unwrap();
db.upsert_node(&folder("root", None, "My Files")).unwrap();
let local = NodeUid::new(VolumeId::from("local"), LinkId::from("dir"));
let mut placeholder = folder("dir", Some("root"), "Keep");
placeholder.uid = local.clone();
db.upsert_node(&placeholder).unwrap();
db.pin_add(&local.to_string(), "Keep", true).unwrap();
let (id, _) = db
.enqueue_op(&PendingOp {
id: 0,
kind: OP_MKDIR.to_string(),
uid: local.to_string(),
parent_uid: Some(uid("root").to_string()),
name: Some("Keep".to_string()),
blob_path: None,
meta_json: None,
created_at: 1,
attempts: 0,
last_error: None,
next_attempt_at: 0,
})
.unwrap();
db.finish_create(
id,
None,
&landing(
&local.to_string(),
&uid("real").to_string(),
&uid("root").to_string(),
"Keep",
),
|_| None,
)
.unwrap();
assert!(db.is_pinned(&uid("real").to_string()).unwrap());
assert!(!db.is_pinned(&local.to_string()).unwrap());
let pins = db.pin_list().unwrap();
assert_eq!(pins.len(), 1);
assert_eq!(pins[0].uid, uid("real").to_string());
assert!(pins[0].recursive);
}
/// A file deleted while its create was on the wire still lands: nothing stops
/// an upload in flight. The node it made is unwanted, so a trash of it is
/// queued in the same transaction, already claimed by the drain that landed it