Skip to content

Commit

Permalink
Cache last known head name, whenever the underlying repository is opened
Browse files Browse the repository at this point in the history
  • Loading branch information
dgyurov committed Jan 29, 2023
1 parent 4a15ff4 commit 3a4594e
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 50 deletions.
4 changes: 2 additions & 2 deletions helix-term/src/commands/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1044,7 +1044,7 @@ fn reload(
let scrolloff = cx.editor.config().scrolloff;
let redraw_handle = cx.editor.redraw_handle.clone();
let (view, doc) = current!(cx.editor);
doc.reload(view, &cx.editor.diff_providers, redraw_handle)
doc.reload(view, &mut cx.editor.diff_providers, redraw_handle)
.map(|_| {
view.ensure_cursor_in_view(doc, scrolloff);
})
Expand Down Expand Up @@ -1087,7 +1087,7 @@ fn reload_all(
view.sync_changes(doc);

let redraw_handle = cx.editor.redraw_handle.clone();
doc.reload(view, &cx.editor.diff_providers, redraw_handle)?;
doc.reload(view, &mut cx.editor.diff_providers, redraw_handle)?;

for view_id in view_ids {
let view = view_mut!(cx.editor, view_id);
Expand Down
7 changes: 3 additions & 4 deletions helix-term/src/ui/statusline.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use helix_core::{coords_at_pos, encoding, find_root, Position};
use helix_core::{coords_at_pos, encoding, Position};
use helix_lsp::lsp::DiagnosticSeverity;
use helix_view::{
document::{Mode, SCRATCH_BUFFER_NAME},
Expand Down Expand Up @@ -472,12 +472,11 @@ fn render_version_control<F>(context: &mut RenderContext, write: F)
where
F: Fn(&mut RenderContext, String, Option<Style>) + Copy,
{
let path = find_root(None, &[]);

let current_branch_name = context
.editor
.diff_providers
.get_current_head_name(&path)
.last_known_head_name
.clone()
.unwrap_or_default();

write(context, current_branch_name, None);
Expand Down
33 changes: 16 additions & 17 deletions helix-vcs/src/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use git::sec::trust::DefaultForLevel;
use git::{Commit, ObjectId, Repository, ThreadSafeRepository};
use git_repository as git;

use crate::DiffProvider;
use crate::{DiffProvider, VersionControlData};

#[cfg(test)]
mod test;
Expand Down Expand Up @@ -54,7 +54,7 @@ impl Git {
}

impl DiffProvider for Git {
fn get_diff_base(&self, file: &Path) -> Option<Vec<u8>> {
fn get_version_control_data(&self, file: &Path) -> Option<VersionControlData> {
debug_assert!(!file.exists() || file.is_file());
debug_assert!(file.is_absolute());

Expand All @@ -64,16 +64,16 @@ impl DiffProvider for Git {
let file_oid = find_file_in_commit(&repo, &head, file)?;

let file_object = repo.find_object(file_oid).ok()?;
let mut data = file_object.detach().data;
let mut diff_base = 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 normalized_file = Vec::with_capacity(diff_base.len());
let mut at_cr = false;
for &byte in &data {
for &byte in &diff_base {
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
Expand All @@ -84,21 +84,20 @@ impl DiffProvider for Git {
at_cr = byte == b'\r';
normalized_file.push(byte)
}
data = normalized_file
diff_base = normalized_file
}
Some(data)
}

fn get_current_head_name(&self, file: &Path) -> Option<String> {
// TODO cache repository lookup
let repo = Git::open_repo(file, None)?.to_thread_local();
let head_ref = repo.head_ref().ok()?;
let head_commit = repo.head_commit().ok()?;
let head_name = repo
.head_ref()
.ok()
.flatten()
.map(|reference| reference.name().shorten().to_string())
.unwrap_or(head.id.to_hex_with_len(8).to_string());

match head_ref {
Some(reference) => Some(reference.name().shorten().to_string()),
None => Some(head_commit.id.to_hex_with_len(8).to_string()),
}
Some(VersionControlData {
diff_base,
head_name,
})
}
}

Expand Down
36 changes: 30 additions & 6 deletions helix-vcs/src/git/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ fn missing_file() {
let file = temp_git.path().join("file.txt");
File::create(&file).unwrap().write_all(b"foo").unwrap();

assert_eq!(Git.get_diff_base(&file), None);
assert_eq!(
Git.get_version_control_data(&file)
.map(|data| data.diff_base),
None
);
}

#[test]
Expand All @@ -64,7 +68,11 @@ fn unmodified_file() {
let contents = b"foo".as_slice();
File::create(&file).unwrap().write_all(contents).unwrap();
create_commit(temp_git.path(), true);
assert_eq!(Git.get_diff_base(&file), Some(Vec::from(contents)));
assert_eq!(
Git.get_version_control_data(&file)
.map(|data| data.diff_base),
Some(Vec::from(contents))
);
}

#[test]
Expand All @@ -76,7 +84,11 @@ fn modified_file() {
create_commit(temp_git.path(), true);
File::create(&file).unwrap().write_all(b"bar").unwrap();

assert_eq!(Git.get_diff_base(&file), Some(Vec::from(contents)));
assert_eq!(
Git.get_version_control_data(&file)
.map(|data| data.diff_base),
Some(Vec::from(contents))
);
}

/// Test that `get_file_head` does not return content for a directory.
Expand All @@ -95,7 +107,11 @@ fn directory() {

std::fs::remove_dir_all(&dir).unwrap();
File::create(&dir).unwrap().write_all(b"bar").unwrap();
assert_eq!(Git.get_diff_base(&dir), None);
assert_eq!(
Git.get_version_control_data(&dir)
.map(|data| data.diff_base),
None
);
}

/// Test that `get_file_head` does not return content for a symlink.
Expand All @@ -116,6 +132,14 @@ fn symlink() {
symlink("file.txt", &file_link).unwrap();

create_commit(temp_git.path(), true);
assert_eq!(Git.get_diff_base(&file_link), None);
assert_eq!(Git.get_diff_base(&file), Some(Vec::from(contents)));
assert_eq!(
Git.get_version_control_data(&file_link)
.map(|data| data.diff_base),
None
);
assert_eq!(
Git.get_version_control_data(&file)
.map(|data| data.diff_base),
Some(Vec::from(contents))
);
}
35 changes: 19 additions & 16 deletions helix-vcs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,42 +12,41 @@ mod diff;

pub use diff::{DiffHandle, Hunk};

pub struct VersionControlData {
pub diff_base: Vec<u8>,
pub head_name: String,
}

pub trait DiffProvider {
/// Returns the data that a diff should be computed against
/// if this provider is used.
/// The data is returned as raw byte without any decoding or encoding performed
/// to ensure all file encodings are handled correctly.
fn get_diff_base(&self, file: &Path) -> Option<Vec<u8>>;
fn get_current_head_name(&self, file: &Path) -> Option<String>;
fn get_version_control_data(&self, file: &Path) -> Option<VersionControlData>;
}

#[doc(hidden)]
pub struct Dummy;
impl DiffProvider for Dummy {
fn get_diff_base(&self, _file: &Path) -> Option<Vec<u8>> {
None
}

fn get_current_head_name(&self, _file: &Path) -> Option<String> {
fn get_version_control_data(&self, _file: &Path) -> Option<VersionControlData> {
None
}
}

pub struct DiffProviderRegistry {
pub last_known_head_name: Option<String>,
providers: Vec<Box<dyn DiffProvider>>,
}

impl DiffProviderRegistry {
pub fn get_diff_base(&self, file: &Path) -> Option<Vec<u8>> {
self.providers
pub fn load_version_control_data(&mut self, file: &Path) -> Option<VersionControlData> {
let data = self
.providers
.iter()
.find_map(|provider| provider.get_diff_base(file))
}
.find_map(|provider| provider.get_version_control_data(file));

pub fn get_current_head_name(&self, file: &Path) -> Option<String> {
self.providers
.iter()
.find_map(|provider| provider.get_current_head_name(file))
self.last_known_head_name = data.as_ref().map(|data| data.head_name.clone());
data
}
}

Expand All @@ -57,6 +56,10 @@ impl Default for DiffProviderRegistry {
// TODO make this configurable when more providers are added
let git: Box<dyn DiffProvider> = Box::new(Git);
let providers = vec![git];
DiffProviderRegistry { providers }

DiffProviderRegistry {
providers,
last_known_head_name: None,
}
}
}
6 changes: 3 additions & 3 deletions helix-view/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ impl Document {
pub fn reload(
&mut self,
view: &mut View,
provider_registry: &DiffProviderRegistry,
provider_registry: &mut DiffProviderRegistry,
redraw_handle: RedrawHandle,
) -> Result<(), Error> {
let encoding = &self.encoding;
Expand All @@ -656,8 +656,8 @@ impl Document {

self.detect_indent_and_line_ending();

match provider_registry.get_diff_base(&path) {
Some(diff_base) => self.set_diff_base(diff_base, redraw_handle),
match provider_registry.load_version_control_data(&path) {
Some(data) => self.set_diff_base(data.diff_base, redraw_handle),
None => self.diff_handle = None,
}

Expand Down
4 changes: 2 additions & 2 deletions helix-view/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1226,8 +1226,8 @@ impl Editor {
let mut doc = Document::open(&path, None, Some(self.syn_loader.clone()))?;

let _ = Self::launch_language_server(&mut self.language_servers, &mut doc);
if let Some(diff_base) = self.diff_providers.get_diff_base(&path) {
doc.set_diff_base(diff_base, self.redraw_handle.clone());
if let Some(data) = self.diff_providers.load_version_control_data(&path) {
doc.set_diff_base(data.diff_base, self.redraw_handle.clone());
}
self.new_document(doc)
};
Expand Down

0 comments on commit 3a4594e

Please sign in to comment.