Move git related things into specialized git crate

Co-Authored-By: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
Julia 2022-09-28 11:43:33 -04:00
parent bf3b3da6ed
commit d5fd531743
17 changed files with 151 additions and 100 deletions

22
Cargo.lock generated
View file

@ -1697,6 +1697,7 @@ dependencies = [
"env_logger", "env_logger",
"futures", "futures",
"fuzzy", "fuzzy",
"git",
"gpui", "gpui",
"indoc", "indoc",
"itertools", "itertools",
@ -2224,6 +2225,23 @@ dependencies = [
"stable_deref_trait", "stable_deref_trait",
] ]
[[package]]
name = "git"
version = "0.1.0"
dependencies = [
"anyhow",
"clock",
"git2",
"lazy_static",
"log",
"parking_lot 0.11.2",
"smol",
"sum_tree",
"text",
"unindent",
"util",
]
[[package]] [[package]]
name = "git2" name = "git2"
version = "0.15.0" version = "0.15.0"
@ -2853,7 +2871,7 @@ dependencies = [
"env_logger", "env_logger",
"futures", "futures",
"fuzzy", "fuzzy",
"git2", "git",
"gpui", "gpui",
"lazy_static", "lazy_static",
"log", "log",
@ -3996,7 +4014,7 @@ dependencies = [
"fsevent", "fsevent",
"futures", "futures",
"fuzzy", "fuzzy",
"git2", "git",
"gpui", "gpui",
"ignore", "ignore",
"language", "language",

View file

@ -25,6 +25,7 @@ clock = { path = "../clock" }
collections = { path = "../collections" } collections = { path = "../collections" }
context_menu = { path = "../context_menu" } context_menu = { path = "../context_menu" }
fuzzy = { path = "../fuzzy" } fuzzy = { path = "../fuzzy" }
git = { path = "../git" }
gpui = { path = "../gpui" } gpui = { path = "../gpui" }
language = { path = "../language" } language = { path = "../language" }
lsp = { path = "../lsp" } lsp = { path = "../lsp" }

View file

@ -16,6 +16,7 @@ use crate::{
}; };
use clock::ReplicaId; use clock::ReplicaId;
use collections::{BTreeMap, HashMap}; use collections::{BTreeMap, HashMap};
use git::diff::{DiffHunk, DiffHunkStatus};
use gpui::{ use gpui::{
color::Color, color::Color,
elements::*, elements::*,
@ -34,7 +35,6 @@ use gpui::{
WeakViewHandle, WeakViewHandle,
}; };
use json::json; use json::json;
use language::git::{DiffHunk, DiffHunkStatus};
use language::{Bias, DiagnosticSeverity, OffsetUtf16, Selection}; use language::{Bias, DiagnosticSeverity, OffsetUtf16, Selection};
use project::ProjectPath; use project::ProjectPath;
use settings::Settings; use settings::Settings;

View file

@ -4,13 +4,13 @@ pub use anchor::{Anchor, AnchorRangeExt};
use anyhow::Result; use anyhow::Result;
use clock::ReplicaId; use clock::ReplicaId;
use collections::{BTreeMap, Bound, HashMap, HashSet}; use collections::{BTreeMap, Bound, HashMap, HashSet};
use git::diff::DiffHunk;
use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task}; use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task};
pub use language::Completion; pub use language::Completion;
use language::{ use language::{
char_kind, git::DiffHunk, AutoindentMode, Buffer, BufferChunks, BufferSnapshot, CharKind, char_kind, AutoindentMode, Buffer, BufferChunks, BufferSnapshot, CharKind, Chunk,
Chunk, DiagnosticEntry, Event, File, IndentSize, Language, OffsetRangeExt, Outline, DiagnosticEntry, Event, File, IndentSize, Language, OffsetRangeExt, Outline, OutlineItem,
OutlineItem, Selection, ToOffset as _, ToOffsetUtf16 as _, ToPoint as _, ToPointUtf16 as _, Selection, ToOffset as _, ToOffsetUtf16 as _, ToPoint as _, ToPointUtf16 as _, TransactionId,
TransactionId,
}; };
use smallvec::SmallVec; use smallvec::SmallVec;
use std::{ use std::{

22
crates/git/Cargo.toml Normal file
View file

@ -0,0 +1,22 @@
[package]
name = "git"
version = "0.1.0"
edition = "2021"
[lib]
path = "src/git.rs"
[dependencies]
anyhow = "1.0.38"
clock = { path = "../clock" }
git2 = { version = "0.15", default-features = false }
lazy_static = "1.4.0"
sum_tree = { path = "../sum_tree" }
text = { path = "../text" }
util = { path = "../util" }
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
smol = "1.2"
parking_lot = "0.11.1"
[dev-dependencies]
unindent = "0.1.7"

View file

@ -259,7 +259,7 @@ mod tests {
use text::Buffer; use text::Buffer;
use unindent::Unindent as _; use unindent::Unindent as _;
#[gpui::test] #[test]
fn test_buffer_diff_simple() { fn test_buffer_diff_simple() {
let head_text = " let head_text = "
one one
@ -308,8 +308,4 @@ mod tests {
); );
} }
} }
// use rand::rngs::StdRng;
// #[gpui::test(iterations = 100)]
// fn test_buffer_diff_random(mut rng: StdRng) {}
} }

