fix: keep a path's bytes, so a filename that is not utf-8 survives

This commit is contained in:
2026-09-09 12:01:59 +00:00
parent b4b6d5918f
commit e146b0460a
8 changed files with 172 additions and 72 deletions

View File

@@ -1,6 +1,7 @@
use fs_err as fs;
use std::env;
use std::ffi::OsString;
use std::os::unix::ffi::OsStringExt;
use std::path::{Path, PathBuf};
use anyhow::{Context, Result, anyhow};
@@ -69,16 +70,21 @@ pub(super) fn resolve(path: &Path) -> Result<PathBuf> {
}
fn git_root(ctx: &Ctx) -> Result<PathBuf> {
// bytes, since the checkout can live at a path that is not utf-8, and with
// the cause kept: git not being installed and the directory not being a
// repository are different problems with the same one-line answer otherwise
let root = RevParse
.capture(ctx)
.map_err(|_| anyhow!("not inside a git repository"))?;
.capture_bytes(ctx)
.context("asking git for the repository root")?;
let root = root.trim().to_string();
let root = root.strip_suffix(b"\n").unwrap_or(&root);
if root.is_empty() {
return Err(anyhow!("git reported an empty repository root"));
}
Ok(fs::canonicalize(&root)?)
Ok(fs::canonicalize(PathBuf::from(OsString::from_vec(
root.to_vec(),
)))?)
}
fn repo_components(ctx: &Ctx, root: &Path) -> Result<PathBuf> {
@@ -170,9 +176,12 @@ fn non_empty_var(name: &str) -> Option<OsString> {
}
pub(super) fn tracked(ctx: &Ctx, repo: &Repo, rel: &Path) -> Result<bool> {
// bytes: the listing echoes back the path asked about, which is not obliged
// to be utf-8, and failing to read it would refuse the path for the wrong
// reason rather than answering whether git tracks it
let listed = LsFiles::tracked(&repo.root)
.limited_to(&[rel])
.capture(ctx)?;
.capture_bytes(ctx)?;
Ok(!listed.is_empty())
}