git: Fix panic in git2 due to empty repo paths (#42304)
Fixes ZED-1VR Release Notes: - Fixed sporadic panic in git features
This commit is contained in:
@@ -14,7 +14,6 @@ use rope::Rope;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use smol::io::{AsyncBufReadExt, AsyncReadExt, BufReader};
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::process::{ExitStatus, Stdio};
|
||||
use std::{
|
||||
@@ -848,7 +847,7 @@ impl GitRepository for RealGitRepository {
|
||||
}
|
||||
|
||||
files.push(CommitFile {
|
||||
path: rel_path.into(),
|
||||
path: RepoPath(Arc::from(rel_path)),
|
||||
old_text,
|
||||
new_text,
|
||||
})
|
||||
@@ -2049,6 +2048,11 @@ fn git_status_args(path_prefixes: &[RepoPath]) -> Vec<OsString> {
|
||||
OsString::from("--no-renames"),
|
||||
OsString::from("-z"),
|
||||
];
|
||||
args.extend(
|
||||
path_prefixes
|
||||
.iter()
|
||||
.map(|path_prefix| path_prefix.as_std_path().into()),
|
||||
);
|
||||
args.extend(path_prefixes.iter().map(|path_prefix| {
|
||||
if path_prefix.is_empty() {
|
||||
Path::new(".").into()
|
||||
@@ -2304,23 +2308,43 @@ async fn run_askpass_command(
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Ord, Hash, PartialOrd, Eq, PartialEq)]
|
||||
pub struct RepoPath(pub Arc<RelPath>);
|
||||
#[derive(Clone, Ord, Hash, PartialOrd, Eq, PartialEq)]
|
||||
pub struct RepoPath(Arc<RelPath>);
|
||||
|
||||
impl std::fmt::Debug for RepoPath {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl RepoPath {
|
||||
pub fn new<S: AsRef<str> + ?Sized>(s: &S) -> Result<Self> {
|
||||
let rel_path = RelPath::unix(s.as_ref())?;
|
||||
Ok(rel_path.into())
|
||||
}
|
||||
|
||||
pub fn from_proto(proto: &str) -> Result<Self> {
|
||||
let rel_path = RelPath::from_proto(proto)?;
|
||||
Ok(rel_path.into())
|
||||
Ok(Self::from_rel_path(rel_path))
|
||||
}
|
||||
|
||||
pub fn from_std_path(path: &Path, path_style: PathStyle) -> Result<Self> {
|
||||
let rel_path = RelPath::new(path, path_style)?;
|
||||
Ok(Self(rel_path.as_ref().into()))
|
||||
Ok(Self::from_rel_path(&rel_path))
|
||||
}
|
||||
|
||||
pub fn from_proto(proto: &str) -> Result<Self> {
|
||||
let rel_path = RelPath::from_proto(proto)?;
|
||||
Ok(Self(rel_path))
|
||||
}
|
||||
|
||||
pub fn from_rel_path(path: &RelPath) -> RepoPath {
|
||||
Self(Arc::from(path))
|
||||
}
|
||||
|
||||
pub fn as_std_path(&self) -> &Path {
|
||||
// git2 does not like empty paths and our RelPath infra turns `.` into ``
|
||||
// so undo that here
|
||||
if self.is_empty() {
|
||||
Path::new(".")
|
||||
} else {
|
||||
self.0.as_std_path()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2329,27 +2353,9 @@ pub fn repo_path<S: AsRef<str> + ?Sized>(s: &S) -> RepoPath {
|
||||
RepoPath(RelPath::unix(s.as_ref()).unwrap().into())
|
||||
}
|
||||
|
||||
impl From<&RelPath> for RepoPath {
|
||||
fn from(value: &RelPath) -> Self {
|
||||
RepoPath(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Cow<'a, RelPath>> for RepoPath {
|
||||
fn from(value: Cow<'a, RelPath>) -> Self {
|
||||
value.as_ref().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Arc<RelPath>> for RepoPath {
|
||||
fn from(value: Arc<RelPath>) -> Self {
|
||||
RepoPath(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RepoPath {
|
||||
fn default() -> Self {
|
||||
RepoPath(RelPath::empty().into())
|
||||
impl AsRef<Arc<RelPath>> for RepoPath {
|
||||
fn as_ref(&self) -> &Arc<RelPath> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2361,12 +2367,6 @@ impl std::ops::Deref for RepoPath {
|
||||
}
|
||||
}
|
||||
|
||||
// impl AsRef<Path> for RepoPath {
|
||||
// fn as_ref(&self) -> &Path {
|
||||
// RelPath::as_ref(&self.0)
|
||||
// }
|
||||
// }
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RepoPathDescendants<'a>(pub &'a RepoPath);
|
||||
|
||||
|
||||
@@ -454,7 +454,7 @@ impl FromStr for GitStatus {
|
||||
let status = entry.as_bytes()[0..2].try_into().unwrap();
|
||||
let status = FileStatus::from_bytes(status).log_err()?;
|
||||
// git-status outputs `/`-delimited repo paths, even on Windows.
|
||||
let path = RepoPath(RelPath::unix(path).log_err()?.into());
|
||||
let path = RepoPath::from_rel_path(RelPath::unix(path).log_err()?);
|
||||
Some((path, status))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
@@ -539,7 +539,7 @@ impl FromStr for TreeDiff {
|
||||
let mut fields = s.split('\0');
|
||||
let mut parsed = HashMap::default();
|
||||
while let Some((status, path)) = fields.next().zip(fields.next()) {
|
||||
let path = RepoPath(RelPath::unix(path)?.into());
|
||||
let path = RepoPath::from_rel_path(RelPath::unix(path)?);
|
||||
|
||||
let mut fields = status.split(" ").skip(2);
|
||||
let old_sha = fields
|
||||
|
||||
Reference in New Issue
Block a user