chore: refactor backend around domain types (#26)
Reviewed-on: #26
This commit was merged in pull request #26.
This commit is contained in:
@@ -17,7 +17,9 @@ use gpui_component::tree::{TreeEntry, TreeItem, TreeState, tree};
|
||||
use gpui_component::{
|
||||
ActiveTheme, Sizable, StyledExt, VirtualListScrollHandle, h_flex, v_flex, v_virtual_list,
|
||||
};
|
||||
use signed_git::{CommitDiff, DiffHunk, DiffLine, DiffLineKind, DiffStatus, FileCommit, FileDiff};
|
||||
use signed_git::{
|
||||
CommitDiff, DiffHunk, DiffLine, DiffLineKind, DiffStatus, FileCommit, FileDiff, Repo,
|
||||
};
|
||||
use signed_state::RepoStore;
|
||||
use signed_ui::{placeholder, tree_row};
|
||||
use utils::relative_time_secs;
|
||||
@@ -355,14 +357,14 @@ impl CommitDiffView {
|
||||
.background_spawn({
|
||||
let worktree = worktree.clone();
|
||||
let id = id.clone();
|
||||
async move { signed_git::worktree_commit(&worktree, &id) }
|
||||
async move { Repo::open(&worktree).and_then(|repo| repo.commit(&id)) }
|
||||
})
|
||||
.await;
|
||||
let diff = cx
|
||||
.background_spawn({
|
||||
let worktree = worktree.clone();
|
||||
let id = id.clone();
|
||||
async move { signed_git::worktree_commit_diff(&worktree, &id) }
|
||||
async move { Repo::open(&worktree).and_then(|repo| repo.commit_diff(&id)) }
|
||||
})
|
||||
.await;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ use gpui_component::{ActiveTheme, Icon, IconName, IconNamed, Sizable, StyledExt,
|
||||
use nostr::prelude::{Event, EventId, Kind, PublicKey, Timestamp};
|
||||
use signed_core::{InboxItem, InboxReadState, RepoAddr};
|
||||
use signed_state::{
|
||||
Backend, BackendEvent, ProfileStore, RefreshGate, RefreshRequest, RepoListStore, query_inbox,
|
||||
Backend, BackendEvent, Inbox, ProfileStore, RefreshGate, RefreshRequest, RepoListStore,
|
||||
};
|
||||
use signed_ui::{Avatar, CountBadge};
|
||||
use utils::relative_time;
|
||||
@@ -199,7 +199,7 @@ impl InboxView {
|
||||
|
||||
let state = self.state.clone();
|
||||
|
||||
let work = cx.background_spawn(async move { query_inbox(&client, me, &state).await });
|
||||
let work = cx.background_spawn(async move { Inbox::query(&client, me, &state).await });
|
||||
|
||||
self.tasks.push(cx.spawn(async move |this, cx| {
|
||||
let (threads, unread_count) = match work.await {
|
||||
|
||||
@@ -8,7 +8,7 @@ use gpui_component::input::TextareaState;
|
||||
use gpui_component::scroll::ScrollableElement;
|
||||
use gpui_component::{ActiveTheme, StyledExt, h_flex, v_flex};
|
||||
use nostr::prelude::EventId;
|
||||
use signed_core::activity_subject;
|
||||
use signed_core::GitEvent;
|
||||
use signed_state::{ProfileStore, RepoStore};
|
||||
use signed_ui::{Avatar, placeholder, status_badge};
|
||||
use utils::relative_time;
|
||||
@@ -103,7 +103,7 @@ impl Render for IssueDetailView {
|
||||
};
|
||||
|
||||
(
|
||||
activity_subject(issue),
|
||||
issue.activity_subject(),
|
||||
profile.name(),
|
||||
profile.picture(),
|
||||
store.status_of(issue),
|
||||
|
||||
@@ -16,7 +16,7 @@ use gpui_component::{
|
||||
ActiveTheme, Icon, VirtualListScrollHandle, WindowExt, h_flex, v_flex, v_virtual_list,
|
||||
};
|
||||
use nostr::prelude::EventId;
|
||||
use signed_core::{RepoStatus, activity_subject};
|
||||
use signed_core::{GitEvent, RepoStatus};
|
||||
use signed_state::{ProfileStore, RepoStore};
|
||||
use signed_ui::{Avatar, SegmentButton, placeholder, status_badge};
|
||||
use utils::relative_time;
|
||||
@@ -146,7 +146,7 @@ impl IssuesView {
|
||||
|
||||
fn render_row(&self, ix: usize, issue_ix: usize, cx: &mut Context<Self>) -> AnyElement {
|
||||
let issue = &self.store.read(cx).issues[issue_ix];
|
||||
let title = activity_subject(issue);
|
||||
let title = issue.activity_subject();
|
||||
let id_hex = issue.id.to_hex();
|
||||
let profile = ProfileStore::global(cx).read(cx).get(&issue.pubkey);
|
||||
let author = profile.name();
|
||||
|
||||
@@ -21,12 +21,9 @@ use gpui_component::{
|
||||
v_virtual_list,
|
||||
};
|
||||
use nostr::prelude::{Event, EventId, Kind, Url};
|
||||
use signed_core::{
|
||||
RepoAddr, activity_subject, branch_name_of, clone_urls_of, current_commit_of, latest_update,
|
||||
merge_base_of, pull_request_patch,
|
||||
};
|
||||
use signed_git::{FileCommit, patch_commits, patch_diffs};
|
||||
use signed_state::{Backend, ProfileStore, RepoStore, ensure_repo_mirror};
|
||||
use signed_core::{GitEvent, PullRequest, RepoAddr};
|
||||
use signed_git::{FileCommit, PatchParser};
|
||||
use signed_state::{Backend, Mirrors, ProfileStore, RepoStore};
|
||||
use signed_ui::{Avatar, CountBadge, placeholder, status_badge};
|
||||
use utils::{relative_time, relative_time_secs};
|
||||
|
||||
@@ -145,23 +142,24 @@ impl PullRequestDetailView {
|
||||
.iter()
|
||||
.find(|pr| pr.id == self.pr_id && pr.kind == Kind::GitPullRequest)
|
||||
.map(|root| {
|
||||
let update = latest_update(store.pull_requests.iter(), root);
|
||||
let update = PullRequest::latest_update(store.pull_requests.iter(), root);
|
||||
|
||||
let tip = update
|
||||
.and_then(current_commit_of)
|
||||
.or_else(|| current_commit_of(root));
|
||||
.and_then(GitEvent::current_commit)
|
||||
.or_else(|| root.current_commit());
|
||||
|
||||
let base = update
|
||||
.and_then(merge_base_of)
|
||||
.or_else(|| merge_base_of(root));
|
||||
.and_then(GitEvent::merge_base)
|
||||
.or_else(|| root.merge_base());
|
||||
|
||||
let clone_urls = clone_urls_of(root)
|
||||
let clone_urls = root
|
||||
.clone_urls()
|
||||
.or_else(|| store.announcement.as_ref().map(|a| a.clone.clone()))
|
||||
.unwrap_or_default();
|
||||
|
||||
PrBinding {
|
||||
description: root.content.clone(),
|
||||
patch: pull_request_patch(root, store.patches.iter()),
|
||||
patch: PullRequest::new(root).patch(store.patches.iter()),
|
||||
tip,
|
||||
base,
|
||||
clone_urls,
|
||||
@@ -235,14 +233,14 @@ impl PullRequestDetailView {
|
||||
let nostr_diff = cx
|
||||
.background_spawn({
|
||||
let patch = patch.clone();
|
||||
async move { patch_diffs(&patch) }
|
||||
async move { PatchParser::patch_diffs(&patch) }
|
||||
})
|
||||
.await;
|
||||
|
||||
let nostr_commits = cx
|
||||
.background_spawn({
|
||||
let patch = patch.clone();
|
||||
async move { patch_commits(&patch) }
|
||||
async move { PatchParser::patch_commits(&patch) }
|
||||
})
|
||||
.await;
|
||||
|
||||
@@ -263,9 +261,10 @@ impl PullRequestDetailView {
|
||||
|
||||
Some(
|
||||
cx.background_spawn(async move {
|
||||
let repo = ensure_repo_mirror(&addr, &clone_urls)?;
|
||||
let repo = Mirrors::ensure(&addr, &clone_urls)?;
|
||||
let gix_repo = repo.inner();
|
||||
|
||||
let workdir = repo
|
||||
let workdir = gix_repo
|
||||
.workdir()
|
||||
.ok_or_else(|| anyhow::anyhow!("repository has no worktree"))?
|
||||
.to_path_buf();
|
||||
@@ -277,17 +276,16 @@ impl PullRequestDetailView {
|
||||
Some(base) => base,
|
||||
// No `merge-base` tag. Use the merge base of the tip and the default branch.
|
||||
None => {
|
||||
let head = repo
|
||||
let head = gix_repo
|
||||
.head_id()
|
||||
.map_err(|_| anyhow::anyhow!("repository has no HEAD"))?;
|
||||
let tip_id = repo.rev_parse_single(tip.as_bytes())?;
|
||||
repo.merge_base(tip_id, head)?.to_string()
|
||||
let tip_id = gix_repo.rev_parse_single(tip.as_bytes())?;
|
||||
gix_repo.merge_base(tip_id, head)?.to_string()
|
||||
}
|
||||
};
|
||||
|
||||
let diff = signed_git::worktree_commit_range_diff(&workdir, &base, &tip)?;
|
||||
let commits =
|
||||
signed_git::worktree_commit_range_commits(&workdir, &base, &tip)?;
|
||||
let diff = repo.range_diff(&base, &tip)?;
|
||||
let commits = repo.commit_range(&base, &tip)?;
|
||||
|
||||
Ok::<_, anyhow::Error>((diff, commits, workdir))
|
||||
})
|
||||
@@ -620,9 +618,9 @@ impl PullRequestDetailView {
|
||||
return div().into_any_element();
|
||||
};
|
||||
(
|
||||
activity_subject(root),
|
||||
root.activity_subject(),
|
||||
store.status_of(root),
|
||||
branch_name_of(root),
|
||||
root.branch_name(),
|
||||
root.pubkey,
|
||||
)
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@ use gpui_component::{
|
||||
ActiveTheme, Icon, IconName, VirtualListScrollHandle, h_flex, v_flex, v_virtual_list,
|
||||
};
|
||||
use nostr::prelude::{EventId, Kind};
|
||||
use signed_core::{RepoStatus, activity_subject};
|
||||
use signed_core::{GitEvent, RepoStatus};
|
||||
use signed_state::{ProfileStore, RepoStore};
|
||||
use signed_ui::{Avatar, DropdownButton, SegmentButton, placeholder, status_badge};
|
||||
use utils::relative_time;
|
||||
@@ -159,7 +159,7 @@ impl PullRequestsView {
|
||||
fn render_row(&self, ix: usize, pr_ix: usize, cx: &mut Context<Self>) -> AnyElement {
|
||||
let pr = &self.store.read(cx).pull_requests[pr_ix];
|
||||
let pr_id = pr.id;
|
||||
let title = activity_subject(pr);
|
||||
let title = pr.activity_subject();
|
||||
let id_hex = pr.id.to_hex();
|
||||
|
||||
let age = relative_time(pr.created_at);
|
||||
|
||||
@@ -21,15 +21,11 @@ use gpui_component::{
|
||||
v_virtual_list,
|
||||
};
|
||||
use nostr::prelude::*;
|
||||
use signed_core::{Announcement, RepoAddr, fork_candidates};
|
||||
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, ensure_repo_mirror, repo_mirror_path,
|
||||
};
|
||||
use signed_core::{Announcement, RepoAddr};
|
||||
use signed_git::{GitCache, Repo};
|
||||
use signed_state::{Backend, CheckoutsStore, Mirrors, RepoListStore, RepoStore};
|
||||
use signed_ui::{CountBadge, placeholder, ref_selector_trigger};
|
||||
use utils::middle_truncate;
|
||||
|
||||
use crate::views::commit_diff::{COMMIT_ROW_HEIGHT, CommitDiffView, DiffPane, commit_row};
|
||||
use crate::views::{repo_tab_avatar, tab_title};
|
||||
@@ -104,17 +100,8 @@ fn shorten_owner(owner: &PublicKey) -> String {
|
||||
hex.chars().take(10).collect()
|
||||
}
|
||||
|
||||
/// Truncate a label for the fixed-width controls of the compare bar.
|
||||
fn truncate_label(label: &str) -> SharedString {
|
||||
const MAX: usize = 18;
|
||||
let mut chars = label.chars();
|
||||
let (prefix, rest) = (chars.by_ref().take(MAX).collect::<String>(), chars.next());
|
||||
let label = if rest.is_some() {
|
||||
format!("{}…", &prefix[..prefix.len().saturating_sub(1)])
|
||||
} else {
|
||||
prefix
|
||||
};
|
||||
SharedString::from(label)
|
||||
SharedString::from(middle_truncate(label, 18, 0))
|
||||
}
|
||||
|
||||
fn checkout_source_item(
|
||||
@@ -407,10 +394,12 @@ impl NewPullRequestView {
|
||||
.background_spawn({
|
||||
let path = path.clone();
|
||||
async move {
|
||||
let repo = gix::open(Path::new(&path)).ok()?;
|
||||
let branches =
|
||||
signed_git::worktree_branches(Path::new(&path)).unwrap_or_default();
|
||||
let current = signed_git::current_branch(&repo).ok().flatten();
|
||||
let repo = Repo::try_open(Path::new(&path));
|
||||
let branches = repo
|
||||
.as_ref()
|
||||
.and_then(|repo| repo.branches().ok())
|
||||
.unwrap_or_default();
|
||||
let current = repo.as_ref().and_then(|repo| repo.current_branch());
|
||||
Some((branches, current))
|
||||
}
|
||||
})
|
||||
@@ -520,7 +509,7 @@ impl NewPullRequestView {
|
||||
};
|
||||
let user = Backend::global(cx).read(cx).current_user();
|
||||
let announcements = RepoListStore::global(cx).read(cx).announcements.clone();
|
||||
fork_candidates(&announcements, &base, euc.as_deref(), user)
|
||||
Announcement::forks_in(&announcements, &base, euc.as_deref(), user)
|
||||
.into_iter()
|
||||
.cloned()
|
||||
.collect()
|
||||
@@ -540,8 +529,8 @@ impl NewPullRequestView {
|
||||
let Some((base, _euc)) = self.base_repo(cx) else {
|
||||
return;
|
||||
};
|
||||
let mirror_path = repo_mirror_path(&base);
|
||||
let namespace = fork_namespace(&announcement);
|
||||
let mirror_path = Mirrors::path(&base);
|
||||
let namespace = GitCache::fork_namespace(&announcement);
|
||||
let clone_urls = announcement.clone.clone();
|
||||
|
||||
let base_clone_urls: Vec<Url> = self
|
||||
@@ -575,14 +564,14 @@ impl NewPullRequestView {
|
||||
let clone_urls = clone_urls.clone();
|
||||
let mirror_path = mirror_path.clone();
|
||||
async move {
|
||||
ensure_repo_mirror(&base, &base_clone_urls)?;
|
||||
Mirrors::ensure(&base, &base_clone_urls)?;
|
||||
let repo = Repo::open(&mirror_path)?;
|
||||
|
||||
// Prune stale imports of any fork. Then import this fork's heads under its namespace.
|
||||
delete_refs_with_prefix(&mirror_path, "refs/fork")?;
|
||||
repo.delete_refs_with_prefix("refs/fork")?;
|
||||
|
||||
// Fetch the fork's refs and import them under the fork's namespace.
|
||||
fetch_repo_refs(
|
||||
&mirror_path,
|
||||
repo.fetch_refs(
|
||||
&clone_urls,
|
||||
&format!("+refs/heads/*:refs/fork/{namespace}/*"),
|
||||
)?;
|
||||
@@ -602,12 +591,12 @@ impl NewPullRequestView {
|
||||
};
|
||||
|
||||
let base_branches = strip(
|
||||
refs_with_prefix(&mirror_path, "refs/remotes/origin")?,
|
||||
repo.refs_with_prefix("refs/remotes/origin")?,
|
||||
"refs/remotes/origin",
|
||||
);
|
||||
|
||||
let compare_branches = strip(
|
||||
refs_with_prefix(&mirror_path, &format!("refs/fork/{namespace}"))?,
|
||||
repo.refs_with_prefix(&format!("refs/fork/{namespace}"))?,
|
||||
&format!("refs/fork/{namespace}"),
|
||||
);
|
||||
|
||||
@@ -781,24 +770,17 @@ impl NewPullRequestView {
|
||||
let base_name = base_name.clone();
|
||||
let compare_name = compare_name.clone();
|
||||
async move {
|
||||
let merge_base = merge_base(Path::new(&repo_path), &base, &compare)?
|
||||
.ok_or_else(|| {
|
||||
let repo = Repo::open(Path::new(&repo_path))?;
|
||||
let merge_base =
|
||||
repo.merge_base(&base, &compare)?.ok_or_else(|| {
|
||||
anyhow::anyhow!(
|
||||
"{base_name} and {compare_name} share no common ancestor"
|
||||
)
|
||||
})?;
|
||||
|
||||
let commits = worktree_commit_range_commits(
|
||||
Path::new(&repo_path),
|
||||
&merge_base,
|
||||
&compare,
|
||||
)?;
|
||||
let commits = repo.commit_range(&merge_base, &compare)?;
|
||||
|
||||
let diff = worktree_commit_range_diff(
|
||||
Path::new(&repo_path),
|
||||
&merge_base,
|
||||
&compare,
|
||||
)?;
|
||||
let diff = repo.range_diff(&merge_base, &compare)?;
|
||||
|
||||
Ok::<_, anyhow::Error>((merge_base, commits, diff))
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ use gpui_component::{ActiveTheme, StyledExt, WindowExt, h_flex, v_flex};
|
||||
use nostr::prelude::PublicKey;
|
||||
use signed_core::Announcement;
|
||||
use signed_state::ProfileStore;
|
||||
use signed_ui::{Avatar, middle_truncate};
|
||||
use signed_ui::Avatar;
|
||||
use utils::middle_truncate;
|
||||
|
||||
pub(super) fn open_about_dialog(announcement: Announcement, window: &mut Window, cx: &mut App) {
|
||||
window.open_dialog(cx, move |dialog, _window, cx| {
|
||||
|
||||
@@ -11,7 +11,7 @@ use gpui_component::spinner::Spinner;
|
||||
use gpui_component::text::{TextView, TextViewState};
|
||||
use gpui_component::tree::{TreeEntry, TreeState, tree};
|
||||
use gpui_component::{ActiveTheme, Sizable, StyledExt, h_flex, v_flex};
|
||||
use signed_git::{FileCommit, WorktreeSnapshot};
|
||||
use signed_git::{FileCommit, Repo, WorktreeSnapshot};
|
||||
use signed_ui::{placeholder, tree_row};
|
||||
|
||||
use crate::views::tree::{TreeItemSeed, tree_items};
|
||||
@@ -611,9 +611,9 @@ impl RepoFilesView {
|
||||
let task: Task<Result<(), Error>> = cx.spawn(async move |this, cx| {
|
||||
let rels: Vec<PathBuf> = paths.iter().map(PathBuf::from).collect();
|
||||
let result = cx
|
||||
.background_spawn(
|
||||
async move { signed_git::worktree_last_commits(&worktree, &rels) },
|
||||
)
|
||||
.background_spawn(async move {
|
||||
Repo::open_cached(&worktree).and_then(|repo| repo.last_commits(&rels))
|
||||
})
|
||||
.await;
|
||||
|
||||
this.update(cx, |this, cx| {
|
||||
|
||||
@@ -8,7 +8,7 @@ use gpui::{Context, Entity, Pixels, Render, Size, Task, WeakEntity, Window, div,
|
||||
use gpui_component::scroll::Scrollbar;
|
||||
use gpui_component::spinner::Spinner;
|
||||
use gpui_component::{ActiveTheme, Sizable, VirtualListScrollHandle, v_flex, v_virtual_list};
|
||||
use signed_git::CommitList;
|
||||
use signed_git::{CommitList, Repo};
|
||||
use signed_state::RepoStore;
|
||||
use signed_ui::placeholder;
|
||||
|
||||
@@ -69,7 +69,9 @@ impl RepoHistoryView {
|
||||
|
||||
let task: Task<Result<(), Error>> = cx.spawn(async move |this, cx| {
|
||||
let result = cx
|
||||
.background_spawn(async move { signed_git::worktree_all_commits(&worktree) })
|
||||
.background_spawn(async move {
|
||||
Repo::open_cached(&worktree).and_then(|repo| repo.all_commits())
|
||||
})
|
||||
.await;
|
||||
|
||||
this.update(cx, |this, cx| {
|
||||
|
||||
@@ -5,7 +5,6 @@ use std::rc::Rc;
|
||||
use anyhow::Error;
|
||||
use assets::CustomIconName;
|
||||
use dock::{BasePanel, DockArea, Panel, PanelEvent, add_center_panel, panel_handle};
|
||||
use gix::Repository;
|
||||
use gpui::prelude::*;
|
||||
use gpui::{
|
||||
Action, Anchor, AnyElement, App, ClipboardItem, Context, Entity, EventEmitter, FocusHandle,
|
||||
@@ -24,16 +23,15 @@ use gpui_component::{
|
||||
use nostr::nips::nip19::Nip19Coordinate;
|
||||
use nostr::prelude::{RelayUrl, ToBech32, Url};
|
||||
use signed_core::{Announcement, RepoAddr, RepoStatus};
|
||||
use signed_git::FileCommit;
|
||||
use signed_git::{FileCommit, GitCache, Repo};
|
||||
use signed_state::{
|
||||
Backend, CheckoutStatus, CheckoutsStore, LocalReposStore, Nip34Binding, Nip34Kind,
|
||||
ProfileStore, RepoListStore, RepoStore, ensure_repo_mirror, open_repo_mirror,
|
||||
pr_proposes_checkout,
|
||||
Backend, CheckoutStatus, CheckoutsStore, LocalReposStore, Mirrors, Nip34Binding, Nip34Kind,
|
||||
ProfileStore, RepoListStore, RepoStore,
|
||||
};
|
||||
use signed_ui::{
|
||||
Avatar, CountBadge, DropdownButton, PixelAvatar, copy_row, menu_copy_row, middle_truncate,
|
||||
ref_selector_trigger,
|
||||
Avatar, CountBadge, DropdownButton, PixelAvatar, copy_row, menu_copy_row, ref_selector_trigger,
|
||||
};
|
||||
use utils::middle_truncate;
|
||||
|
||||
mod about;
|
||||
mod actions;
|
||||
@@ -326,7 +324,7 @@ impl RepoDetailView {
|
||||
let task: gpui::Task<Result<(), Error>> = cx.spawn_in(window, async move |this, cx| {
|
||||
let data = cx
|
||||
.background_spawn(async move {
|
||||
let repo = gix::open(&local_path)?;
|
||||
let repo = Repo::open(&local_path)?;
|
||||
load_repo_data(&repo)
|
||||
})
|
||||
.await;
|
||||
@@ -360,7 +358,7 @@ impl RepoDetailView {
|
||||
let disk = {
|
||||
let addr = addr.clone();
|
||||
cx.background_spawn(async move {
|
||||
match open_repo_mirror(&addr)? {
|
||||
match Mirrors::open(&addr)? {
|
||||
Some(repo) => Ok(Some(load_repo_data(&repo)?)),
|
||||
None => Ok(None),
|
||||
}
|
||||
@@ -377,7 +375,7 @@ impl RepoDetailView {
|
||||
let addr = addr.clone();
|
||||
let clone_urls = clone_urls.clone();
|
||||
cx.background_spawn(async move {
|
||||
let repo = ensure_repo_mirror(&addr, &clone_urls)?;
|
||||
let repo = Mirrors::ensure(&addr, &clone_urls)?;
|
||||
load_repo_data(&repo)
|
||||
})
|
||||
.await
|
||||
@@ -404,42 +402,27 @@ impl RepoDetailView {
|
||||
let addr = addr.clone();
|
||||
|
||||
cx.background_spawn(async move {
|
||||
let Some(repo) = open_repo_mirror(&addr)? else {
|
||||
let Some(repo) = Mirrors::open(&addr)? else {
|
||||
return Ok::<_, Error>(None);
|
||||
};
|
||||
|
||||
// Best-effort, a fetch failure, e.g. offline, keeps the cached state.
|
||||
signed_git::fetch_all(&repo).ok();
|
||||
repo.fetch().ok();
|
||||
|
||||
let worktree = repo.workdir().map(Path::to_path_buf);
|
||||
let moved = repo.fast_forward_branches().unwrap_or(false);
|
||||
|
||||
let moved = match &worktree {
|
||||
Some(worktree) => {
|
||||
signed_git::fast_forward_branches(worktree).unwrap_or(false)
|
||||
}
|
||||
None => false,
|
||||
};
|
||||
|
||||
let (branches, tags) = match &worktree {
|
||||
Some(_) => (
|
||||
signed_git::repo_branches(&repo).unwrap_or_default(),
|
||||
signed_git::repo_tags(&repo).unwrap_or_default(),
|
||||
),
|
||||
None => (Vec::new(), Vec::new()),
|
||||
};
|
||||
|
||||
let current_branch = signed_git::current_branch(&repo).unwrap_or(None);
|
||||
let head_commit = signed_git::head_commit(&repo).unwrap_or(None);
|
||||
|
||||
Ok::<_, Error>(Some((moved, branches, tags, current_branch, head_commit)))
|
||||
Ok::<_, Error>(Some((moved, repo.snapshot()?)))
|
||||
})
|
||||
}
|
||||
.await;
|
||||
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
if let Ok(Some((moved, branches, tags, current_branch, head_commit))) = refresh {
|
||||
let branches: Vec<SharedString> = branches.iter().map(Into::into).collect();
|
||||
let tags: Vec<SharedString> = tags.iter().map(Into::into).collect();
|
||||
if let Ok(Some((moved, snapshot))) = refresh {
|
||||
let branches: Vec<SharedString> =
|
||||
snapshot.branches.iter().map(Into::into).collect();
|
||||
let tags: Vec<SharedString> = snapshot.tags.iter().map(Into::into).collect();
|
||||
let current_branch = snapshot.current_branch.clone();
|
||||
let head_commit = snapshot.head_commit.clone();
|
||||
|
||||
let branches_changed = this.refs.set_branches(
|
||||
branches,
|
||||
@@ -531,8 +514,8 @@ impl RepoDetailView {
|
||||
.as_ref()
|
||||
.map(|name| name.to_string())
|
||||
.filter(|name| !name.trim().is_empty())
|
||||
.unwrap_or_else(|| addr.identifier.clone());
|
||||
let name = signed_git::sanitize_path_component(&name);
|
||||
.unwrap_or_else(|| addr.identifier().to_owned());
|
||||
let name = GitCache::sanitize_path_component(&name);
|
||||
|
||||
if name.is_empty() {
|
||||
"repository".to_owned()
|
||||
@@ -617,13 +600,12 @@ impl RepoDetailView {
|
||||
let task: gpui::Task<Result<(), Error>> = cx.spawn_in(window, async move |this, cx| {
|
||||
let result = cx
|
||||
.background_spawn(async move {
|
||||
let repo = Repo::open(&worktree);
|
||||
match kind {
|
||||
RefKind::Branch => {
|
||||
signed_git::worktree_checkout_branch(&worktree, &checkout_name)
|
||||
}
|
||||
RefKind::Tag => {
|
||||
signed_git::worktree_checkout_tag(&worktree, &checkout_name)
|
||||
repo.and_then(|repo| repo.checkout_branch(&checkout_name))
|
||||
}
|
||||
RefKind::Tag => repo.and_then(|repo| repo.checkout_tag(&checkout_name)),
|
||||
}
|
||||
})
|
||||
.await;
|
||||
@@ -665,7 +647,7 @@ impl RepoDetailView {
|
||||
let task: gpui::Task<Result<(), Error>> = cx.spawn(async move |this, cx| {
|
||||
let result = cx
|
||||
.background_spawn(async move {
|
||||
let snapshot = signed_git::worktree_snapshot(&worktree)?;
|
||||
let snapshot = Repo::open(&worktree)?.snapshot()?;
|
||||
// Build the tree off the main thread, like [`Self::load_repo`].
|
||||
let tree = build_tree_items(&snapshot.entries);
|
||||
let paths = sorted_worktree_paths(&snapshot.entries);
|
||||
@@ -716,7 +698,7 @@ impl RepoDetailView {
|
||||
let task: gpui::Task<Result<(), Error>> = cx.spawn(async move |this, cx| {
|
||||
let result = cx
|
||||
.background_spawn(async move {
|
||||
let snapshot = signed_git::worktree_snapshot(&worktree)?;
|
||||
let snapshot = Repo::open(&worktree)?.snapshot()?;
|
||||
let tree = build_tree_items(&snapshot.entries);
|
||||
let paths = sorted_worktree_paths(&snapshot.entries);
|
||||
Ok::<_, Error>((snapshot, tree, paths))
|
||||
@@ -1523,8 +1505,12 @@ impl RepoDetailView {
|
||||
continue;
|
||||
}
|
||||
for pr in &store.pull_requests {
|
||||
if pr_proposes_checkout(pr, store.status_of(pr) == RepoStatus::Open, user, &status)
|
||||
{
|
||||
if CheckoutsStore::pr_proposes_checkout(
|
||||
pr,
|
||||
store.status_of(pr) == RepoStatus::Open,
|
||||
user,
|
||||
&status,
|
||||
) {
|
||||
continue 'status;
|
||||
}
|
||||
}
|
||||
@@ -1857,7 +1843,7 @@ fn fork_row(announcement: &Announcement, cx: &mut Context<RepoDetailView>) -> Op
|
||||
.map(SharedString::from)
|
||||
.unwrap_or_else(|| SharedString::from(a.id.clone()))
|
||||
})
|
||||
.unwrap_or_else(|| SharedString::from(addr.identifier.clone()));
|
||||
.unwrap_or_else(|| SharedString::from(addr.identifier().to_owned()));
|
||||
(SharedString::from(format!("Forked from {name}")), true)
|
||||
}
|
||||
None => (SharedString::from(upstream.display().as_str()), false),
|
||||
@@ -1900,7 +1886,7 @@ impl ShareTargets {
|
||||
fn from_announcement(announcement: &Announcement) -> Self {
|
||||
let addr = announcement.addr();
|
||||
let coordinate = addr.to_string();
|
||||
let naddr = Nip19Coordinate::new(addr, announcement.relays.iter().cloned())
|
||||
let naddr = Nip19Coordinate::new(addr.into(), announcement.relays.iter().cloned())
|
||||
.to_bech32()
|
||||
.expect("a complete coordinate always encodes to naddr");
|
||||
|
||||
@@ -1952,38 +1938,21 @@ fn truncate_naddr_link(url: &str, tail: usize) -> String {
|
||||
format!("{}...{}", &url[..end], &url[url.len() - tail..])
|
||||
}
|
||||
|
||||
fn load_repo_data(repo: &Repository) -> Result<RepoData, Error> {
|
||||
let entries = signed_git::worktree_entries(repo)?;
|
||||
let tree = build_tree_items(&entries);
|
||||
let readme_path = signed_git::find_readme(repo)?;
|
||||
|
||||
let readme = match &readme_path {
|
||||
Some(path) => signed_git::worktree_read(repo, path)?,
|
||||
None => None,
|
||||
};
|
||||
|
||||
fn load_repo_data(repo: &Repo) -> Result<RepoData, Error> {
|
||||
let snapshot = repo.snapshot()?;
|
||||
let worktree = repo.workdir().map(Path::to_path_buf);
|
||||
let head_commit = signed_git::head_commit(repo).unwrap_or(None);
|
||||
|
||||
let (branches, tags, current_branch) = match &worktree {
|
||||
Some(_) => (
|
||||
signed_git::repo_branches(repo).unwrap_or_default(),
|
||||
signed_git::repo_tags(repo).unwrap_or_default(),
|
||||
signed_git::current_branch(repo).unwrap_or(None),
|
||||
),
|
||||
None => (Vec::new(), Vec::new(), None),
|
||||
};
|
||||
let tree = build_tree_items(&snapshot.entries);
|
||||
|
||||
Ok(RepoData {
|
||||
tree,
|
||||
entries,
|
||||
readme_path,
|
||||
readme,
|
||||
entries: snapshot.entries,
|
||||
readme_path: snapshot.readme_path,
|
||||
readme: snapshot.readme,
|
||||
worktree,
|
||||
branches,
|
||||
tags,
|
||||
current_branch,
|
||||
head_commit,
|
||||
branches: snapshot.branches,
|
||||
tags: snapshot.tags,
|
||||
current_branch: snapshot.current_branch,
|
||||
head_commit: snapshot.head_commit,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -228,7 +228,7 @@ impl RepoListView {
|
||||
.map(SharedString::from)
|
||||
.unwrap_or_else(|| SharedString::from(a.id.clone()))
|
||||
})
|
||||
.unwrap_or_else(|| SharedString::from(addr.identifier.clone()));
|
||||
.unwrap_or_else(|| SharedString::from(addr.identifier().to_owned()));
|
||||
Some(SharedString::from(format!("forked from {name}")))
|
||||
});
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ use nostr::prelude::RelayUrl;
|
||||
use signed_core::{Announcement, RepoAddr};
|
||||
use signed_state::{
|
||||
Backend, BackendEvent, CheckoutsStore, LocalReposStore, Nip34Binding, Nip34Kind, Profile,
|
||||
ProfileStore, RepoListStore, ResolvedLocalRepo, resolve_local_repos,
|
||||
ProfileStore, RepoListStore, ResolvedLocalRepo,
|
||||
};
|
||||
use signed_ui::{Avatar, NavItem, PixelAvatar, title_bar_drag_handlers};
|
||||
|
||||
@@ -136,7 +136,7 @@ impl SidebarPanel {
|
||||
|
||||
let local = LocalReposStore::global(cx).read(cx);
|
||||
let local_repos =
|
||||
resolve_local_repos(&local.repos, &repo_list.announcements, &announcements);
|
||||
LocalReposStore::resolve(&local.repos, &repo_list.announcements, &announcements);
|
||||
|
||||
(announcements, local_repos, local.scanning)
|
||||
};
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use dock::{DockArea, DockEvent, DockLayout, DockPlacement, SignedDockSkin, panel_handle};
|
||||
use gpui::prelude::*;
|
||||
use gpui::{Context, Entity, Render, Subscription, Window, div, px};
|
||||
use gpui_component::{Root, StyledExt, Theme};
|
||||
use gpui_component::notification::NotificationType;
|
||||
use gpui_component::{Root, StyledExt, Theme, WindowExt};
|
||||
use settings::{AppearanceMode, SettingsStore};
|
||||
use signed_state::{Backend, BackendEvent};
|
||||
|
||||
@@ -66,6 +67,10 @@ impl Workspace {
|
||||
if matches!(event, BackendEvent::PassphraseRequired) {
|
||||
passphrase_dialog::open(window, cx);
|
||||
}
|
||||
|
||||
if let BackendEvent::Error(message) = event {
|
||||
window.push_notification((NotificationType::Error, message.clone()), cx);
|
||||
}
|
||||
},
|
||||
));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user