Add a command for building and installing a locally-developed Zed extension (#8781)
This PR adds an `zed: Install Local Extension` action, which lets you select a path to a folder containing a Zed extension, and install that . When you select a directory, the extension will be compiled (both the Tree-sitter grammars and the Rust code for the extension itself) and installed as a Zed extension, using a symlink. ### Details A few dependencies are needed to build an extension: * The Rust `wasm32-wasi` target. This is automatically installed if needed via `rustup`. * A wasi-preview1 adapter WASM module, for building WASM components with Rust. This is automatically downloaded if needed from a `wasmtime` GitHub release * For building Tree-sitter parsers, a distribution of `wasi-sdk`. This is automatically downloaded if needed from a `wasi-sdk` GitHub release. The downloaded artifacts are cached in a support directory called `Zed/extensions/build`. ### Tasks UX * [x] Show local extensions in the Extensions view * [x] Provide a button for recompiling a linked extension * [x] Make this action discoverable by adding a button for it on the Extensions view * [ ] Surface errors (don't just write them to the Zed log) Packaging * [ ] Create a separate executable that performs the extension compilation. We'll switch the packaging system in our [extensions](https://github.com/zed-industries/extensions) repo to use this binary, so that there is one canonical definition of how to build/package an extensions. ### Release Notes: - N/A --------- Co-authored-by: Marshall <marshall@zed.dev> Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
This commit is contained in:
parent
e273198ada
commit
675ae24964
18 changed files with 1662 additions and 763 deletions
|
@ -43,6 +43,7 @@ use std::ffi::OsStr;
|
|||
#[async_trait::async_trait]
|
||||
pub trait Fs: Send + Sync {
|
||||
async fn create_dir(&self, path: &Path) -> Result<()>;
|
||||
async fn create_symlink(&self, path: &Path, target: PathBuf) -> Result<()>;
|
||||
async fn create_file(&self, path: &Path, options: CreateOptions) -> Result<()>;
|
||||
async fn create_file_with(
|
||||
&self,
|
||||
|
@ -124,6 +125,16 @@ impl Fs for RealFs {
|
|||
Ok(smol::fs::create_dir_all(path).await?)
|
||||
}
|
||||
|
||||
async fn create_symlink(&self, path: &Path, target: PathBuf) -> Result<()> {
|
||||
#[cfg(target_family = "unix")]
|
||||
smol::fs::unix::symlink(target, path).await?;
|
||||
|
||||
#[cfg(target_family = "windows")]
|
||||
Err(anyhow!("not supported yet on windows"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_file(&self, path: &Path, options: CreateOptions) -> Result<()> {
|
||||
let mut open_options = smol::fs::OpenOptions::new();
|
||||
open_options.write(true).create(true);
|
||||
|
@ -994,6 +1005,25 @@ impl Fs for FakeFs {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_symlink(&self, path: &Path, target: PathBuf) -> Result<()> {
|
||||
let mut state = self.state.lock();
|
||||
let file = Arc::new(Mutex::new(FakeFsEntry::Symlink { target }));
|
||||
state
|
||||
.write_path(path.as_ref(), move |e| match e {
|
||||
btree_map::Entry::Vacant(e) => {
|
||||
e.insert(file);
|
||||
Ok(())
|
||||
}
|
||||
btree_map::Entry::Occupied(mut e) => {
|
||||
*e.get_mut() = file;
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
state.emit_event(&[path]);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_file_with(
|
||||
&self,
|
||||
path: &Path,
|
||||
|
@ -1503,8 +1533,9 @@ mod tests {
|
|||
]
|
||||
);
|
||||
|
||||
fs.insert_symlink("/root/dir2/link-to-dir3", "./dir3".into())
|
||||
.await;
|
||||
fs.create_symlink("/root/dir2/link-to-dir3".as_ref(), "./dir3".into())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
fs.canonicalize("/root/dir2/link-to-dir3".as_ref())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue