Verify removing worktrees while host is offline

This commit is contained in:
Antonio Scandurra 2022-12-21 11:47:01 +01:00
parent 59d7f06c57
commit ecd80c553c
2 changed files with 59 additions and 27 deletions

View file

@ -1328,21 +1328,24 @@ async fn test_project_reconnect(
"/root-1",
json!({
"dir1": {
"a.txt": "a-contents",
"b.txt": "b-contents",
"a.txt": "a",
"b.txt": "b",
"subdir1": {
"c.txt": "c-contents",
"d.txt": "d-contents",
"e.txt": "e-contents",
"c.txt": "c",
"d.txt": "d",
"e.txt": "e",
}
},
"dir2": {
"x.txt": "x-contents",
"y.txt": "y-contents",
"z.txt": "z-contents",
"v.txt": "v",
},
"dir3": {
"w.txt": "w-contents",
"w.txt": "w",
"x.txt": "x",
"y.txt": "y",
},
"dir4": {
"z.txt": "z",
},
}),
)
@ -1352,7 +1355,7 @@ async fn test_project_reconnect(
.insert_tree(
"/root-2",
json!({
"2.txt": "2-contents",
"2.txt": "2",
}),
)
.await;
@ -1361,7 +1364,7 @@ async fn test_project_reconnect(
.insert_tree(
"/root-3",
json!({
"3.txt": "3-contents",
"3.txt": "3",
}),
)
.await;
@ -1394,6 +1397,23 @@ async fn test_project_reconnect(
assert!(worktree.as_local().unwrap().is_shared());
worktree.id()
});
let (worktree_a2, _) = project_a1
.update(cx_a, |p, cx| {
p.find_or_create_local_worktree("/root-1/dir2", true, cx)
})
.await
.unwrap();
worktree_a2
.read_with(cx_a, |tree, _| tree.as_local().unwrap().scan_complete())
.await;
let worktree2_id = worktree_a2.read_with(cx_a, |tree, _| {
assert!(tree.as_local().unwrap().is_shared());
tree.id()
});
deterministic.run_until_parked();
project_b1.read_with(cx_b, |project, cx| {
assert!(project.worktree_for_id(worktree2_id, cx).is_some())
});
// Drop client A's connection.
server.forbid_connections();
@ -1436,17 +1456,22 @@ async fn test_project_reconnect(
.await
.unwrap();
// While disconnected, add a worktree to client A's project.
let (worktree_a2, _) = project_a1
// While disconnected, add and remove worktrees from client A's project.
project_a1
.update(cx_a, |project, cx| {
project.remove_worktree(worktree2_id, cx)
})
.await;
let (worktree_a3, _) = project_a1
.update(cx_a, |p, cx| {
p.find_or_create_local_worktree("/root-1/dir2", true, cx)
p.find_or_create_local_worktree("/root-1/dir3", true, cx)
})
.await
.unwrap();
worktree_a2
worktree_a3
.read_with(cx_a, |tree, _| tree.as_local().unwrap().scan_complete())
.await;
let worktree2_id = worktree_a2.read_with(cx_a, |tree, _| {
let worktree3_id = worktree_a3.read_with(cx_a, |tree, _| {
assert!(tree.as_local().unwrap().is_shared());
tree.id()
});
@ -1455,6 +1480,11 @@ async fn test_project_reconnect(
// While disconnected, close project 2
cx_a.update(|_| drop(project_a2));
// While disconnected, mutate a buffer on both the host and the guest.
buffer_a1.update(cx_a, |buf, cx| buf.edit([(0..0, "X")], None, cx));
buffer_b1.update(cx_b, |buf, cx| buf.edit([(1..1, "Y")], None, cx));
deterministic.run_until_parked();
// Client A reconnects. Their project is re-shared, and client B re-joins it.
server.allow_connections();
client_a
@ -1486,13 +1516,13 @@ async fn test_project_reconnect(
]
);
assert_eq!(
worktree_a2
worktree_a3
.read(cx)
.snapshot()
.paths()
.map(|p| p.to_str().unwrap())
.collect::<Vec<_>>(),
vec!["x.txt", "y.txt", "z.txt"]
vec!["w.txt", "x.txt", "y.txt"]
);
});
project_b1.read_with(cx_b, |project, cx| {
@ -1520,16 +1550,17 @@ async fn test_project_reconnect(
"subdir2/i.txt"
]
);
assert!(project.worktree_for_id(worktree2_id, cx).is_none());
assert_eq!(
project
.worktree_for_id(worktree2_id, cx)
.worktree_for_id(worktree3_id, cx)
.unwrap()
.read(cx)
.snapshot()
.paths()
.map(|p| p.to_str().unwrap())
.collect::<Vec<_>>(),
vec!["x.txt", "y.txt", "z.txt"]
vec!["w.txt", "x.txt", "y.txt"]
);
});
project_b2.read_with(cx_b, |project, _| assert!(project.is_read_only()));
@ -1552,22 +1583,22 @@ async fn test_project_reconnect(
.unwrap();
// While client B is disconnected, add and remove worktrees from client A's project.
let (worktree_a3, _) = project_a1
let (worktree_a4, _) = project_a1
.update(cx_a, |p, cx| {
p.find_or_create_local_worktree("/root-1/dir3", true, cx)
p.find_or_create_local_worktree("/root-1/dir4", true, cx)
})
.await
.unwrap();
worktree_a3
worktree_a4
.read_with(cx_a, |tree, _| tree.as_local().unwrap().scan_complete())
.await;
let worktree3_id = worktree_a3.read_with(cx_a, |tree, _| {
let worktree4_id = worktree_a4.read_with(cx_a, |tree, _| {
assert!(tree.as_local().unwrap().is_shared());
tree.id()
});
project_a1
.update(cx_a, |project, cx| {
project.remove_worktree(worktree2_id, cx)
project.remove_worktree(worktree3_id, cx)
})
.await;
deterministic.run_until_parked();
@ -1610,14 +1641,14 @@ async fn test_project_reconnect(
assert!(project.worktree_for_id(worktree2_id, cx).is_none());
assert_eq!(
project
.worktree_for_id(worktree3_id, cx)
.worktree_for_id(worktree4_id, cx)
.unwrap()
.read(cx)
.snapshot()
.paths()
.map(|p| p.to_str().unwrap())
.collect::<Vec<_>>(),
vec!["w.txt"]
vec!["z.txt"]
);
});
project_b3.read_with(cx_b, |project, _| assert!(project.is_read_only()));

View file

@ -4645,6 +4645,7 @@ impl Project {
.remove(&old_peer_id)
.ok_or_else(|| anyhow!("received UpdateProjectCollaborator for unknown peer"))?;
this.collaborators.insert(new_peer_id, collaborator);
if let Some(buffers) = this.shared_buffers.remove(&old_peer_id) {
this.shared_buffers.insert(new_peer_id, buffers);
}