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