diff --git a/crates/paths/src/lib.rs b/crates/paths/src/lib.rs index f370bad..c5b3da6 100644 --- a/crates/paths/src/lib.rs +++ b/crates/paths/src/lib.rs @@ -90,9 +90,13 @@ pub fn nostr_dir() -> &'static PathBuf { } /// Returns the path to the local git clone cache, the grasp mirrors. +/// +/// The mirrors are disposable and re-cloned from their grasp server on +/// demand, so the cache lives in the OS temp directory for the system to +/// reclaim. pub fn repos_dir() -> &'static PathBuf { static REPOS_DIR: OnceLock = OnceLock::new(); - REPOS_DIR.get_or_init(|| data_dir().join("repos")) + REPOS_DIR.get_or_init(|| std::env::temp_dir().join(APP_NAME_LOWERCASE).join("repos")) } pub fn settings_file() -> &'static PathBuf { diff --git a/crates/signed_state/src/backend.rs b/crates/signed_state/src/backend.rs index 95d30e5..9c44ad5 100644 --- a/crates/signed_state/src/backend.rs +++ b/crates/signed_state/src/backend.rs @@ -13,7 +13,7 @@ use nostr_sdk::prelude::*; use signed_core::{Announcement, RepoAddr, build_state, filters, identifier_from_name}; use signed_nostr::{SignedAuthUrlHandler, UniversalSigner, Update}; -use crate::git_store::GitStore; +use crate::git_store::git_cache; use crate::inbox::Inbox; use crate::repos::RepoListStore; @@ -756,7 +756,7 @@ impl Backend { announcement: Announcement, cx: &mut Context, ) -> Task> { - let cache = GitStore::global(cx).cache().clone(); + let cache = git_cache(); let path = cache.repo_path(&announcement.addr()); self.push_repo_from(announcement, path, None, cx) } diff --git a/crates/signed_state/src/checkouts.rs b/crates/signed_state/src/checkouts.rs index 3f6dd50..d3fe96c 100644 --- a/crates/signed_state/src/checkouts.rs +++ b/crates/signed_state/src/checkouts.rs @@ -9,7 +9,7 @@ use settings::{CheckoutRecord, SettingsStore}; use signed_core::{Announcement, RepoAddr}; use crate::backend::{Backend, BackendEvent}; -use crate::git_store::GitStore; +use crate::git_store::git_cache; use crate::refresh::{RefreshGate, RefreshRequest}; use crate::repos::{LocalReposStore, RepoListStore}; @@ -328,7 +328,7 @@ impl CheckoutsStore { let announcements = RepoListStore::global(cx).read(cx).announcements.clone(); let scanned = LocalReposStore::global(cx).read(cx).repos.clone(); - let cache_root = GitStore::global(cx).cache().root().canonicalize().ok(); + let cache_root = git_cache().root().canonicalize().ok(); let requested: Vec<(RepoAddr, Option)> = self .status_requested diff --git a/crates/signed_state/src/git_store.rs b/crates/signed_state/src/git_store.rs index f284482..1193954 100644 --- a/crates/signed_state/src/git_store.rs +++ b/crates/signed_state/src/git_store.rs @@ -1,32 +1,19 @@ use std::path::PathBuf; +use std::sync::OnceLock; -use gpui::{App, Global}; use signed_git::GitCache; -struct GlobalGitStore(GitCache); - -impl Global for GlobalGitStore {} +static GIT_CACHE: OnceLock = OnceLock::new(); /// Global access to the on-disk git clone cache, the grasp mirrors. -#[derive(Debug, Clone)] -pub struct GitStore(GitCache); +pub fn git_cache() -> &'static GitCache { + GIT_CACHE + .get() + .expect("git cache is initialized by signed_state::init") +} -impl GitStore { - pub fn set_global(root: impl Into, cx: &mut App) -> Self { - let store = Self::new(root); - cx.set_global(GlobalGitStore(store.0.clone())); - store - } - - pub fn global(cx: &App) -> Self { - Self(cx.global::().0.clone()) - } - - fn new(root: impl Into) -> Self { - Self(GitCache::new(root.into())) - } - - pub fn cache(&self) -> &GitCache { - &self.0 +pub(crate) fn set_git_cache(root: impl Into) { + if GIT_CACHE.set(GitCache::new(root.into())).is_err() { + log::warn!("git cache root is already set, keeping the first one"); } } diff --git a/crates/signed_state/src/lib.rs b/crates/signed_state/src/lib.rs index d3dc6c4..d80a3d9 100644 --- a/crates/signed_state/src/lib.rs +++ b/crates/signed_state/src/lib.rs @@ -11,7 +11,8 @@ use std::path::{Path, PathBuf}; pub use backend::{Backend, BackendEvent, user_grasp_list_servers}; pub use checkouts::{CheckoutStatus, CheckoutsStore, pr_proposes_checkout}; -pub use git_store::GitStore; +pub use git_store::git_cache; +use git_store::set_git_cache; use gpui::{App, AppContext}; pub use inbox::{Inbox, query_inbox}; pub use nostr_sdk::prelude::Timestamp; @@ -31,6 +32,7 @@ pub fn init( // rustls uses the `aws_lc_rs` provider by default. let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); + // Initialize the nostr client and signer let (client, signer) = cx.foreground_executor().block_on(async move { let path = db_path.as_ref().to_path_buf(); new_backend(path) @@ -38,11 +40,22 @@ pub fn init( .expect("failed to initialize nostr backend") }); + // Set Git cache for the repos root + set_git_cache(repos_root); + + // Set global stores for the backend Backend::set_global(cx.new(|cx| Backend::new(client, signer, cx)), cx); + + // Set global stores for the profile ProfileStore::set_global(cx.new(ProfileStore::new), cx); + + // Set global stores for the repo list and local repos RepoListStore::set_global(cx.new(RepoListStore::new), cx); - GitStore::set_global(repos_root, cx); + + // Set global stores for the local repos LocalReposStore::set_global(cx.new(|cx| LocalReposStore::new(scan_paths, cx)), cx); + + // Set global stores for the checkouts CheckoutsStore::set_global(cx.new(CheckoutsStore::new), cx); } @@ -50,10 +63,10 @@ pub fn init( #[cfg(target_arch = "wasm32")] pub fn init(cx: &mut App) { let (client, signer) = new_backend().expect("failed to initialize nostr backend"); + set_git_cache(PathBuf::new()); Backend::set_global(cx.new(|cx| Backend::new(client, signer, cx)), cx); ProfileStore::set_global(cx.new(ProfileStore::new), cx); RepoListStore::set_global(cx.new(RepoListStore::new), cx); - GitStore::set_global(PathBuf::new(), cx); LocalReposStore::set_global(cx.new(|cx| LocalReposStore::new(Vec::new(), cx)), cx); CheckoutsStore::set_global(cx.new(|cx| CheckoutsStore::new(cx)), cx); } diff --git a/crates/signed_state/src/repo.rs b/crates/signed_state/src/repo.rs index 395f1e2..f7cfcc7 100644 --- a/crates/signed_state/src/repo.rs +++ b/crates/signed_state/src/repo.rs @@ -17,7 +17,7 @@ use crate::backend::{ user_grasp_list_servers, }; use crate::checkouts::CheckoutsStore; -use crate::git_store::GitStore; +use crate::git_store::git_cache; use crate::refresh::{RefreshGate, RefreshRequest}; use crate::repos::RepoListStore; @@ -1196,7 +1196,7 @@ impl RepoStore { return; } - let cache = GitStore::global(cx).cache().clone(); + let cache = git_cache(); let clone_urls: Vec = self .announcement diff --git a/crates/workspace/src/views/pull_requests/detail.rs b/crates/workspace/src/views/pull_requests/detail.rs index 392ad41..3ddeac1 100644 --- a/crates/workspace/src/views/pull_requests/detail.rs +++ b/crates/workspace/src/views/pull_requests/detail.rs @@ -26,7 +26,7 @@ use signed_core::{ merge_base_of, pull_request_patch, }; use signed_git::{FileCommit, patch_commits, patch_diffs}; -use signed_state::{Backend, GitStore, ProfileStore, RepoStore}; +use signed_state::{Backend, ProfileStore, RepoStore, git_cache}; use signed_ui::{CountBadge, UserAvatar, placeholder, status_badge}; use utils::{relative_time, relative_time_secs}; @@ -217,7 +217,7 @@ impl PullRequestDetailView { self.current_commit = binding.tip.clone().map(SharedString::from); cx.notify(); - let cache = GitStore::global(cx).cache().clone(); + let cache = git_cache(); self.load_generation = self.load_generation.wrapping_add(1); let generation = self.load_generation; diff --git a/crates/workspace/src/views/pull_requests/new.rs b/crates/workspace/src/views/pull_requests/new.rs index 2241dee..fd57427 100644 --- a/crates/workspace/src/views/pull_requests/new.rs +++ b/crates/workspace/src/views/pull_requests/new.rs @@ -26,7 +26,7 @@ use signed_git::{ delete_refs_with_prefix, fetch_repo_refs, fork_namespace, merge_base, refs_with_prefix, worktree_commit_range_commits, worktree_commit_range_diff, }; -use signed_state::{Backend, CheckoutsStore, GitStore, RepoListStore, RepoStore}; +use signed_state::{Backend, CheckoutsStore, RepoListStore, RepoStore, git_cache}; use signed_ui::{CountBadge, placeholder, ref_selector_trigger}; use crate::views::commit_diff::{COMMIT_ROW_HEIGHT, CommitDiffView, DiffPane, commit_row}; @@ -533,7 +533,7 @@ impl NewPullRequestView { let Some((base, _euc)) = self.base_repo(cx) else { return; }; - let cache = GitStore::global(cx).cache().clone(); + let cache = git_cache(); let mirror_path = cache.repo_path(&base); let namespace = fork_namespace(&announcement); let clone_urls = announcement.clone.clone(); diff --git a/crates/workspace/src/views/repo/mod.rs b/crates/workspace/src/views/repo/mod.rs index eacdae1..8b94914 100644 --- a/crates/workspace/src/views/repo/mod.rs +++ b/crates/workspace/src/views/repo/mod.rs @@ -26,8 +26,8 @@ use nostr::prelude::{RelayUrl, ToBech32, Url}; use signed_core::{Announcement, RepoAddr, RepoStatus}; use signed_git::FileCommit; use signed_state::{ - Backend, CheckoutStatus, CheckoutsStore, GitStore, LocalReposStore, ProfileStore, - RepoListStore, RepoStore, pr_proposes_checkout, + Backend, CheckoutStatus, CheckoutsStore, LocalReposStore, ProfileStore, RepoListStore, + RepoStore, git_cache, pr_proposes_checkout, }; use signed_ui::{ CountBadge, DropdownButton, PixelAvatar, UserAvatar, copy_row, menu_copy_row, middle_truncate, @@ -343,7 +343,7 @@ impl RepoDetailView { self.repo_started = true; - let cache = GitStore::global(cx).cache().clone(); + let cache = git_cache(); let addr = announcement.addr(); let clone_urls: Vec = announcement.clone.clone();