askpass: Fix cli path when executed in a remote server (#39475)
Closes #39469 Closes #39438 Closes #39458 I'm not able to test it, i would appreciate if somebody could do it. I think this bug was present also for SSH remote projects Release Notes: - Fixed an issue where zed bin was not found in remote servers for askpass --------- Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
This commit is contained in:
+45
-16
@@ -1,3 +1,4 @@
|
||||
use anyhow::Context;
|
||||
use globset::{Glob, GlobSet, GlobSetBuilder};
|
||||
use itertools::Itertools;
|
||||
use regex::Regex;
|
||||
@@ -35,8 +36,19 @@ pub fn home_dir() -> &'static PathBuf {
|
||||
}
|
||||
|
||||
pub trait PathExt {
|
||||
/// Compacts a given file path by replacing the user's home directory
|
||||
/// prefix with a tilde (`~`).
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * A `PathBuf` containing the compacted file path. If the input path
|
||||
/// does not have the user's home directory prefix, or if we are not on
|
||||
/// Linux or macOS, the original path is returned unchanged.
|
||||
fn compact(&self) -> PathBuf;
|
||||
|
||||
/// Returns a file's extension or, if the file is hidden, its name without the leading dot
|
||||
fn extension_or_hidden_file_name(&self) -> Option<&str>;
|
||||
|
||||
fn try_from_bytes<'a>(bytes: &'a [u8]) -> anyhow::Result<Self>
|
||||
where
|
||||
Self: From<&'a Path>,
|
||||
@@ -48,7 +60,6 @@ pub trait PathExt {
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
use anyhow::Context as _;
|
||||
use tendril::fmt::{Format, WTF8};
|
||||
WTF8::validate(bytes)
|
||||
.then(|| {
|
||||
@@ -60,19 +71,24 @@ pub trait PathExt {
|
||||
.with_context(|| format!("Invalid WTF-8 sequence: {bytes:?}"))
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a local path to one that can be used inside of WSL.
|
||||
/// Returns `None` if the path cannot be converted into a WSL one (network share).
|
||||
fn local_to_wsl(&self) -> Option<PathBuf>;
|
||||
|
||||
/// Returns a file's "full" joined collection of extensions, in the case where a file does not
|
||||
/// just have a singular extension but instead has multiple (e.g File.tar.gz, Component.stories.tsx)
|
||||
///
|
||||
/// Will provide back the extensions joined together such as tar.gz or stories.tsx
|
||||
fn multiple_extensions(&self) -> Option<String>;
|
||||
|
||||
/// Try to make a shell-safe representation of the path.
|
||||
///
|
||||
/// For Unix, the path is escaped to be safe for POSIX shells
|
||||
fn try_shell_safe(&self) -> anyhow::Result<String>;
|
||||
}
|
||||
|
||||
impl<T: AsRef<Path>> PathExt for T {
|
||||
/// Compacts a given file path by replacing the user's home directory
|
||||
/// prefix with a tilde (`~`).
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * A `PathBuf` containing the compacted file path. If the input path
|
||||
/// does not have the user's home directory prefix, or if we are not on
|
||||
/// Linux or macOS, the original path is returned unchanged.
|
||||
fn compact(&self) -> PathBuf {
|
||||
if cfg!(any(target_os = "linux", target_os = "freebsd")) || cfg!(target_os = "macos") {
|
||||
match self.as_ref().strip_prefix(home_dir().as_path()) {
|
||||
@@ -89,7 +105,6 @@ impl<T: AsRef<Path>> PathExt for T {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a file's extension or, if the file is hidden, its name without the leading dot
|
||||
fn extension_or_hidden_file_name(&self) -> Option<&str> {
|
||||
let path = self.as_ref();
|
||||
let file_name = path.file_name()?.to_str()?;
|
||||
@@ -102,8 +117,6 @@ impl<T: AsRef<Path>> PathExt for T {
|
||||
.or_else(|| path.file_stem()?.to_str())
|
||||
}
|
||||
|
||||
/// Converts a local path to one that can be used inside of WSL.
|
||||
/// Returns `None` if the path cannot be converted into a WSL one (network share).
|
||||
fn local_to_wsl(&self) -> Option<PathBuf> {
|
||||
// quite sketchy to convert this back to path at the end, but a lot of functions only accept paths
|
||||
// todo: ideally rework them..?
|
||||
@@ -133,10 +146,6 @@ impl<T: AsRef<Path>> PathExt for T {
|
||||
Some(new_path.into())
|
||||
}
|
||||
|
||||
/// Returns a file's "full" joined collection of extensions, in the case where a file does not
|
||||
/// just have a singular extension but instead has multiple (e.g File.tar.gz, Component.stories.tsx)
|
||||
///
|
||||
/// Will provide back the extensions joined together such as tar.gz or stories.tsx
|
||||
fn multiple_extensions(&self) -> Option<String> {
|
||||
let path = self.as_ref();
|
||||
let file_name = path.file_name()?.to_str()?;
|
||||
@@ -153,6 +162,26 @@ impl<T: AsRef<Path>> PathExt for T {
|
||||
|
||||
Some(parts.into_iter().join("."))
|
||||
}
|
||||
|
||||
fn try_shell_safe(&self) -> anyhow::Result<String> {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
Ok(self.as_ref().to_string_lossy().to_string())
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
let path_str = self
|
||||
.as_ref()
|
||||
.to_str()
|
||||
.with_context(|| "Path contains invalid UTF-8")?;
|
||||
|
||||
// As of writing, this can only be fail if the path contains a null byte, which shouldn't be possible
|
||||
// but shlex has annotated the error as #[non_exhaustive] so we can't make it a compile error if other
|
||||
// errors are introduced in the future :(
|
||||
Ok(shlex::try_quote(path_str)?.into_owned())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// In memory, this is identical to `Path`. On non-Windows conversions to this type are no-ops. On
|
||||
|
||||
+11
-30
@@ -18,7 +18,9 @@ pub mod time;
|
||||
use anyhow::{Context as _, Result};
|
||||
use futures::Future;
|
||||
use itertools::Either;
|
||||
use paths::PathExt;
|
||||
use regex::Regex;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{LazyLock, OnceLock};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
@@ -288,27 +290,19 @@ fn load_shell_from_passwd() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
/// Returns a shell escaped path for the current zed executable
|
||||
pub fn get_shell_safe_zed_path() -> anyhow::Result<String> {
|
||||
let zed_path = std::env::current_exe()
|
||||
.context("Failed to determine current zed executable path.")?
|
||||
.to_string_lossy()
|
||||
.trim_end_matches(" (deleted)") // see https://github.com/rust-lang/rust/issues/69343
|
||||
.to_string();
|
||||
let zed_path =
|
||||
std::env::current_exe().context("Failed to determine current zed executable path.")?;
|
||||
|
||||
// As of writing, this can only be fail if the path contains a null byte, which shouldn't be possible
|
||||
// but shlex has annotated the error as #[non_exhaustive] so we can't make it a compile error if other
|
||||
// errors are introduced in the future :(
|
||||
let zed_path_escaped =
|
||||
shlex::try_quote(&zed_path).context("Failed to shell-escape Zed executable path.")?;
|
||||
|
||||
Ok(zed_path_escaped.to_string())
|
||||
zed_path
|
||||
.try_shell_safe()
|
||||
.context("Failed to shell-escape Zed executable path.")
|
||||
}
|
||||
|
||||
/// Returns a shell escaped path for the zed cli executable, this function
|
||||
/// Returns a path for the zed cli executable, this function
|
||||
/// should be called from the zed executable, not zed-cli.
|
||||
pub fn get_shell_safe_zed_cli_path() -> Result<String> {
|
||||
pub fn get_zed_cli_path() -> Result<PathBuf> {
|
||||
let zed_path =
|
||||
std::env::current_exe().context("Failed to determine current zed executable path.")?;
|
||||
let parent = zed_path
|
||||
@@ -329,7 +323,7 @@ pub fn get_shell_safe_zed_cli_path() -> Result<String> {
|
||||
anyhow::bail!("unsupported platform for determining zed-cli path");
|
||||
};
|
||||
|
||||
let zed_cli_path = possible_locations
|
||||
possible_locations
|
||||
.iter()
|
||||
.find_map(|p| {
|
||||
parent
|
||||
@@ -343,20 +337,7 @@ pub fn get_shell_safe_zed_cli_path() -> Result<String> {
|
||||
"could not find zed-cli from any of: {}",
|
||||
possible_locations.join(", ")
|
||||
)
|
||||
})?
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
Ok(zed_cli_path)
|
||||
}
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
Ok(shlex::try_quote(&zed_cli_path)
|
||||
.context("Failed to shell-escape Zed executable path.")?
|
||||
.to_string())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
|
||||
Reference in New Issue
Block a user