From db010da4b9679de795466a11624b7aa88d5a2e2e Mon Sep 17 00:00:00 2001 From: Ren Amamiya Date: Sun, 13 Sep 2026 21:22:13 +0700 Subject: [PATCH] refactor git cache --- Cargo.lock | 1 + crates/signed_state/Cargo.toml | 1 + crates/signed_state/src/backend.rs | 5 ++-- crates/signed_state/src/checkouts.rs | 4 +-- crates/signed_state/src/git_store.rs | 26 +++++++++++++++++-- crates/signed_state/src/lib.rs | 2 +- crates/signed_state/src/repo.rs | 6 ++--- .../src/views/pull_requests/detail.rs | 7 ++--- .../workspace/src/views/pull_requests/new.rs | 14 +++++----- crates/workspace/src/views/repo/mod.rs | 12 +++------ 10 files changed, 46 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a67be4f..7a27540 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8006,6 +8006,7 @@ dependencies = [ "bitcoin_hashes 1.2.0", "flume 0.11.1", "futures", + "gix", "gpui", "log", "nostr", diff --git a/crates/signed_state/Cargo.toml b/crates/signed_state/Cargo.toml index 554c38b..7e23203 100644 --- a/crates/signed_state/Cargo.toml +++ b/crates/signed_state/Cargo.toml @@ -17,6 +17,7 @@ nostr-connect.workspace = true bitcoin_hashes = "1" +gix.workspace = true gpui.workspace = true flume.workspace = true futures.workspace = true diff --git a/crates/signed_state/src/backend.rs b/crates/signed_state/src/backend.rs index 9c44ad5..fa9fccf 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::git_cache; +use crate::git_store::repo_mirror_path; use crate::inbox::Inbox; use crate::repos::RepoListStore; @@ -756,8 +756,7 @@ impl Backend { announcement: Announcement, cx: &mut Context, ) -> Task> { - let cache = git_cache(); - let path = cache.repo_path(&announcement.addr()); + let path = repo_mirror_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 d3fe96c..52d0214 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::git_cache; +use crate::git_store::repo_mirror_root; 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 = git_cache().root().canonicalize().ok(); + let cache_root = repo_mirror_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 1193954..00cc6da 100644 --- a/crates/signed_state/src/git_store.rs +++ b/crates/signed_state/src/git_store.rs @@ -1,17 +1,39 @@ use std::path::PathBuf; use std::sync::OnceLock; +use anyhow::Result; +use gix::Repository; +use signed_core::RepoAddr; use signed_git::GitCache; static GIT_CACHE: OnceLock = OnceLock::new(); -/// Global access to the on-disk git clone cache, the grasp mirrors. -pub fn git_cache() -> &'static GitCache { +fn git_cache() -> &'static GitCache { GIT_CACHE .get() .expect("git cache is initialized by signed_state::init") } +/// The root directory of the repository mirrors. +pub(crate) fn repo_mirror_root() -> PathBuf { + git_cache().root().to_path_buf() +} + +/// The on-disk path of the mirror of `addr`. +pub fn repo_mirror_path(addr: &RepoAddr) -> PathBuf { + git_cache().repo_path(addr) +} + +/// Open the mirror of `addr`, if it has been cloned. +pub fn open_repo_mirror(addr: &RepoAddr) -> Result> { + git_cache().open(addr) +} + +/// Open the mirror of `addr`, cloning it first when it does not exist yet. +pub fn ensure_repo_mirror>(addr: &RepoAddr, clone_urls: &[U]) -> Result { + git_cache().ensure_clone(addr, clone_urls) +} + 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 d80a3d9..97afe9f 100644 --- a/crates/signed_state/src/lib.rs +++ b/crates/signed_state/src/lib.rs @@ -11,8 +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::git_cache; 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 nostr_sdk::prelude::Timestamp; diff --git a/crates/signed_state/src/repo.rs b/crates/signed_state/src/repo.rs index f7cfcc7..8ad9539 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::git_cache; +use crate::git_store::ensure_repo_mirror; use crate::refresh::{RefreshGate, RefreshRequest}; use crate::repos::RepoListStore; @@ -1196,8 +1196,6 @@ impl RepoStore { return; } - let cache = git_cache(); - let clone_urls: Vec = self .announcement .as_ref() @@ -1223,7 +1221,7 @@ impl RepoStore { let root = root.clone(); let apply = cx.background_spawn(async move { - let repo = cache.ensure_clone(&addr, &clone_urls)?; + let repo = ensure_repo_mirror(&addr, &clone_urls)?; let workdir = repo .workdir() .ok_or_else(|| anyhow::anyhow!("repository has no worktree"))? diff --git a/crates/workspace/src/views/pull_requests/detail.rs b/crates/workspace/src/views/pull_requests/detail.rs index 3ddeac1..0a45185 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, ProfileStore, RepoStore, git_cache}; +use signed_state::{Backend, ProfileStore, RepoStore, ensure_repo_mirror}; use signed_ui::{CountBadge, UserAvatar, placeholder, status_badge}; use utils::{relative_time, relative_time_secs}; @@ -217,8 +217,6 @@ impl PullRequestDetailView { self.current_commit = binding.tip.clone().map(SharedString::from); cx.notify(); - let cache = git_cache(); - self.load_generation = self.load_generation.wrapping_add(1); let generation = self.load_generation; @@ -257,7 +255,6 @@ impl PullRequestDetailView { let git = if use_nostr { None } else { - let cache = cache.clone(); let addr = addr.clone(); let clone_urls = clone_urls.clone(); let base = base.clone(); @@ -265,7 +262,7 @@ impl PullRequestDetailView { Some( cx.background_spawn(async move { - let repo = cache.ensure_clone(&addr, &clone_urls)?; + let repo = ensure_repo_mirror(&addr, &clone_urls)?; let workdir = repo .workdir() diff --git a/crates/workspace/src/views/pull_requests/new.rs b/crates/workspace/src/views/pull_requests/new.rs index fd57427..4eac45a 100644 --- a/crates/workspace/src/views/pull_requests/new.rs +++ b/crates/workspace/src/views/pull_requests/new.rs @@ -26,7 +26,9 @@ 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, RepoListStore, RepoStore, git_cache}; +use signed_state::{ + Backend, CheckoutsStore, RepoListStore, RepoStore, ensure_repo_mirror, repo_mirror_path, +}; use signed_ui::{CountBadge, placeholder, ref_selector_trigger}; use crate::views::commit_diff::{COMMIT_ROW_HEIGHT, CommitDiffView, DiffPane, commit_row}; @@ -73,7 +75,7 @@ struct ForkCompare { announcement: Announcement, /// Import namespace of the form `/`. namespace: String, - /// Path of the target repository's GitCache mirror. + /// Path of the target repository's mirror. mirror_path: PathBuf, } @@ -533,8 +535,7 @@ impl NewPullRequestView { let Some((base, _euc)) = self.base_repo(cx) else { return; }; - let cache = git_cache(); - let mirror_path = cache.repo_path(&base); + let mirror_path = repo_mirror_path(&base); let namespace = fork_namespace(&announcement); let clone_urls = announcement.clone.clone(); @@ -563,17 +564,16 @@ impl NewPullRequestView { cx.spawn_in(window, async move |this, cx| { // The fork and base must share history for a merge-base to exist. // The target's mirror is the object store both sides land in. - // `ensure_clone` fetches `origin` when the mirror already exists. + // `ensure_repo_mirror` fetches `origin` when the mirror already exists. let result = cx .background_spawn({ - let cache = cache.clone(); let base = base.clone(); let base_clone_urls = base_clone_urls.clone(); let namespace = namespace.clone(); let clone_urls = clone_urls.clone(); let mirror_path = mirror_path.clone(); async move { - cache.ensure_clone(&base, &base_clone_urls)?; + ensure_repo_mirror(&base, &base_clone_urls)?; // Prune stale imports of any fork. // Then import this fork's heads under its namespace. diff --git a/crates/workspace/src/views/repo/mod.rs b/crates/workspace/src/views/repo/mod.rs index 8b94914..747ca4d 100644 --- a/crates/workspace/src/views/repo/mod.rs +++ b/crates/workspace/src/views/repo/mod.rs @@ -27,7 +27,7 @@ use signed_core::{Announcement, RepoAddr, RepoStatus}; use signed_git::FileCommit; use signed_state::{ Backend, CheckoutStatus, CheckoutsStore, LocalReposStore, ProfileStore, RepoListStore, - RepoStore, git_cache, pr_proposes_checkout, + RepoStore, ensure_repo_mirror, open_repo_mirror, pr_proposes_checkout, }; use signed_ui::{ CountBadge, DropdownButton, PixelAvatar, UserAvatar, copy_row, menu_copy_row, middle_truncate, @@ -343,15 +343,13 @@ impl RepoDetailView { self.repo_started = true; - let cache = git_cache(); let addr = announcement.addr(); let clone_urls: Vec = announcement.clone.clone(); let disk = { - let cache = cache.clone(); let addr = addr.clone(); cx.background_spawn(async move { - match cache.open(&addr)? { + match open_repo_mirror(&addr)? { Some(repo) => Ok(Some(load_repo_data(&repo)?)), None => Ok(None), } @@ -365,11 +363,10 @@ impl RepoDetailView { let data = match disk { Ok(Some(data)) => Ok(data), Ok(None) => { - let cache = cache.clone(); let addr = addr.clone(); let clone_urls = clone_urls.clone(); cx.background_spawn(async move { - let repo = cache.ensure_clone(&addr, &clone_urls)?; + let repo = ensure_repo_mirror(&addr, &clone_urls)?; load_repo_data(&repo) }) .await @@ -393,11 +390,10 @@ impl RepoDetailView { } let refresh = { - let cache = cache.clone(); let addr = addr.clone(); cx.background_spawn(async move { - let Some(repo) = cache.open(&addr)? else { + let Some(repo) = open_repo_mirror(&addr)? else { return Ok::<_, Error>(None); };