reorganize signed_core into method-based APIs

This commit is contained in:
2026-10-03 12:03:29 +07:00
parent d00ee33eab
commit 023267001d
20 changed files with 833 additions and 697 deletions
+48 -41
View File
@@ -9,7 +9,8 @@ use nostr::event::IntoEventBuilder;
use nostr_sdk::prelude::*;
use settings::{EventFetchingStrategy, SettingsStore};
use signed_core::{
Announcement, Deletions, RepoAddr, RepoStatus, filters, parse_state, pull_request_patches,
Announcement, Deletions, Filters, GitEvent, PullRequest, RepoAddr, RepoState, RepoStatus,
filters,
};
use signed_git::Nip34Binding;
use signed_nostr::UniversalSigner;
@@ -210,8 +211,8 @@ impl RepoStore {
let deletion =
update.kind == Kind::EventDeletion || update.kind == Kind::RequestToVanish;
let coordinate = update.coordinate.as_ref() == Some(addr);
let author = update.author == addr.public_key;
let coordinate = update.coordinate.as_ref() == Some(addr.coordinate());
let author = update.author == addr.public_key();
let authored = (update.kind == Kind::GitRepoAnnouncement
|| update.kind == Kind::RepoState)
@@ -251,12 +252,12 @@ impl RepoStore {
let mut filters = vec![
Filter::new()
.kinds([Kind::GitRepoAnnouncement, Kind::RepoState])
.author(addr.public_key)
.identifier(addr.identifier.clone()),
filters::activity(addr),
.author(addr.public_key())
.identifier(addr.identifier()),
addr.activity_filter(),
];
// Deletion requests, NIP-09/62, must be known before any event is shown.
filters.extend(filters::deletions_for_repo(addr));
filters.extend(addr.deletion_filters());
filters
}
@@ -290,8 +291,8 @@ impl RepoStore {
let mut pubkeys = maintainers.to_vec();
// NIP-34 events tag the announcement author,
// which may not be a maintainer for subordinate forks.
if !pubkeys.contains(&addr.public_key) {
pubkeys.push(addr.public_key);
if !pubkeys.contains(&addr.public_key()) {
pubkeys.push(addr.public_key());
}
vec![
@@ -299,16 +300,16 @@ impl RepoStore {
Filter::new()
.kinds([Kind::GitRepoAnnouncement, Kind::RepoState])
.authors(pubkeys.clone())
.identifier(addr.identifier.clone()),
.identifier(addr.identifier()),
// Activity tagging a maintainer, resolved to their read relays.
Filter::new()
.kinds(filters::ACTIVITY_KINDS)
.coordinate(addr)
.coordinate(addr.coordinate())
.pubkeys(pubkeys.clone()),
// Activity authored by a maintainer, resolved to their write relays.
Filter::new()
.kinds(filters::ACTIVITY_KINDS)
.coordinate(addr)
.coordinate(addr.coordinate())
.authors(pubkeys.clone()),
// Deletions authored by a maintainer.
Filter::new()
@@ -377,10 +378,10 @@ impl RepoStore {
let work = cx.background_spawn(async move {
let (announcements, states, activity, deletion_events) = async {
let db = client.database();
let announcements = db.query(filters::announcement(&addr)).await?;
let states = db.query(filters::state(&addr)).await?;
let activity = db.query(filters::activity(&addr)).await?;
let deletion_events = db.query(filters::deletions()).await?;
let announcements = db.query(addr.announcement_filter()).await?;
let states = db.query(addr.state_filter()).await?;
let activity = db.query(addr.activity_filter()).await?;
let deletion_events = db.query(Filters::deletions()).await?;
Ok::<_, Error>((announcements, states, activity, deletion_events))
}
@@ -397,7 +398,7 @@ impl RepoStore {
.and_then(Announcement::from_event);
let all_states = states.into_iter().filter(|e| !deletions.is_deleted(e));
let state = utils::latest(all_states).map(|state| parse_state(&state));
let state = utils::latest(all_states).map(|state| RepoState::parse(&state));
let (mut issues, mut patches, mut pull_requests, mut statuses, mut comments) =
(Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new());
@@ -425,7 +426,7 @@ impl RepoStore {
.chain(&pull_requests)
.map(|e| e.id);
for filter in filters::comments_for(roots) {
for filter in Filters::comments_for(roots) {
for event in db.query(filter).await? {
if seen_comments.insert(event.id) {
comments.push(event);
@@ -443,7 +444,7 @@ impl RepoStore {
.map(|e| e.id);
for root in roots {
for event in db.query(filters::statuses_for([root])).await? {
for event in db.query(Filters::statuses_for([root])).await? {
if seen_statuses.insert(event.id) {
statuses.push(event);
}
@@ -516,7 +517,7 @@ impl RepoStore {
let head_changed = state
.as_ref()
.is_some_and(|(_, head)| this.head.as_deref() != head.as_deref());
.is_some_and(|state| this.head.as_deref() != state.head.as_deref());
let changed = first_pass
|| (!keep_hint && this.announcement != announcement)
@@ -549,8 +550,8 @@ impl RepoStore {
this.sync_maintainer_relays(&maintainers, cx);
if let Some((_, head)) = state {
this.head = head;
if let Some(state) = state {
this.head = state.head;
}
this.issues = issues;
@@ -579,8 +580,8 @@ impl RepoStore {
if !new_roots.is_empty() {
this.root_fetches.extend(new_roots.iter().copied());
let mut root_filters = filters::comments_for(new_roots.clone());
root_filters.push(filters::statuses_for(new_roots.iter().copied()));
let mut root_filters = Filters::comments_for(new_roots.clone());
root_filters.push(Filters::statuses_for(new_roots.iter().copied()));
let announced: Vec<RelayUrl> = this.repo_relays.iter().cloned().collect();
let backend = Backend::global(cx);
@@ -621,7 +622,7 @@ impl RepoStore {
pub fn is_author(&self, user: &PublicKey) -> bool {
self.addr
.as_ref()
.is_some_and(|addr| &addr.public_key == user)
.is_some_and(|addr| addr.public_key() == *user)
}
pub fn open_issue(&mut self, subject: Option<String>, content: String, cx: &mut Context<Self>) {
@@ -631,7 +632,7 @@ impl RepoStore {
};
let builder = GitIssue {
repository: addr,
repository: addr.into(),
content,
subject,
labels: Vec::new(),
@@ -644,7 +645,7 @@ impl RepoStore {
pub fn comments_of(&self, root: &EventId) -> impl Iterator<Item = &Event> {
self.comments
.iter()
.filter(move |e| signed_core::references_root(e, root))
.filter(move |e| e.references_root(root))
}
/// Comment on a root event, an issue or PR, per NIP-34, kind 1111.
@@ -745,9 +746,9 @@ impl RepoStore {
// The author's npub names their GRASP-06 namespace, `/prs/...`.
let author_npub = user.to_bech32().unwrap();
let owner = addr.public_key;
let owner = addr.public_key();
let euc = self.announcement.as_ref().and_then(|a| a.euc.clone());
let repo_id = addr.identifier.clone();
let repo_id = addr.identifier().to_owned();
let base_npub = owner.to_bech32().unwrap();
let push_relays = self
.announcement
@@ -857,7 +858,7 @@ impl RepoStore {
let clone = pr_clone_urls(prs_urls, base_clone);
let builder = GitPullRequest {
repository: addr.clone(),
repository: addr.clone().into(),
content: description,
subject,
labels: Vec::new(),
@@ -1069,7 +1070,8 @@ impl RepoStore {
// The first revision patch replies to the original root patch, NIP-34.
// Use the PR's `e` tag, or the oldest patch of the linked set if the PR has none.
let root_patch_id = root.tags.event_ids().next().or_else(|| {
pull_request_patches(root, self.patches.iter())
PullRequest::new(root)
.patches(self.patches.iter())
.first()
.map(|p| p.id)
});
@@ -1079,7 +1081,7 @@ impl RepoStore {
return;
};
let owner = addr.public_key;
let owner = addr.public_key();
let euc = self.announcement.as_ref().and_then(|a| a.euc.clone());
let root = root.clone();
@@ -1110,7 +1112,7 @@ impl RepoStore {
let builder = {
let builder = GitPullRequestUpdate {
repository: addr.clone(),
repository: addr.clone().into(),
pull_request_event: root.id,
pull_request_author: root.pubkey,
current_commit,
@@ -1182,9 +1184,9 @@ impl RepoStore {
let builder = EventBuilder::new(status.kind(), "").tags([
root_ref,
Tag::public_key(addr.public_key),
Tag::public_key(addr.public_key()),
Tag::public_key(root.pubkey),
Tag::coordinate(addr, None),
Tag::coordinate(addr.clone().into(), None),
]);
self.publish(builder, cx);
@@ -1479,7 +1481,7 @@ fn resolve_statuses(
.map(|root| {
let events = by_root.get(&root.id).map(Vec::as_slice).unwrap_or(&[]);
let status =
signed_core::resolve_status(events.iter().copied(), &root.pubkey, maintainers);
signed_core::RepoStatus::resolve(events.iter().copied(), &root.pubkey, maintainers);
(root.id, status)
})
.collect()
@@ -1518,7 +1520,10 @@ async fn publish_patch_series(
));
};
let mut tags = vec![Tag::coordinate(addr.clone(), None), Tag::public_key(owner)];
let mut tags = vec![
Tag::coordinate(addr.clone().into(), None),
Tag::public_key(owner),
];
if ix == 0 {
if let Ok(tag) = Tag::parse(["t", first_marker]) {
@@ -1586,11 +1591,13 @@ fn comment_builder(
CommentBuilder::new(content, parent_target)
.root(root_target)
.into_event_builder()
.tags([Tag::coordinate(addr.clone(), None)])
.tags([Tag::coordinate(addr.clone().into(), None)])
}
#[cfg(test)]
mod tests {
use signed_core::GitEvent;
use std::collections::HashSet;
use nostr_sdk::prelude::*;
@@ -1612,7 +1619,7 @@ mod tests {
let root = EventBuilder::new(Kind::GitIssue, "issue body")
.finalize(&keys)
.expect("signed event");
let addr = Coordinate::new(Kind::GitRepoAnnouncement, root.pubkey).identifier("my-repo");
let addr = signed_core::RepoAddr::new(root.pubkey, "my-repo");
let relay = RelayUrl::parse("wss://relay.example.com").expect("valid relay URL");
let event = comment_builder(&root, None, Some(&relay), &addr, "hi".into())
@@ -1639,14 +1646,14 @@ mod tests {
assert_eq!(e.as_slice()[1], root.id.to_hex());
// Signed's own `references_root` must keep matching the comment.
assert!(signed_core::references_root(&event, &root.id));
assert!(event.references_root(&root.id));
}
#[test]
fn maintainer_filters_name_owner_and_maintainers() {
let owner = Keys::generate().public_key();
let maintainer = Keys::generate().public_key();
let addr = Coordinate::new(Kind::GitRepoAnnouncement, owner).identifier("my-repo");
let addr = signed_core::RepoAddr::new(owner, "my-repo");
// The owner is not among the maintainers, as on a subordinate fork.
let filters = RepoStore::maintainer_filters(&addr, &[maintainer]);