Detailed changes
@@ -23,6 +23,7 @@ use std::{
path::PathBuf,
sync::{Arc, LazyLock},
};
+use text::LineEnding;
use util::{paths::PathStyle, rel_path::RelPath};
pub static LOAD_INDEX_TEXT_TASK: LazyLock<TaskLabel> = LazyLock::new(TaskLabel::new);
@@ -452,7 +453,12 @@ impl GitRepository for FakeGitRepository {
})
}
- fn blame(&self, path: RepoPath, _content: Rope) -> BoxFuture<'_, Result<git::blame::Blame>> {
+ fn blame(
+ &self,
+ path: RepoPath,
+ _content: Rope,
+ _line_ending: LineEnding,
+ ) -> BoxFuture<'_, Result<git::blame::Blame>> {
self.with_state_async(false, move |state| {
state
.blames
@@ -803,7 +803,7 @@ impl Fs for RealFs {
}
let file = smol::fs::File::create(path).await?;
let mut writer = smol::io::BufWriter::with_capacity(buffer_size, file);
- for chunk in chunks(text, line_ending) {
+ for chunk in text::chunks_with_line_ending(text, line_ending) {
writer.write_all(chunk.as_bytes()).await?;
}
writer.flush().await?;
@@ -2555,7 +2555,7 @@ impl Fs for FakeFs {
async fn save(&self, path: &Path, text: &Rope, line_ending: LineEnding) -> Result<()> {
self.simulate_random_delay().await;
let path = normalize_path(path);
- let content = chunks(text, line_ending).collect::<String>();
+ let content = text::chunks_with_line_ending(text, line_ending).collect::<String>();
if let Some(path) = path.parent() {
self.create_dir(path).await?;
}
@@ -2773,25 +2773,6 @@ impl Fs for FakeFs {
}
}
-fn chunks(rope: &Rope, line_ending: LineEnding) -> impl Iterator<Item = &str> {
- rope.chunks().flat_map(move |chunk| {
- let mut newline = false;
- let end_with_newline = chunk.ends_with('\n').then_some(line_ending.as_str());
- chunk
- .lines()
- .flat_map(move |line| {
- let ending = if newline {
- Some(line_ending.as_str())
- } else {
- None
- };
- newline = true;
- ending.into_iter().chain([line])
- })
- .chain(end_with_newline)
- })
-}
-
pub fn normalize_path(path: &Path) -> PathBuf {
let mut components = path.components().peekable();
let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
@@ -8,7 +8,7 @@ use gpui::SharedString;
use serde::{Deserialize, Serialize};
use std::process::Stdio;
use std::{ops::Range, path::Path};
-use text::Rope;
+use text::{LineEnding, Rope};
use time::OffsetDateTime;
use time::UtcOffset;
use time::macros::format_description;
@@ -35,8 +35,10 @@ impl Blame {
working_directory: &Path,
path: &RepoPath,
content: &Rope,
+ line_ending: LineEnding,
) -> Result<Self> {
- let output = run_git_blame(git_binary, working_directory, path, content).await?;
+ let output =
+ run_git_blame(git_binary, working_directory, path, content, line_ending).await?;
let mut entries = parse_git_blame(&output)?;
entries.sort_unstable_by(|a, b| a.range.start.cmp(&b.range.start));
@@ -63,12 +65,12 @@ async fn run_git_blame(
working_directory: &Path,
path: &RepoPath,
contents: &Rope,
+ line_ending: LineEnding,
) -> Result<String> {
let mut child = util::command::new_smol_command(git_binary)
.current_dir(working_directory)
.arg("blame")
.arg("--incremental")
- .arg("-w")
.arg("--contents")
.arg("-")
.arg(path.as_unix_str())
@@ -83,7 +85,7 @@ async fn run_git_blame(
.as_mut()
.context("failed to get pipe to stdin of git blame command")?;
- for chunk in contents.chunks() {
+ for chunk in text::chunks_with_line_ending(contents, line_ending) {
stdin.write_all(chunk.as_bytes()).await?;
}
stdin.flush().await?;
@@ -14,6 +14,7 @@ use rope::Rope;
use schemars::JsonSchema;
use serde::Deserialize;
use smol::io::{AsyncBufReadExt, AsyncReadExt, BufReader};
+use text::LineEnding;
use std::collections::HashSet;
use std::ffi::{OsStr, OsString};
@@ -487,7 +488,12 @@ pub trait GitRepository: Send + Sync {
fn show(&self, commit: String) -> BoxFuture<'_, Result<CommitDetails>>;
fn load_commit(&self, commit: String, cx: AsyncApp) -> BoxFuture<'_, Result<CommitDiff>>;
- fn blame(&self, path: RepoPath, content: Rope) -> BoxFuture<'_, Result<crate::blame::Blame>>;
+ fn blame(
+ &self,
+ path: RepoPath,
+ content: Rope,
+ line_ending: LineEnding,
+ ) -> BoxFuture<'_, Result<crate::blame::Blame>>;
fn file_history(&self, path: RepoPath) -> BoxFuture<'_, Result<FileHistory>>;
fn file_history_paginated(
&self,
@@ -1512,7 +1518,12 @@ impl GitRepository for RealGitRepository {
.boxed()
}
- fn blame(&self, path: RepoPath, content: Rope) -> BoxFuture<'_, Result<crate::blame::Blame>> {
+ fn blame(
+ &self,
+ path: RepoPath,
+ content: Rope,
+ line_ending: LineEnding,
+ ) -> BoxFuture<'_, Result<crate::blame::Blame>> {
let working_directory = self.working_directory();
let git_binary_path = self.any_git_binary_path.clone();
let executor = self.executor.clone();
@@ -1524,6 +1535,7 @@ impl GitRepository for RealGitRepository {
&working_directory?,
&path,
&content,
+ line_ending,
)
.await
})
@@ -1031,6 +1031,7 @@ impl GitStore {
Some(version) => buffer.rope_for_version(version),
None => buffer.as_rope().clone(),
};
+ let line_ending = buffer.line_ending();
let version = version.unwrap_or(buffer.version());
let buffer_id = buffer.remote_id();
@@ -1042,7 +1043,7 @@ impl GitStore {
.map_err(|err| anyhow::anyhow!(err))?;
match repository_state {
RepositoryState::Local(LocalRepositoryState { backend, .. }) => backend
- .blame(repo_path.clone(), content)
+ .blame(repo_path.clone(), content, line_ending)
.await
.with_context(|| format!("Failed to blame {:?}", repo_path.as_ref()))
.map(Some),
@@ -3387,6 +3387,25 @@ impl LineEnding {
}
}
+pub fn chunks_with_line_ending(rope: &Rope, line_ending: LineEnding) -> impl Iterator<Item = &str> {
+ rope.chunks().flat_map(move |chunk| {
+ let mut newline = false;
+ let end_with_newline = chunk.ends_with('\n').then_some(line_ending.as_str());
+ chunk
+ .lines()
+ .flat_map(move |line| {
+ let ending = if newline {
+ Some(line_ending.as_str())
+ } else {
+ None
+ };
+ newline = true;
+ ending.into_iter().chain([line])
+ })
+ .chain(end_with_newline)
+ })
+}
+
#[cfg(debug_assertions)]
pub mod debug {
use super::*;