consolidate git operations into a Repo type
This commit is contained in:
@@ -12,6 +12,7 @@ use nostr_connect::prelude::*;
|
||||
use nostr_sdk::client::SyncSummary;
|
||||
use nostr_sdk::prelude::*;
|
||||
use signed_core::{Announcement, Filters, RepoAddr, RepoState, filters};
|
||||
use signed_git::{GitCache, Repo};
|
||||
use signed_nostr::{SignedAuthUrlHandler, UniversalSigner, Update};
|
||||
|
||||
use crate::git_store::repo_mirror_path;
|
||||
@@ -408,7 +409,7 @@ impl Backend {
|
||||
|
||||
// Initialize directly at the user's chosen destination.
|
||||
let destination = {
|
||||
let dir_name = signed_git::sanitize_path_component(&name);
|
||||
let dir_name = GitCache::sanitize_path_component(&name);
|
||||
let dir_name = if dir_name.is_empty() {
|
||||
"repository".to_owned()
|
||||
} else {
|
||||
@@ -431,11 +432,11 @@ impl Backend {
|
||||
bail!("destination {} already exists", destination.display());
|
||||
}
|
||||
|
||||
let commit = signed_git::init_repository(&destination, &name, &description)?;
|
||||
let commit = Repo::init(&destination, &name, &description)?;
|
||||
|
||||
if let Some(base) = servers.first().and_then(grasp_base_url) {
|
||||
let url = format!("{base}/{owner}/{repo_id}.git");
|
||||
signed_git::set_origin(&destination, &url)?;
|
||||
Repo::open(&destination)?.set_origin(&url)?;
|
||||
}
|
||||
|
||||
Ok::<_, Error>(commit)
|
||||
@@ -500,7 +501,9 @@ impl Backend {
|
||||
&owner,
|
||||
&servers,
|
||||
&executor,
|
||||
signed_git::push_main,
|
||||
|path, base, owner, repo_id| {
|
||||
Repo::open(path)?.push_main(base, owner, repo_id)
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
@@ -585,8 +588,9 @@ impl Backend {
|
||||
let work = cx.background_spawn({
|
||||
let path = path.clone();
|
||||
async move {
|
||||
let state = signed_git::worktree_ref_state(&path)?;
|
||||
let euc = signed_git::root_commit(&path)?;
|
||||
let repo = Repo::open(&path)?;
|
||||
let state = repo.ref_state()?;
|
||||
let euc = repo.root_commit()?;
|
||||
Ok::<_, Error>((state, euc))
|
||||
}
|
||||
});
|
||||
@@ -651,7 +655,9 @@ impl Backend {
|
||||
&owner,
|
||||
&servers,
|
||||
&executor,
|
||||
signed_git::push_all,
|
||||
|path, base, owner, repo_id| {
|
||||
Repo::open(path)?.push_all(base, owner, repo_id)
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
@@ -687,7 +693,9 @@ impl Backend {
|
||||
let url = format!("{base}/{owner}/{repo_id}.git");
|
||||
let path = path.clone();
|
||||
cx.background_spawn(async move {
|
||||
signed_git::ensure_origin(&path, &url).ok();
|
||||
Repo::open(&path)
|
||||
.and_then(|repo| repo.ensure_origin(&url))
|
||||
.ok();
|
||||
})
|
||||
.await;
|
||||
}
|
||||
@@ -699,7 +707,9 @@ impl Backend {
|
||||
Ok(naddr) => {
|
||||
let path = path.clone();
|
||||
cx.background_spawn(async move {
|
||||
if let Err(error) = signed_git::set_nostr_repo(&path, &naddr) {
|
||||
if let Err(error) =
|
||||
Repo::open(&path).and_then(|repo| repo.set_nostr_repo(&naddr))
|
||||
{
|
||||
log::warn!(
|
||||
"failed to record the NIP-34 marker for {}: {error}",
|
||||
path.display()
|
||||
@@ -783,7 +793,7 @@ impl Backend {
|
||||
let mut state = {
|
||||
let work = cx.background_spawn({
|
||||
let path = path.clone();
|
||||
async move { signed_git::worktree_ref_state(&path) }
|
||||
async move { Repo::open(&path).and_then(|repo| repo.ref_state()) }
|
||||
});
|
||||
work.await?
|
||||
};
|
||||
@@ -837,7 +847,9 @@ impl Backend {
|
||||
&owner,
|
||||
&relays,
|
||||
&executor,
|
||||
signed_git::push_all,
|
||||
|path, base, owner, repo_id| {
|
||||
Repo::open(path)?.push_all(base, owner, repo_id)
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
@@ -1571,7 +1583,7 @@ async fn push_staged_to_grasps(
|
||||
owner: &str,
|
||||
servers: &[RelayUrl],
|
||||
executor: &BackgroundExecutor,
|
||||
push: fn(&Path, &str, &str, &str) -> Result<(), Error>,
|
||||
push: impl Fn(&Path, &str, &str, &str) -> Result<(), Error>,
|
||||
) -> PushOutcome {
|
||||
let mut outcome = PushOutcome::default();
|
||||
|
||||
@@ -1647,7 +1659,9 @@ async fn push_staged_to_grasps(
|
||||
// pushed data is already there.
|
||||
if let Some(last_reason) = &reason
|
||||
&& is_stale_advertisement_race(last_reason)
|
||||
&& signed_git::remote_has_refs(path, &git_url, refs).unwrap_or(false)
|
||||
&& Repo::open(path)
|
||||
.and_then(|repo| repo.remote_has_refs(&git_url, refs))
|
||||
.unwrap_or(false)
|
||||
{
|
||||
if let Some(event) = staged_event {
|
||||
keep_newest(&mut outcome.state_event, event);
|
||||
|
||||
@@ -7,6 +7,7 @@ use gpui::{App, AppContext, Context, Entity, Global, Subscription};
|
||||
use nostr::prelude::*;
|
||||
use settings::{CheckoutRecord, SettingsStore};
|
||||
use signed_core::{Announcement, RepoAddr};
|
||||
use signed_git::Repo;
|
||||
use utils::same_repo_url;
|
||||
|
||||
use crate::backend::{Backend, BackendEvent};
|
||||
@@ -338,8 +339,14 @@ impl CheckoutsStore {
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let origin = signed_git::origin_url(path).ok().flatten();
|
||||
let root = signed_git::root_commit(path).ok().flatten();
|
||||
let origin = Repo::open(path)
|
||||
.and_then(|repo| repo.origin_url())
|
||||
.ok()
|
||||
.flatten();
|
||||
let root = Repo::open(path)
|
||||
.and_then(|repo| repo.root_commit())
|
||||
.ok()
|
||||
.flatten();
|
||||
facts.push((path.clone(), origin, root));
|
||||
}
|
||||
|
||||
@@ -555,14 +562,15 @@ fn resolve_associations<'a>(
|
||||
}
|
||||
|
||||
fn checkout_status(path: &Path, announced_head: Option<&str>) -> Option<CheckoutStatus> {
|
||||
let branches = signed_git::worktree_branches(path).ok()?;
|
||||
let repo = Repo::try_open(path)?;
|
||||
let branches = repo.branches().ok()?;
|
||||
|
||||
if branches.is_empty() || signed_git::worktree_dirty(path) {
|
||||
if branches.is_empty() || repo.is_dirty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let branch = signed_git::worktree_current_branch(path)?;
|
||||
let head = signed_git::head_commit_id(path).ok().flatten()?;
|
||||
let branch = repo.current_branch()?;
|
||||
let head = repo.head()?;
|
||||
let base = announced_head
|
||||
.filter(|name| branches.iter().any(|b| b == name))
|
||||
.map(str::to_owned)
|
||||
@@ -573,7 +581,7 @@ fn checkout_status(path: &Path, announced_head: Option<&str>) -> Option<Checkout
|
||||
return None;
|
||||
}
|
||||
|
||||
let ahead = signed_git::worktree_commits_ahead(path, &base, &branch);
|
||||
let ahead = repo.commits_ahead(&base, &branch);
|
||||
(ahead > 0).then_some(CheckoutStatus {
|
||||
path: path.to_path_buf(),
|
||||
branch,
|
||||
@@ -585,31 +593,33 @@ fn checkout_status(path: &Path, announced_head: Option<&str>) -> Option<Checkout
|
||||
|
||||
/// The `ready to push` status of one checkout of the user's own repository.
|
||||
fn checkout_push_status(path: &Path, fetch: bool) -> Option<CheckoutStatus> {
|
||||
if signed_git::worktree_dirty(path) {
|
||||
let repo = Repo::try_open(path)?;
|
||||
if repo.is_dirty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let branch = signed_git::worktree_current_branch(path)?;
|
||||
let head = signed_git::head_commit_id(path).ok().flatten()?;
|
||||
let origin = signed_git::origin_url(path).ok().flatten()?;
|
||||
let branch = repo.current_branch()?;
|
||||
let head = repo.head()?;
|
||||
let origin = repo.origin_url().ok().flatten()?;
|
||||
|
||||
if fetch {
|
||||
signed_git::fetch_repo_refs(path, &[origin], "+refs/heads/*:refs/remotes/origin/*").ok();
|
||||
repo.fetch_refs(&[origin], "+refs/heads/*:refs/remotes/origin/*")
|
||||
.ok();
|
||||
}
|
||||
|
||||
let remote = format!("refs/remotes/origin/{branch}");
|
||||
|
||||
// A branch never fetched or pushed yet compares against the remote HEAD.
|
||||
// The remote HEAD is the fork point in practice.
|
||||
let base = if signed_git::worktree_ref_exists(path, &remote) {
|
||||
let base = if repo.ref_exists(&remote) {
|
||||
remote
|
||||
} else if signed_git::worktree_ref_exists(path, "refs/remotes/origin/HEAD") {
|
||||
} else if repo.ref_exists("refs/remotes/origin/HEAD") {
|
||||
"refs/remotes/origin/HEAD".to_owned()
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let ahead = signed_git::worktree_commits_ahead(path, &base, &branch);
|
||||
let ahead = repo.commits_ahead(&base, &branch);
|
||||
|
||||
(ahead > 0).then_some(CheckoutStatus {
|
||||
path: path.to_path_buf(),
|
||||
@@ -730,7 +740,7 @@ mod tests {
|
||||
fn checkout_status_reports_ahead_branches_only() {
|
||||
let dir = tempfile::tempdir().expect("tempdir");
|
||||
let path = dir.path().join("repo");
|
||||
let _initial = signed_git::init_repository(&path, "My Repo", "").expect("init");
|
||||
let _initial = Repo::init(&path, "My Repo", "").expect("init");
|
||||
let run = |args: &[&str]| {
|
||||
let status = Command::new("git")
|
||||
.current_dir(&path)
|
||||
@@ -777,7 +787,7 @@ mod tests {
|
||||
// Act like a grasp server and allow them.
|
||||
let dir = tempfile::tempdir().expect("tempdir");
|
||||
let remote = dir.path().join("remote");
|
||||
signed_git::init_repository(&remote, "My Repo", "").expect("init");
|
||||
Repo::init(&remote, "My Repo", "").expect("init");
|
||||
let config = Command::new("git")
|
||||
.args(["config", "receive.denyCurrentBranch", "ignore"])
|
||||
.current_dir(&remote)
|
||||
|
||||
@@ -2,10 +2,9 @@ use std::path::PathBuf;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use anyhow::Result;
|
||||
use gix::Repository;
|
||||
use nostr::prelude::Url;
|
||||
use signed_core::RepoAddr;
|
||||
use signed_git::GitCache;
|
||||
use signed_git::{GitCache, Repo};
|
||||
|
||||
static GIT_CACHE: OnceLock<GitCache> = OnceLock::new();
|
||||
|
||||
@@ -26,12 +25,12 @@ pub fn repo_mirror_path(addr: &RepoAddr) -> PathBuf {
|
||||
}
|
||||
|
||||
/// Open the mirror of `addr`, if it has been cloned.
|
||||
pub fn open_repo_mirror(addr: &RepoAddr) -> Result<Option<Repository>> {
|
||||
pub fn open_repo_mirror(addr: &RepoAddr) -> Result<Option<Repo>> {
|
||||
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: &[Url]) -> Result<Repository> {
|
||||
pub fn ensure_repo_mirror(addr: &RepoAddr, clone_urls: &[Url]) -> Result<Repo> {
|
||||
git_cache().ensure_clone(addr, clone_urls)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ use signed_core::{
|
||||
Announcement, Deletions, Filters, GitEvent, PullRequest, RepoAddr, RepoState, RepoStatus,
|
||||
filters,
|
||||
};
|
||||
use signed_git::Nip34Binding;
|
||||
use signed_git::{Nip34Binding, PatchParser, Repo};
|
||||
use signed_nostr::UniversalSigner;
|
||||
|
||||
use crate::backend::{
|
||||
@@ -700,7 +700,7 @@ impl RepoStore {
|
||||
return;
|
||||
};
|
||||
|
||||
let series: Vec<String> = signed_git::split_patch_series(&patch)
|
||||
let series: Vec<String> = PatchParser::split_patch_series(&patch)
|
||||
.into_iter()
|
||||
.map(str::to_owned)
|
||||
.collect();
|
||||
@@ -906,9 +906,9 @@ impl RepoStore {
|
||||
let mut pushed = 0;
|
||||
|
||||
for (url, label) in &targets {
|
||||
match signed_git::push_commit_ref(
|
||||
&path, url, &tip, &reference,
|
||||
) {
|
||||
match Repo::open(&path)
|
||||
.and_then(|repo| repo.push_ref(url, &tip, &reference))
|
||||
{
|
||||
Ok(()) => pushed += 1,
|
||||
Err(e) => failures.push(format!("{label}: {e}")),
|
||||
}
|
||||
@@ -986,7 +986,7 @@ impl RepoStore {
|
||||
let merge_base = merge_base.clone();
|
||||
let compare_ref = compare_ref.clone();
|
||||
async move {
|
||||
signed_git::format_patch_between(&repo_path, &merge_base, &compare_ref)
|
||||
Repo::open(&repo_path)?.format_patch_between(&merge_base, &compare_ref)
|
||||
}
|
||||
})
|
||||
.await;
|
||||
@@ -1037,7 +1037,7 @@ impl RepoStore {
|
||||
return;
|
||||
}
|
||||
|
||||
let series: Vec<String> = signed_git::split_patch_series(&patch)
|
||||
let series: Vec<String> = PatchParser::split_patch_series(&patch)
|
||||
.into_iter()
|
||||
.map(str::to_owned)
|
||||
.collect();
|
||||
@@ -1368,7 +1368,9 @@ impl RepoStore {
|
||||
|
||||
let clone = {
|
||||
let destination = destination.clone();
|
||||
cx.background_spawn(async move { signed_git::clone_repo(&clone_urls, &destination) })
|
||||
// The clone's repository handle is dropped in the task: gix handles
|
||||
// are not `Send`, they must not cross the spawn boundary.
|
||||
cx.background_spawn(async move { Repo::clone(&clone_urls, &destination).map(|_| ()) })
|
||||
};
|
||||
|
||||
cx.spawn(async move |this, cx| {
|
||||
@@ -1596,11 +1598,10 @@ fn comment_builder(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use signed_core::GitEvent;
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use nostr_sdk::prelude::*;
|
||||
use signed_core::GitEvent;
|
||||
|
||||
use super::{RepoStore, comment_builder, patch_current_commit};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user