Compare commits

...

2 Commits

Author SHA1 Message Date
Nathan Sobo
d97c881737 WIP 2024-05-09 13:06:51 -06:00
Nathan Sobo
576d394e1a WIP: Start on a command to open the N most recently changed files. 2024-05-08 22:41:39 -06:00
6 changed files with 135 additions and 1 deletions

10
Cargo.lock generated
View File

@@ -4451,6 +4451,16 @@ dependencies = [
"util",
]
[[package]]
name = "git_ui"
version = "0.1.0"
dependencies = [
"git",
"gpui",
"serde",
"workspace",
]
[[package]]
name = "glob"
version = "0.3.1"

View File

@@ -35,6 +35,7 @@ members = [
"crates/fsevent",
"crates/fuzzy",
"crates/git",
"crates/git_ui",
"crates/git_hosting_providers",
"crates/go_to_line",
"crates/google_ai",

View File

@@ -1,7 +1,7 @@
use crate::blame::Blame;
use crate::GitHostingProviderRegistry;
use anyhow::{Context, Result};
use collections::HashMap;
use collections::{HashMap, HashSet};
use git2::{BranchType, StatusShow};
use parking_lot::Mutex;
use rope::Rope;
@@ -62,6 +62,8 @@ pub trait GitRepository: Send {
fn create_branch(&self, _: &str) -> Result<()>;
fn blame(&self, path: &Path, content: Rope) -> Result<crate::blame::Blame>;
fn recently_changed_paths(&self, max: usize) -> Result<Vec<(SystemTime, PathBuf)>>;
}
impl std::fmt::Debug for dyn GitRepository {
@@ -259,6 +261,44 @@ impl GitRepository for RealGitRepository {
self.hosting_provider_registry.clone(),
)
}
fn recently_changed_paths(&self, max: usize) -> Result<Vec<(SystemTime, PathBuf)>> {
let mut revwalk = self.repository.revwalk()?;
revwalk.push_head()?;
let mut included = HashSet::<PathBuf>::default();
let mut changed_paths = Vec::new();
for oid in revwalk {
let oid = oid?;
let commit = self.repository.find_commit(oid)?;
let tree = commit.tree()?;
let diff = self.repository.diff_tree_to_tree(None, Some(&tree), None)?;
diff.foreach(
&mut |delta, _| {
if let Some(path) = delta.new_file().path() {
if !included.contains(path) {
included.insert(path.into());
let time = commit.time().seconds();
let system_time =
SystemTime::UNIX_EPOCH + std::time::Duration::new(time as u64, 0);
changed_paths.push((system_time, path.to_path_buf()));
}
}
true
},
None,
None,
None,
)?;
if included.len() >= max {
break;
}
}
changed_paths.truncate(max);
Ok(changed_paths)
}
}
fn matches_index(repo: &LibGitRepository, path: &RepoPath, mtime: SystemTime) -> bool {
@@ -377,6 +417,10 @@ impl GitRepository for FakeGitRepository {
.with_context(|| format!("failed to get blame for {:?}", path))
.cloned()
}
fn recently_changed_paths(&self, max: usize) -> Result<Vec<(SystemTime, PathBuf)>> {
todo!()
}
}
fn check_path_to_repo_path_errors(relative_file_path: &Path) -> Result<()> {

20
crates/git_ui/Cargo.toml Normal file
View File

@@ -0,0 +1,20 @@
[package]
name = "git_ui"
version = "0.1.0"
edition = "2021"
[lib]
path = "./src/git_ui.rs"
[dependencies]
gpui.workspace = true
git.workspace = true
workspace.workspace = true
serde.workspace = true
[dev-dependencies]
gpui = { workspace = true, features = ["test-support"] }
workspace = { workspace = true, features = ["test-support"] }
[lints]
workspace = true

View File

@@ -0,0 +1,58 @@
use std::{
path::{Path, PathBuf},
time::{self, Instant, SystemTime},
};
use gpui::{AppContext, ViewContext};
use serde::Deserialize;
use workspace::Workspace;
#[derive(Deserialize)]
struct OpenRecentlyChanged {
count: usize,
}
gpui::impl_actions!(git, [OpenRecentlyChanged]);
pub fn init(cx: &mut AppContext) {
cx.observe_new_views(
|workspace: &mut Workspace, cx: &mut ViewContext<Workspace>| {
workspace.register_action(open_recently_changed);
},
)
.detach();
}
fn open_recently_changed(
workspace: &mut Workspace,
action: &OpenRecentlyChanged,
cx: &mut ViewContext<Workspace>,
) {
let worktrees = workspace.project().read(cx).worktrees().collect::<Vec<_>>();
let mut repos = Vec::new();
for worktree in worktrees {
if let Some(local_worktree) = worktree.read(cx).as_local() {
if let Some(local_repo) = local_worktree
.repository_for_path(Path::new(""))
.and_then(|repo| local_worktree.get_local_repo(&repo))
{
repos.push(local_repo.repo().clone());
}
}
}
if !repos.is_empty() {
let recent_paths = cx.background_executor().spawn(async move {
let mut paths = Vec::new();
for repo in repos {
paths.extend(repo.lock().recently_changed_paths(100))?;
}
anyhow::Ok(paths)
});
cx.spawn(|this, cx| async move {
// let recent_paths =
})
}
}

View File

@@ -3139,6 +3139,7 @@ impl File {
pub struct Entry {
pub id: ProjectEntryId,
pub kind: EntryKind,
/// Relative path of the entry in the worktree.
pub path: Arc<Path>,
pub inode: u64,
pub mtime: Option<SystemTime>,