Skip to content
This repository was archived by the owner on Aug 1, 2022. It is now read-only.

Commit 2924251

Browse files
committed
simplify patch listing in proxy to make it more portable
Signed-off-by: Thomas Scholtes <[email protected]>
1 parent 7484082 commit 2924251

File tree

1 file changed

+91
-81
lines changed

1 file changed

+91
-81
lines changed

upstream-proxy/src/patch.rs

Lines changed: 91 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@
66

77
//! [`list`] all the [`Patch`]es for project.
88
9+
use anyhow::Context as _;
910
use either::Either;
1011
use radicle_git_ext::Oid;
11-
use radicle_source::surf::git::RefScope;
1212
use serde::Serialize;
1313

14-
use link_crypto::PeerId;
1514
use link_identities::git::Urn;
1615

1716
use crate::project;
@@ -43,106 +42,117 @@ pub struct Patch {
4342
/// # Errors
4443
/// * Cannot access the monorepo
4544
/// * Cannot find references within the monorepo
46-
pub async fn list(
47-
peer: &crate::peer::Peer,
48-
project_urn: Urn,
49-
) -> Result<Vec<Patch>, crate::error::Error> {
50-
let mut patches = Vec::new();
51-
45+
pub async fn list(peer: &crate::peer::Peer, project_urn: Urn) -> anyhow::Result<Vec<Patch>> {
5246
let default_branch_head_commit_id = {
53-
let project = crate::daemon::state::get_project(peer.librad_peer(), project_urn.clone())
54-
.await?
55-
.ok_or_else(|| crate::daemon::state::Error::ProjectNotFound(project_urn.clone()))?;
56-
let delegate = project
47+
let project = peer
48+
.librad_peer()
49+
.using_storage({
50+
let project_urn = project_urn.clone();
51+
move |store| librad::git::identities::project::get(store, &project_urn)
52+
})
53+
.await
54+
.context("failed to access storage")?
55+
.context("failed to get project")?
56+
.ok_or_else(|| anyhow::anyhow!("project {project_urn} not found"))?;
57+
let first_delegate = project
5758
.delegations()
5859
.iter()
5960
.flat_map(|either| match either {
6061
Either::Left(pk) => Either::Left(std::iter::once(pk)),
6162
Either::Right(indirect) => Either::Right(indirect.delegations().iter()),
6263
})
6364
.next()
64-
.expect("missing delegation");
65-
let default_branch = crate::daemon::state::get_branch(
66-
peer.librad_peer(),
67-
project_urn.clone(),
68-
Some(PeerId::from(*delegate)),
69-
None,
70-
)
71-
.await?;
72-
crate::browser::using(peer, default_branch, move |browser| {
73-
Ok(browser.get().first().clone())
74-
})?
75-
.id
65+
.context("project does not have any delegations")?;
66+
let first_delegate = librad::PeerId::from(*first_delegate);
67+
let remote = if first_delegate == peer.librad_peer().peer_id() {
68+
None
69+
} else {
70+
Some(first_delegate)
71+
};
72+
73+
let default_branch_ref_name =
74+
if let Some(ref default_branch_name) = project.subject().default_branch {
75+
default_branch_name
76+
.parse::<radicle_git_ext::RefLike>()
77+
.context("invalid default branch name")?
78+
} else {
79+
librad::reflike!("main")
80+
};
81+
82+
let reference = librad::git::types::Reference::head(
83+
librad::git::types::Namespace::from(project_urn.clone()),
84+
remote,
85+
default_branch_ref_name,
86+
);
87+
peer.monorepo_unblock(move |repo| Ok(reference.oid(&repo)?))
88+
.await
89+
.context("failed to resolve git reference")?
7690
};
7791

92+
let mut patches = Vec::new();
93+
7894
for project_peer in
7995
crate::daemon::state::list_project_peers(peer.librad_peer(), project_urn.clone()).await?
8096
{
81-
let remote = match &project_peer {
82-
crate::daemon::project::Peer::Local { .. } => None,
83-
crate::daemon::project::Peer::Remote { peer_id, .. } => Some(*peer_id),
84-
};
85-
86-
let ref_scope = match remote {
87-
Some(remote) => RefScope::Remote {
88-
name: Some(remote.to_string()),
97+
let namespace = project_urn.encode_id();
98+
let ref_glob = match &project_peer {
99+
crate::daemon::project::Peer::Local { .. } => {
100+
format!("refs/namespaces/{namespace}/refs/tags/{TAG_PREFIX}*")
89101
},
90-
None => RefScope::Local,
91-
};
92-
93-
let branch = match crate::daemon::state::get_branch(
94-
peer.librad_peer(),
95-
project_urn.clone(),
96-
remote,
97-
None,
98-
)
99-
.await
100-
{
101-
Ok(branch) => branch,
102-
Err(crate::daemon::state::Error::MissingRef { .. }) => {
103-
// The peer hasn’t published any branches yet.
104-
continue;
102+
crate::daemon::project::Peer::Remote { peer_id, .. } => {
103+
format!("refs/namespaces/{namespace}/refs/remotes/{peer_id}/tags/{TAG_PREFIX}*")
105104
},
106-
Err(e) => return Err(e.into()),
107105
};
108106

109-
crate::browser::using(peer, branch, {
110-
let patches = &mut patches;
111-
move |browser| {
112-
let tags = browser.list_tags(ref_scope)?;
113-
for tag in tags {
114-
match tag {
115-
radicle_source::surf::git::Tag::Light { .. } => {
116-
continue;
117-
},
118-
radicle_source::surf::git::Tag::Annotated {
119-
target_id,
120-
name,
121-
message,
122-
..
123-
} => {
124-
let id = match name.to_string().strip_prefix(TAG_PREFIX) {
125-
Some(id) => id.to_string(),
126-
None => continue,
127-
};
107+
let patch = peer
108+
.monorepo_unblock({
109+
move |repo| {
110+
let mut patches = vec![];
111+
for ref_result in repo
112+
.references_glob(&ref_glob)
113+
.context("failed to get references from glob")?
114+
{
115+
let reference = ref_result.context("failed to resolve reference")?;
116+
let tag = reference
117+
.peel_to_tag()
118+
.context("failed to peel reference to tag")?;
128119

129-
let merge_base = browser
130-
.merge_base(target_id, default_branch_head_commit_id)?
131-
.map(Oid::from);
132-
patches.push(Patch {
133-
id,
134-
peer: project_peer.clone().into(),
135-
message,
136-
commit: Oid::from(target_id),
137-
merge_base,
138-
});
139-
},
120+
let id = tag
121+
.name()
122+
.ok_or_else(|| anyhow::anyhow!("tag name is not valid UTF-8"))?
123+
.strip_prefix(TAG_PREFIX)
124+
.expect("tag name must have prefix")
125+
.to_string();
126+
let commit_id = tag.target_id();
127+
let merge_base =
128+
match repo.merge_base(commit_id, default_branch_head_commit_id) {
129+
Ok(base) => Some(Oid::from(base)),
130+
Err(err) if err.code() == git2::ErrorCode::NotFound => None,
131+
Err(err) => {
132+
return Err(err)
133+
.context("failed to determine merge base for commits")
134+
},
135+
};
136+
patches.push(Patch {
137+
id,
138+
peer: project_peer.clone().into(),
139+
message: Some(
140+
tag.message()
141+
.ok_or_else(|| {
142+
anyhow::anyhow!("tag message is not valid UTF-8")
143+
})?
144+
.to_string(),
145+
),
146+
commit: Oid::from(commit_id),
147+
merge_base,
148+
})
140149
}
150+
Ok(patches)
141151
}
152+
})
153+
.await?;
142154

143-
Ok(())
144-
}
145-
})?;
155+
patches.extend(patch)
146156
}
147157

148158
Ok(patches)

0 commit comments

Comments
 (0)