cli: Consolidate policy/scope variants
* Policy::Track -> Policy::Allow * Scope::Trusted -> Scope::Followed
This commit is contained in:
parent
4605348d68
commit
f453090e27
|
|
@ -153,8 +153,8 @@ You can see all replicated and locally-available repositories using:
|
||||||
$ rad ls
|
$ rad ls
|
||||||
|
|
||||||
By default, your node will subscribe to updates from _all_ peers. This
|
By default, your node will subscribe to updates from _all_ peers. This
|
||||||
behavior can be changed by passing *--scope trusted* when cloning. It can
|
behavior can be changed by passing *--scope followed* when cloning. It can
|
||||||
also be changed later via the *rad track* command.
|
also be changed later via the *rad seed* command.
|
||||||
|
|
||||||
=== Publishing a repository on Radicle
|
=== Publishing a repository on Radicle
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
Trying to clone a repository that is not in our routing table returns an error:
|
Trying to clone a repository that is not in our routing table returns an error:
|
||||||
|
|
||||||
``` (fail)
|
``` (fail)
|
||||||
$ rad clone rad:zVNuptPuk5XauitpCWSNVCXGGfXW --scope trusted
|
$ rad clone rad:zVNuptPuk5XauitpCWSNVCXGGfXW --scope followed
|
||||||
✓ Tracking relationship established for rad:zVNuptPuk5XauitpCWSNVCXGGfXW with scope 'trusted'
|
✓ Tracking relationship established for rad:zVNuptPuk5XauitpCWSNVCXGGfXW with scope 'followed'
|
||||||
✗ Error: no seeds found for rad:zVNuptPuk5XauitpCWSNVCXGGfXW
|
✗ Error: no seeds found for rad:zVNuptPuk5XauitpCWSNVCXGGfXW
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ To create a local copy of a repository on the radicle network, we use the
|
||||||
`clone` command, followed by the identifier or *RID* of the repository:
|
`clone` command, followed by the identifier or *RID* of the repository:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --scope trusted
|
$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --scope followed
|
||||||
✓ Tracking relationship established for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'trusted'
|
✓ Tracking relationship established for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
|
||||||
✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MknSL…StBU8Vi..
|
✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MknSL…StBU8Vi..
|
||||||
✓ Forking under z6Mkt67…v4N1tRk..
|
✓ Forking under z6Mkt67…v4N1tRk..
|
||||||
✓ Creating checkout in ./heartwood..
|
✓ Creating checkout in ./heartwood..
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ $ rad config
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"policy": "block",
|
"policy": "block",
|
||||||
"scope": "trusted"
|
"scope": "followed"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ Given a private repo `rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu` belonging to Alice,
|
||||||
Bob tries to fetch it, and even though he's connected to Alice, it fails.
|
Bob tries to fetch it, and even though he's connected to Alice, it fails.
|
||||||
|
|
||||||
``` ~bob
|
``` ~bob
|
||||||
$ rad seed rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu --scope trusted
|
$ rad seed rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu --scope followed
|
||||||
✓ Seeding policy updated for rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu with scope 'trusted'
|
✓ Seeding policy updated for rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu with scope 'followed'
|
||||||
$ rad ls
|
$ rad ls
|
||||||
```
|
```
|
||||||
``` ~bob (fail)
|
``` ~bob (fail)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ To create your first radicle project, navigate to a git repository, and run
|
||||||
the `init` command:
|
the `init` command:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rad init --name heartwood --description "Radicle Heartwood Protocol & Stack" --no-confirm --public --scope trusted
|
$ rad init --name heartwood --description "Radicle Heartwood Protocol & Stack" --no-confirm --public --scope followed
|
||||||
|
|
||||||
Initializing public radicle 👾 project in .
|
Initializing public radicle 👾 project in .
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,11 +34,11 @@ repository that was already created:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rad node seeding
|
$ rad node seeding
|
||||||
╭──────────────────────────────────────────────────────╮
|
╭───────────────────────────────────────────────────────╮
|
||||||
│ RID Scope Policy │
|
│ RID Scope Policy │
|
||||||
├──────────────────────────────────────────────────────┤
|
├───────────────────────────────────────────────────────┤
|
||||||
│ rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji trusted track │
|
│ rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji followed allow │
|
||||||
╰──────────────────────────────────────────────────────╯
|
╰───────────────────────────────────────────────────────╯
|
||||||
```
|
```
|
||||||
|
|
||||||
If we wish to see which nodes we are following:
|
If we wish to see which nodes we are following:
|
||||||
|
|
@ -48,7 +48,7 @@ $ rad node following
|
||||||
╭───────────────────────────────────────────────────────────────────────────╮
|
╭───────────────────────────────────────────────────────────────────────────╮
|
||||||
│ DID Alias Policy │
|
│ DID Alias Policy │
|
||||||
├───────────────────────────────────────────────────────────────────────────┤
|
├───────────────────────────────────────────────────────────────────────────┤
|
||||||
│ did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk Bob track │
|
│ did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk Bob allow │
|
||||||
╰───────────────────────────────────────────────────────────────────────────╯
|
╰───────────────────────────────────────────────────────────────────────────╯
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,6 @@ $ rad follow did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --alias ev
|
||||||
Now let's track one of Eve's repositories:
|
Now let's track one of Eve's repositories:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rad seed rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --scope trusted --no-fetch
|
$ rad seed rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --scope followed --no-fetch
|
||||||
✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'trusted'
|
✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
let tracking = profile.tracking()?;
|
let tracking = profile.tracking()?;
|
||||||
if let Some(repo) = tracking.repo_policy(&rid)? {
|
if let Some(repo) = tracking.repo_policy(&rid)? {
|
||||||
let tracking = match repo.policy {
|
let tracking = match repo.policy {
|
||||||
Policy::Track => term::format::positive("tracked"),
|
Policy::Allow => term::format::positive("tracked"),
|
||||||
Policy::Block => term::format::negative("blocked"),
|
Policy::Block => term::format::negative("blocked"),
|
||||||
};
|
};
|
||||||
println!(
|
println!(
|
||||||
|
|
|
||||||
|
|
@ -25,15 +25,15 @@ Usage
|
||||||
To delete a policy, use the `--delete` flag.
|
To delete a policy, use the `--delete` flag.
|
||||||
|
|
||||||
When seeding a repository, a scope can be specified: this can be either `all` or
|
When seeding a repository, a scope can be specified: this can be either `all` or
|
||||||
`trusted`. When using `all`, all remote nodes will be followed for that repository.
|
`followed`. When using `all`, all remote nodes will be followed for that repository.
|
||||||
On the other hand, with `trusted`, only the repository delegates will be followed,
|
On the other hand, with `followed`, only the repository delegates will be followed,
|
||||||
plus any remote that is explicitly followed via `rad follow <nid>`.
|
plus any remote that is explicitly followed via `rad follow <nid>`.
|
||||||
|
|
||||||
Options
|
Options
|
||||||
|
|
||||||
--delete, -d Delete the seeding policy
|
--delete, -d Delete the seeding policy
|
||||||
--[no-]fetch Fetch repository after updating seeding policy
|
--[no-]fetch Fetch repository after updating seeding policy
|
||||||
--scope <scope> Peer follow scope for a repository
|
--scope <scope> Peer follow scope for this repository
|
||||||
--verbose, -v Verbose output
|
--verbose, -v Verbose output
|
||||||
--help Print help
|
--help Print help
|
||||||
"#,
|
"#,
|
||||||
|
|
|
||||||
|
|
@ -700,7 +700,7 @@ fn rad_clean() {
|
||||||
let mut bob = bob.spawn();
|
let mut bob = bob.spawn();
|
||||||
let mut eve = eve.spawn();
|
let mut eve = eve.spawn();
|
||||||
alice.handle.track_repo(acme, Scope::All).unwrap();
|
alice.handle.track_repo(acme, Scope::All).unwrap();
|
||||||
eve.handle.track_repo(acme, Scope::Trusted).unwrap();
|
eve.handle.track_repo(acme, Scope::Followed).unwrap();
|
||||||
|
|
||||||
bob.connect(&alice).converge([&alice]);
|
bob.connect(&alice).converge([&alice]);
|
||||||
eve.connect(&alice).converge([&alice]);
|
eve.connect(&alice).converge([&alice]);
|
||||||
|
|
@ -769,7 +769,7 @@ fn rad_clone() {
|
||||||
let mut alice = alice.spawn();
|
let mut alice = alice.spawn();
|
||||||
let mut bob = bob.spawn();
|
let mut bob = bob.spawn();
|
||||||
// Prevent Alice from fetching Bob's fork, as we're not testing that and it may cause errors.
|
// Prevent Alice from fetching Bob's fork, as we're not testing that and it may cause errors.
|
||||||
alice.handle.track_repo(acme, Scope::Trusted).unwrap();
|
alice.handle.track_repo(acme, Scope::Followed).unwrap();
|
||||||
|
|
||||||
bob.connect(&alice).converge([&alice]);
|
bob.connect(&alice).converge([&alice]);
|
||||||
|
|
||||||
|
|
@ -873,8 +873,8 @@ fn rad_clone_connect() {
|
||||||
|
|
||||||
let eve = eve.spawn();
|
let eve = eve.spawn();
|
||||||
|
|
||||||
alice.handle.track_repo(acme, Scope::Trusted).unwrap();
|
alice.handle.track_repo(acme, Scope::Followed).unwrap();
|
||||||
bob.handle.track_repo(acme, Scope::Trusted).unwrap();
|
bob.handle.track_repo(acme, Scope::Followed).unwrap();
|
||||||
alice.connect(&bob);
|
alice.connect(&bob);
|
||||||
bob.routes_to(&[(acme, alice.id)]);
|
bob.routes_to(&[(acme, alice.id)]);
|
||||||
eve.routes_to(&[(acme, alice.id), (acme, bob.id)]);
|
eve.routes_to(&[(acme, alice.id), (acme, bob.id)]);
|
||||||
|
|
@ -1257,7 +1257,7 @@ fn test_replication_via_seed() {
|
||||||
let alice = environment.node(Config::test(Alias::new("alice")));
|
let alice = environment.node(Config::test(Alias::new("alice")));
|
||||||
let bob = environment.node(Config::test(Alias::new("bob")));
|
let bob = environment.node(Config::test(Alias::new("bob")));
|
||||||
let seed = environment.node(Config {
|
let seed = environment.node(Config {
|
||||||
policy: Policy::Track,
|
policy: Policy::Allow,
|
||||||
scope: Scope::All,
|
scope: Scope::All,
|
||||||
..Config::test(Alias::new("seed"))
|
..Config::test(Alias::new("seed"))
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
//! delegate data for the repository.
|
//! delegate data for the repository.
|
||||||
//! 2. [`SpecialRefs`]: fetches the special references, `rad/id` and
|
//! 2. [`SpecialRefs`]: fetches the special references, `rad/id` and
|
||||||
//! `rad/sigrefs`, for each configured namespace, i.e. tracked
|
//! `rad/sigrefs`, for each configured namespace, i.e. tracked
|
||||||
//! and delegate peers if the scope is trusted and all peers is the
|
//! and delegate peers if the scope is "followed" and all peers is the
|
||||||
//! scope is all.
|
//! scope is all.
|
||||||
//! 3. [`DataRefs`]: fetches the `Oid`s for each reference listed in
|
//! 3. [`DataRefs`]: fetches the `Oid`s for each reference listed in
|
||||||
//! the `rad/sigrefs` for each fetched peer in the
|
//! the `rad/sigrefs` for each fetched peer in the
|
||||||
|
|
@ -241,7 +241,7 @@ impl ProtocolStage for SpecialRefs {
|
||||||
fn ls_refs(&self) -> Option<NonEmpty<BString>> {
|
fn ls_refs(&self) -> Option<NonEmpty<BString>> {
|
||||||
match &self.tracked {
|
match &self.tracked {
|
||||||
tracking::Tracked::All => Some(NonEmpty::new("refs/namespaces".into())),
|
tracking::Tracked::All => Some(NonEmpty::new("refs/namespaces".into())),
|
||||||
tracking::Tracked::Trusted { remotes } => NonEmpty::collect(
|
tracking::Tracked::Followed { remotes } => NonEmpty::collect(
|
||||||
remotes
|
remotes
|
||||||
.iter()
|
.iter()
|
||||||
.chain(self.delegates.iter())
|
.chain(self.delegates.iter())
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ pub use radicle::node::tracking::{Policy, Scope};
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Tracked {
|
pub enum Tracked {
|
||||||
All,
|
All,
|
||||||
Trusted { remotes: HashSet<PublicKey> },
|
Followed { remotes: HashSet<PublicKey> },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tracked {
|
impl Tracked {
|
||||||
|
|
@ -23,17 +23,17 @@ impl Tracked {
|
||||||
log::error!(target: "fetch", "Attempted to fetch untracked repo {rid}");
|
log::error!(target: "fetch", "Attempted to fetch untracked repo {rid}");
|
||||||
Err(error::Tracking::BlockedPolicy { rid })
|
Err(error::Tracking::BlockedPolicy { rid })
|
||||||
}
|
}
|
||||||
Policy::Track => match entry.scope {
|
Policy::Allow => match entry.scope {
|
||||||
Scope::All => Ok(Self::All),
|
Scope::All => Ok(Self::All),
|
||||||
Scope::Trusted => {
|
Scope::Followed => {
|
||||||
let nodes = config
|
let nodes = config
|
||||||
.node_policies()
|
.node_policies()
|
||||||
.map_err(|err| error::Tracking::FailedNodes { rid, err })?;
|
.map_err(|err| error::Tracking::FailedNodes { rid, err })?;
|
||||||
let trusted: HashSet<_> = nodes
|
let followed: HashSet<_> = nodes
|
||||||
.filter_map(|node| (node.policy == Policy::Track).then_some(node.id))
|
.filter_map(|node| (node.policy == Policy::Allow).then_some(node.id))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(Tracked::Trusted { remotes: trusted })
|
Ok(Tracked::Followed { remotes: followed })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -425,7 +425,7 @@ where
|
||||||
self.filter = Filter::new(
|
self.filter = Filter::new(
|
||||||
self.tracking
|
self.tracking
|
||||||
.repo_policies()?
|
.repo_policies()?
|
||||||
.filter_map(|t| (t.policy == tracking::Policy::Track).then_some(t.id)),
|
.filter_map(|t| (t.policy == tracking::Policy::Allow).then_some(t.id)),
|
||||||
);
|
);
|
||||||
Ok(updated)
|
Ok(updated)
|
||||||
}
|
}
|
||||||
|
|
@ -570,7 +570,7 @@ where
|
||||||
self.filter = Filter::new(
|
self.filter = Filter::new(
|
||||||
self.tracking
|
self.tracking
|
||||||
.repo_policies()?
|
.repo_policies()?
|
||||||
.filter_map(|t| (t.policy == tracking::Policy::Track).then_some(t.id)),
|
.filter_map(|t| (t.policy == tracking::Policy::Allow).then_some(t.id)),
|
||||||
);
|
);
|
||||||
// Try to establish some connections.
|
// Try to establish some connections.
|
||||||
self.maintain_connections();
|
self.maintain_connections();
|
||||||
|
|
@ -1266,7 +1266,7 @@ where
|
||||||
"Service::handle_announcement: error accessing repo tracking configuration",
|
"Service::handle_announcement: error accessing repo tracking configuration",
|
||||||
);
|
);
|
||||||
|
|
||||||
if repo_entry.policy == tracking::Policy::Track {
|
if repo_entry.policy == tracking::Policy::Allow {
|
||||||
let (fresh, stale) = match self.refs_status_of(message, &repo_entry.scope) {
|
let (fresh, stale) = match self.refs_status_of(message, &repo_entry.scope) {
|
||||||
Ok(RefsStatus { fresh, stale }) => (fresh, stale),
|
Ok(RefsStatus { fresh, stale }) => (fresh, stale),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
@ -1424,13 +1424,13 @@ where
|
||||||
// Second, check the scope.
|
// Second, check the scope.
|
||||||
match scope {
|
match scope {
|
||||||
tracking::Scope::All => Ok(refs),
|
tracking::Scope::All => Ok(refs),
|
||||||
tracking::Scope::Trusted => {
|
tracking::Scope::Followed => {
|
||||||
match self.tracking.namespaces_for(&self.storage, &message.rid) {
|
match self.tracking.namespaces_for(&self.storage, &message.rid) {
|
||||||
Ok(Namespaces::All) => Ok(refs),
|
Ok(Namespaces::All) => Ok(refs),
|
||||||
Ok(Namespaces::Trusted(mut trusted)) => {
|
Ok(Namespaces::Followed(mut followed)) => {
|
||||||
// Get the set of trusted nodes except self.
|
// Get the set of followed nodes except self.
|
||||||
trusted.remove(self.nid());
|
followed.remove(self.nid());
|
||||||
refs.fresh.retain(|r| trusted.contains(&r.remote));
|
refs.fresh.retain(|r| followed.contains(&r.remote));
|
||||||
|
|
||||||
Ok(refs)
|
Ok(refs)
|
||||||
}
|
}
|
||||||
|
|
@ -1817,7 +1817,7 @@ where
|
||||||
|
|
||||||
/// Return a new filter object, based on our tracking policy.
|
/// Return a new filter object, based on our tracking policy.
|
||||||
fn filter(&self) -> Filter {
|
fn filter(&self) -> Filter {
|
||||||
if self.config.policy == tracking::Policy::Track {
|
if self.config.policy == tracking::Policy::Allow {
|
||||||
// TODO: Remove bits for blocked repos.
|
// TODO: Remove bits for blocked repos.
|
||||||
Filter::default()
|
Filter::default()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1920,7 +1920,7 @@ where
|
||||||
let missing = self
|
let missing = self
|
||||||
.tracking
|
.tracking
|
||||||
.repo_policies()?
|
.repo_policies()?
|
||||||
.filter_map(|t| (t.policy == tracking::Policy::Track).then_some(t.id))
|
.filter_map(|t| (t.policy == tracking::Policy::Allow).then_some(t.id))
|
||||||
.filter(|rid| !inventory.contains(rid));
|
.filter(|rid| !inventory.contains(rid));
|
||||||
|
|
||||||
for rid in missing {
|
for rid in missing {
|
||||||
|
|
|
||||||
|
|
@ -420,7 +420,7 @@ impl<G: cyphernet::Ecdh<Pk = NodeId> + Signer + Clone> Node<G> {
|
||||||
|
|
||||||
assert!(self
|
assert!(self
|
||||||
.tracking
|
.tracking
|
||||||
.track_repo(&id, node::tracking::Scope::Trusted)
|
.track_repo(&id, node::tracking::Scope::Followed)
|
||||||
.unwrap());
|
.unwrap());
|
||||||
|
|
||||||
log::debug!(
|
log::debug!(
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ where
|
||||||
config.config.external_addresses.push(local_addr.into());
|
config.config.external_addresses.push(local_addr.into());
|
||||||
|
|
||||||
for rid in storage.inventory().unwrap() {
|
for rid in storage.inventory().unwrap() {
|
||||||
tracking.track_repo(&rid, Scope::Trusted).unwrap();
|
tracking.track_repo(&rid, Scope::Followed).unwrap();
|
||||||
}
|
}
|
||||||
let announcement = service::gossip::node(&config.config, config.local_time.as_secs());
|
let announcement = service::gossip::node(&config.config, config.local_time.as_secs());
|
||||||
let emitter: Emitter<Event> = Default::default();
|
let emitter: Emitter<Event> = Default::default();
|
||||||
|
|
|
||||||
|
|
@ -422,7 +422,7 @@ impl<S: WriteStorage + 'static, G: Signer> Simulation<S, G> {
|
||||||
radicle::test::fetch(
|
radicle::test::fetch(
|
||||||
&repo,
|
&repo,
|
||||||
&nid,
|
&nid,
|
||||||
Namespaces::Trusted(namespaces.clone()),
|
Namespaces::Followed(namespaces.clone()),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
@ -655,7 +655,7 @@ impl<S: WriteStorage + 'static, G: Signer> Simulation<S, G> {
|
||||||
Rc::new(Ok(fetch::FetchResult {
|
Rc::new(Ok(fetch::FetchResult {
|
||||||
updated: vec![],
|
updated: vec![],
|
||||||
namespaces: match namespaces {
|
namespaces: match namespaces {
|
||||||
Namespaces::Trusted(hs) => hs,
|
Namespaces::Followed(hs) => hs,
|
||||||
Namespaces::All => HashSet::new(),
|
Namespaces::All => HashSet::new(),
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
|
|
|
||||||
|
|
@ -742,7 +742,7 @@ fn test_refs_announcement_fetch_trusted_no_inventory() {
|
||||||
let bob_inv = bob.storage().inventory().unwrap();
|
let bob_inv = bob.storage().inventory().unwrap();
|
||||||
let rid = bob_inv[0];
|
let rid = bob_inv[0];
|
||||||
|
|
||||||
alice.track_repo(&rid, tracking::Scope::Trusted).unwrap();
|
alice.track_repo(&rid, tracking::Scope::Followed).unwrap();
|
||||||
alice.connect_to(&bob);
|
alice.connect_to(&bob);
|
||||||
|
|
||||||
// Alice receives Bob's refs.
|
// Alice receives Bob's refs.
|
||||||
|
|
@ -755,11 +755,11 @@ fn test_refs_announcement_fetch_trusted_no_inventory() {
|
||||||
/// Alice and Bob both have the same repo.
|
/// Alice and Bob both have the same repo.
|
||||||
///
|
///
|
||||||
/// First, Alice will not fetch from Bob's `RefsAnnouncement` as Alice does not
|
/// First, Alice will not fetch from Bob's `RefsAnnouncement` as Alice does not
|
||||||
/// track Bob as `Trusted`.
|
/// track Bob as `Followed`.
|
||||||
///
|
///
|
||||||
/// Later Alice tracks Bob, and will be able to fetch Bob's refs.
|
/// Later Alice follows Bob, and will be able to fetch Bob's refs.
|
||||||
#[test]
|
#[test]
|
||||||
fn test_refs_announcement_trusted() {
|
fn test_refs_announcement_followed() {
|
||||||
logger::init(log::Level::Debug);
|
logger::init(log::Level::Debug);
|
||||||
|
|
||||||
// Create MockStorage for Alice and Bob. Both will have repo with `rid`.
|
// Create MockStorage for Alice and Bob. Both will have repo with `rid`.
|
||||||
|
|
@ -796,9 +796,9 @@ fn test_refs_announcement_trusted() {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Alice uses Scope::Trusted, and did not track Bob yet.
|
// Alice uses Scope::Followed, and did not track Bob yet.
|
||||||
alice.connect_to(&bob);
|
alice.connect_to(&bob);
|
||||||
alice.track_repo(&rid, tracking::Scope::Trusted).unwrap();
|
alice.track_repo(&rid, tracking::Scope::Followed).unwrap();
|
||||||
|
|
||||||
// Alice receives Bob's refs
|
// Alice receives Bob's refs
|
||||||
alice.receive(bob.id(), bob.refs_announcement(rid));
|
alice.receive(bob.id(), bob.refs_announcement(rid));
|
||||||
|
|
@ -1538,14 +1538,14 @@ fn test_push_and_pull() {
|
||||||
assert!(eve.get(proj_id).unwrap().is_none());
|
assert!(eve.get(proj_id).unwrap().is_none());
|
||||||
assert!(bob.get(proj_id).unwrap().is_none());
|
assert!(bob.get(proj_id).unwrap().is_none());
|
||||||
|
|
||||||
// Bob tracks Alice's project.
|
// Bob seeds Alice's project.
|
||||||
let (sender, _) = chan::bounded(1);
|
let (sender, _) = chan::bounded(1);
|
||||||
bob.command(service::Command::TrackRepo(
|
bob.command(service::Command::TrackRepo(
|
||||||
proj_id,
|
proj_id,
|
||||||
tracking::Scope::default(),
|
tracking::Scope::default(),
|
||||||
sender,
|
sender,
|
||||||
));
|
));
|
||||||
// Eve tracks Alice's project.
|
// Eve seeds Alice's project.
|
||||||
let (sender, _) = chan::bounded(1);
|
let (sender, _) = chan::bounded(1);
|
||||||
eve.command(service::Command::TrackRepo(
|
eve.command(service::Command::TrackRepo(
|
||||||
proj_id,
|
proj_id,
|
||||||
|
|
|
||||||
|
|
@ -284,7 +284,7 @@ fn test_replication_invalid() {
|
||||||
converge([&alice, &bob]);
|
converge([&alice, &bob]);
|
||||||
|
|
||||||
alice.handle.track_node(*carol.public_key(), None).unwrap();
|
alice.handle.track_node(*carol.public_key(), None).unwrap();
|
||||||
alice.handle.track_repo(acme, Scope::Trusted).unwrap();
|
alice.handle.track_repo(acme, Scope::Followed).unwrap();
|
||||||
let result = alice.handle.fetch(acme, bob.id, DEFAULT_TIMEOUT).unwrap();
|
let result = alice.handle.fetch(acme, bob.id, DEFAULT_TIMEOUT).unwrap();
|
||||||
|
|
||||||
// Fetch is successful despite not fetching Carol's refs, since she isn't a delegate.
|
// Fetch is successful despite not fetching Carol's refs, since she isn't a delegate.
|
||||||
|
|
@ -367,7 +367,7 @@ fn test_dont_fetch_owned_refs() {
|
||||||
alice.connect(&bob);
|
alice.connect(&bob);
|
||||||
converge([&alice, &bob]);
|
converge([&alice, &bob]);
|
||||||
|
|
||||||
assert!(bob.handle.track_repo(acme, Scope::Trusted).unwrap());
|
assert!(bob.handle.track_repo(acme, Scope::Followed).unwrap());
|
||||||
|
|
||||||
let result = bob.handle.fetch(acme, alice.id, DEFAULT_TIMEOUT).unwrap();
|
let result = bob.handle.fetch(acme, alice.id, DEFAULT_TIMEOUT).unwrap();
|
||||||
assert!(result.is_success());
|
assert!(result.is_success());
|
||||||
|
|
@ -380,7 +380,7 @@ fn test_dont_fetch_owned_refs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fetch_trusted_remotes() {
|
fn test_fetch_followed_remotes() {
|
||||||
logger::init(log::Level::Debug);
|
logger::init(log::Level::Debug);
|
||||||
|
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
|
@ -402,18 +402,18 @@ fn test_fetch_trusted_remotes() {
|
||||||
alice.connect(&bob);
|
alice.connect(&bob);
|
||||||
converge([&alice, &bob]);
|
converge([&alice, &bob]);
|
||||||
|
|
||||||
let trusted = signers
|
let followed = signers
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| *s.public_key())
|
.map(|s| *s.public_key())
|
||||||
.take(2)
|
.take(2)
|
||||||
.collect::<HashSet<_>>();
|
.collect::<HashSet<_>>();
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
trusted.len() < signers.len(),
|
followed.len() < signers.len(),
|
||||||
"Bob is only trusting a subset of peers"
|
"Bob is only trusting a subset of peers"
|
||||||
);
|
);
|
||||||
assert!(bob.handle.track_repo(acme, Scope::Trusted).unwrap());
|
assert!(bob.handle.track_repo(acme, Scope::Followed).unwrap());
|
||||||
for nid in &trusted {
|
for nid in &followed {
|
||||||
assert!(bob.handle.track_node(*nid, None).unwrap());
|
assert!(bob.handle.track_node(*nid, None).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -429,8 +429,8 @@ fn test_fetch_trusted_remotes() {
|
||||||
.collect::<Result<HashSet<_>, _>>()
|
.collect::<Result<HashSet<_>, _>>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert!(bob_remotes.len() == trusted.len() + 1);
|
assert!(bob_remotes.len() == followed.len() + 1);
|
||||||
assert!(bob_remotes.is_superset(&trusted));
|
assert!(bob_remotes.is_superset(&followed));
|
||||||
assert!(bob_remotes.contains(&alice.id));
|
assert!(bob_remotes.contains(&alice.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -450,7 +450,7 @@ fn test_missing_remote() {
|
||||||
alice.connect(&bob);
|
alice.connect(&bob);
|
||||||
converge([&alice, &bob]);
|
converge([&alice, &bob]);
|
||||||
|
|
||||||
assert!(bob.handle.track_repo(acme, Scope::Trusted).unwrap());
|
assert!(bob.handle.track_repo(acme, Scope::Followed).unwrap());
|
||||||
assert!(bob.handle.track_node(*carol.public_key(), None).unwrap());
|
assert!(bob.handle.track_node(*carol.public_key(), None).unwrap());
|
||||||
let result = bob.handle.fetch(acme, alice.id, DEFAULT_TIMEOUT).unwrap();
|
let result = bob.handle.fetch(acme, alice.id, DEFAULT_TIMEOUT).unwrap();
|
||||||
assert!(result.is_success());
|
assert!(result.is_success());
|
||||||
|
|
@ -477,7 +477,7 @@ fn test_fetch_preserve_owned_refs() {
|
||||||
alice.connect(&bob);
|
alice.connect(&bob);
|
||||||
converge([&alice, &bob]);
|
converge([&alice, &bob]);
|
||||||
|
|
||||||
assert!(bob.handle.track_repo(acme, Scope::Trusted).unwrap());
|
assert!(bob.handle.track_repo(acme, Scope::Followed).unwrap());
|
||||||
assert!(bob.handle.track_node(alice.id, None).unwrap());
|
assert!(bob.handle.track_node(alice.id, None).unwrap());
|
||||||
|
|
||||||
let result = bob.handle.fetch(acme, alice.id, DEFAULT_TIMEOUT).unwrap();
|
let result = bob.handle.fetch(acme, alice.id, DEFAULT_TIMEOUT).unwrap();
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,12 @@ pub struct Node {
|
||||||
pub policy: Policy,
|
pub policy: Policy,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tracking policy.
|
/// Resource policy.
|
||||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub enum Policy {
|
pub enum Policy {
|
||||||
/// The resource is tracked.
|
/// The resource is allowed.
|
||||||
Track,
|
Allow,
|
||||||
/// The resource is blocked.
|
/// The resource is blocked.
|
||||||
#[default]
|
#[default]
|
||||||
Block,
|
Block,
|
||||||
|
|
@ -39,7 +39,7 @@ pub enum Policy {
|
||||||
impl fmt::Display for Policy {
|
impl fmt::Display for Policy {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Track => write!(f, "track"),
|
Self::Allow => write!(f, "allow"),
|
||||||
Self::Block => write!(f, "block"),
|
Self::Block => write!(f, "block"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -50,7 +50,7 @@ impl FromStr for Policy {
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
match s {
|
match s {
|
||||||
"track" => Ok(Self::Track),
|
"allow" => Ok(Self::Allow),
|
||||||
"block" => Ok(Self::Block),
|
"block" => Ok(Self::Block),
|
||||||
_ => Err(s.to_owned()),
|
_ => Err(s.to_owned()),
|
||||||
}
|
}
|
||||||
|
|
@ -64,7 +64,7 @@ impl sqlite::BindableWithIndex for Policy {
|
||||||
i: I,
|
i: I,
|
||||||
) -> sqlite::Result<()> {
|
) -> sqlite::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
Self::Track => "track",
|
Self::Allow => "allow",
|
||||||
Self::Block => "block",
|
Self::Block => "block",
|
||||||
}
|
}
|
||||||
.bind(stmt, i)
|
.bind(stmt, i)
|
||||||
|
|
@ -78,7 +78,7 @@ impl TryFrom<&sqlite::Value> for Policy {
|
||||||
let message = Some("sql: invalid policy".to_owned());
|
let message = Some("sql: invalid policy".to_owned());
|
||||||
|
|
||||||
match value {
|
match value {
|
||||||
sqlite::Value::String(s) if s == "track" => Ok(Policy::Track),
|
sqlite::Value::String(s) if s == "allow" => Ok(Policy::Allow),
|
||||||
sqlite::Value::String(s) if s == "block" => Ok(Policy::Block),
|
sqlite::Value::String(s) if s == "block" => Ok(Policy::Block),
|
||||||
_ => Err(sqlite::Error {
|
_ => Err(sqlite::Error {
|
||||||
code: None,
|
code: None,
|
||||||
|
|
@ -88,21 +88,21 @@ impl TryFrom<&sqlite::Value> for Policy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tracking scope of a repository tracking policy.
|
/// Follow scope of a seeded repository.
|
||||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub enum Scope {
|
pub enum Scope {
|
||||||
/// Track remotes of nodes that are already tracked.
|
/// Seed remotes that are explicitly followed.
|
||||||
#[default]
|
#[default]
|
||||||
Trusted,
|
Followed,
|
||||||
/// Track all remotes.
|
/// Seed all remotes.
|
||||||
All,
|
All,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Scope {
|
impl fmt::Display for Scope {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Scope::Trusted => f.write_str("trusted"),
|
Scope::Followed => f.write_str("followed"),
|
||||||
Scope::All => f.write_str("all"),
|
Scope::All => f.write_str("all"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -117,7 +117,7 @@ impl FromStr for Scope {
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
match s {
|
match s {
|
||||||
"trusted" => Ok(Self::Trusted),
|
"followed" => Ok(Self::Followed),
|
||||||
"all" => Ok(Self::All),
|
"all" => Ok(Self::All),
|
||||||
_ => Err(ParseScopeError(s.to_string())),
|
_ => Err(ParseScopeError(s.to_string())),
|
||||||
}
|
}
|
||||||
|
|
@ -131,7 +131,7 @@ impl sqlite::BindableWithIndex for Scope {
|
||||||
i: I,
|
i: I,
|
||||||
) -> sqlite::Result<()> {
|
) -> sqlite::Result<()> {
|
||||||
let s = match self {
|
let s = match self {
|
||||||
Self::Trusted => "trusted",
|
Self::Followed => "followed",
|
||||||
Self::All => "all",
|
Self::All => "all",
|
||||||
};
|
};
|
||||||
s.bind(stmt, i)
|
s.bind(stmt, i)
|
||||||
|
|
|
||||||
|
|
@ -16,21 +16,21 @@ pub use crate::node::tracking::{Alias, Node, Policy, Repo, Scope};
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum NamespacesError {
|
pub enum NamespacesError {
|
||||||
#[error("Failed to find tracking policy for {rid}")]
|
#[error("failed to find tracking policy for {rid}")]
|
||||||
FailedPolicy {
|
FailedPolicy {
|
||||||
rid: Id,
|
rid: Id,
|
||||||
#[source]
|
#[source]
|
||||||
err: Error,
|
err: Error,
|
||||||
},
|
},
|
||||||
#[error("Cannot fetch {rid} as it is not tracked")]
|
#[error("cannot fetch {rid} as it is not tracked")]
|
||||||
BlockedPolicy { rid: Id },
|
BlockedPolicy { rid: Id },
|
||||||
#[error("Failed to get tracking nodes for {rid}")]
|
#[error("failed to get tracking nodes for {rid}")]
|
||||||
FailedNodes {
|
FailedNodes {
|
||||||
rid: Id,
|
rid: Id,
|
||||||
#[source]
|
#[source]
|
||||||
err: Error,
|
err: Error,
|
||||||
},
|
},
|
||||||
#[error("Failed to get delegates for {rid}")]
|
#[error("failed to get delegates for {rid}")]
|
||||||
FailedDelegates {
|
FailedDelegates {
|
||||||
rid: Id,
|
rid: Id,
|
||||||
#[source]
|
#[source]
|
||||||
|
|
@ -38,8 +38,8 @@ pub enum NamespacesError {
|
||||||
},
|
},
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Git(#[from] crate::git::raw::Error),
|
Git(#[from] crate::git::raw::Error),
|
||||||
#[error("Could not find any trusted nodes for {rid}")]
|
#[error("could not find any followed nodes for {rid}")]
|
||||||
NoTrusted { rid: Id },
|
NoFollowed { rid: Id },
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tracking configuration.
|
/// Tracking configuration.
|
||||||
|
|
@ -77,13 +77,13 @@ impl<T> Config<T> {
|
||||||
/// Check if a repository is tracked.
|
/// Check if a repository is tracked.
|
||||||
pub fn is_repo_tracked(&self, id: &Id) -> Result<bool, Error> {
|
pub fn is_repo_tracked(&self, id: &Id) -> Result<bool, Error> {
|
||||||
self.repo_policy(id)
|
self.repo_policy(id)
|
||||||
.map(|entry| entry.policy == Policy::Track)
|
.map(|entry| entry.policy == Policy::Allow)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a node is tracked.
|
/// Check if a node is tracked.
|
||||||
pub fn is_node_tracked(&self, id: &NodeId) -> Result<bool, Error> {
|
pub fn is_node_tracked(&self, id: &NodeId) -> Result<bool, Error> {
|
||||||
self.node_policy(id)
|
self.node_policy(id)
|
||||||
.map(|entry| entry.policy == Policy::Track)
|
.map(|entry| entry.policy == Policy::Allow)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a node's tracking information.
|
/// Get a node's tracking information.
|
||||||
|
|
@ -120,14 +120,14 @@ impl<T> Config<T> {
|
||||||
error!(target: "service", "Attempted to fetch untracked repo {rid}");
|
error!(target: "service", "Attempted to fetch untracked repo {rid}");
|
||||||
Err(NamespacesError::BlockedPolicy { rid: *rid })
|
Err(NamespacesError::BlockedPolicy { rid: *rid })
|
||||||
}
|
}
|
||||||
Policy::Track => match entry.scope {
|
Policy::Allow => match entry.scope {
|
||||||
Scope::All => Ok(Namespaces::All),
|
Scope::All => Ok(Namespaces::All),
|
||||||
Scope::Trusted => {
|
Scope::Followed => {
|
||||||
let nodes = self
|
let nodes = self
|
||||||
.node_policies()
|
.node_policies()
|
||||||
.map_err(|err| FailedNodes { rid: *rid, err })?;
|
.map_err(|err| FailedNodes { rid: *rid, err })?;
|
||||||
let mut trusted: HashSet<_> = nodes
|
let mut followed: HashSet<_> = nodes
|
||||||
.filter_map(|node| (node.policy == Policy::Track).then_some(node.id))
|
.filter_map(|node| (node.policy == Policy::Allow).then_some(node.id))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if let Ok(repo) = storage.repository(*rid) {
|
if let Ok(repo) = storage.repository(*rid) {
|
||||||
|
|
@ -135,15 +135,15 @@ impl<T> Config<T> {
|
||||||
.delegates()
|
.delegates()
|
||||||
.map_err(|err| FailedDelegates { rid: *rid, err })?
|
.map_err(|err| FailedDelegates { rid: *rid, err })?
|
||||||
.map(PublicKey::from);
|
.map(PublicKey::from);
|
||||||
trusted.extend(delegates);
|
followed.extend(delegates);
|
||||||
};
|
};
|
||||||
if trusted.is_empty() {
|
if followed.is_empty() {
|
||||||
// Nb. returning All here because the
|
// Nb. returning All here because the
|
||||||
// fetching logic will correctly determine
|
// fetching logic will correctly determine
|
||||||
// trusted and delegate remotes.
|
// followed and delegate remotes.
|
||||||
Ok(Namespaces::All)
|
Ok(Namespaces::All)
|
||||||
} else {
|
} else {
|
||||||
Ok(Namespaces::Trusted(trusted))
|
Ok(Namespaces::Followed(followed))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2,30 +2,30 @@
|
||||||
-- Service configuration schema.
|
-- Service configuration schema.
|
||||||
--
|
--
|
||||||
|
|
||||||
-- Node tracking policy.
|
-- Node follow policies.
|
||||||
create table if not exists "node-policies" (
|
create table if not exists "following" (
|
||||||
-- Node ID.
|
-- Node ID.
|
||||||
"id" text primary key not null,
|
"id" text primary key not null,
|
||||||
-- Node alias. May override the alias announced by the node.
|
-- Node alias. May override the alias announced by the node.
|
||||||
"alias" text default '',
|
"alias" text default '',
|
||||||
-- Tracking policy for this node.
|
-- Tracking policy for this node.
|
||||||
"policy" text default 'track'
|
"policy" text default 'allow'
|
||||||
--
|
--
|
||||||
) strict;
|
) strict;
|
||||||
|
|
||||||
-- Repository tracking policy.
|
-- Repository seeding policies.
|
||||||
create table if not exists "repo-policies" (
|
create table if not exists "seeding" (
|
||||||
-- Repository ID.
|
-- Repository ID.
|
||||||
"id" text primary key not null,
|
"id" text primary key not null,
|
||||||
-- Tracking scope for this repository.
|
-- Tracking scope for this repository.
|
||||||
--
|
--
|
||||||
-- Valid values are:
|
-- Valid values are:
|
||||||
--
|
--
|
||||||
-- "trusted" track repository delegates and remotes in the `node-policies` table.
|
-- "followed" seed repository delegates and remotes in the `following` table.
|
||||||
-- "all" track all remotes.
|
-- "all" seed all remotes.
|
||||||
--
|
--
|
||||||
"scope" text default 'trusted',
|
"scope" text default 'followed',
|
||||||
-- Tracking policy for this repository.
|
-- Tracking policy for this repository.
|
||||||
"policy" text default 'track'
|
"policy" text default 'allow'
|
||||||
--
|
--
|
||||||
) strict;
|
) strict;
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ impl Config<Write> {
|
||||||
/// Track a node.
|
/// Track a node.
|
||||||
pub fn track_node(&mut self, id: &NodeId, alias: Option<&str>) -> Result<bool, Error> {
|
pub fn track_node(&mut self, id: &NodeId, alias: Option<&str>) -> Result<bool, Error> {
|
||||||
let mut stmt = self.db.prepare(
|
let mut stmt = self.db.prepare(
|
||||||
"INSERT INTO `node-policies` (id, alias)
|
"INSERT INTO `following` (id, alias)
|
||||||
VALUES (?1, ?2)
|
VALUES (?1, ?2)
|
||||||
ON CONFLICT DO UPDATE
|
ON CONFLICT DO UPDATE
|
||||||
SET alias = ?2 WHERE alias != ?2",
|
SET alias = ?2 WHERE alias != ?2",
|
||||||
|
|
@ -134,7 +134,7 @@ impl Config<Write> {
|
||||||
/// Track a repository.
|
/// Track a repository.
|
||||||
pub fn track_repo(&mut self, id: &Id, scope: Scope) -> Result<bool, Error> {
|
pub fn track_repo(&mut self, id: &Id, scope: Scope) -> Result<bool, Error> {
|
||||||
let mut stmt = self.db.prepare(
|
let mut stmt = self.db.prepare(
|
||||||
"INSERT INTO `repo-policies` (id, scope)
|
"INSERT INTO `seeding` (id, scope)
|
||||||
VALUES (?1, ?2)
|
VALUES (?1, ?2)
|
||||||
ON CONFLICT DO UPDATE
|
ON CONFLICT DO UPDATE
|
||||||
SET scope = ?2 WHERE scope != ?2",
|
SET scope = ?2 WHERE scope != ?2",
|
||||||
|
|
@ -150,7 +150,7 @@ impl Config<Write> {
|
||||||
/// Set a node's tracking policy.
|
/// Set a node's tracking policy.
|
||||||
pub fn set_node_policy(&mut self, id: &NodeId, policy: Policy) -> Result<bool, Error> {
|
pub fn set_node_policy(&mut self, id: &NodeId, policy: Policy) -> Result<bool, Error> {
|
||||||
let mut stmt = self.db.prepare(
|
let mut stmt = self.db.prepare(
|
||||||
"INSERT INTO `node-policies` (id, policy)
|
"INSERT INTO `following` (id, policy)
|
||||||
VALUES (?1, ?2)
|
VALUES (?1, ?2)
|
||||||
ON CONFLICT DO UPDATE
|
ON CONFLICT DO UPDATE
|
||||||
SET policy = ?2 WHERE policy != ?2",
|
SET policy = ?2 WHERE policy != ?2",
|
||||||
|
|
@ -166,7 +166,7 @@ impl Config<Write> {
|
||||||
/// Set a repository's tracking policy.
|
/// Set a repository's tracking policy.
|
||||||
pub fn set_repo_policy(&mut self, id: &Id, policy: Policy) -> Result<bool, Error> {
|
pub fn set_repo_policy(&mut self, id: &Id, policy: Policy) -> Result<bool, Error> {
|
||||||
let mut stmt = self.db.prepare(
|
let mut stmt = self.db.prepare(
|
||||||
"INSERT INTO `repo-policies` (id, policy)
|
"INSERT INTO `seeding` (id, policy)
|
||||||
VALUES (?1, ?2)
|
VALUES (?1, ?2)
|
||||||
ON CONFLICT DO UPDATE
|
ON CONFLICT DO UPDATE
|
||||||
SET policy = ?2 WHERE policy != ?2",
|
SET policy = ?2 WHERE policy != ?2",
|
||||||
|
|
@ -181,9 +181,7 @@ impl Config<Write> {
|
||||||
|
|
||||||
/// Untrack a node.
|
/// Untrack a node.
|
||||||
pub fn untrack_node(&mut self, id: &NodeId) -> Result<bool, Error> {
|
pub fn untrack_node(&mut self, id: &NodeId) -> Result<bool, Error> {
|
||||||
let mut stmt = self
|
let mut stmt = self.db.prepare("DELETE FROM `following` WHERE id = ?")?;
|
||||||
.db
|
|
||||||
.prepare("DELETE FROM `node-policies` WHERE id = ?")?;
|
|
||||||
|
|
||||||
stmt.bind((1, id))?;
|
stmt.bind((1, id))?;
|
||||||
stmt.next()?;
|
stmt.next()?;
|
||||||
|
|
@ -193,9 +191,7 @@ impl Config<Write> {
|
||||||
|
|
||||||
/// Untrack a repository.
|
/// Untrack a repository.
|
||||||
pub fn untrack_repo(&mut self, id: &Id) -> Result<bool, Error> {
|
pub fn untrack_repo(&mut self, id: &Id) -> Result<bool, Error> {
|
||||||
let mut stmt = self
|
let mut stmt = self.db.prepare("DELETE FROM `seeding` WHERE id = ?")?;
|
||||||
.db
|
|
||||||
.prepare("DELETE FROM `repo-policies` WHERE id = ?")?;
|
|
||||||
|
|
||||||
stmt.bind((1, id))?;
|
stmt.bind((1, id))?;
|
||||||
stmt.next()?;
|
stmt.next()?;
|
||||||
|
|
@ -212,7 +208,7 @@ impl<T> Config<T> {
|
||||||
Ok(matches!(
|
Ok(matches!(
|
||||||
self.node_policy(id)?,
|
self.node_policy(id)?,
|
||||||
Some(Node {
|
Some(Node {
|
||||||
policy: Policy::Track,
|
policy: Policy::Allow,
|
||||||
..
|
..
|
||||||
})
|
})
|
||||||
))
|
))
|
||||||
|
|
@ -223,7 +219,7 @@ impl<T> Config<T> {
|
||||||
Ok(matches!(
|
Ok(matches!(
|
||||||
self.repo_policy(id)?,
|
self.repo_policy(id)?,
|
||||||
Some(Repo {
|
Some(Repo {
|
||||||
policy: Policy::Track,
|
policy: Policy::Allow,
|
||||||
..
|
..
|
||||||
})
|
})
|
||||||
))
|
))
|
||||||
|
|
@ -233,7 +229,7 @@ impl<T> Config<T> {
|
||||||
pub fn node_policy(&self, id: &NodeId) -> Result<Option<Node>, Error> {
|
pub fn node_policy(&self, id: &NodeId) -> Result<Option<Node>, Error> {
|
||||||
let mut stmt = self
|
let mut stmt = self
|
||||||
.db
|
.db
|
||||||
.prepare("SELECT alias, policy FROM `node-policies` WHERE id = ?")?;
|
.prepare("SELECT alias, policy FROM `following` WHERE id = ?")?;
|
||||||
|
|
||||||
stmt.bind((1, id))?;
|
stmt.bind((1, id))?;
|
||||||
|
|
||||||
|
|
@ -259,7 +255,7 @@ impl<T> Config<T> {
|
||||||
pub fn repo_policy(&self, id: &Id) -> Result<Option<Repo>, Error> {
|
pub fn repo_policy(&self, id: &Id) -> Result<Option<Repo>, Error> {
|
||||||
let mut stmt = self
|
let mut stmt = self
|
||||||
.db
|
.db
|
||||||
.prepare("SELECT scope, policy FROM `repo-policies` WHERE id = ?")?;
|
.prepare("SELECT scope, policy FROM `seeding` WHERE id = ?")?;
|
||||||
|
|
||||||
stmt.bind((1, id))?;
|
stmt.bind((1, id))?;
|
||||||
|
|
||||||
|
|
@ -277,7 +273,7 @@ impl<T> Config<T> {
|
||||||
pub fn node_policies(&self) -> Result<Box<dyn Iterator<Item = Node>>, Error> {
|
pub fn node_policies(&self) -> Result<Box<dyn Iterator<Item = Node>>, Error> {
|
||||||
let mut stmt = self
|
let mut stmt = self
|
||||||
.db
|
.db
|
||||||
.prepare("SELECT id, alias, policy FROM `node-policies`")?
|
.prepare("SELECT id, alias, policy FROM `following`")?
|
||||||
.into_iter();
|
.into_iter();
|
||||||
let mut entries = Vec::new();
|
let mut entries = Vec::new();
|
||||||
|
|
||||||
|
|
@ -301,7 +297,7 @@ impl<T> Config<T> {
|
||||||
pub fn repo_policies(&self) -> Result<Box<dyn Iterator<Item = Repo>>, Error> {
|
pub fn repo_policies(&self) -> Result<Box<dyn Iterator<Item = Repo>>, Error> {
|
||||||
let mut stmt = self
|
let mut stmt = self
|
||||||
.db
|
.db
|
||||||
.prepare("SELECT id, scope, policy FROM `repo-policies`")?
|
.prepare("SELECT id, scope, policy FROM `seeding`")?
|
||||||
.into_iter();
|
.into_iter();
|
||||||
let mut entries = Vec::new();
|
let mut entries = Vec::new();
|
||||||
|
|
||||||
|
|
@ -412,8 +408,8 @@ mod test {
|
||||||
|
|
||||||
assert!(db.track_repo(&id, Scope::All).unwrap());
|
assert!(db.track_repo(&id, Scope::All).unwrap());
|
||||||
assert_eq!(db.repo_policy(&id).unwrap().unwrap().scope, Scope::All);
|
assert_eq!(db.repo_policy(&id).unwrap().unwrap().scope, Scope::All);
|
||||||
assert!(db.track_repo(&id, Scope::Trusted).unwrap());
|
assert!(db.track_repo(&id, Scope::Followed).unwrap());
|
||||||
assert_eq!(db.repo_policy(&id).unwrap().unwrap().scope, Scope::Trusted);
|
assert_eq!(db.repo_policy(&id).unwrap().unwrap().scope, Scope::Followed);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -422,7 +418,7 @@ mod test {
|
||||||
let mut db = Config::open(":memory:").unwrap();
|
let mut db = Config::open(":memory:").unwrap();
|
||||||
|
|
||||||
assert!(db.track_repo(&id, Scope::All).unwrap());
|
assert!(db.track_repo(&id, Scope::All).unwrap());
|
||||||
assert_eq!(db.repo_policy(&id).unwrap().unwrap().policy, Policy::Track);
|
assert_eq!(db.repo_policy(&id).unwrap().unwrap().policy, Policy::Allow);
|
||||||
assert!(db.set_repo_policy(&id, Policy::Block).unwrap());
|
assert!(db.set_repo_policy(&id, Policy::Block).unwrap());
|
||||||
assert_eq!(db.repo_policy(&id).unwrap().unwrap().policy, Policy::Block);
|
assert_eq!(db.repo_policy(&id).unwrap().unwrap().policy, Policy::Block);
|
||||||
}
|
}
|
||||||
|
|
@ -433,7 +429,7 @@ mod test {
|
||||||
let mut db = Config::open(":memory:").unwrap();
|
let mut db = Config::open(":memory:").unwrap();
|
||||||
|
|
||||||
assert!(db.track_node(&id, None).unwrap());
|
assert!(db.track_node(&id, None).unwrap());
|
||||||
assert_eq!(db.node_policy(&id).unwrap().unwrap().policy, Policy::Track);
|
assert_eq!(db.node_policy(&id).unwrap().unwrap().policy, Policy::Allow);
|
||||||
assert!(db.set_node_policy(&id, Policy::Block).unwrap());
|
assert!(db.set_node_policy(&id, Policy::Block).unwrap());
|
||||||
assert_eq!(db.node_policy(&id).unwrap().unwrap().policy, Policy::Block);
|
assert_eq!(db.node_policy(&id).unwrap().unwrap().policy, Policy::Block);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,8 @@ pub enum Namespaces {
|
||||||
/// All namespaces.
|
/// All namespaces.
|
||||||
#[default]
|
#[default]
|
||||||
All,
|
All,
|
||||||
/// The trusted set of namespaces.
|
/// The followed set of namespaces.
|
||||||
Trusted(HashSet<PublicKey>),
|
Followed(HashSet<PublicKey>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Namespaces {
|
impl Namespaces {
|
||||||
|
|
@ -48,7 +48,7 @@ impl Namespaces {
|
||||||
dst: (*NAMESPACES_GLOB).clone(),
|
dst: (*NAMESPACES_GLOB).clone(),
|
||||||
force: true,
|
force: true,
|
||||||
}],
|
}],
|
||||||
Namespaces::Trusted(pks) => pks
|
Namespaces::Followed(pks) => pks
|
||||||
.iter()
|
.iter()
|
||||||
.map(|pk| {
|
.map(|pk| {
|
||||||
let ns = pk.to_namespace().with_pattern(git::refspec::STAR);
|
let ns = pk.to_namespace().with_pattern(git::refspec::STAR);
|
||||||
|
|
@ -65,7 +65,7 @@ impl Namespaces {
|
||||||
|
|
||||||
impl FromIterator<PublicKey> for Namespaces {
|
impl FromIterator<PublicKey> for Namespaces {
|
||||||
fn from_iter<T: IntoIterator<Item = PublicKey>>(iter: T) -> Self {
|
fn from_iter<T: IntoIterator<Item = PublicKey>>(iter: T) -> Self {
|
||||||
Self::Trusted(iter.into_iter().collect())
|
Self::Followed(iter.into_iter().collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ pub fn fetch<W: WriteRepository>(
|
||||||
) -> Result<Vec<RefUpdate>, crate::storage::FetchError> {
|
) -> Result<Vec<RefUpdate>, crate::storage::FetchError> {
|
||||||
let namespace = match namespaces.into() {
|
let namespace = match namespaces.into() {
|
||||||
Namespaces::All => None,
|
Namespaces::All => None,
|
||||||
Namespaces::Trusted(trusted) => trusted.into_iter().next(),
|
Namespaces::Followed(followed) => followed.into_iter().next(),
|
||||||
};
|
};
|
||||||
let mut updates = Vec::new();
|
let mut updates = Vec::new();
|
||||||
let mut callbacks = git2::RemoteCallbacks::new();
|
let mut callbacks = git2::RemoteCallbacks::new();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue