Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions app/src/sftp_manager/fm_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,18 @@ impl FileManagerRegistry {
self.backends.get(&id).cloned()
}

/// A live backend for *any* open pane browsing `fs`. Lets a non-file-manager
/// caller (e.g. the workspace opening a remote file for editing over classic
/// SSH) borrow an already-established SFTP connection for that host instead
/// of opening a second one. Returns `None` if no open pane browses `fs` yet
/// has a backend registered.
pub fn backend_for_namespace(&self, fs: &FsNamespace) -> Option<Arc<dyn SftpBackend>> {
self.panes
.iter()
.filter(|p| &p.fs == fs)
.find_map(|p| self.backends.get(&p.id).cloned())
}

/// Remove a pane (on close). A no-op if it was never registered. Drops the
/// pane's backend handle too (releasing its session once nothing else holds it).
pub fn remove(&mut self, id: u64) {
Expand Down Expand Up @@ -227,6 +239,33 @@ mod tests {
assert!(reg.backend_for(1).is_none());
}

#[test]
fn backend_for_namespace_finds_a_live_backend_for_the_host() {
use super::super::sftp_backend::InMemorySftpBackend;
let mut reg = FileManagerRegistry::new();
let host = FsNamespace::Remote("h1".into());
// Two panes on the same host; only the second has a backend registered.
reg.upsert(desc(1, host.clone(), "/a"));
reg.upsert(desc(2, host.clone(), "/b"));
reg.upsert(desc(3, FsNamespace::Local, "/c"));
assert!(reg.backend_for_namespace(&host).is_none());

let backend: Arc<dyn SftpBackend> =
Arc::new(InMemorySftpBackend::new(PathBuf::from("/")));
reg.set_backend(2, backend);
// A pane on the host now has a backend → resolves.
assert!(reg.backend_for_namespace(&host).is_some());
// A different host / the local namespace does not.
assert!(reg
.backend_for_namespace(&FsNamespace::Remote("other".into()))
.is_none());
assert!(reg.backend_for_namespace(&FsNamespace::Local).is_none());

// Dropping the only backed pane makes it unresolvable again.
reg.remove(2);
assert!(reg.backend_for_namespace(&host).is_none());
}

#[test]
fn plan_transfer_covers_every_direction() {
let local = FsNamespace::Local;
Expand Down
Loading
Loading