update
This commit is contained in:
@@ -34,7 +34,7 @@ pub use repo::{
|
||||
repo_tags, root_commit, worktree_branches, worktree_current_branch, worktree_ref_exists,
|
||||
worktree_ref_state,
|
||||
};
|
||||
pub use scan::find_git_repos;
|
||||
pub use scan::{LocalRepo, find_git_repos};
|
||||
pub use worktree::{
|
||||
WorktreeSnapshot, find_readme, worktree_checkout_branch, worktree_checkout_tag,
|
||||
worktree_commits_ahead, worktree_dirty, worktree_entries, worktree_read, worktree_snapshot,
|
||||
|
||||
@@ -2,12 +2,21 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use ignore::WalkBuilder;
|
||||
|
||||
use crate::nip34::{Nip34Binding, detect_nip34};
|
||||
|
||||
/// Caps nesting so pathological trees can't stall the scan.
|
||||
const SCAN_MAX_DEPTH: usize = 12;
|
||||
|
||||
/// Walk `root` recursively and collect the paths of git repositories below it.
|
||||
/// `.gitignore` and `.ignore` files are honoured.
|
||||
pub fn find_git_repos(root: &Path) -> Vec<PathBuf> {
|
||||
/// A git repository discovered under a scan root.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LocalRepo {
|
||||
pub path: PathBuf,
|
||||
/// `None` for a plain repository.
|
||||
pub nip34: Option<Nip34Binding>,
|
||||
}
|
||||
|
||||
/// Walk `root` recursively and collect the git repositories below it.
|
||||
pub fn find_git_repos(root: &Path) -> Vec<LocalRepo> {
|
||||
if !root.is_dir() {
|
||||
return Vec::new();
|
||||
}
|
||||
@@ -38,4 +47,10 @@ pub fn find_git_repos(root: &Path) -> Vec<PathBuf> {
|
||||
}
|
||||
|
||||
roots
|
||||
.into_iter()
|
||||
.map(|path| {
|
||||
let nip34 = detect_nip34(&path);
|
||||
LocalRepo { path, nip34 }
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -42,7 +42,10 @@ fn find_git_repos_discovers_repositories_recursively() {
|
||||
std::fs::create_dir_all(outer.join(".git")).unwrap();
|
||||
std::fs::create_dir_all(outer.join("sub/other/.git")).unwrap();
|
||||
|
||||
let mut found = find_git_repos(root);
|
||||
let mut found: Vec<PathBuf> = find_git_repos(root)
|
||||
.into_iter()
|
||||
.map(|repo| repo.path)
|
||||
.collect();
|
||||
found.sort();
|
||||
|
||||
let mut expected = vec![
|
||||
|
||||
@@ -350,7 +350,9 @@ impl CheckoutsStore {
|
||||
//
|
||||
// The facts are the origin URL and the root commit, both CLI reads.
|
||||
let mut facts: Vec<(PathBuf, Option<String>, Option<String>)> = Vec::new();
|
||||
for path in scanned.iter() {
|
||||
for scanned in scanned.iter() {
|
||||
let path = &scanned.path;
|
||||
|
||||
// The browser's mirror clones share the announce URLs and EUCs. They are not user checkouts.
|
||||
if cache_root
|
||||
.as_ref()
|
||||
|
||||
@@ -16,12 +16,13 @@ use git_store::set_git_cache;
|
||||
pub use git_store::{ensure_repo_mirror, open_repo_mirror, repo_mirror_path};
|
||||
use gpui::{App, AppContext};
|
||||
pub use inbox::{Inbox, query_inbox};
|
||||
pub use local_repos::LocalReposStore;
|
||||
pub use local_repos::{LocalReposStore, local_repo_addr};
|
||||
pub use nostr_sdk::prelude::Timestamp;
|
||||
pub use profile::{Profile, ProfileStore};
|
||||
pub use refresh::{RefreshGate, RefreshRequest};
|
||||
pub use repo::RepoStore;
|
||||
pub use repos::{RepoActivityCounts, RepoListStore};
|
||||
pub use signed_git::{GraspSignals, LocalRepo, Nip34Binding, Nip34Kind};
|
||||
use signed_nostr::new_backend;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
|
||||
@@ -3,7 +3,8 @@ use std::sync::Arc;
|
||||
|
||||
use anyhow::Error;
|
||||
use gpui::{App, AppContext, Context, Entity, Global, Task};
|
||||
use signed_git::find_git_repos;
|
||||
use signed_core::{RepoAddr, repo_addr};
|
||||
use signed_git::{LocalRepo, find_git_repos};
|
||||
|
||||
struct GlobalLocalReposStore(Entity<LocalReposStore>);
|
||||
|
||||
@@ -13,7 +14,7 @@ impl Global for GlobalLocalReposStore {}
|
||||
pub struct LocalReposStore {
|
||||
pub roots: Arc<Vec<PathBuf>>,
|
||||
/// Git repositories discovered under [`Self::roots`], sorted by path.
|
||||
pub repos: Arc<Vec<PathBuf>>,
|
||||
pub repos: Arc<Vec<LocalRepo>>,
|
||||
pub scanning: bool,
|
||||
scan_dirty: bool,
|
||||
}
|
||||
@@ -48,7 +49,7 @@ impl LocalReposStore {
|
||||
self.repos = Arc::new(
|
||||
self.repos
|
||||
.iter()
|
||||
.filter(|repo| repo.as_path() != path)
|
||||
.filter(|repo| repo.path.as_path() != path)
|
||||
.cloned()
|
||||
.collect(),
|
||||
);
|
||||
@@ -75,8 +76,8 @@ impl LocalReposStore {
|
||||
for root in roots.iter() {
|
||||
repos.extend(find_git_repos(root));
|
||||
}
|
||||
repos.sort();
|
||||
repos.dedup();
|
||||
repos.sort_by(|a, b| a.path.cmp(&b.path));
|
||||
repos.dedup_by(|a, b| a.path == b.path);
|
||||
repos
|
||||
});
|
||||
|
||||
@@ -103,3 +104,13 @@ impl LocalReposStore {
|
||||
task.detach();
|
||||
}
|
||||
}
|
||||
|
||||
/// The NIP-34 coordinate a repository's detection resolved, when both the owner
|
||||
/// and the identifier were recovered.
|
||||
pub fn local_repo_addr(repo: &LocalRepo) -> Option<RepoAddr> {
|
||||
let binding = repo.nip34.as_ref()?;
|
||||
let owner = binding.owner?;
|
||||
let identifier = binding.identifier.as_deref()?;
|
||||
|
||||
Some(repo_addr(owner, identifier))
|
||||
}
|
||||
|
||||
@@ -132,13 +132,13 @@ impl SidebarPanel {
|
||||
.read(cx)
|
||||
.repos
|
||||
.iter()
|
||||
.filter(|path| {
|
||||
let Some(name) = path.file_name() else {
|
||||
.filter(|repo| {
|
||||
let Some(name) = repo.path.file_name() else {
|
||||
return true;
|
||||
};
|
||||
!ids.contains(&identifier_from_name(&name.to_string_lossy()))
|
||||
})
|
||||
.cloned()
|
||||
.map(|repo| repo.path.clone())
|
||||
.collect()
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Local repository NIP-34 detection
|
||||
|
||||
Status: plan, not yet implemented.
|
||||
Status: Phases 1–2 implemented. Phases 3–5 pending.
|
||||
|
||||
## Motivation
|
||||
|
||||
@@ -195,18 +195,22 @@ Implemented.
|
||||
|
||||
### Phase 2 — thread `LocalRepo` through the state layer
|
||||
|
||||
- [ ] `crates/signed_git/src/scan.rs`: change `find_git_repos` to `Vec<LocalRepo>`; in the walk,
|
||||
Implemented.
|
||||
|
||||
- [x] `crates/signed_git/src/scan.rs`: change `find_git_repos` to `Vec<LocalRepo>`; in the walk,
|
||||
`detect_nip34` each kept path.
|
||||
- [ ] `crates/signed_git/src/tests.rs`: update `find_git_repos_*` expectations to the new type
|
||||
- [x] `crates/signed_git/src/tests.rs`: update `find_git_repos_*` expectations to the new type
|
||||
(compare `.path`).
|
||||
- [ ] `crates/signed_state/src/local_repos.rs`: `repos: Arc<Vec<LocalRepo>>`; `remove(&path)`
|
||||
- [x] `crates/signed_state/src/local_repos.rs`: `repos: Arc<Vec<LocalRepo>>`; `remove(&path)`
|
||||
filters on `.path`; the background scan already returns the richer vector unchanged.
|
||||
- [ ] `crates/signed_state/src/checkouts.rs` (~`run_refresh`): iterate `.path` instead of bare
|
||||
- [x] `crates/signed_state/src/checkouts.rs` (`run_refresh`): iterate `.path` instead of bare
|
||||
paths when collecting `scanned`.
|
||||
- [ ] `crates/signed_state/src/lib.rs`: re-export `LocalRepo`, `Nip34Binding`, `Nip34Kind` (and
|
||||
`GraspSignals` if the UI needs the flags).
|
||||
- [ ] `crates/signed_state/src/local_repos.rs`: add a helper that resolves a binding to a
|
||||
`RepoAddr` (`signed_core::repo_addr(owner, identifier)`) when both are known.
|
||||
- [x] `crates/signed_state/src/lib.rs`: re-export `LocalRepo`, `Nip34Binding`, `Nip34Kind` and
|
||||
`GraspSignals`.
|
||||
- [x] `crates/signed_state/src/local_repos.rs`: `local_repo_addr(&LocalRepo) -> Option<RepoAddr>`
|
||||
resolves a binding when both owner and identifier are known.
|
||||
- [x] `crates/workspace/src/views/sidebar/mod.rs`: minimal adaptation of the existing folder-name
|
||||
dedupe to the new entry type so the tree compiles; the badge/dedupe rewrite is Phase 3.
|
||||
|
||||
### Phase 3 — sidebar: derive the local list and link to announcements
|
||||
|
||||
|
||||
Reference in New Issue
Block a user