Add the ability to edit remote directories over SSH (#14530)
This is a first step towards allowing you to edit remote projects directly over SSH. We'll start with a pretty bare-bones feature set, and incrementally add further features. ### Todo Distribution * [x] Build nightly releases of `zed-remote-server` binaries * [x] linux (arm + x86) * [x] mac (arm + x86) * [x] Build stable + preview releases of `zed-remote-server` * [x] download and cache remote server binaries as needed when opening ssh project * [x] ensure server has the latest version of the binary Auth * [x] allow specifying password at the command line * [x] auth via ssh keys * [x] UI password prompt Features * [x] upload remote server binary to server automatically * [x] opening directories * [x] tracking file system updates * [x] opening, editing, saving buffers * [ ] file operations (rename, delete, create) * [ ] git diffs * [ ] project search Release Notes: - N/A --------- Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
This commit is contained in:
parent
7733bf686b
commit
b9a53ffa0b
50 changed files with 2194 additions and 250 deletions
78
crates/remote_server/src/main.rs
Normal file
78
crates/remote_server/src/main.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
use fs::RealFs;
|
||||
use futures::channel::mpsc;
|
||||
use gpui::Context as _;
|
||||
use remote::{
|
||||
protocol::{read_message, write_message},
|
||||
SshSession,
|
||||
};
|
||||
use remote_server::HeadlessProject;
|
||||
use smol::{io::AsyncWriteExt, stream::StreamExt as _, Async};
|
||||
use std::{env, io, mem, process, sync::Arc};
|
||||
|
||||
fn main() {
|
||||
env::set_var("RUST_BACKTRACE", "1");
|
||||
env::set_var("RUST_LOG", "remote=trace");
|
||||
|
||||
let subcommand = std::env::args().nth(1);
|
||||
match subcommand.as_deref() {
|
||||
Some("run") => {}
|
||||
Some("version") => {
|
||||
println!("{}", env!("ZED_PKG_VERSION"));
|
||||
return;
|
||||
}
|
||||
_ => {
|
||||
eprintln!("usage: remote <run|version>");
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
env_logger::init();
|
||||
|
||||
gpui::App::headless().run(move |cx| {
|
||||
HeadlessProject::init(cx);
|
||||
|
||||
let (incoming_tx, incoming_rx) = mpsc::unbounded();
|
||||
let (outgoing_tx, mut outgoing_rx) = mpsc::unbounded();
|
||||
|
||||
let mut stdin = Async::new(io::stdin()).unwrap();
|
||||
let mut stdout = Async::new(io::stdout()).unwrap();
|
||||
|
||||
let session = SshSession::server(incoming_rx, outgoing_tx, cx);
|
||||
let project = cx.new_model(|cx| {
|
||||
HeadlessProject::new(
|
||||
session.clone(),
|
||||
Arc::new(RealFs::new(Default::default(), None)),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
||||
cx.background_executor()
|
||||
.spawn(async move {
|
||||
let mut output_buffer = Vec::new();
|
||||
while let Some(message) = outgoing_rx.next().await {
|
||||
write_message(&mut stdout, &mut output_buffer, message).await?;
|
||||
stdout.flush().await?;
|
||||
}
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach();
|
||||
|
||||
cx.background_executor()
|
||||
.spawn(async move {
|
||||
let mut input_buffer = Vec::new();
|
||||
loop {
|
||||
let message = match read_message(&mut stdin, &mut input_buffer).await {
|
||||
Ok(message) => message,
|
||||
Err(error) => {
|
||||
log::warn!("error reading message: {:?}", error);
|
||||
process::exit(0);
|
||||
}
|
||||
};
|
||||
incoming_tx.unbounded_send(message).ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
mem::forget(project);
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue