From 81ae768a4ea20543bc16246a46552a69204fd7c1 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Sun, 4 Feb 2024 03:23:33 +0900 Subject: Use gix pipeline filter instead of manual crlf implementation (#9503) --- helix-vcs/Cargo.toml | 2 +- helix-vcs/src/git.rs | 38 ++++++++++++++++---------------------- 2 files changed, 17 insertions(+), 23 deletions(-) (limited to 'helix-vcs') diff --git a/helix-vcs/Cargo.toml b/helix-vcs/Cargo.toml index 051134e4..6aa50dcf 100644 --- a/helix-vcs/Cargo.toml +++ b/helix-vcs/Cargo.toml @@ -19,7 +19,7 @@ tokio = { version = "1", features = ["rt", "rt-multi-thread", "time", "sync", "p parking_lot = "0.12" arc-swap = { version = "1.6.0" } -gix = { version = "0.58.0", default-features = false , optional = true } +gix = { version = "0.58.0", features = ["attributes"], default-features = false, optional = true } imara-diff = "0.1.5" anyhow = "1" diff --git a/helix-vcs/src/git.rs b/helix-vcs/src/git.rs index e4d45301..995bade0 100644 --- a/helix-vcs/src/git.rs +++ b/helix-vcs/src/git.rs @@ -1,5 +1,7 @@ use anyhow::{bail, Context, Result}; use arc_swap::ArcSwap; +use gix::filter::plumbing::driver::apply::Delay; +use std::io::Read; use std::path::Path; use std::sync::Arc; @@ -76,29 +78,21 @@ impl DiffProvider for Git { let file_oid = find_file_in_commit(&repo, &head, file)?; let file_object = repo.find_object(file_oid)?; - let mut data = file_object.detach().data; - // convert LF to CRLF if configured to avoid showing every line as changed - if repo - .config_snapshot() - .boolean("core.autocrlf") - .unwrap_or(false) - { - let mut normalized_file = Vec::with_capacity(data.len()); - let mut at_cr = false; - for &byte in &data { - if byte == b'\n' { - // if this is a LF instead of a CRLF (last byte was not a CR) - // insert a new CR to generate a CRLF - if !at_cr { - normalized_file.push(b'\r'); - } - } - at_cr = byte == b'\r'; - normalized_file.push(byte) - } - data = normalized_file + let data = file_object.detach().data; + // Get the actual data that git would make out of the git object. + // This will apply the user's git config or attributes like crlf conversions. + if let Some(work_dir) = repo.work_dir() { + let rela_path = file.strip_prefix(work_dir)?; + let rela_path = gix::path::try_into_bstr(rela_path)?; + let (mut pipeline, _) = repo.filter_pipeline(None)?; + let mut worktree_outcome = + pipeline.convert_to_worktree(&data, rela_path.as_ref(), Delay::Forbid)?; + let mut buf = Vec::with_capacity(data.len()); + worktree_outcome.read_to_end(&mut buf)?; + Ok(buf) + } else { + Ok(data) } - Ok(data) } fn get_current_head_name(&self, file: &Path) -> Result>>> { -- cgit v1.2.3-70-g09d2