cli: Add private repo support to `rad sync`
We can't use `node::seeds` for private repos.
This commit is contained in:
parent
87c38118d1
commit
a1df6d3748
|
|
@ -0,0 +1,49 @@
|
|||
Alice initializes a *private* repo.
|
||||
|
||||
``` ~alice
|
||||
$ rad init --name heartwood --description "radicle heartwood protocol & stack" --no-confirm --announce --private
|
||||
|
||||
Initializing private radicle 👾 project in .
|
||||
|
||||
✓ Project heartwood created
|
||||
✓ Syncing inventory..
|
||||
✓ Announcing inventory..
|
||||
|
||||
Your project's Repository ID (RID) is rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu.
|
||||
You can show it any time by running `rad .`
|
||||
```
|
||||
|
||||
Bob tries to clone it, and even though he's connected to Alice, it fails.
|
||||
|
||||
``` ~bob
|
||||
$ rad track rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu
|
||||
✓ Tracking policy updated for rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu with scope 'trusted'
|
||||
```
|
||||
``` ~bob (fail)
|
||||
$ rad sync rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu --fetch --seed z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --timeout 3
|
||||
✗ Fetching rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu from z6MknSL…StBU8Vi.. <canceled>
|
||||
✗ Sync failed: failed to call node: i/o: timed out reading from control socket
|
||||
```
|
||||
|
||||
She allows Bob to view the repository. And when she syncs, one node (Bob) gets
|
||||
the refs.
|
||||
|
||||
``` ~alice
|
||||
$ rad id edit --allow did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk -q
|
||||
e98cd6a0a3e94837b382e59e02b3ea83991a8244
|
||||
$ rad id accept e98cd6a0a3e94837b382e59e02b3ea83991a8244 -q
|
||||
$ rad id commit e98cd6a0a3e94837b382e59e02b3ea83991a8244 -q
|
||||
c568f8aac97db40a5e63e1261872bfbd9a3a61e4
|
||||
$ rad sync --announce --timeout 1
|
||||
✓ Synced with 1 node(s)
|
||||
```
|
||||
|
||||
Bob can now fetch the private repo:
|
||||
|
||||
``` ~bob
|
||||
$ rad sync rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu --fetch
|
||||
✓ Fetching rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu from z6MknSL…StBU8Vi..
|
||||
✓ Fetched repository from 1 seed(s)
|
||||
$ rad ls --private
|
||||
heartwood rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu f2de534 radicle heartwood protocol & stack
|
||||
```
|
||||
|
|
@ -6,7 +6,8 @@ use anyhow::{anyhow, Context as _};
|
|||
|
||||
use radicle::node;
|
||||
use radicle::node::{FetchResult, FetchResults, Handle as _, Node};
|
||||
use radicle::prelude::{Id, NodeId};
|
||||
use radicle::prelude::{Id, NodeId, Profile};
|
||||
use radicle::storage::{ReadRepository, ReadStorage};
|
||||
|
||||
use crate::terminal as term;
|
||||
use crate::terminal::args::{Args, Error, Help};
|
||||
|
|
@ -192,13 +193,13 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
|||
let failed = results.failed().count();
|
||||
|
||||
if success == 0 {
|
||||
term::error(format!("Failed to fetch repository from {failed} seed(s)"));
|
||||
anyhow::bail!("repository fetch from {failed} seed(s) failed");
|
||||
} else {
|
||||
term::success!("Fetched repository from {success} seed(s)");
|
||||
}
|
||||
}
|
||||
if [SyncDirection::Announce, SyncDirection::Both].contains(&options.sync.direction) {
|
||||
announce(rid, mode, options.timeout, node)?;
|
||||
announce(rid, mode, options.timeout, node, &profile)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -208,9 +209,21 @@ fn announce(
|
|||
_mode: SyncMode,
|
||||
timeout: time::Duration,
|
||||
mut node: Node,
|
||||
profile: &Profile,
|
||||
) -> anyhow::Result<()> {
|
||||
let seeds = node.seeds(rid)?;
|
||||
let connected = seeds.connected().map(|s| s.nid).collect::<Vec<_>>();
|
||||
let repo = profile.storage.repository(rid)?;
|
||||
let (_, doc) = repo.identity_doc()?;
|
||||
let connected: Vec<_> = if doc.visibility.is_public() {
|
||||
let seeds = node.seeds(rid)?;
|
||||
seeds.connected().map(|s| s.nid).collect()
|
||||
} else {
|
||||
node.sessions()?
|
||||
.into_iter()
|
||||
.filter(|s| s.state.is_connected() && doc.is_visible_to(&s.nid))
|
||||
.map(|s| s.nid)
|
||||
.collect()
|
||||
};
|
||||
|
||||
if connected.is_empty() {
|
||||
term::info!("Not connected to any seeds.");
|
||||
return Ok(());
|
||||
|
|
|
|||
|
|
@ -1159,6 +1159,38 @@ fn rad_patch_pull_update() {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rad_init_private() {
|
||||
logger::init(log::Level::Debug);
|
||||
|
||||
let mut environment = Environment::new();
|
||||
let alice = environment.node(Config::test(Alias::new("alice")));
|
||||
let bob = environment.node(Config::test(Alias::new("bob")));
|
||||
let working = environment.tmp().join("working");
|
||||
|
||||
fixtures::repository(working.join("alice"));
|
||||
|
||||
let alice = alice.spawn();
|
||||
let mut bob = bob.spawn();
|
||||
|
||||
bob.connect(&alice).converge([&alice]);
|
||||
|
||||
formula(&environment.tmp(), "examples/rad-init-private.md")
|
||||
.unwrap()
|
||||
.home(
|
||||
"alice",
|
||||
working.join("alice"),
|
||||
[("RAD_HOME", alice.home.path().display())],
|
||||
)
|
||||
.home(
|
||||
"bob",
|
||||
bob.home.path(),
|
||||
[("RAD_HOME", bob.home.path().display())],
|
||||
)
|
||||
.run()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn framework_home() {
|
||||
logger::init(log::Level::Debug);
|
||||
|
|
|
|||
|
|
@ -722,21 +722,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Called when a remote requests a repository be uploaded to it.
|
||||
/// The upload is authorized if this function returns `true`.
|
||||
pub fn upload(&mut self, rid: Id, remote: &NodeId) -> bool {
|
||||
let Ok(repo) = self.storage.repository(rid) else {
|
||||
return false;
|
||||
};
|
||||
let Ok((_, doc)) = repo.identity_doc() else {
|
||||
return false;
|
||||
};
|
||||
if !doc.is_visible_to(remote) {
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/// Inbound connection attempt.
|
||||
pub fn accepted(&mut self, addr: Address) -> bool {
|
||||
// Always accept trusted connections.
|
||||
|
|
|
|||
Loading…
Reference in New Issue