12
crates/git/src/git.rs Normal file
View file

@ -0,0 +1,12 @@
use std::ffi::OsStr;
pub use git2 as libgit;
pub use lazy_static::lazy_static;
pub mod diff;
pub mod repository;
lazy_static! {
pub static ref DOT_GIT: &'static OsStr = OsStr::new(".git");
pub static ref GITIGNORE: &'static OsStr = OsStr::new(".gitignore");
}

View file

@ -1,7 +1,7 @@
use anyhow::Result; use anyhow::Result;
use git2::{Repository as LibGitRepository, RepositoryOpenFlags as LibGitRepositoryOpenFlags}; use git2::Repository as LibGitRepository;
use parking_lot::Mutex; use parking_lot::Mutex;
use std::{ffi::OsStr, path::Path, sync::Arc}; use std::{path::Path, sync::Arc};
use util::ResultExt; use util::ResultExt;
#[derive(Clone)] #[derive(Clone)]
@ -53,21 +53,17 @@ impl GitRepository {
self.scan_id self.scan_id
} }
pub(super) fn set_scan_id(&mut self, scan_id: usize) { pub fn set_scan_id(&mut self, scan_id: usize) {
println!("setting scan id");
self.scan_id = scan_id; self.scan_id = scan_id;
} }
pub fn with_repo<F: FnOnce(&mut git2::Repository)>(&mut self, f: F) { pub async fn load_head_text(&self, relative_file_path: &Path) -> Option<String> {
let mut git2 = self.libgit_repository.lock(); fn logic(repo: &LibGitRepository, relative_file_path: &Path) -> Result<Option<String>> {
f(&mut git2)
}
pub async fn load_head_text(&self, file_path: &Path) -> Option<String> {
fn logic(repo: &LibGitRepository, file_path: &Path) -> Result<Option<String>> {
let object = repo let object = repo
.head()? .head()?
.peel_to_tree()? .peel_to_tree()?
.get_path(file_path)? .get_path(relative_file_path)?
.to_object(&repo)?; .to_object(&repo)?;
let content = match object.as_blob() { let content = match object.as_blob() {
@ -79,7 +75,7 @@ impl GitRepository {
Ok(Some(head_text)) Ok(Some(head_text))
} }
match logic(&self.libgit_repository.lock(), file_path) { match logic(&self.libgit_repository.as_ref().lock(), relative_file_path) {
Ok(value) => return value, Ok(value) => return value,
Err(err) => log::error!("Error loading head text: {:?}", err), Err(err) => log::error!("Error loading head text: {:?}", err),
} }

View file

@ -25,6 +25,7 @@ client = { path = "../client" }
clock = { path = "../clock" } clock = { path = "../clock" }
collections = { path = "../collections" } collections = { path = "../collections" }
fuzzy = { path = "../fuzzy" } fuzzy = { path = "../fuzzy" }
git = { path = "../git" }
gpui = { path = "../gpui" } gpui = { path = "../gpui" }
lsp = { path = "../lsp" } lsp = { path = "../lsp" }
rpc = { path = "../rpc" } rpc = { path = "../rpc" }
@ -51,7 +52,6 @@ smol = "1.2"
tree-sitter = "0.20" tree-sitter = "0.20"
tree-sitter-rust = { version = "*", optional = true } tree-sitter-rust = { version = "*", optional = true }
tree-sitter-typescript = { version = "*", optional = true } tree-sitter-typescript = { version = "*", optional = true }
git2 = { version = "0.15", default-features = false }
[dev-dependencies] [dev-dependencies]
client = { path = "../client", features = ["test-support"] } client = { path = "../client", features = ["test-support"] }

View file

@ -1,4 +1,3 @@
use crate::git;
pub use crate::{ pub use crate::{
diagnostic_set::DiagnosticSet, diagnostic_set::DiagnosticSet,
highlight_map::{HighlightId, HighlightMap}, highlight_map::{HighlightId, HighlightMap},
@ -47,14 +46,14 @@ pub use {tree_sitter_rust, tree_sitter_typescript};
pub use lsp::DiagnosticSeverity; pub use lsp::DiagnosticSeverity;
struct GitDiffStatus { struct GitDiffStatus {
diff: git::BufferDiff, diff: git::diff::BufferDiff,
update_in_progress: bool, update_in_progress: bool,
update_requested: bool, update_requested: bool,
} }
pub struct Buffer { pub struct Buffer {
text: TextBuffer, text: TextBuffer,
head_text: Option<Arc<String>>, head_text: Option<String>,
git_diff_status: GitDiffStatus, git_diff_status: GitDiffStatus,
file: Option<Arc<dyn File>>, file: Option<Arc<dyn File>>,
saved_version: clock::Global, saved_version: clock::Global,
@ -83,7 +82,7 @@ pub struct Buffer {
pub struct BufferSnapshot { pub struct BufferSnapshot {
text: text::BufferSnapshot, text: text::BufferSnapshot,
pub git_diff: git::BufferDiff, pub git_diff: git::diff::BufferDiff,
pub(crate) syntax: SyntaxSnapshot, pub(crate) syntax: SyntaxSnapshot,
file: Option<Arc<dyn File>>, file: Option<Arc<dyn File>>,
diagnostics: DiagnosticSet, diagnostics: DiagnosticSet,
@ -353,7 +352,7 @@ impl Buffer {
) -> Self { ) -> Self {
Self::build( Self::build(
TextBuffer::new(replica_id, cx.model_id() as u64, base_text.into()), TextBuffer::new(replica_id, cx.model_id() as u64, base_text.into()),
head_text.map(|h| Arc::new(h.into())), head_text.map(|h| h.into().into_boxed_str().into()),
Some(file), Some(file),
) )
} }
@ -364,7 +363,11 @@ impl Buffer {
file: Option<Arc<dyn File>>, file: Option<Arc<dyn File>>,
) -> Result<Self> { ) -> Result<Self> {
let buffer = TextBuffer::new(replica_id, message.id, message.base_text); let buffer = TextBuffer::new(replica_id, message.id, message.base_text);
let mut this = Self::build(buffer, message.head_text.map(|text| Arc::new(text)), file); let mut this = Self::build(
buffer,
message.head_text.map(|text| text.into_boxed_str().into()),
file,
);
this.text.set_line_ending(proto::deserialize_line_ending( this.text.set_line_ending(proto::deserialize_line_ending(
proto::LineEnding::from_i32(message.line_ending) proto::LineEnding::from_i32(message.line_ending)
.ok_or_else(|| anyhow!("missing line_ending"))?, .ok_or_else(|| anyhow!("missing line_ending"))?,
@ -420,11 +423,7 @@ impl Buffer {
self self
} }
fn build( fn build(buffer: TextBuffer, head_text: Option<String>, file: Option<Arc<dyn File>>) -> Self {
buffer: TextBuffer,
head_text: Option<Arc<String>>,
file: Option<Arc<dyn File>>,
) -> Self {
let saved_mtime = if let Some(file) = file.as_ref() { let saved_mtime = if let Some(file) = file.as_ref() {
file.mtime() file.mtime()
} else { } else {
@ -440,7 +439,7 @@ impl Buffer {
text: buffer, text: buffer,
head_text, head_text,
git_diff_status: GitDiffStatus { git_diff_status: GitDiffStatus {
diff: git::BufferDiff::new(), diff: git::diff::BufferDiff::new(),
update_in_progress: false, update_in_progress: false,
update_requested: false, update_requested: false,
}, },
@ -613,7 +612,7 @@ impl Buffer {
cx, cx,
); );
} }
self.update_git(cx); self.git_diff_recalc(cx);
cx.emit(Event::Reloaded); cx.emit(Event::Reloaded);
cx.notify(); cx.notify();
} }
@ -663,9 +662,8 @@ impl Buffer {
task task
} }
pub fn update_git(&mut self, cx: &mut ModelContext<Self>) { pub fn update_head_text(&mut self, head_text: Option<String>, cx: &mut ModelContext<Self>) {
//Grab head text self.head_text = head_text;
self.git_diff_recalc(cx); self.git_diff_recalc(cx);
} }
@ -674,6 +672,7 @@ impl Buffer {
} }
pub fn git_diff_recalc(&mut self, cx: &mut ModelContext<Self>) { pub fn git_diff_recalc(&mut self, cx: &mut ModelContext<Self>) {
println!("recalc");
if self.git_diff_status.update_in_progress { if self.git_diff_status.update_in_progress {
self.git_diff_status.update_requested = true; self.git_diff_status.update_requested = true;
return; return;
@ -2221,7 +2220,7 @@ impl BufferSnapshot {
pub fn git_diff_hunks_in_range<'a>( pub fn git_diff_hunks_in_range<'a>(
&'a self, &'a self,
query_row_range: Range<u32>, query_row_range: Range<u32>,
) -> impl 'a + Iterator<Item = git::DiffHunk<u32>> { ) -> impl 'a + Iterator<Item = git::diff::DiffHunk<u32>> {
self.git_diff.hunks_in_range(query_row_range, self) self.git_diff.hunks_in_range(query_row_range, self)
} }

View file

@ -1,6 +1,5 @@
mod buffer; mod buffer;
mod diagnostic_set; mod diagnostic_set;
pub mod git;
mod highlight_map; mod highlight_map;
mod outline; mod outline;
pub mod proto; pub mod proto;

View file

@ -24,6 +24,7 @@ collections = { path = "../collections" }
db = { path = "../db" } db = { path = "../db" }
fsevent = { path = "../fsevent" } fsevent = { path = "../fsevent" }
fuzzy = { path = "../fuzzy" } fuzzy = { path = "../fuzzy" }
git = { path = "../git" }
gpui = { path = "../gpui" } gpui = { path = "../gpui" }
language = { path = "../language" } language = { path = "../language" }
lsp = { path = "../lsp" } lsp = { path = "../lsp" }
@ -52,8 +53,6 @@ smol = "1.2.5"
thiserror = "1.0.29" thiserror = "1.0.29"
toml = "0.5" toml = "0.5"
rocksdb = "0.18" rocksdb = "0.18"
git2 = { version = "0.15", default-features = false }
[dev-dependencies] [dev-dependencies]
client = { path = "../client", features = ["test-support"] } client = { path = "../client", features = ["test-support"] }

View file

@ -1,11 +1,9 @@
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use fsevent::EventStream; use fsevent::EventStream;
use futures::{future::BoxFuture, Stream, StreamExt}; use futures::{future::BoxFuture, Stream, StreamExt};
use language::git::libgit::{Repository, RepositoryOpenFlags};
use language::LineEnding; use language::LineEnding;
use smol::io::{AsyncReadExt, AsyncWriteExt}; use smol::io::{AsyncReadExt, AsyncWriteExt};
use std::{ use std::{
ffi::OsStr,
io, io,
os::unix::fs::MetadataExt, os::unix::fs::MetadataExt,
path::{Component, Path, PathBuf}, path::{Component, Path, PathBuf},
@ -22,8 +20,6 @@ use futures::lock::Mutex;
#[cfg(any(test, feature = "test-support"))] #[cfg(any(test, feature = "test-support"))]
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use crate::git_repository::GitRepository;
#[async_trait::async_trait] #[async_trait::async_trait]
pub trait Fs: Send + Sync { pub trait Fs: Send + Sync {
async fn create_dir(&self, path: &Path) -> Result<()>; async fn create_dir(&self, path: &Path) -> Result<()>;

View file

@ -1,5 +1,4 @@
pub mod fs; pub mod fs;
mod git_repository;
mod ignore; mod ignore;
mod lsp_command; mod lsp_command;
pub mod search; pub mod search;
@ -13,7 +12,7 @@ use client::{proto, Client, PeerId, TypedEnvelope, User, UserStore};
use clock::ReplicaId; use clock::ReplicaId;
use collections::{hash_map, BTreeMap, HashMap, HashSet}; use collections::{hash_map, BTreeMap, HashMap, HashSet};
use futures::{future::Shared, AsyncWriteExt, Future, FutureExt, StreamExt, TryFutureExt}; use futures::{future::Shared, AsyncWriteExt, Future, FutureExt, StreamExt, TryFutureExt};
use git_repository::GitRepository; use git::repository::GitRepository;
use gpui::{ use gpui::{
AnyModelHandle, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, AnyModelHandle, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle,
MutableAppContext, Task, UpgradeModelHandle, WeakModelHandle, MutableAppContext, Task, UpgradeModelHandle, WeakModelHandle,
@ -4538,6 +4537,7 @@ impl Project {
cx.subscribe(worktree, |this, worktree, event, cx| match event { cx.subscribe(worktree, |this, worktree, event, cx| match event {
worktree::Event::UpdatedEntries => this.update_local_worktree_buffers(worktree, cx), worktree::Event::UpdatedEntries => this.update_local_worktree_buffers(worktree, cx),
worktree::Event::UpdatedGitRepositories(updated_repos) => { worktree::Event::UpdatedGitRepositories(updated_repos) => {
println!("{updated_repos:#?}");
this.update_local_worktree_buffers_git_repos(updated_repos, cx) this.update_local_worktree_buffers_git_repos(updated_repos, cx)
} }
}) })
@ -4649,24 +4649,35 @@ impl Project {
fn update_local_worktree_buffers_git_repos( fn update_local_worktree_buffers_git_repos(
&mut self, &mut self,
updated_repos: &[GitRepository], repos: &[GitRepository],
cx: &mut ModelContext<Self>, cx: &mut ModelContext<Self>,
) { ) {
for (buffer_id, buffer) in &self.opened_buffers { //TODO: Produce protos
if let Some(buffer) = buffer.upgrade(cx) {
buffer.update(cx, |buffer, cx| {
let updated = updated_repos.iter().any(|repo| {
buffer
.file()
.and_then(|file| file.as_local())
.map(|file| repo.manages(&file.abs_path(cx)))
.unwrap_or(false)
});
if updated { for (_, buffer) in &self.opened_buffers {
buffer.update_git(cx); if let Some(buffer) = buffer.upgrade(cx) {
} let file = match buffer.read(cx).file().and_then(|file| file.as_local()) {
}); Some(file) => file,
None => return,
};
let path = file.path().clone();
let abs_path = file.abs_path(cx);
println!("got file");
let repo = match repos.iter().find(|repo| repo.manages(&abs_path)) {
Some(repo) => repo.clone(),
None => return,
};
println!("got repo");
cx.spawn(|_, mut cx| async move {
let head_text = repo.load_head_text(&path).await;
buffer.update(&mut cx, |buffer, cx| {
println!("got calling update");
buffer.update_head_text(head_text, cx);
});
})
.detach();
} }
} }
} }

View file

@ -1,10 +1,9 @@
use crate::{copy_recursive, git_repository::GitRepository, ProjectEntryId, RemoveOptions};
use super::{ use super::{
fs::{self, Fs}, fs::{self, Fs},
ignore::IgnoreStack, ignore::IgnoreStack,
DiagnosticSummary, DiagnosticSummary,
}; };
use crate::{copy_recursive, ProjectEntryId, RemoveOptions};
use ::ignore::gitignore::{Gitignore, GitignoreBuilder}; use ::ignore::gitignore::{Gitignore, GitignoreBuilder};
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use client::{proto, Client}; use client::{proto, Client};
@ -18,6 +17,8 @@ use futures::{
Stream, StreamExt, Stream, StreamExt,
}; };
use fuzzy::CharBag; use fuzzy::CharBag;
use git::repository::GitRepository;
use git::{DOT_GIT, GITIGNORE};
use gpui::{ use gpui::{
executor, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext, executor, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext,
Task, Task,
@ -48,7 +49,7 @@ use std::{
time::{Duration, SystemTime}, time::{Duration, SystemTime},
}; };
use sum_tree::{Bias, Edit, SeekTarget, SumTree, TreeMap, TreeSet}; use sum_tree::{Bias, Edit, SeekTarget, SumTree, TreeMap, TreeSet};
use util::{ResultExt, TryFutureExt, DOT_GIT, GITIGNORE}; use util::{ResultExt, TryFutureExt};
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)]
pub struct WorktreeId(usize); pub struct WorktreeId(usize);
@ -523,7 +524,10 @@ impl LocalWorktree {
match self.scan_state() { match self.scan_state() {
ScanState::Idle => { ScanState::Idle => {
let new_snapshot = self.background_snapshot.lock().clone(); let new_snapshot = self.background_snapshot.lock().clone();
let updated_repos = self.list_updated_repos(&new_snapshot); let updated_repos = Self::list_updated_repos(
&self.snapshot.git_repositories,
&new_snapshot.git_repositories,
);
self.snapshot = new_snapshot; self.snapshot = new_snapshot;
if let Some(share) = self.share.as_mut() { if let Some(share) = self.share.as_mut() {
@ -541,7 +545,10 @@ impl LocalWorktree {
let is_fake_fs = self.fs.is_fake(); let is_fake_fs = self.fs.is_fake();
let new_snapshot = self.background_snapshot.lock().clone(); let new_snapshot = self.background_snapshot.lock().clone();
let updated_repos = self.list_updated_repos(&new_snapshot); let updated_repos = Self::list_updated_repos(
&self.snapshot.git_repositories,
&new_snapshot.git_repositories,
);
self.snapshot = new_snapshot; self.snapshot = new_snapshot;
self.poll_task = Some(cx.spawn_weak(|this, mut cx| async move { self.poll_task = Some(cx.spawn_weak(|this, mut cx| async move {
@ -573,16 +580,20 @@ impl LocalWorktree {
cx.notify(); cx.notify();
} }
fn list_updated_repos(&self, new_snapshot: &LocalSnapshot) -> Vec<GitRepository> { fn list_updated_repos(
let old_snapshot = &self.snapshot; old_repos: &[GitRepository],
new_repos: &[GitRepository],
) -> Vec<GitRepository> {
println!("old repos: {:#?}", old_repos);
println!("new repos: {:#?}", new_repos);
fn diff<'a>( fn diff<'a>(
a: &'a LocalSnapshot, a: &'a [GitRepository],
b: &'a LocalSnapshot, b: &'a [GitRepository],
updated: &mut HashMap<&'a Path, GitRepository>, updated: &mut HashMap<&'a Path, GitRepository>,
) { ) {
for a_repo in &a.git_repositories { for a_repo in a {
let matched = b.git_repositories.iter().find(|b_repo| { let matched = b.iter().find(|b_repo| {
a_repo.git_dir_path() == b_repo.git_dir_path() a_repo.git_dir_path() == b_repo.git_dir_path()
&& a_repo.scan_id() == b_repo.scan_id() && a_repo.scan_id() == b_repo.scan_id()
}); });
@ -595,10 +606,10 @@ impl LocalWorktree {
let mut updated = HashMap::<&Path, GitRepository>::default(); let mut updated = HashMap::<&Path, GitRepository>::default();
diff(old_snapshot, new_snapshot, &mut updated); diff(old_repos, new_repos, &mut updated);
diff(new_snapshot, old_snapshot, &mut updated); diff(new_repos, old_repos, &mut updated);
updated.into_values().collect() dbg!(updated.into_values().collect())
} }
pub fn scan_complete(&self) -> impl Future<Output = ()> { pub fn scan_complete(&self) -> impl Future<Output = ()> {
@ -653,7 +664,7 @@ impl LocalWorktree {
settings::GitFilesIncluded::All | settings::GitFilesIncluded::OnlyTracked settings::GitFilesIncluded::All | settings::GitFilesIncluded::OnlyTracked
) { ) {
let results = if let Some(repo) = snapshot.repo_for(&abs_path) { let results = if let Some(repo) = snapshot.repo_for(&abs_path) {
repo.load_head_text(&abs_path).await repo.load_head_text(&path).await
} else { } else {
None None
}; };
@ -1362,6 +1373,7 @@ impl LocalSnapshot {
} }
pub(crate) fn in_dot_git(&mut self, path: &Path) -> Option<&mut GitRepository> { pub(crate) fn in_dot_git(&mut self, path: &Path) -> Option<&mut GitRepository> {
println!("chechking {path:?}");
self.git_repositories self.git_repositories
.iter_mut() .iter_mut()
.rev() //git_repository is ordered lexicographically .rev() //git_repository is ordered lexicographically
@ -1510,7 +1522,6 @@ impl LocalSnapshot {
parent_path: Arc<Path>, parent_path: Arc<Path>,
entries: impl IntoIterator<Item = Entry>, entries: impl IntoIterator<Item = Entry>,
ignore: Option<Arc<Gitignore>>, ignore: Option<Arc<Gitignore>>,
fs: &dyn Fs,
) { ) {
let mut parent_entry = if let Some(parent_entry) = let mut parent_entry = if let Some(parent_entry) =
self.entries_by_path.get(&PathKey(parent_path.clone()), &()) self.entries_by_path.get(&PathKey(parent_path.clone()), &())
@ -2391,12 +2402,9 @@ impl BackgroundScanner {
new_entries.push(child_entry); new_entries.push(child_entry);
} }
self.snapshot.lock().populate_dir( self.snapshot
job.path.clone(), .lock()
new_entries, .populate_dir(job.path.clone(), new_entries, new_ignore);
new_ignore,
self.fs.as_ref(),
);
for new_job in new_jobs { for new_job in new_jobs {
job.scan_queue.send(new_job).await.unwrap(); job.scan_queue.send(new_job).await.unwrap();
} }
@ -2595,7 +2603,7 @@ impl BackgroundScanner {
.git_repositories .git_repositories
.iter() .iter()
.cloned() .cloned()
.filter(|repo| git2::Repository::open(repo.git_dir_path()).is_ok()) .filter(|repo| git::libgit::Repository::open(repo.git_dir_path()).is_ok())
.collect(); .collect();
snapshot.git_repositories = new_repos; snapshot.git_repositories = new_repos;

View file

@ -2,20 +2,13 @@
pub mod test; pub mod test;
use futures::Future; use futures::Future;
use lazy_static::lazy_static;
use std::{ use std::{
cmp::Ordering, cmp::Ordering,
ffi::OsStr,
ops::AddAssign, ops::AddAssign,
pin::Pin, pin::Pin,
task::{Context, Poll}, task::{Context, Poll},
}; };
lazy_static! {
pub static ref DOT_GIT: &'static OsStr = OsStr::new(".git");
pub static ref GITIGNORE: &'static OsStr = OsStr::new(".gitignore");
}
pub fn truncate(s: &str, max_chars: usize) -> &str { pub fn truncate(s: &str, max_chars: usize) -> &str {
match s.char_indices().nth(max_chars) { match s.char_indices().nth(max_chars) {
None => s, None => s,

View file

@ -2,14 +2,15 @@ mod assertions;
mod marked_text; mod marked_text;
use git2; use git2;
use std::path::{Path, PathBuf}; use std::{
ffi::OsStr,
path::{Path, PathBuf},
};
use tempdir::TempDir; use tempdir::TempDir;
pub use assertions::*; pub use assertions::*;
pub use marked_text::*; pub use marked_text::*;
use crate::DOT_GIT;
pub fn temp_tree(tree: serde_json::Value) -> TempDir { pub fn temp_tree(tree: serde_json::Value) -> TempDir {
let dir = TempDir::new("").unwrap(); let dir = TempDir::new("").unwrap();
write_tree(dir.path(), tree); write_tree(dir.path(), tree);
@ -28,7 +29,7 @@ fn write_tree(path: &Path, tree: serde_json::Value) {
Value::Object(_) => { Value::Object(_) => {
fs::create_dir(&path).unwrap(); fs::create_dir(&path).unwrap();
if path.file_name() == Some(&DOT_GIT) { if path.file_name() == Some(&OsStr::new(".git")) {
git2::Repository::init(&path.parent().unwrap()).unwrap(); git2::Repository::init(&path.parent().unwrap()).unwrap();
} }