Merge branch 'main' into cv-main-xx1jlt
This commit is contained in:
@@ -195,6 +195,7 @@ fn git_command_error(operation: &str, stderr: &[u8]) -> AppCommandError {
|
|||||||
|
|
||||||
async fn detect_conflicts(path: &str) -> Result<Vec<String>, AppCommandError> {
|
async fn detect_conflicts(path: &str) -> Result<Vec<String>, AppCommandError> {
|
||||||
let output = crate::process::tokio_command("git")
|
let output = crate::process::tokio_command("git")
|
||||||
|
.args(["-c", "core.quotePath=false"])
|
||||||
.args(["diff", "--name-only", "--diff-filter=U"])
|
.args(["diff", "--name-only", "--diff-filter=U"])
|
||||||
.current_dir(path)
|
.current_dir(path)
|
||||||
.output()
|
.output()
|
||||||
@@ -207,7 +208,7 @@ async fn detect_conflicts(path: &str) -> Result<Vec<String>, AppCommandError> {
|
|||||||
|
|
||||||
Ok(String::from_utf8_lossy(&output.stdout)
|
Ok(String::from_utf8_lossy(&output.stdout)
|
||||||
.lines()
|
.lines()
|
||||||
.map(|l| l.trim().to_string())
|
.map(|l| unquote_git_path(l))
|
||||||
.filter(|l| !l.is_empty())
|
.filter(|l| !l.is_empty())
|
||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
@@ -1046,6 +1047,7 @@ pub async fn git_stash_show(
|
|||||||
stash_ref: String,
|
stash_ref: String,
|
||||||
) -> Result<Vec<GitStatusEntry>, AppCommandError> {
|
) -> Result<Vec<GitStatusEntry>, AppCommandError> {
|
||||||
let output = crate::process::tokio_command("git")
|
let output = crate::process::tokio_command("git")
|
||||||
|
.args(["-c", "core.quotePath=false"])
|
||||||
.args(["stash", "show", "--name-status", &stash_ref])
|
.args(["stash", "show", "--name-status", &stash_ref])
|
||||||
.current_dir(&path)
|
.current_dir(&path)
|
||||||
.output()
|
.output()
|
||||||
@@ -1063,7 +1065,7 @@ pub async fn git_stash_show(
|
|||||||
.filter_map(|line| {
|
.filter_map(|line| {
|
||||||
let mut parts = line.splitn(2, '\t');
|
let mut parts = line.splitn(2, '\t');
|
||||||
let status = parts.next()?.trim().to_string();
|
let status = parts.next()?.trim().to_string();
|
||||||
let file = parts.next()?.trim().to_string();
|
let file = unquote_git_path(parts.next()?);
|
||||||
Some(GitStatusEntry { status, file })
|
Some(GitStatusEntry { status, file })
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@@ -1074,6 +1076,7 @@ pub async fn git_stash_show(
|
|||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn git_status(path: String) -> Result<Vec<GitStatusEntry>, AppCommandError> {
|
pub async fn git_status(path: String) -> Result<Vec<GitStatusEntry>, AppCommandError> {
|
||||||
let output = crate::process::tokio_command("git")
|
let output = crate::process::tokio_command("git")
|
||||||
|
.args(["-c", "core.quotePath=false"])
|
||||||
.args(["status", "--porcelain=v1", "-uall"])
|
.args(["status", "--porcelain=v1", "-uall"])
|
||||||
.current_dir(&path)
|
.current_dir(&path)
|
||||||
.output()
|
.output()
|
||||||
@@ -1089,7 +1092,7 @@ pub async fn git_status(path: String) -> Result<Vec<GitStatusEntry>, AppCommandE
|
|||||||
.filter(|l| !l.is_empty())
|
.filter(|l| !l.is_empty())
|
||||||
.map(|line| {
|
.map(|line| {
|
||||||
let status = line[..2].trim().to_string();
|
let status = line[..2].trim().to_string();
|
||||||
let file = line[3..].to_string();
|
let file = unquote_git_path(&line[3..]);
|
||||||
GitStatusEntry { status, file }
|
GitStatusEntry { status, file }
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@@ -1837,6 +1840,20 @@ fn to_git_literal_pathspec(path: &str) -> String {
|
|||||||
format!(":(literal){path}")
|
format!(":(literal){path}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove surrounding quotes from a git output path.
|
||||||
|
/// Git quotes paths containing non-ASCII or special characters, e.g.
|
||||||
|
/// `"path/\344\270\255\346\226\207.txt"`. With `core.quotePath=false`
|
||||||
|
/// the octal escapes are gone, but the quotes may still appear for paths
|
||||||
|
/// with spaces, tabs, etc.
|
||||||
|
fn unquote_git_path(path: &str) -> String {
|
||||||
|
let trimmed = path.trim();
|
||||||
|
if trimmed.len() >= 2 && trimmed.starts_with('"') && trimmed.ends_with('"') {
|
||||||
|
trimmed[1..trimmed.len() - 1].to_string()
|
||||||
|
} else {
|
||||||
|
trimmed.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn normalize_slash_path(path: &Path) -> String {
|
fn normalize_slash_path(path: &Path) -> String {
|
||||||
path.to_string_lossy().replace('\\', "/")
|
path.to_string_lossy().replace('\\', "/")
|
||||||
}
|
}
|
||||||
@@ -3174,6 +3191,7 @@ pub async fn git_log(
|
|||||||
args.push(b.clone());
|
args.push(b.clone());
|
||||||
}
|
}
|
||||||
let output = crate::process::tokio_command("git")
|
let output = crate::process::tokio_command("git")
|
||||||
|
.args(["-c", "core.quotePath=false"])
|
||||||
.args(&args)
|
.args(&args)
|
||||||
.current_dir(&path)
|
.current_dir(&path)
|
||||||
.output()
|
.output()
|
||||||
@@ -3367,7 +3385,7 @@ impl GitLogEntryBuilder {
|
|||||||
fn parse_raw_file_line(line: &str) -> Option<(String, String)> {
|
fn parse_raw_file_line(line: &str) -> Option<(String, String)> {
|
||||||
let mut parts = line.split('\t');
|
let mut parts = line.split('\t');
|
||||||
let meta = parts.next()?;
|
let meta = parts.next()?;
|
||||||
let file_path = parts.next()?.to_string();
|
let file_path = unquote_git_path(parts.next()?);
|
||||||
let status = meta
|
let status = meta
|
||||||
.split_whitespace()
|
.split_whitespace()
|
||||||
.last()
|
.last()
|
||||||
@@ -3381,7 +3399,7 @@ fn parse_numstat_file_line(line: &str) -> Option<(u32, u32, String)> {
|
|||||||
let mut parts = line.splitn(3, '\t');
|
let mut parts = line.splitn(3, '\t');
|
||||||
let additions = parse_numstat_count(parts.next()?);
|
let additions = parse_numstat_count(parts.next()?);
|
||||||
let deletions = parse_numstat_count(parts.next()?);
|
let deletions = parse_numstat_count(parts.next()?);
|
||||||
let file_path = parts.next()?.to_string();
|
let file_path = unquote_git_path(parts.next()?);
|
||||||
Some((additions, deletions, file_path))
|
Some((additions, deletions, file_path))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user