Compare commits

..

No commits in common. "d091265d2769cdcc3c3ec615a29285c47ca28b50" and "ac1c06dd319edd94bb7bcbafd1da309fa587be0f" have entirely different histories.

30 changed files with 305 additions and 414 deletions

View file

@ -15,7 +15,6 @@ once_cell = "1.4"
slog = { version = "2", features = ["max_level_trace", "release_max_level_trace"] } slog = { version = "2", features = ["max_level_trace", "release_max_level_trace"] }
slog-term = "2.5" slog-term = "2.5"
slog-async = "2.7" slog-async = "2.7"
nonzero_ext = "0.3.0"
[dev-dependencies] [dev-dependencies]
tempfile = "3" tempfile = "3"

View file

@ -1,24 +1,13 @@
use std::path::{self, PathBuf}; use std::path::{Path as ActualPath, PathBuf};
use std::rc::Rc;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Path(Rc<path::Path>); pub struct Path(PathBuf);
impl Path { // FIXME: This is a specialization since with Path: Into<PathBuf>
pub(crate) fn clone_rc(&self) -> Rc<path::Path> {
Rc::clone(&self.0)
}
pub fn join(&self, path: impl AsRef<path::Path>) -> Self {
Self::from(self.0.join(path))
}
}
// FIXME: This is a specialization since with Path: AsRef<path::Path>
// it would overwrite impl<T> From <T> for T // it would overwrite impl<T> From <T> for T
//impl<T: AsRef<path::Path>> From<T> for Path { //impl<T: Into<PathBuf>> From<T> for Path {
// fn from(v: T) -> Self { // fn from(v: T) -> Self {
// Self(v.as_ref().into()) // Path(v.into())
// } // }
//} //}
@ -26,8 +15,7 @@ macro_rules! path_from {
( $t:ty ) => { ( $t:ty ) => {
impl From<$t> for Path { impl From<$t> for Path {
fn from(v: $t) -> Self { fn from(v: $t) -> Self {
let path: &path::Path = v.as_ref(); Self(v.into())
Self(path.into())
} }
} }
}; };
@ -37,35 +25,23 @@ path_from!(String);
path_from!(&str); path_from!(&str);
path_from!(PathBuf); path_from!(PathBuf);
impl From<Rc<path::Path>> for Path { impl From<Path> for PathBuf {
fn from(v: Rc<path::Path>) -> Self {
Self(v)
}
}
impl AsRef<path::Path> for Path {
fn as_ref(&self) -> &path::Path {
&self.0
}
}
impl From<Path> for Rc<path::Path> {
fn from(v: Path) -> Self { fn from(v: Path) -> Self {
v.0 v.0
} }
} }
impl From<&Path> for Rc<path::Path> { impl AsRef<ActualPath> for Path {
fn from(v: &Path) -> Self { fn as_ref(&self) -> &ActualPath {
v.0.clone() &self.0
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct UserName(pub Rc<str>); pub struct UserName(pub String);
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct ServiceName(pub Rc<str>); pub struct ServiceName(pub String);
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct DatabaseName(pub Rc<str>); pub struct DatabaseName(pub String);

View file

@ -2,7 +2,7 @@ use std::env;
use std::process::exit; use std::process::exit;
pub fn schematics_main(run: &dyn Fn(bool) -> Result<(), ()>) { pub fn schematics_main(run: &dyn Fn(bool) -> Result<(), ()>) {
let args: Box<[String]> = env::args().collect(); let args: Vec<String> = env::args().collect();
let dry_run = match args.len() { let dry_run = match args.len() {
1 => false, 1 => false,
2 => { 2 => {

View file

@ -15,8 +15,7 @@ pub fn create_static_output(
.to_str() .to_str()
.ok_or("Filename is not valid unicode")? .ok_or("Filename is not valid unicode")?
.to_uppercase(); .to_uppercase();
let file = read_file(source_path)?; let content = String::from_utf8(read_file(source_path)?)?;
let content = std::str::from_utf8(&file)?;
let fence = content.chars().filter(|&c| c == '#').collect::<String>() + "#"; let fence = content.chars().filter(|&c| c == '#').collect::<String>() + "#";
writeln!( writeln!(

View file

@ -41,8 +41,7 @@ use crate::templates::systemd::{
}; };
use crate::to_artifact::ToArtifact; use crate::to_artifact::ToArtifact;
use std::fmt::Display; use std::fmt::Display;
use std::path::Path; use std::path::{Path, PathBuf};
use std::rc::Rc;
pub trait ImplementationBuilder<R> { pub trait ImplementationBuilder<R> {
type Prerequisites: ToArtifact; type Prerequisites: ToArtifact;
@ -65,13 +64,13 @@ impl<D> ImplementationBuilder<Key<D>> for DefaultBuilder {
type Prerequisites = (); type Prerequisites = ();
fn prerequisites(_resource: &Key<D>) -> Self::Prerequisites {} fn prerequisites(_resource: &Key<D>) -> Self::Prerequisites {}
type Implementation = KeySymbol<StdCommandRunner, Rc<Path>>; type Implementation = KeySymbol<StdCommandRunner, PathBuf>;
fn create( fn create(
_resource: &Key<D>, _resource: &Key<D>,
target: &<Key<D> as Resource>::Artifact, target: &<Key<D> as Resource>::Artifact,
(): <Self::Prerequisites as ToArtifact>::Artifact, (): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation { ) -> Self::Implementation {
KeySymbol::new(StdCommandRunner, target.clone_rc()) KeySymbol::new(StdCommandRunner, target.clone().into())
} }
} }
@ -81,7 +80,7 @@ impl<D: Clone> ImplementationBuilder<Csr<D>> for DefaultBuilder {
Key(resource.0.clone()) Key(resource.0.clone())
} }
type Implementation = CsrSymbol<StdCommandRunner, D, Rc<Path>, Rc<Path>>; type Implementation = CsrSymbol<StdCommandRunner, D, PathBuf, PathBuf>;
fn create( fn create(
resource: &Csr<D>, resource: &Csr<D>,
target: &<Csr<D> as Resource>::Artifact, target: &<Csr<D> as Resource>::Artifact,
@ -90,8 +89,8 @@ impl<D: Clone> ImplementationBuilder<Csr<D>> for DefaultBuilder {
CsrSymbol::new( CsrSymbol::new(
StdCommandRunner, StdCommandRunner,
resource.0.clone(), resource.0.clone(),
key.clone_rc(), key.into(),
target.clone_rc(), target.clone().into(),
) )
} }
} }
@ -117,7 +116,7 @@ impl<D: Clone> ImplementationBuilder<Cert<D>> for DefaultBuilder {
} }
type Implementation = type Implementation =
CertSymbol<SetuidCommandRunner<Rc<str>>, SetuidCommandRunner<Rc<str>>, D, Rc<Path>>; CertSymbol<SetuidCommandRunner<String>, SetuidCommandRunner<String>, D, PathBuf>;
fn create( fn create(
resource: &Cert<D>, resource: &Cert<D>,
target: &<Cert<D> as Resource>::Artifact, target: &<Cert<D> as Resource>::Artifact,
@ -126,11 +125,11 @@ impl<D: Clone> ImplementationBuilder<Cert<D>> for DefaultBuilder {
CertSymbol::new( CertSymbol::new(
resource.0.clone(), resource.0.clone(),
SetuidCommandRunner::new(user_name.0), SetuidCommandRunner::new(user_name.0),
root_cert.clone_rc(), root_cert.into(),
account_key.clone_rc(), account_key.into(),
challenges_dir.clone_rc(), challenges_dir.into(),
csr.clone_rc(), csr.into(),
target.clone_rc(), target.clone().into(),
) )
} }
} }
@ -141,13 +140,13 @@ impl<D: Clone> ImplementationBuilder<CertChain<D>> for DefaultBuilder {
(Cert(resource.0.clone()), AcmeRootCert) (Cert(resource.0.clone()), AcmeRootCert)
} }
type Implementation = ConcatSymbol<[Rc<Path>; 2], Rc<Path>, Rc<Path>>; type Implementation = ConcatSymbol<[PathBuf; 2], PathBuf, PathBuf>;
fn create( fn create(
_resource: &CertChain<D>, _resource: &CertChain<D>,
target: &<CertChain<D> as Resource>::Artifact, target: &<CertChain<D> as Resource>::Artifact,
(cert, root_cert): <Self::Prerequisites as ToArtifact>::Artifact, (cert, root_cert): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation { ) -> Self::Implementation {
ConcatSymbol::new([cert.clone_rc(), root_cert.clone_rc()], target.clone_rc()) ConcatSymbol::new([cert.into(), root_cert.into()], target.clone().into())
} }
} }
@ -157,13 +156,13 @@ impl<D: Clone> ImplementationBuilder<KeyAndCertBundle<D>> for DefaultBuilder {
(CertChain(resource.0.clone()), Key(resource.0.clone())) (CertChain(resource.0.clone()), Key(resource.0.clone()))
} }
type Implementation = ConcatSymbol<[Rc<Path>; 2], Rc<Path>, Rc<Path>>; type Implementation = ConcatSymbol<[PathBuf; 2], PathBuf, PathBuf>;
fn create( fn create(
_resource: &KeyAndCertBundle<D>, _resource: &KeyAndCertBundle<D>,
target: &<KeyAndCertBundle<D> as Resource>::Artifact, target: &<KeyAndCertBundle<D> as Resource>::Artifact,
(cert_chain, key): <Self::Prerequisites as ToArtifact>::Artifact, (cert_chain, key): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation { ) -> Self::Implementation {
ConcatSymbol::new([key.clone_rc(), cert_chain.clone_rc()], target.clone_rc()) ConcatSymbol::new([key.into(), cert_chain.into()], target.clone().into())
} }
} }
@ -171,7 +170,7 @@ impl<P: AsRef<Path> + Clone> ImplementationBuilder<File<P>> for DefaultBuilder {
type Prerequisites = (); type Prerequisites = ();
fn prerequisites(_resource: &File<P>) -> Self::Prerequisites {} fn prerequisites(_resource: &File<P>) -> Self::Prerequisites {}
type Implementation = FileSymbol<P, Rc<str>>; type Implementation = FileSymbol<P, String>;
fn create( fn create(
resource: &File<P>, resource: &File<P>,
_target: &<File<P> as Resource>::Artifact, _target: &<File<P> as Resource>::Artifact,
@ -202,7 +201,7 @@ impl ImplementationBuilder<DefaultServer> for DefaultBuilder {
} }
type Implementation = ( type Implementation = (
FileSymbol<Rc<Path>, Box<str>>, FileSymbol<PathBuf, String>,
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>, ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
); );
fn create( fn create(
@ -212,8 +211,8 @@ impl ImplementationBuilder<DefaultServer> for DefaultBuilder {
) -> Self::Implementation { ) -> Self::Implementation {
( (
FileSymbol::new( FileSymbol::new(
target.clone_rc(), target.clone().into(),
nginx::default_server(challenges_snippet_path).into(), nginx::default_server(challenges_snippet_path),
), ),
ReloadServiceSymbol::new(StdCommandRunner, "nginx"), ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
) )
@ -231,7 +230,7 @@ impl<D: AsRef<str> + Clone + Display> ImplementationBuilder<ServeCustom<D>> for
} }
type Implementation = ( type Implementation = (
FileSymbol<Rc<Path>, Box<str>>, FileSymbol<PathBuf, String>,
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>, ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
); );
fn create( fn create(
@ -241,8 +240,8 @@ impl<D: AsRef<str> + Clone + Display> ImplementationBuilder<ServeCustom<D>> for
) -> Self::Implementation { ) -> Self::Implementation {
( (
FileSymbol::new( FileSymbol::new(
target.clone_rc(), target.clone().into(),
nginx::server_config(&resource.0, cert, key, &resource.1, challenges_snippet_path).into(), nginx::server_config(&resource.0, cert, key, &resource.1, challenges_snippet_path),
), ),
ReloadServiceSymbol::new(StdCommandRunner, "nginx"), ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
) )
@ -268,7 +267,7 @@ impl<D: Clone + Display, P: AsRef<Path>, C: Clone + Into<PhpFpmPoolConfig>>
} }
type Implementation = ( type Implementation = (
FileSymbol<Rc<Path>, Box<str>>, FileSymbol<PathBuf, String>,
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>, ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
); );
fn create( fn create(
@ -278,15 +277,14 @@ impl<D: Clone + Display, P: AsRef<Path>, C: Clone + Into<PhpFpmPoolConfig>>
) -> Self::Implementation { ) -> Self::Implementation {
( (
FileSymbol::new( FileSymbol::new(
target.clone_rc(), target.clone().into(),
nginx::server_config( nginx::server_config(
&resource.0, &resource.0,
cert, cert,
key, key,
nginx::php_snippet(resource.2, pool.0, &resource.1) + &resource.3, nginx::php_snippet(resource.2, pool.0, &resource.1) + &resource.3,
challenges_snippet_path, challenges_snippet_path,
) ),
.into(),
), ),
ReloadServiceSymbol::new(StdCommandRunner, "nginx"), ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
) )
@ -318,7 +316,7 @@ impl<D: Clone + Display, P: Clone + AsRef<Path>> ImplementationBuilder<ServeServ
} }
type Implementation = ( type Implementation = (
FileSymbol<Rc<Path>, Box<str>>, FileSymbol<PathBuf, String>,
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>, ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
); );
fn create( fn create(
@ -328,15 +326,14 @@ impl<D: Clone + Display, P: Clone + AsRef<Path>> ImplementationBuilder<ServeServ
) -> Self::Implementation { ) -> Self::Implementation {
( (
FileSymbol::new( FileSymbol::new(
target.clone_rc(), target.clone().into(),
nginx::server_config( nginx::server_config(
&resource.0, &resource.0,
cert, cert,
key, key,
nginx::proxy_snippet(&socket.0, &resource.3), nginx::proxy_snippet(&socket.0, &resource.3),
challenges_snippet_path, challenges_snippet_path,
) ),
.into(),
), ),
ReloadServiceSymbol::new(StdCommandRunner, "nginx"), ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
) )
@ -354,7 +351,7 @@ impl<D: AsRef<str> + Clone + Display> ImplementationBuilder<ServeRedir<D>> for D
} }
type Implementation = ( type Implementation = (
FileSymbol<Rc<Path>, Box<str>>, FileSymbol<PathBuf, String>,
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>, ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
); );
fn create( fn create(
@ -364,15 +361,14 @@ impl<D: AsRef<str> + Clone + Display> ImplementationBuilder<ServeRedir<D>> for D
) -> Self::Implementation { ) -> Self::Implementation {
( (
FileSymbol::new( FileSymbol::new(
target.clone_rc(), target.clone().into(),
nginx::server_config( nginx::server_config(
&resource.0, &resource.0,
cert, cert,
key, key,
nginx::redir_snippet(resource.1.as_ref()), nginx::redir_snippet(resource.1.as_ref()),
challenges_snippet_path, challenges_snippet_path,
) ),
.into(),
), ),
ReloadServiceSymbol::new(StdCommandRunner, "nginx"), ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
) )
@ -392,7 +388,7 @@ impl<D: AsRef<str> + Clone + Display, P: AsRef<Path>> ImplementationBuilder<Serv
} }
type Implementation = ( type Implementation = (
FileSymbol<Rc<Path>, Box<str>>, FileSymbol<PathBuf, String>,
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>, ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
); );
fn create( fn create(
@ -402,15 +398,14 @@ impl<D: AsRef<str> + Clone + Display, P: AsRef<Path>> ImplementationBuilder<Serv
) -> Self::Implementation { ) -> Self::Implementation {
( (
FileSymbol::new( FileSymbol::new(
target.clone_rc(), target.clone().into(),
nginx::server_config( nginx::server_config(
&resource.0, &resource.0,
cert, cert,
key, key,
nginx::static_snippet(resource.1.as_ref()), nginx::static_snippet(resource.1.as_ref()),
challenges_snippet_path, challenges_snippet_path,
) ),
.into(),
), ),
ReloadServiceSymbol::new(StdCommandRunner, "nginx"), ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
) )
@ -422,8 +417,8 @@ impl<D: Clone> ImplementationBuilder<PhpFpmPool<D>> for DefaultBuilder {
fn prerequisites(_resource: &PhpFpmPool<D>) -> Self::Prerequisites {} fn prerequisites(_resource: &PhpFpmPool<D>) -> Self::Prerequisites {}
type Implementation = ( type Implementation = (
FileSymbol<Rc<Path>, Box<str>>, FileSymbol<PathBuf, String>,
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, Rc<str>>, ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, String>,
); );
fn create( fn create(
resource: &PhpFpmPool<D>, resource: &PhpFpmPool<D>,
@ -432,8 +427,8 @@ impl<D: Clone> ImplementationBuilder<PhpFpmPool<D>> for DefaultBuilder {
) -> Self::Implementation { ) -> Self::Implementation {
( (
FileSymbol::new( FileSymbol::new(
conf_path.clone_rc(), conf_path.clone().into(),
php_fpm_pool_config(&user_name.0, socket_path, &resource.1).into(), php_fpm_pool_config(&user_name.0, socket_path, &resource.1),
), ),
ReloadServiceSymbol::new(StdCommandRunner, service_name.0.clone()), ReloadServiceSymbol::new(StdCommandRunner, service_name.0.clone()),
) )
@ -446,10 +441,10 @@ impl<D, P: AsRef<Path>> ImplementationBuilder<SystemdSocketService<D, P>> for De
type Implementation = ( type Implementation = (
// First three could be parallel // First three could be parallel
FileSymbol<Rc<Path>, Box<str>>, FileSymbol<PathBuf, String>,
SystemdUserSessionSymbol<'static, Rc<str>, StdCommandRunner>, SystemdUserSessionSymbol<'static, String, StdCommandRunner>,
OwnerSymbol<StdCommandRunner, StdCommandRunner, Box<Path>, Rc<str>>, OwnerSymbol<StdCommandRunner, StdCommandRunner, PathBuf, String>,
UserServiceSymbol<'static, Rc<Path>, Rc<str>>, UserServiceSymbol<'static, PathBuf, String>,
); );
fn create( fn create(
resource: &SystemdSocketService<D, P>, resource: &SystemdSocketService<D, P>,
@ -458,7 +453,7 @@ impl<D, P: AsRef<Path>> ImplementationBuilder<SystemdSocketService<D, P>> for De
) -> Self::Implementation { ) -> Self::Implementation {
( (
FileSymbol::new( FileSymbol::new(
conf_path.clone_rc(), conf_path.clone().into(),
if resource.4 { if resource.4 {
systemd_nodejs_service(&resource.2, socket_path, &resource.3) systemd_nodejs_service(&resource.2, socket_path, &resource.3)
} else { } else {
@ -468,16 +463,15 @@ impl<D, P: AsRef<Path>> ImplementationBuilder<SystemdSocketService<D, P>> for De
&resource.3, &resource.3,
"", "",
) )
} },
.into(),
), ),
SystemdUserSessionSymbol::new(user_name.0.clone(), &StdCommandRunner), SystemdUserSessionSymbol::new(user_name.0.clone(), &StdCommandRunner),
OwnerSymbol::new( OwnerSymbol::new(
conf_path.as_ref().parent().unwrap().into(), conf_path.as_ref().parent().unwrap().to_path_buf(),
user_name.0.clone(), user_name.0.clone(),
StdCommandRunner, StdCommandRunner,
), ),
UserServiceSymbol::new(socket_path.clone_rc(), user_name.0.clone(), resource.1), UserServiceSymbol::new(socket_path.clone().into(), user_name.0.clone(), resource.1),
) )
} }
} }
@ -522,7 +516,7 @@ impl<P: Clone + AsRef<Path>> ImplementationBuilder<StoredDirectory<P>> for Defau
) -> Self::Implementation { ) -> Self::Implementation {
SavedDirectorySymbol::new( SavedDirectorySymbol::new(
resource.1.clone(), resource.1.clone(),
SimpleStorage::new(target.clone_rc()), SimpleStorage::new(target.clone().into()),
StorageDirection::Store, StorageDirection::Store,
StdCommandRunner, StdCommandRunner,
) )
@ -541,7 +535,7 @@ impl<P: Clone + AsRef<Path>> ImplementationBuilder<LoadedDirectory<P>> for Defau
) -> Self::Implementation { ) -> Self::Implementation {
SavedDirectorySymbol::new( SavedDirectorySymbol::new(
resource.1.clone(), resource.1.clone(),
SimpleStorage::new(target.clone_rc()), SimpleStorage::new(target.clone().into()),
StorageDirection::Load, StorageDirection::Load,
StdCommandRunner, StdCommandRunner,
) )
@ -552,7 +546,7 @@ impl<D: Clone> ImplementationBuilder<UserForDomain<D>> for DefaultBuilder {
type Prerequisites = (); type Prerequisites = ();
fn prerequisites(_resource: &UserForDomain<D>) -> Self::Prerequisites {} fn prerequisites(_resource: &UserForDomain<D>) -> Self::Prerequisites {}
type Implementation = UserSymbol<Rc<str>, StdCommandRunner>; type Implementation = UserSymbol<String, StdCommandRunner>;
fn create( fn create(
_resource: &UserForDomain<D>, _resource: &UserForDomain<D>,
(user_name, _home_path): &<UserForDomain<D> as Resource>::Artifact, (user_name, _home_path): &<UserForDomain<D> as Resource>::Artifact,
@ -566,7 +560,7 @@ impl ImplementationBuilder<User> for DefaultBuilder {
type Prerequisites = (); type Prerequisites = ();
fn prerequisites(_resource: &User) -> Self::Prerequisites {} fn prerequisites(_resource: &User) -> Self::Prerequisites {}
type Implementation = UserSymbol<Rc<str>, StdCommandRunner>; type Implementation = UserSymbol<String, StdCommandRunner>;
fn create( fn create(
resource: &User, resource: &User,
(): &<User as Resource>::Artifact, (): &<User as Resource>::Artifact,
@ -580,7 +574,7 @@ impl<P: AsRef<Path> + Clone> ImplementationBuilder<Owner<P>> for DefaultBuilder
type Prerequisites = (); type Prerequisites = ();
fn prerequisites(_resource: &Owner<P>) -> Self::Prerequisites {} fn prerequisites(_resource: &Owner<P>) -> Self::Prerequisites {}
type Implementation = OwnerSymbol<StdCommandRunner, StdCommandRunner, P, Rc<str>>; type Implementation = OwnerSymbol<StdCommandRunner, StdCommandRunner, P, String>;
fn create( fn create(
resource: &Owner<P>, resource: &Owner<P>,
(): &<Owner<P> as Resource>::Artifact, (): &<Owner<P> as Resource>::Artifact,
@ -594,7 +588,7 @@ impl ImplementationBuilder<AcmeUser> for DefaultBuilder {
type Prerequisites = (); type Prerequisites = ();
fn prerequisites(_resource: &AcmeUser) -> Self::Prerequisites {} fn prerequisites(_resource: &AcmeUser) -> Self::Prerequisites {}
type Implementation = UserSymbol<Rc<str>, StdCommandRunner>; type Implementation = UserSymbol<String, StdCommandRunner>;
fn create( fn create(
_resource: &AcmeUser, _resource: &AcmeUser,
user_name: &<AcmeUser as Resource>::Artifact, user_name: &<AcmeUser as Resource>::Artifact,
@ -611,8 +605,8 @@ impl ImplementationBuilder<AcmeChallengesDir> for DefaultBuilder {
} }
type Implementation = ( type Implementation = (
DirSymbol<Rc<Path>>, DirSymbol<PathBuf>,
OwnerSymbol<StdCommandRunner, StdCommandRunner, Rc<Path>, Rc<str>>, OwnerSymbol<StdCommandRunner, StdCommandRunner, PathBuf, String>,
); );
fn create( fn create(
_resource: &AcmeChallengesDir, _resource: &AcmeChallengesDir,
@ -620,8 +614,8 @@ impl ImplementationBuilder<AcmeChallengesDir> for DefaultBuilder {
user_name: <Self::Prerequisites as ToArtifact>::Artifact, user_name: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation { ) -> Self::Implementation {
( (
DirSymbol::new(target.clone_rc()), DirSymbol::new(target.clone().into()),
OwnerSymbol::new(target.clone_rc(), user_name.0, StdCommandRunner), OwnerSymbol::new(target.clone().into(), user_name.0, StdCommandRunner),
) )
} }
} }
@ -632,15 +626,15 @@ impl ImplementationBuilder<AcmeChallengesNginxSnippet> for DefaultBuilder {
AcmeChallengesDir AcmeChallengesDir
} }
type Implementation = FileSymbol<Rc<Path>, Box<str>>; type Implementation = FileSymbol<PathBuf, String>;
fn create( fn create(
_resource: &AcmeChallengesNginxSnippet, _resource: &AcmeChallengesNginxSnippet,
target: &<AcmeChallengesNginxSnippet as Resource>::Artifact, target: &<AcmeChallengesNginxSnippet as Resource>::Artifact,
challenges_dir: <Self::Prerequisites as ToArtifact>::Artifact, challenges_dir: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation { ) -> Self::Implementation {
FileSymbol::new( FileSymbol::new(
target.clone_rc(), target.clone().into(),
nginx::acme_challenges_snippet(challenges_dir).into(), nginx::acme_challenges_snippet(challenges_dir),
) )
} }
} }
@ -652,8 +646,8 @@ impl ImplementationBuilder<AcmeAccountKey> for DefaultBuilder {
} }
type Implementation = ( type Implementation = (
KeySymbol<StdCommandRunner, Rc<Path>>, KeySymbol<StdCommandRunner, PathBuf>,
OwnerSymbol<StdCommandRunner, StdCommandRunner, Rc<Path>, Rc<str>>, OwnerSymbol<StdCommandRunner, StdCommandRunner, PathBuf, String>,
); );
fn create( fn create(
_resource: &AcmeAccountKey, _resource: &AcmeAccountKey,
@ -661,8 +655,8 @@ impl ImplementationBuilder<AcmeAccountKey> for DefaultBuilder {
user_name: <Self::Prerequisites as ToArtifact>::Artifact, user_name: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation { ) -> Self::Implementation {
( (
KeySymbol::new(StdCommandRunner, target.clone_rc()), KeySymbol::new(StdCommandRunner, target.clone().into()),
OwnerSymbol::new(target.clone_rc(), user_name.0, StdCommandRunner), OwnerSymbol::new(target.clone().into(), user_name.0, StdCommandRunner),
) )
} }
} }
@ -671,13 +665,13 @@ impl ImplementationBuilder<AcmeRootCert> for DefaultBuilder {
type Prerequisites = (); type Prerequisites = ();
fn prerequisites(_resource: &AcmeRootCert) -> Self::Prerequisites {} fn prerequisites(_resource: &AcmeRootCert) -> Self::Prerequisites {}
type Implementation = FileSymbol<Rc<Path>, &'static str>; type Implementation = FileSymbol<PathBuf, &'static str>;
fn create( fn create(
_resource: &AcmeRootCert, _resource: &AcmeRootCert,
target: &<AcmeRootCert as Resource>::Artifact, target: &<AcmeRootCert as Resource>::Artifact,
(): <Self::Prerequisites as ToArtifact>::Artifact, (): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation { ) -> Self::Implementation {
FileSymbol::new(target.clone_rc(), LETS_ENCRYPT_R3) FileSymbol::new(target.clone().into(), LETS_ENCRYPT_R3)
} }
} }
@ -685,7 +679,7 @@ impl<D> ImplementationBuilder<MariaDbUser<D>> for DefaultBuilder {
type Prerequisites = (); type Prerequisites = ();
fn prerequisites(_resource: &MariaDbUser<D>) -> Self::Prerequisites {} fn prerequisites(_resource: &MariaDbUser<D>) -> Self::Prerequisites {}
type Implementation = MariaDbUserSymbol<'static, Rc<str>, StdCommandRunner>; type Implementation = MariaDbUserSymbol<'static, String, StdCommandRunner>;
fn create( fn create(
_resource: &MariaDbUser<D>, _resource: &MariaDbUser<D>,
user_name: &<MariaDbUser<D> as Resource>::Artifact, user_name: &<MariaDbUser<D> as Resource>::Artifact,
@ -702,15 +696,15 @@ impl<D: Clone> ImplementationBuilder<MariaDbDatabase<D>> for DefaultBuilder {
} }
type Implementation = ( type Implementation = (
MariaDbDatabaseSymbol<'static, Rc<str>, SimpleStorage, StdCommandRunner>, MariaDbDatabaseSymbol<'static, String, SimpleStorage, StdCommandRunner>,
MariaDbDumpSymbol<'static, Rc<str>, StdCommandRunner, SimpleStorage>, MariaDbDumpSymbol<'static, String, StdCommandRunner, SimpleStorage>,
); );
fn create( fn create(
_resource: &MariaDbDatabase<D>, _resource: &MariaDbDatabase<D>,
(db_name, _, data_path): &<MariaDbDatabase<D> as Resource>::Artifact, (db_name, _, data_path): &<MariaDbDatabase<D> as Resource>::Artifact,
_: <Self::Prerequisites as ToArtifact>::Artifact, _: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation { ) -> Self::Implementation {
let db_dump = SimpleStorage::new(data_path.clone_rc()); let db_dump = SimpleStorage::new(data_path.clone().into());
( (
MariaDbDatabaseSymbol::new(db_name.0.clone(), db_dump.clone(), &StdCommandRunner), MariaDbDatabaseSymbol::new(db_name.0.clone(), db_dump.clone(), &StdCommandRunner),
MariaDbDumpSymbol::new(db_name.0.clone(), db_dump, &StdCommandRunner), MariaDbDumpSymbol::new(db_name.0.clone(), db_dump, &StdCommandRunner),
@ -722,13 +716,13 @@ impl<D: Clone> ImplementationBuilder<PostgresqlDatabase<D>> for DefaultBuilder {
type Prerequisites = (); type Prerequisites = ();
fn prerequisites(_: &PostgresqlDatabase<D>) -> Self::Prerequisites {} fn prerequisites(_: &PostgresqlDatabase<D>) -> Self::Prerequisites {}
type Implementation = (PostgreSQLDatabaseSymbol<'static, Rc<str>, Rc<str>, StdCommandRunner>,); type Implementation = (PostgreSQLDatabaseSymbol<'static, String, String, StdCommandRunner>,);
fn create( fn create(
_resource: &PostgresqlDatabase<D>, _resource: &PostgresqlDatabase<D>,
(db_name, data_path): &<PostgresqlDatabase<D> as Resource>::Artifact, (db_name, data_path): &<PostgresqlDatabase<D> as Resource>::Artifact,
_: <Self::Prerequisites as ToArtifact>::Artifact, _: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation { ) -> Self::Implementation {
let db_dump = SimpleStorage::new(data_path.clone_rc()); let db_dump = SimpleStorage::new(data_path.clone().into());
(PostgreSQLDatabaseSymbol::new( (PostgreSQLDatabaseSymbol::new(
db_name.0.clone(), db_name.0.clone(),
db_dump.read_filename().unwrap().to_str().unwrap().into(), db_dump.read_filename().unwrap().to_str().unwrap().into(),
@ -738,9 +732,9 @@ impl<D: Clone> ImplementationBuilder<PostgresqlDatabase<D>> for DefaultBuilder {
} }
impl<P: Clone + AsRef<Path>> ImplementationBuilder<WordpressPlugin<P>> for DefaultBuilder { impl<P: Clone + AsRef<Path>> ImplementationBuilder<WordpressPlugin<P>> for DefaultBuilder {
type Prerequisites = Dir<Rc<Path>>; type Prerequisites = Dir<PathBuf>;
fn prerequisites(resource: &WordpressPlugin<P>) -> Self::Prerequisites { fn prerequisites(resource: &WordpressPlugin<P>) -> Self::Prerequisites {
Dir::new(resource.0.as_ref().join("wp-content/plugins")) Dir(resource.0.as_ref().join("wp-content/plugins"))
} }
type Implementation = WordpressPluginSymbol<'static, P, &'static str, StdCommandRunner>; type Implementation = WordpressPluginSymbol<'static, P, &'static str, StdCommandRunner>;
@ -753,21 +747,21 @@ impl<P: Clone + AsRef<Path>> ImplementationBuilder<WordpressPlugin<P>> for Defau
} }
} }
impl<P: AsRef<Path>> ImplementationBuilder<WordpressTranslation<P>> for DefaultBuilder { impl<P: Clone + AsRef<Path>> ImplementationBuilder<WordpressTranslation<P>> for DefaultBuilder {
type Prerequisites = Dir<Rc<Path>>; type Prerequisites = Dir<PathBuf>;
fn prerequisites(resource: &WordpressTranslation<P>) -> Self::Prerequisites { fn prerequisites(resource: &WordpressTranslation<P>) -> Self::Prerequisites {
Dir::new(resource.0.as_ref().join("wp-content/languages")) Dir(resource.0.as_ref().join("wp-content/languages"))
} }
type Implementation = type Implementation =
WordpressTranslationSymbol<'static, &'static str, Box<Path>, StdCommandRunner>; WordpressTranslationSymbol<'static, &'static str, PathBuf, StdCommandRunner>;
fn create( fn create(
resource: &WordpressTranslation<P>, resource: &WordpressTranslation<P>,
(): &<WordpressTranslation<P> as Resource>::Artifact, (): &<WordpressTranslation<P> as Resource>::Artifact,
_: <Self::Prerequisites as ToArtifact>::Artifact, _: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation { ) -> Self::Implementation {
WordpressTranslationSymbol::new( WordpressTranslationSymbol::new(
(*resource.0.as_ref().join("wp-content/languages")).into(), resource.0.as_ref().join("wp-content/languages"),
resource.1, resource.1,
resource.2, resource.2,
&StdCommandRunner, &StdCommandRunner,
@ -781,7 +775,7 @@ impl<D: Clone> ImplementationBuilder<Cron<D>> for DefaultBuilder {
UserForDomain(resource.0.clone()) UserForDomain(resource.0.clone())
} }
type Implementation = CronSymbol<'static, Box<str>, Rc<str>, StdCommandRunner>; type Implementation = CronSymbol<'static, String, String, StdCommandRunner>;
fn create( fn create(
resource: &Cron<D>, resource: &Cron<D>,
(): &<Cron<D> as Resource>::Artifact, (): &<Cron<D> as Resource>::Artifact,

View file

@ -19,7 +19,7 @@ fn check_success(output: Output) -> Result<Output, Box<dyn Error>> {
if output.status.success() { if output.status.success() {
Ok(output) Ok(output)
} else { } else {
Err(std::str::from_utf8(&output.stderr)?.into()) Err(String::from_utf8(output.stderr)?.into())
} }
} }
@ -93,7 +93,7 @@ struct TempSetEnv<'a> {
} }
impl<'a> TempSetEnv<'a> { impl<'a> TempSetEnv<'a> {
fn new(name: &'a str, new_value: impl AsRef<OsStr>) -> TempSetEnv<'a> { fn new(name: &'a str, new_value: String) -> TempSetEnv<'a> {
let old_value = env::var(name); let old_value = env::var(name);
env::set_var(name, new_value); env::set_var(name, new_value);
TempSetEnv { TempSetEnv {

View file

@ -12,8 +12,7 @@ use crate::resources::{
use crate::to_artifact::ToArtifact; use crate::to_artifact::ToArtifact;
use std::fmt::Display; use std::fmt::Display;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::path::Path; use std::path::{Path, PathBuf};
use std::rc::Rc;
pub trait Policy { pub trait Policy {
#[must_use] #[must_use]
@ -22,13 +21,13 @@ pub trait Policy {
} }
#[must_use] #[must_use]
fn user_home(user_name: &str) -> Rc<Path> { fn user_home(user_name: &str) -> PathBuf {
Path::new("/home").join(user_name).into() Path::new("/home").join(user_name)
} }
#[must_use] #[must_use]
fn user_name_for_domain(domain_name: &'_ str) -> Rc<str> { fn user_name_for_domain(domain_name: &'_ str) -> String {
domain_name.split('.').rev().fold(String::new(), |result, part| if result.is_empty() { result } else { result + "_" } + part).into() domain_name.split('.').rev().fold(String::new(), |result, part| if result.is_empty() { result } else { result + "_" } + part)
} }
#[must_use] #[must_use]
@ -37,8 +36,8 @@ pub trait Policy {
} }
#[must_use] #[must_use]
fn path_for_data(name: impl Display) -> Rc<Path> { fn path_for_data(name: impl Display) -> PathBuf {
Path::new("/root/data").join(format!("_{name}")).into() Path::new("/root/data").join(format!("_{name}"))
} }
} }
@ -60,37 +59,37 @@ pub struct DefaultLocator<P = DefaultPolicy> {
} }
impl<P, D: AsRef<str>> ResourceLocator<Key<D>> for DefaultLocator<P> { impl<P, D: AsRef<str>> ResourceLocator<Key<D>> for DefaultLocator<P> {
type Prerequisites = Dir<Rc<Path>>; type Prerequisites = Dir<PathBuf>;
fn locate(resource: &Key<D>) -> (<Key<D> as Resource>::Artifact, Self::Prerequisites) { fn locate(resource: &Key<D>) -> (<Key<D> as Resource>::Artifact, Self::Prerequisites) {
( (
PathArtifact::from(format!("/etc/ssl/private/{}.key", resource.0.as_ref())), PathArtifact::from(format!("/etc/ssl/private/{}.key", resource.0.as_ref())),
Dir::new("/etc/ssl/private"), Dir("/etc/ssl/private".into()),
) )
} }
} }
impl<P, D: AsRef<str>> ResourceLocator<Csr<D>> for DefaultLocator<P> { impl<P, D: AsRef<str>> ResourceLocator<Csr<D>> for DefaultLocator<P> {
type Prerequisites = Dir<Rc<Path>>; type Prerequisites = Dir<PathBuf>;
fn locate(resource: &Csr<D>) -> (<Csr<D> as Resource>::Artifact, Self::Prerequisites) { fn locate(resource: &Csr<D>) -> (<Csr<D> as Resource>::Artifact, Self::Prerequisites) {
( (
PathArtifact::from(format!("/etc/ssl/local_certs/{}.csr", resource.0.as_ref())), PathArtifact::from(format!("/etc/ssl/local_certs/{}.csr", resource.0.as_ref())),
Dir::new("/etc/ssl/local_certs"), Dir("/etc/ssl/local_certs".into()),
) )
} }
} }
impl<P, D: AsRef<str>> ResourceLocator<Cert<D>> for DefaultLocator<P> { impl<P, D: AsRef<str>> ResourceLocator<Cert<D>> for DefaultLocator<P> {
type Prerequisites = Dir<Rc<Path>>; type Prerequisites = Dir<PathBuf>;
fn locate(resource: &Cert<D>) -> (<Cert<D> as Resource>::Artifact, Self::Prerequisites) { fn locate(resource: &Cert<D>) -> (<Cert<D> as Resource>::Artifact, Self::Prerequisites) {
( (
PathArtifact::from(format!("/etc/ssl/local_certs/{}.crt", resource.0.as_ref())), PathArtifact::from(format!("/etc/ssl/local_certs/{}.crt", resource.0.as_ref())),
Dir::new("/etc/ssl/local_certs"), Dir("/etc/ssl/local_certs".into()),
) )
} }
} }
impl<P, D: AsRef<str>> ResourceLocator<CertChain<D>> for DefaultLocator<P> { impl<P, D: AsRef<str>> ResourceLocator<CertChain<D>> for DefaultLocator<P> {
type Prerequisites = Dir<Rc<Path>>; type Prerequisites = Dir<PathBuf>;
fn locate( fn locate(
resource: &CertChain<D>, resource: &CertChain<D>,
) -> (<CertChain<D> as Resource>::Artifact, Self::Prerequisites) { ) -> (<CertChain<D> as Resource>::Artifact, Self::Prerequisites) {
@ -99,13 +98,13 @@ impl<P, D: AsRef<str>> ResourceLocator<CertChain<D>> for DefaultLocator<P> {
"/etc/ssl/local_certs/{}.chained.crt", "/etc/ssl/local_certs/{}.chained.crt",
resource.0.as_ref() resource.0.as_ref()
)), )),
Dir::new("/etc/ssl/local_certs"), Dir("/etc/ssl/local_certs".into()),
) )
} }
} }
impl<P, D: AsRef<str>> ResourceLocator<KeyAndCertBundle<D>> for DefaultLocator<P> { impl<P, D: AsRef<str>> ResourceLocator<KeyAndCertBundle<D>> for DefaultLocator<P> {
type Prerequisites = Dir<Rc<Path>>; type Prerequisites = Dir<PathBuf>;
fn locate( fn locate(
resource: &KeyAndCertBundle<D>, resource: &KeyAndCertBundle<D>,
) -> ( ) -> (
@ -117,34 +116,34 @@ impl<P, D: AsRef<str>> ResourceLocator<KeyAndCertBundle<D>> for DefaultLocator<P
"/etc/ssl/private/{}.with_key.crt", "/etc/ssl/private/{}.with_key.crt",
resource.0.as_ref() resource.0.as_ref()
)), )),
Dir::new("/etc/ssl/private"), Dir("/etc/ssl/private".into()),
) )
} }
} }
impl<POLICY, P: AsRef<Path>> ResourceLocator<File<P>> for DefaultLocator<POLICY> { impl<POLICY, P: AsRef<Path>> ResourceLocator<File<P>> for DefaultLocator<POLICY> {
type Prerequisites = Dir<Rc<Path>>; type Prerequisites = Dir<PathBuf>;
fn locate(resource: &File<P>) -> (<File<P> as Resource>::Artifact, Self::Prerequisites) { fn locate(resource: &File<P>) -> (<File<P> as Resource>::Artifact, Self::Prerequisites) {
((), Dir::new(resource.0.as_ref().parent().unwrap())) ((), Dir(resource.0.as_ref().parent().unwrap().into()))
} }
} }
impl<'a, POLICY, P: AsRef<Path>> ResourceLocator<GitCheckout<'a, P>> for DefaultLocator<POLICY> { impl<'a, POLICY, P: AsRef<Path>> ResourceLocator<GitCheckout<'a, P>> for DefaultLocator<POLICY> {
type Prerequisites = Dir<Rc<Path>>; type Prerequisites = Dir<PathBuf>;
fn locate( fn locate(
resource: &GitCheckout<'a, P>, resource: &GitCheckout<'a, P>,
) -> ( ) -> (
<GitCheckout<'a, P> as Resource>::Artifact, <GitCheckout<'a, P> as Resource>::Artifact,
Self::Prerequisites, Self::Prerequisites,
) { ) {
((), Dir::new(resource.0.as_ref().parent().unwrap())) ((), Dir(resource.0.as_ref().parent().unwrap().into()))
} }
} }
impl<POLICY, P: Clone + AsRef<Path>> ResourceLocator<Dir<P>> for DefaultLocator<POLICY> { impl<POLICY, P: Clone + AsRef<Path>> ResourceLocator<Dir<P>> for DefaultLocator<POLICY> {
type Prerequisites = Option<Dir<Rc<Path>>>; type Prerequisites = Option<Dir<PathBuf>>;
fn locate(resource: &Dir<P>) -> (<Dir<P> as Resource>::Artifact, Self::Prerequisites) { fn locate(resource: &Dir<P>) -> (<Dir<P> as Resource>::Artifact, Self::Prerequisites) {
((), resource.0.as_ref().parent().map(Dir::new)) ((), resource.0.as_ref().parent().map(|p| Dir(p.into())))
} }
} }
@ -174,7 +173,7 @@ impl<POLICY: Policy, P: AsRef<Path>> ResourceLocator<StoredDirectory<P>>
impl<POLICY: Policy, P: AsRef<Path>> ResourceLocator<LoadedDirectory<P>> impl<POLICY: Policy, P: AsRef<Path>> ResourceLocator<LoadedDirectory<P>>
for DefaultLocator<POLICY> for DefaultLocator<POLICY>
{ {
type Prerequisites = Dir<Rc<Path>>; type Prerequisites = Dir<PathBuf>;
fn locate( fn locate(
resource: &LoadedDirectory<P>, resource: &LoadedDirectory<P>,
) -> ( ) -> (
@ -183,13 +182,13 @@ impl<POLICY: Policy, P: AsRef<Path>> ResourceLocator<LoadedDirectory<P>>
) { ) {
( (
PathArtifact::from(POLICY::path_for_data(resource.0)), PathArtifact::from(POLICY::path_for_data(resource.0)),
Dir::new(resource.1.as_ref().parent().unwrap()), Dir(resource.1.as_ref().parent().unwrap().into()),
) )
} }
} }
impl<P: Policy> ResourceLocator<AcmeAccountKey> for DefaultLocator<P> { impl<P: Policy> ResourceLocator<AcmeAccountKey> for DefaultLocator<P> {
type Prerequisites = Dir<Rc<Path>>; type Prerequisites = Dir<PathBuf>;
fn locate( fn locate(
_resource: &AcmeAccountKey, _resource: &AcmeAccountKey,
) -> (<AcmeAccountKey as Resource>::Artifact, Self::Prerequisites) { ) -> (<AcmeAccountKey as Resource>::Artifact, Self::Prerequisites) {
@ -208,7 +207,7 @@ impl<P: Policy> ResourceLocator<AcmeUser> for DefaultLocator<P> {
} }
impl<P: Policy> ResourceLocator<AcmeChallengesDir> for DefaultLocator<P> { impl<P: Policy> ResourceLocator<AcmeChallengesDir> for DefaultLocator<P> {
type Prerequisites = Dir<Rc<Path>>; type Prerequisites = Dir<PathBuf>;
fn locate( fn locate(
_resource: &AcmeChallengesDir, _resource: &AcmeChallengesDir,
) -> ( ) -> (
@ -237,7 +236,7 @@ impl<P: Policy> ResourceLocator<AcmeChallengesNginxSnippet> for DefaultLocator<P
} }
impl<P: Policy> ResourceLocator<AcmeRootCert> for DefaultLocator<P> { impl<P: Policy> ResourceLocator<AcmeRootCert> for DefaultLocator<P> {
type Prerequisites = Dir<Rc<Path>>; type Prerequisites = Dir<PathBuf>;
fn locate( fn locate(
_resource: &AcmeRootCert, _resource: &AcmeRootCert,
) -> (<AcmeRootCert as Resource>::Artifact, Self::Prerequisites) { ) -> (<AcmeRootCert as Resource>::Artifact, Self::Prerequisites) {
@ -371,7 +370,7 @@ impl<D: Clone + AsRef<str>, P: Policy> ResourceLocator<PhpFpmPool<D>> for Defaul
php_version, user.0 php_version, user.0
)), )),
user, user,
ServiceNameArtifact(format!("php{php_version}-fpm").into()), ServiceNameArtifact(format!("php{php_version}-fpm")),
), ),
(), (),
) )
@ -381,7 +380,7 @@ impl<D: Clone + AsRef<str>, P: Policy> ResourceLocator<PhpFpmPool<D>> for Defaul
impl<D: Clone + AsRef<str>, P, POLICY: Policy> ResourceLocator<SystemdSocketService<D, P>> impl<D: Clone + AsRef<str>, P, POLICY: Policy> ResourceLocator<SystemdSocketService<D, P>>
for DefaultLocator<POLICY> for DefaultLocator<POLICY>
{ {
type Prerequisites = Dir<Rc<Path>>; type Prerequisites = Dir<PathBuf>;
fn locate( fn locate(
resource: &SystemdSocketService<D, P>, resource: &SystemdSocketService<D, P>,
) -> ( ) -> (
@ -397,7 +396,7 @@ impl<D: Clone + AsRef<str>, P, POLICY: Policy> ResourceLocator<SystemdSocketServ
PathArtifact::from(service_dir_path.join(format!("{}.service", resource.1))), PathArtifact::from(service_dir_path.join(format!("{}.service", resource.1))),
user_name, user_name,
), ),
Dir::new(service_dir_path), Dir(service_dir_path),
) )
} }
} }

View file

@ -4,7 +4,7 @@ use crate::artifacts::{
}; };
use crate::templates::php::FpmPoolConfig; use crate::templates::php::FpmPoolConfig;
use std::hash::Hash; use std::hash::Hash;
use std::path::Path; use std::path::PathBuf;
pub trait Resource { pub trait Resource {
type Artifact; type Artifact;
@ -41,41 +41,23 @@ impl<D> Resource for KeyAndCertBundle<D> {
} }
#[derive(Debug, Hash, PartialEq, Eq)] #[derive(Debug, Hash, PartialEq, Eq)]
pub struct File<P>(pub P, pub Rc<str>); pub struct File<P>(pub P, pub String);
impl<P> Resource for File<P> { impl<P> Resource for File<P> {
type Artifact = (); type Artifact = ();
} }
impl File<Rc<Path>> {
pub fn new(p: impl Into<Rc<Path>>, content: impl AsRef<str>) -> Self {
Self(p.into(), content.as_ref().into())
}
}
#[derive(Debug, Hash, PartialEq, Eq)] #[derive(Debug, Hash, PartialEq, Eq)]
pub struct GitCheckout<'a, P>(pub P, pub &'a str, pub &'a str); pub struct GitCheckout<'a, P>(pub P, pub &'a str, pub &'a str);
impl<'a, P> Resource for GitCheckout<'a, P> { impl<'a, P> Resource for GitCheckout<'a, P> {
type Artifact = (); type Artifact = ();
} }
impl<'a> GitCheckout<'a, Rc<Path>> {
pub fn new(target: impl Into<Rc<Path>>, src: &'a str, head: &'a str) -> Self {
Self(target.into(), src, head)
}
}
#[derive(Debug, Hash, PartialEq, Eq)] #[derive(Debug, Hash, PartialEq, Eq)]
pub struct Dir<P>(pub P); pub struct Dir<P>(pub P);
impl<P> Resource for Dir<P> { impl<P> Resource for Dir<P> {
type Artifact = (); type Artifact = ();
} }
impl Dir<Rc<Path>> {
pub fn new(p: impl AsRef<Path>) -> Self {
Self(p.as_ref().into())
}
}
#[derive(Debug, Hash, PartialEq, Eq)] #[derive(Debug, Hash, PartialEq, Eq)]
pub struct UserForDomain<D>(pub D); pub struct UserForDomain<D>(pub D);
impl<D> Resource for UserForDomain<D> { impl<D> Resource for UserForDomain<D> {
@ -124,11 +106,10 @@ impl<P> Resource for LoadedDirectory<P> {
type Artifact = PathArtifact; type Artifact = PathArtifact;
} }
pub fn get_saved_directory( pub fn get_saved_directory<P: Clone>(
storage_name: &'static str, storage_name: &'static str,
target: impl Into<Rc<Path>>, target: P,
) -> (StoredDirectory<Rc<Path>>, LoadedDirectory<Rc<Path>>) { ) -> (StoredDirectory<P>, LoadedDirectory<P>) {
let target = target.into();
( (
StoredDirectory(storage_name, target.clone()), StoredDirectory(storage_name, target.clone()),
LoadedDirectory(storage_name, target), LoadedDirectory(storage_name, target),
@ -136,7 +117,7 @@ pub fn get_saved_directory(
} }
#[derive(Debug, Hash, PartialEq, Eq)] #[derive(Debug, Hash, PartialEq, Eq)]
pub struct User(pub Rc<str>); pub struct User(pub String);
impl Resource for User { impl Resource for User {
type Artifact = (); type Artifact = ();
} }
@ -153,32 +134,20 @@ impl<P> Resource for NpmInstall<P> {
type Artifact = (); type Artifact = ();
} }
impl NpmInstall<Rc<Path>> {
pub fn new(path: impl Into<Rc<Path>>) -> Self {
Self(path.into())
}
}
#[derive(Debug, Hash, PartialEq, Eq)] #[derive(Debug, Hash, PartialEq, Eq)]
pub struct Owner<P>(pub Rc<str>, pub P); pub struct Owner<P>(pub String, pub P);
impl<P> Resource for Owner<P> { impl<P> Resource for Owner<P> {
type Artifact = (); type Artifact = ();
} }
impl Owner<Rc<Path>> {
pub fn new(user: &UserNameArtifact, p: impl Into<Rc<Path>>) -> Self {
Self(user.0.clone(), p.into())
}
}
#[derive(Debug, Hash, PartialEq, Eq)] #[derive(Debug, Hash, PartialEq, Eq)]
pub struct ServeCustom<D>(pub D, pub Rc<str>); pub struct ServeCustom<D>(pub D, pub String);
impl<D> Resource for ServeCustom<D> { impl<D> Resource for ServeCustom<D> {
type Artifact = PathArtifact; type Artifact = PathArtifact;
} }
#[derive(Debug, Hash, PartialEq, Eq)] #[derive(Debug, Hash, PartialEq, Eq)]
pub struct ServePhp<D, P, C>(pub D, pub P, pub &'static str, pub Rc<str>, pub C); pub struct ServePhp<D, P, C>(pub D, pub P, pub &'static str, pub String, pub C);
impl<D, P, C> Resource for ServePhp<D, P, C> { impl<D, P, C> Resource for ServePhp<D, P, C> {
type Artifact = PathArtifact; type Artifact = PathArtifact;
} }
@ -189,25 +158,6 @@ pub struct ServeService<D, P>(pub D, pub &'static str, pub P, pub P, pub P, pub
impl<D, P> Resource for ServeService<D, P> { impl<D, P> Resource for ServeService<D, P> {
type Artifact = PathArtifact; type Artifact = PathArtifact;
} }
impl<D> ServeService<D, Rc<Path>> {
pub fn new(
domain: D,
service_name: &'static str,
exec: impl Into<Rc<Path>>,
static_path: impl Into<Rc<Path>>,
working_directory: impl Into<Rc<Path>>,
is_nodejs: bool,
) -> Self {
Self(
domain,
service_name,
exec.into(),
static_path.into(),
working_directory.into(),
is_nodejs,
)
}
}
#[derive(Debug, Hash, PartialEq, Eq)] #[derive(Debug, Hash, PartialEq, Eq)]
pub struct ServeRedir<D>(pub D, pub D); pub struct ServeRedir<D>(pub D, pub D);
@ -221,12 +171,6 @@ impl<D, P> Resource for ServeStatic<D, P> {
type Artifact = PathArtifact; type Artifact = PathArtifact;
} }
impl<D> ServeStatic<D, Rc<Path>> {
pub fn new(domain: D, path: impl Into<Rc<Path>>) -> Self {
Self(domain, path.into())
}
}
#[derive(Debug, Hash, PartialEq, Eq)] #[derive(Debug, Hash, PartialEq, Eq)]
pub struct DefaultServer; pub struct DefaultServer;
impl Resource for DefaultServer { impl Resource for DefaultServer {
@ -269,26 +213,14 @@ impl<P> Resource for WordpressPlugin<P> {
type Artifact = (); type Artifact = ();
} }
impl WordpressPlugin<Rc<Path>> {
pub fn new(path: impl Into<Rc<Path>>, name: &'static str) -> Self {
Self(path.into(), name)
}
}
#[derive(Debug, Hash, PartialEq, Eq)] #[derive(Debug, Hash, PartialEq, Eq)]
pub struct WordpressTranslation<P>(pub P, pub &'static str, pub &'static str); pub struct WordpressTranslation<P>(pub P, pub &'static str, pub &'static str);
impl<P> Resource for WordpressTranslation<P> { impl<P> Resource for WordpressTranslation<P> {
type Artifact = (); type Artifact = ();
} }
impl WordpressTranslation<Rc<Path>> {
pub fn new(path: impl Into<Rc<Path>>, version: &'static str, lang: &'static str) -> Self {
Self(path.into(), version, lang)
}
}
#[derive(Debug, Hash, PartialEq, Eq)] #[derive(Debug, Hash, PartialEq, Eq)]
pub struct Cron<D>(pub D, pub Rc<str>); pub struct Cron<D>(pub D, pub String);
impl<D> Resource for Cron<D> { impl<D> Resource for Cron<D> {
type Artifact = (); type Artifact = ();
} }
@ -355,38 +287,38 @@ default_resources!(
Cron: Cron<D>, Cron: Cron<D>,
Csr: Csr<D>, Csr: Csr<D>,
DefaultServer: DefaultServer, DefaultServer: DefaultServer,
Dir: Dir<Rc<Path>>, Dir: Dir<PathBuf>,
File: File<Rc<Path>>, File: File<PathBuf>,
GitCheckout: GitCheckout<'a, Rc<Path>>, GitCheckout: GitCheckout<'a, PathBuf>,
Key: Key<D>, Key: Key<D>,
KeyAndCertBundle: KeyAndCertBundle<D>, KeyAndCertBundle: KeyAndCertBundle<D>,
LoadedDirectory: LoadedDirectory<Rc<Path>>, LoadedDirectory: LoadedDirectory<PathBuf>,
MariaDbDatabase: MariaDbDatabase<D>, MariaDbDatabase: MariaDbDatabase<D>,
MariaDbUser: MariaDbUser<D>, MariaDbUser: MariaDbUser<D>,
PostgresqlDatabase: PostgresqlDatabase<D>, PostgresqlDatabase: PostgresqlDatabase<D>,
SystemdSocketService: SystemdSocketService<D, Rc<Path>>, SystemdSocketService: SystemdSocketService<D, PathBuf>,
NpmInstall: NpmInstall<Rc<Path>>, NpmInstall: NpmInstall<PathBuf>,
Owner: Owner<Rc<Path>>, Owner: Owner<PathBuf>,
PhpFpmPool: PhpFpmPool<D>, PhpFpmPool: PhpFpmPool<D>,
ServeCustom: ServeCustom<D>, ServeCustom: ServeCustom<D>,
ServeService: ServeService<D, Rc<Path>>, ServeService: ServeService<D, PathBuf>,
ServePhp: ServePhp<D, Rc<Path>, FpmPoolConfig>, ServePhp: ServePhp<D, PathBuf, FpmPoolConfig>,
ServeRedir: ServeRedir<D>, ServeRedir: ServeRedir<D>,
ServeStatic: ServeStatic<D, Rc<Path>>, ServeStatic: ServeStatic<D, PathBuf>,
StoredDirectory: StoredDirectory<Rc<Path>>, StoredDirectory: StoredDirectory<PathBuf>,
User: User, User: User,
UserForDomain: UserForDomain<D>, UserForDomain: UserForDomain<D>,
WordpressPlugin: WordpressPlugin<Rc<Path>>, WordpressPlugin: WordpressPlugin<PathBuf>,
WordpressTranslation: WordpressTranslation<Rc<Path>>, WordpressTranslation: WordpressTranslation<PathBuf>,
); );
pub fn serve_php<D, C: Into<FpmPoolConfig>>( pub fn serve_php<D, P: Into<PathBuf>, C: Into<FpmPoolConfig>>(
domain: D, domain: D,
path: impl Into<Rc<Path>>, path: P,
root_filename: &'static str, root_filename: &'static str,
nginx_config: impl Into<Rc<str>>, nginx_config: impl Into<String>,
pool_config: C, pool_config: C,
) -> ServePhp<D, Rc<Path>, FpmPoolConfig> { ) -> ServePhp<D, PathBuf, FpmPoolConfig> {
ServePhp( ServePhp(
domain, domain,
path.into(), path.into(),

View file

@ -169,7 +169,7 @@ impl<
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::symbol_runner::TestSymbolRunner; use super::SymbolRunner;
use crate::async_utils::run; use crate::async_utils::run;
use crate::loggers::{Entry, StoringLogger}; use crate::loggers::{Entry, StoringLogger};
use crate::resources::{FromArtifact, FromResource, Resource}; use crate::resources::{FromArtifact, FromResource, Resource};
@ -178,11 +178,33 @@ mod test {
use crate::{ImplementationBuilder, ResourceLocator, Setup}; use crate::{ImplementationBuilder, ResourceLocator, Setup};
use async_trait::async_trait; use async_trait::async_trait;
use regex::Regex; use regex::Regex;
use slog::{info, Logger};
use std::cell::RefCell; use std::cell::RefCell;
use std::error::Error; use std::error::Error;
use std::fmt::Debug; use std::fmt::Debug;
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
struct TestSymbolRunner {
count: Rc<RefCell<usize>>,
}
#[async_trait(?Send)]
impl SymbolRunner for TestSymbolRunner {
async fn run_symbol<S: Symbol + Debug>(
&self,
symbol: &S,
logger: &Logger,
force: bool,
) -> Result<bool, Box<dyn Error>> {
info!(logger, "run");
let run = force || !symbol.target_reached().await?;
if run {
*self.count.borrow_mut() += 1;
}
Ok(run)
}
}
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]
struct TestResource<T>(&'static str, T); struct TestResource<T>(&'static str, T);
impl<T> Resource for TestResource<T> { impl<T> Resource for TestResource<T> {
@ -286,7 +308,10 @@ mod test {
>, >,
StoringLogger, StoringLogger,
) { ) {
let (count, runner) = TestSymbolRunner::new(); let count = Rc::new(RefCell::new(0));
let runner = TestSymbolRunner {
count: Rc::clone(&count),
};
let logger = StoringLogger::new(); let logger = StoringLogger::new();
(count, Setup::new_with(runner, logger.clone()), logger) (count, Setup::new_with(runner, logger.clone()), logger)
} }

View file

@ -53,10 +53,10 @@ for_each_tuple!(runnable_for_tuple);
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::super::symbol_runner::TestSymbolRunner;
use super::Runnable; use super::Runnable;
use crate::async_utils::run; use crate::async_utils::run;
use crate::symbols::Symbol; use crate::symbols::Symbol;
use crate::SymbolRunner;
use async_trait::async_trait; use async_trait::async_trait;
use slog::{o, Discard, Logger}; use slog::{o, Discard, Logger};
use std::cell::RefCell; use std::cell::RefCell;
@ -103,11 +103,39 @@ mod test {
} }
} }
struct TestSymbolRunner {
count: Rc<RefCell<usize>>,
}
fn get_runner() -> (Rc<RefCell<usize>>, TestSymbolRunner) {
let count = Rc::new(RefCell::new(0));
let runner = TestSymbolRunner {
count: Rc::clone(&count),
};
(count, runner)
}
#[async_trait(?Send)]
impl SymbolRunner for TestSymbolRunner {
async fn run_symbol<S: Symbol + Debug>(
&self,
symbol: &S,
_logger: &Logger,
force: bool,
) -> Result<bool, Box<dyn Error>> {
let run = force || !symbol.target_reached().await?;
if run {
*self.count.borrow_mut() += 1;
}
Ok(run)
}
}
fn run_symbol( fn run_symbol(
runnable: impl Runnable, runnable: impl Runnable,
force: bool, force: bool,
) -> (Rc<RefCell<usize>>, Result<bool, Box<dyn Error>>) { ) -> (Rc<RefCell<usize>>, Result<bool, Box<dyn Error>>) {
let (count, runner) = TestSymbolRunner::new(); let (count, runner) = get_runner();
let res = run(runnable.run(&runner, &Logger::root(Discard, o!()), force)); let res = run(runnable.run(&runner, &Logger::root(Discard, o!()), force));
(count, res) (count, res)
} }

View file

@ -2,13 +2,9 @@ use crate::async_utils::sleep;
use crate::symbols::Symbol; use crate::symbols::Symbol;
use async_trait::async_trait; use async_trait::async_trait;
use slog::{debug, info, o, trace, Logger}; use slog::{debug, info, o, trace, Logger};
#[cfg(test)]
use std::cell::RefCell;
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::fmt::Debug; use std::fmt::Debug;
#[cfg(test)]
use std::rc::Rc;
use std::time::Duration; use std::time::Duration;
#[async_trait(?Send)] #[async_trait(?Send)]
@ -202,40 +198,6 @@ where
} }
} }
#[cfg(test)]
pub struct TestSymbolRunner {
count: Rc<RefCell<usize>>,
}
#[cfg(test)]
impl TestSymbolRunner {
pub fn new() -> (Rc<RefCell<usize>>, Self) {
let count = Rc::new(RefCell::new(0));
let runner = TestSymbolRunner {
count: Rc::clone(&count),
};
(count, runner)
}
}
#[cfg(test)]
#[async_trait(?Send)]
impl SymbolRunner for TestSymbolRunner {
async fn run_symbol<S: Symbol + Debug>(
&self,
symbol: &S,
logger: &Logger,
force: bool,
) -> Result<bool, Box<dyn Error>> {
info!(logger, "run");
let run = force || !symbol.target_reached().await?;
if run {
*self.count.borrow_mut() += 1;
}
Ok(run)
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::{DrySymbolRunner, InitializingSymbolRunner, ReportingSymbolRunner, SymbolRunner}; use super::{DrySymbolRunner, InitializingSymbolRunner, ReportingSymbolRunner, SymbolRunner};

View file

@ -1,46 +1,49 @@
use std::error::Error; use std::error::Error;
use std::fs::read_dir; use std::fs::read_dir;
use std::path::Path; use std::path::PathBuf;
use std::rc::Rc;
use std::str::FromStr; use std::str::FromStr;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
pub trait Storage { pub trait Storage {
fn write_filename(&self) -> Box<Path>; fn write_filename(&self) -> PathBuf;
fn read_filename(&self) -> Result<Box<Path>, Box<dyn Error>>; fn read_filename(&self) -> Result<PathBuf, Box<dyn Error>>;
fn recent_date(&self) -> Result<u64, Box<dyn Error>>; fn recent_date(&self) -> Result<u64, Box<dyn Error>>;
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct SimpleStorage(Rc<Path>); pub struct SimpleStorage(PathBuf);
impl SimpleStorage { impl SimpleStorage {
#[must_use] #[must_use]
pub const fn new(base: Rc<Path>) -> Self { pub const fn new(base: PathBuf) -> Self {
Self(base) Self(base)
} }
fn get_path(&self, date: u64) -> Box<Path> { fn get_path(&self, date: Option<u64>) -> PathBuf {
self.0.join(date.to_string()).into() match date {
Some(d) => self.0.join(d.to_string()),
None => self.0.clone(),
}
} }
} }
impl Storage for SimpleStorage { impl Storage for SimpleStorage {
fn write_filename(&self) -> Box<Path> { fn write_filename(&self) -> PathBuf {
self.get_path( self.get_path(Some(
SystemTime::now() SystemTime::now()
.duration_since(UNIX_EPOCH) .duration_since(UNIX_EPOCH)
.unwrap() .unwrap()
.as_secs(), .as_secs(),
) ))
} }
fn read_filename(&self) -> Result<Box<Path>, Box<dyn Error>> { fn read_filename(&self) -> Result<PathBuf, Box<dyn Error>> {
Ok(self.get_path(self.recent_date()?)) Ok(self.get_path(Some(self.recent_date()?)))
} }
fn recent_date(&self) -> Result<u64, Box<dyn Error>> { fn recent_date(&self) -> Result<u64, Box<dyn Error>> {
read_dir(&self.0)? let dir = self.get_path(None);
read_dir(dir)?
.map(|entry| { .map(|entry| {
entry entry
.ok() .ok()

View file

@ -102,7 +102,7 @@ impl<_C: CommandRunner, C: Borrow<_C>, D: AsRef<str>, P: AsRef<Path>> Symbol for
{ {
Ok(false) Ok(false)
} else { } else {
Err(std::str::from_utf8(&output.stderr)?.into()) Err(String::from_utf8(output.stderr)?.into())
} }
} }

View file

@ -10,11 +10,11 @@ pub struct Cron<'r, C, U, R> {
command_runner: &'r R, command_runner: &'r R,
} }
impl<'r, U, R> Cron<'r, Box<str>, U, R> { impl<'r, U, R> Cron<'r, String, U, R> {
pub fn new<C: AsRef<str>>(user: U, content: C, command_runner: &'r R) -> Self { pub fn new<C: AsRef<str>>(user: U, content: C, command_runner: &'r R) -> Self {
Self { Self {
user, user,
content: (String::from(content.as_ref()) + "\n").into(), content: String::from(content.as_ref()) + "\n",
command_runner, command_runner,
} }
} }

View file

@ -42,14 +42,15 @@ impl<P: AsRef<Path>, C: CommandRunner> Symbol for GitSubmodules<'_, P, C> {
if !self.target.as_ref().exists() { if !self.target.as_ref().exists() {
return Ok(false); return Ok(false);
} }
let output = String::from_utf8(
self
._run_in_target_repo(args!["submodule", "status"])
.await?,
)?;
Ok( Ok(
std::str::from_utf8( output
&self .lines()
._run_in_target_repo(args!["submodule", "status"]) .all(|line| line.is_empty() || line.starts_with(' ')),
.await?,
)?
.lines()
.all(|line| line.is_empty() || line.starts_with(' ')),
) )
} }

View file

@ -11,7 +11,7 @@ pub struct Database<'a, D, S, C> {
command_runner: &'a C, command_runner: &'a C,
} }
impl<'a, D, S, C> Database<'a, D, S, C> { impl<'a, D, S, C: CommandRunner> Database<'a, D, S, C> {
pub const fn new(db_name: D, seed_file: S, command_runner: &'a C) -> Self { pub const fn new(db_name: D, seed_file: S, command_runner: &'a C) -> Self {
Self { Self {
db_name, db_name,
@ -19,9 +19,7 @@ impl<'a, D, S, C> Database<'a, D, S, C> {
command_runner, command_runner,
} }
} }
}
impl<'a, D, S, C: CommandRunner> Database<'a, D, S, C> {
async fn run_sql(&self, sql: &str) -> Result<String, Box<dyn Error>> { async fn run_sql(&self, sql: &str) -> Result<String, Box<dyn Error>> {
let b = self let b = self
.command_runner .command_runner

View file

@ -12,7 +12,7 @@ pub struct Dump<'a, N, C, S> {
command_runner: &'a C, command_runner: &'a C,
} }
impl<'a, N, C, S> Dump<'a, N, C, S> { impl<'a, N, C: CommandRunner, S> Dump<'a, N, C, S> {
pub const fn new(db_name: N, storage: S, command_runner: &'a C) -> Self { pub const fn new(db_name: N, storage: S, command_runner: &'a C) -> Self {
Self { Self {
db_name, db_name,
@ -20,9 +20,7 @@ impl<'a, N, C, S> Dump<'a, N, C, S> {
command_runner, command_runner,
} }
} }
}
impl<'a, N, C: CommandRunner, S> Dump<'a, N, C, S> {
async fn run_sql(&self, sql: &str) -> Result<String, Box<dyn Error>> { async fn run_sql(&self, sql: &str) -> Result<String, Box<dyn Error>> {
let b = self let b = self
.command_runner .command_runner

View file

@ -9,16 +9,14 @@ pub struct User<'a, U, C> {
command_runner: &'a C, command_runner: &'a C,
} }
impl<'a, U: AsRef<str>, C> User<'a, U, C> { impl<'a, U: AsRef<str>, C: CommandRunner> User<'a, U, C> {
pub const fn new(user_name: U, command_runner: &'a C) -> Self { pub const fn new(user_name: U, command_runner: &'a C) -> Self {
Self { Self {
user_name, user_name,
command_runner, command_runner,
} }
} }
}
impl<'a, U: AsRef<str>, C: CommandRunner> User<'a, U, C> {
async fn run_sql(&self, sql: &str) -> Result<String, Box<dyn Error>> { async fn run_sql(&self, sql: &str) -> Result<String, Box<dyn Error>> {
let b = self let b = self
.command_runner .command_runner

View file

@ -6,12 +6,12 @@ use std::fmt;
use std::path::Path; use std::path::Path;
#[derive(Debug)] #[derive(Debug)]
pub struct Install<'a, T: AsRef<Path>, C> { pub struct Install<'a, T: AsRef<Path>, C: CommandRunner> {
target: T, target: T,
command_runner: &'a C, command_runner: &'a C,
} }
impl<'a, T: AsRef<Path>, C> Install<'a, T, C> { impl<'a, T: AsRef<Path>, C: CommandRunner> Install<'a, T, C> {
pub const fn new(target: T, command_runner: &'a C) -> Self { pub const fn new(target: T, command_runner: &'a C) -> Self {
Self { Self {
target, target,
@ -51,7 +51,7 @@ impl<T: AsRef<Path>, C: CommandRunner> Symbol for Install<'_, T, C> {
.await?; .await?;
Ok( Ok(
result.status.success() result.status.success()
&& !std::str::from_utf8(&result.stdout) && !String::from_utf8(result.stdout)
.unwrap() .unwrap()
.contains("(empty)"), .contains("(empty)"),
) )

View file

@ -5,23 +5,21 @@ use std::error::Error;
use std::fmt; use std::fmt;
#[derive(Debug)] #[derive(Debug)]
pub struct PostgreSQLDatabase<'a, N, S, C> { pub struct PostgreSQLDatabase<'a, N: AsRef<str>, S: AsRef<str>, C: CommandRunner> {
name: N, name: N,
seed_file: S, seed_file: S,
command_runner: &'a C, command_runner: &'a C,
} }
impl<'a, N, S, C> PostgreSQLDatabase<'a, N, S, C> { impl<'a, N: AsRef<str>, S: AsRef<str>, C: CommandRunner> PostgreSQLDatabase<'a, N, S, C> {
pub const fn new(name: N, seed_file: S, command_runner: &'a C) -> Self { pub const fn new(name: N, seed_file: S, command_runner: &'a C) -> Self {
Self { PostgreSQLDatabase {
name, name,
seed_file, seed_file,
command_runner, command_runner,
} }
} }
}
impl<'a, N: AsRef<str>, S: AsRef<str>, C: CommandRunner> PostgreSQLDatabase<'a, N, S, C> {
async fn run_sql(&self, sql: &str) -> Result<String, Box<dyn Error>> { async fn run_sql(&self, sql: &str) -> Result<String, Box<dyn Error>> {
let b = self let b = self
.command_runner .command_runner

View file

@ -73,7 +73,7 @@ impl<_C: CommandRunner, C: Borrow<_C>, P: AsRef<Path>, S: Storage> Symbol
], ],
) )
.await?; .await?;
let modified_date = u64::from_str(std::str::from_utf8(&output)?.trim_end())?; let modified_date = u64::from_str(String::from_utf8(output)?.trim_end())?;
if if self.dir == StorageDirection::Store { if if self.dir == StorageDirection::Store {
modified_date > dump_date modified_date > dump_date
} else { } else {
@ -84,17 +84,13 @@ impl<_C: CommandRunner, C: Borrow<_C>, P: AsRef<Path>, S: Storage> Symbol
.borrow() .borrow()
.run_with_args( .run_with_args(
"diff", "diff",
args![ args!["-rq", self.storage.read_filename()?, self.path.as_ref()],
"-rq",
self.storage.read_filename()?.as_os_str(),
self.path.as_ref()
],
) )
.await?; .await?;
match output.status.code() { match output.status.code() {
Some(0) => Ok(true), Some(0) => Ok(true),
Some(1) => Ok(false), Some(1) => Ok(false),
_ => Err(std::str::from_utf8(&output.stderr)?.into()), _ => Err(String::from_utf8(output.stderr)?.into()),
} }
} else { } else {
Ok(true) Ok(true)
@ -113,11 +109,7 @@ impl<_C: CommandRunner, C: Borrow<_C>, P: AsRef<Path>, S: Storage> Symbol
.borrow() .borrow()
.run_successfully( .run_successfully(
"cp", "cp",
args![ args!["-a", self.storage.read_filename()?, self.path.as_ref()],
"-a",
self.storage.read_filename()?.as_os_str(),
self.path.as_ref()
],
) )
.await .await
} else { } else {
@ -126,11 +118,7 @@ impl<_C: CommandRunner, C: Borrow<_C>, P: AsRef<Path>, S: Storage> Symbol
.borrow() .borrow()
.run_successfully( .run_successfully(
"cp", "cp",
args![ args!["-a", self.path.as_ref(), self.storage.write_filename()],
"-a",
self.path.as_ref(),
self.storage.write_filename().as_os_str()
],
) )
.await .await
} }

View file

@ -30,9 +30,9 @@ impl<S: AsRef<Path>, U: AsRef<str>> UserService<'_, S, U> {
loop { loop {
let result = self.command_runner.run_with_args("systemctl", args).await?; let result = self.command_runner.run_with_args("systemctl", args).await?;
if result.status.success() { if result.status.success() {
return Ok(std::str::from_utf8(&result.stdout)?.trim_end().to_string()); return Ok(String::from_utf8(result.stdout)?.trim_end().to_string());
} }
let raw_stderr = std::str::from_utf8(&result.stderr)?; let raw_stderr = String::from_utf8(result.stderr)?;
let stderr = raw_stderr.trim_end(); let stderr = raw_stderr.trim_end();
if stderr != "Failed to connect to bus: No such file or directory" { if stderr != "Failed to connect to bus: No such file or directory" {
return Err(stderr.into()); return Err(stderr.into());
@ -61,8 +61,8 @@ impl<S: AsRef<Path>, U: AsRef<str>> UserService<'_, S, U> {
"ActiveState=active" => return Ok(true), "ActiveState=active" => return Ok(true),
"ActiveState=failed" => { "ActiveState=failed" => {
return Err( return Err(
std::str::from_utf8( String::from_utf8(
&self self
.command_runner .command_runner
.get_output( .get_output(
"journalctl", "journalctl",

View file

@ -1,16 +1,14 @@
use crate::command_runner::CommandRunner; use crate::command_runner::CommandRunner;
use crate::symbols::Symbol; use crate::symbols::Symbol;
use async_trait::async_trait; use async_trait::async_trait;
use nonzero_ext::nonzero;
use std::error::Error; use std::error::Error;
use std::num::NonZeroU32;
use std::path::Path; use std::path::Path;
#[derive(Debug)] #[derive(Debug)]
pub struct Key<C, P> { pub struct Key<C, P> {
file_path: P, file_path: P,
command_runner: C, command_runner: C,
bits: NonZeroU32, bits: u32,
} }
impl<C, P> Key<C, P> { impl<C, P> Key<C, P> {
@ -18,7 +16,7 @@ impl<C, P> Key<C, P> {
Self { Self {
file_path, file_path,
command_runner, command_runner,
bits: nonzero!(4096u32), // FIXME: Policy bits: 4096,
} }
} }
} }

View file

@ -6,7 +6,7 @@ use std::error::Error;
use std::fs::File as FsFile; use std::fs::File as FsFile;
use std::io; use std::io;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use std::path::Path; use std::path::{Path, PathBuf};
#[derive(Debug)] #[derive(Debug)]
pub struct Plugin<'a, P, N, R> { pub struct Plugin<'a, P, N, R> {
@ -15,7 +15,7 @@ pub struct Plugin<'a, P, N, R> {
command_runner: &'a R, command_runner: &'a R,
} }
impl<'a, P: AsRef<Path>, N: AsRef<str>, R> Plugin<'a, P, N, R> { impl<'a, P: AsRef<Path>, N: AsRef<str>, R: CommandRunner> Plugin<'a, P, N, R> {
pub const fn new(base: P, name: N, command_runner: &'a R) -> Self { pub const fn new(base: P, name: N, command_runner: &'a R) -> Self {
Self { Self {
base, base,
@ -24,13 +24,12 @@ impl<'a, P: AsRef<Path>, N: AsRef<str>, R> Plugin<'a, P, N, R> {
} }
} }
fn get_path(&self) -> Box<Path> { fn get_path(&self) -> PathBuf {
self self
.base .base
.as_ref() .as_ref()
.join("wp-content/plugins") .join("wp-content/plugins")
.join(self.name.as_ref()) .join(self.name.as_ref())
.into()
} }
} }
@ -42,8 +41,8 @@ impl<P: AsRef<Path>, N: AsRef<str>, R: CommandRunner> Symbol for Plugin<'_, P, N
return Ok(false); return Ok(false);
} }
let path = base_path.join(self.name.as_ref().to_owned() + ".php"); let path = base_path.join(self.name.as_ref().to_owned() + ".php");
let mut version: Option<Box<str>> = None; let mut version = String::new();
let mut plugin_uri: Option<Box<str>> = None; let mut plugin_uri = String::new();
match FsFile::open(path) { match FsFile::open(path) {
Err(e) => { Err(e) => {
// Check if file exists // Check if file exists
@ -57,12 +56,11 @@ impl<P: AsRef<Path>, N: AsRef<str>, R: CommandRunner> Symbol for Plugin<'_, P, N
let reader = BufReader::new(file); let reader = BufReader::new(file);
let regex = Regex::new("(?m)^(Plugin URI|Version): (.+)$")?; let regex = Regex::new("(?m)^(Plugin URI|Version): (.+)$")?;
for content in reader.lines() { for content in reader.lines() {
let content = content?; for matches in regex.captures_iter(&(content?)) {
for matches in regex.captures_iter(&content) {
if &matches[1] == "Plugin URI" { if &matches[1] == "Plugin URI" {
plugin_uri = Some(matches[2].into()); plugin_uri = matches[2].to_string();
} else { } else {
version = Some(matches[2].into()); version = matches[2].to_string();
} }
} }
} }
@ -77,14 +75,14 @@ impl<P: AsRef<Path>, N: AsRef<str>, R: CommandRunner> Symbol for Plugin<'_, P, N
format!( format!(
r###"plugins={{"plugins":{{"{0}/{0}.php":{{"Version":"{1}", "PluginURI":"{2}"}}}}}}"###, r###"plugins={{"plugins":{{"{0}/{0}.php":{{"Version":"{1}", "PluginURI":"{2}"}}}}}}"###,
self.name.as_ref(), self.name.as_ref(),
version.as_deref().unwrap_or_default(), version,
plugin_uri.as_deref().unwrap_or_default() plugin_uri
), ),
"https://api.wordpress.org/plugins/update-check/1.1/", "https://api.wordpress.org/plugins/update-check/1.1/",
], ],
) )
.await?; .await?;
Ok(std::str::from_utf8(&upstream)?.contains(r###""plugins":[]"###)) Ok(String::from_utf8(upstream)?.contains(r###""plugins":[]"###))
} }
async fn execute(&self) -> Result<(), Box<dyn Error>> { async fn execute(&self) -> Result<(), Box<dyn Error>> {
@ -99,7 +97,7 @@ impl<P: AsRef<Path>, N: AsRef<str>, R: CommandRunner> Symbol for Plugin<'_, P, N
.await?; .await?;
self self
.command_runner .command_runner
.run_successfully("rm", args!["-rf", self.get_path().as_os_str()]) .run_successfully("rm", args!["-rf", self.get_path()])
.await?; .await?;
self self
.command_runner .command_runner

View file

@ -8,6 +8,7 @@ use std::fs::File as FsFile;
use std::io; use std::io;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use std::path::Path; use std::path::Path;
use std::path::PathBuf;
#[derive(Debug)] #[derive(Debug)]
pub struct Translation<'a, C, D, R> { pub struct Translation<'a, C, D, R> {
@ -17,7 +18,7 @@ pub struct Translation<'a, C, D, R> {
command_runner: &'a R, command_runner: &'a R,
} }
impl<'a, D, C: AsRef<str>, R> Translation<'a, C, D, R> { impl<'a, D, C: AsRef<str>, R: CommandRunner> Translation<'a, C, D, R> {
pub const fn new(path: D, version: &'a str, locale: C, command_runner: &'a R) -> Self { pub const fn new(path: D, version: &'a str, locale: C, command_runner: &'a R) -> Self {
Self { Self {
path, path,
@ -29,7 +30,7 @@ impl<'a, D, C: AsRef<str>, R> Translation<'a, C, D, R> {
} }
impl<C: AsRef<str>, D: AsRef<Path>, R: CommandRunner> Translation<'_, C, D, R> { impl<C: AsRef<str>, D: AsRef<Path>, R: CommandRunner> Translation<'_, C, D, R> {
fn get_pairs(&self) -> impl Iterator<Item = (Box<str>, Box<Path>)> + '_ { fn get_pairs(&self) -> Vec<(String, PathBuf)> {
let version_x = self let version_x = self
.version .version
.trim_end_matches(|c: char| c.is_ascii_digit()) .trim_end_matches(|c: char| c.is_ascii_digit())
@ -41,19 +42,21 @@ impl<C: AsRef<str>, D: AsRef<Path>, R: CommandRunner> Translation<'_, C, D, R> {
} else { } else {
locale.to_lowercase().replace('_', "-") locale.to_lowercase().replace('_', "-")
}; };
[ let mut res = vec![];
for &(in_slug, out_slug) in &[
("", ""), ("", ""),
("cc/", "continents-cities-"), ("cc/", "continents-cities-"),
("admin/", "admin-"), ("admin/", "admin-"),
("admin/network/", "admin-network-"), ("admin/network/", "admin-network-"),
].into_iter().flat_map(move |(in_slug, out_slug)|{ ] {
["po", "mo"].map(|format| for format in &["po", "mo"] {
( res.push((
format!("https://translate.wordpress.org/projects/wp/{version_x}/{in_slug}{path_locale}/default/export-translations?format={format}").into(), format!("https://translate.wordpress.org/projects/wp/{version_x}/{in_slug}{path_locale}/default/export-translations?format={format}"),
self.path.as_ref().join(format!("{}{}.{}", out_slug, self.locale.as_ref(), format)).into() [self.path.as_ref(), format!("{}{}.{}", out_slug, self.locale.as_ref(), format).as_ref()].iter().collect()
)) ));
} }
) }
res
} }
} }
@ -77,7 +80,7 @@ impl<C: AsRef<str>, D: AsRef<Path>, R: CommandRunner> Symbol for Translation<'_,
let reader = BufReader::new(file); let reader = BufReader::new(file);
for content in reader.lines() { for content in reader.lines() {
if let Some(match_result) = match_date.captures(&content?) { if let Some(match_result) = match_date.captures(&content?) {
newest = max(newest, match_result[1].into()); newest = max(newest, match_result[1].to_string());
break; break;
} }
} }
@ -96,7 +99,7 @@ impl<C: AsRef<str>, D: AsRef<Path>, R: CommandRunner> Symbol for Translation<'_,
)], )],
) )
.await?; .await?;
Ok(std::str::from_utf8(&upstream)?.contains(&format!( Ok(String::from_utf8(upstream)?.contains(&format!(
r###"language":"{}","version":"{}","updated":"{}"###, r###"language":"{}","version":"{}","updated":"{}"###,
self.locale.as_ref(), self.locale.as_ref(),
self.version, self.version,
@ -108,10 +111,7 @@ impl<C: AsRef<str>, D: AsRef<Path>, R: CommandRunner> Symbol for Translation<'_,
for (source, target) in self.get_pairs() { for (source, target) in self.get_pairs() {
self self
.command_runner .command_runner
.run_successfully( .run_successfully("curl", args!["--compressed", "-o", target, source,])
"curl",
args!["--compressed", "-o", target.as_os_str(), source.as_ref(),],
)
.await?; .await?;
} }
Ok(()) Ok(())

View file

@ -1,5 +1,4 @@
use std::fmt::Display; use std::fmt::Display;
use std::num::NonZeroUsize;
use std::path::Path; use std::path::Path;
#[must_use] #[must_use]
@ -102,11 +101,11 @@ impl<T: AsRef<Path>> SocketSpec for T {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct LocalTcpSocket(NonZeroUsize); pub struct LocalTcpSocket(usize);
impl LocalTcpSocket { impl LocalTcpSocket {
#[must_use] #[must_use]
pub const fn new(x: NonZeroUsize) -> Self { pub const fn new(x: usize) -> Self {
Self(x) Self(x)
} }
} }

View file

@ -1,11 +1,10 @@
use std::fmt::{Display, Error, Formatter}; use std::fmt::{Display, Error, Formatter};
use std::num::NonZeroUsize;
use std::path::Path; use std::path::Path;
#[derive(Clone, Debug, PartialEq, Hash, Eq)] #[derive(Clone, Debug, PartialEq, Hash, Eq)]
pub struct FpmPoolConfig { pub struct FpmPoolConfig {
max_children: NonZeroUsize, max_children: usize,
custom: Option<Box<str>>, custom: Option<String>,
} }
impl Display for FpmPoolConfig { impl Display for FpmPoolConfig {
@ -20,14 +19,14 @@ impl Display for FpmPoolConfig {
impl From<usize> for FpmPoolConfig { impl From<usize> for FpmPoolConfig {
fn from(max_children: usize) -> Self { fn from(max_children: usize) -> Self {
Self { Self {
max_children: NonZeroUsize::try_from(max_children).unwrap(), max_children,
custom: None, custom: None,
} }
} }
} }
impl FpmPoolConfig { impl FpmPoolConfig {
pub fn new(max_children: NonZeroUsize, custom: impl Into<Box<str>>) -> Self { pub fn new(max_children: usize, custom: impl Into<String>) -> Self {
Self { Self {
max_children, max_children,
custom: Some(custom.into()), custom: Some(custom.into()),

View file

@ -3,7 +3,7 @@ use schematics::symbols::file::File as FileSymbol;
use schematics::symbols::Symbol; use schematics::symbols::Symbol;
use std::fs::File; use std::fs::File;
use std::io::Write; use std::io::Write;
use std::path::Path; use std::path::{Path, PathBuf};
use tempfile::{tempdir, TempDir}; use tempfile::{tempdir, TempDir};
fn get_dir(content: Option<&str>) -> TempDir { fn get_dir(content: Option<&str>) -> TempDir {
@ -19,8 +19,8 @@ fn get_dir(content: Option<&str>) -> TempDir {
tmp_dir tmp_dir
} }
fn get_symbol(path: &Path) -> FileSymbol<Box<Path>, &str> { fn get_symbol(path: &Path) -> FileSymbol<PathBuf, &str> {
FileSymbol::new(path.join("filename").into(), "target content") FileSymbol::new(path.join("filename"), "target content")
} }
// Normal cases // Normal cases

View file

@ -9,7 +9,6 @@ use schematics::SymbolRunner;
use slog::{info, Logger as SlogLogger}; use slog::{info, Logger as SlogLogger};
use std::error::Error; use std::error::Error;
use std::fmt::Debug; use std::fmt::Debug;
use std::path::Path;
use std::time::Duration; use std::time::Duration;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -61,7 +60,7 @@ fn test(
#[test] #[test]
fn can_create_an_acme_user() { fn can_create_an_acme_user() {
let mut result = test(1, |setup| { let mut result = test(1, |setup| {
assert_eq!(&*(run(setup.add(AcmeUser)).unwrap().0).0, "acme"); assert_eq!((run(setup.add(AcmeUser)).unwrap().0).0, "acme");
}); });
let entry = result let entry = result
.pop() .pop()
@ -134,8 +133,8 @@ fn can_create_an_acme_cert() {
#[test] #[test]
fn can_create_a_git_checkout() { fn can_create_a_git_checkout() {
let mut result = test(1, |setup| { let mut result = test(1, |setup| {
run(setup.add(GitCheckout::new( run(setup.add(GitCheckout(
"/tmp/somepath".as_ref() as &Path, "/tmp/somepath".into(),
"/tmp/some_src_repo", "/tmp/some_src_repo",
"master", "master",
))) )))

View file

@ -16,7 +16,7 @@ fn get_dir<'a, I: IntoIterator<Item = &'a &'a str>>(content: I) -> TempDir {
} }
fn get_storage(path: &Path) -> SimpleStorage { fn get_storage(path: &Path) -> SimpleStorage {
SimpleStorage::new(path.join("_filename").into()) SimpleStorage::new(path.join("_filename"))
} }
// Normal cases // Normal cases
@ -33,7 +33,7 @@ fn single_file() {
); );
assert_eq!( assert_eq!(
dir.path().join("_filename").join("12345"), dir.path().join("_filename").join("12345"),
Path::new(&*storage.read_filename().unwrap()) Path::new(&storage.read_filename().unwrap())
); );
assert_eq!(storage.recent_date().unwrap(), 12345); assert_eq!(storage.recent_date().unwrap(), 12345);
} }
@ -50,7 +50,7 @@ fn two_files() {
); );
assert_eq!( assert_eq!(
dir.path().join("_filename").join("23456"), dir.path().join("_filename").join("23456"),
Path::new(&*storage.read_filename().unwrap()) Path::new(&storage.read_filename().unwrap())
); );
assert_eq!(storage.recent_date().unwrap(), 23456); assert_eq!(storage.recent_date().unwrap(), 23456);
} }
@ -67,7 +67,7 @@ fn another_two_files() {
); );
assert_eq!( assert_eq!(
dir.path().join("_filename").join("23456"), dir.path().join("_filename").join("23456"),
Path::new(&*storage.read_filename().unwrap()) Path::new(&storage.read_filename().unwrap())
); );
assert_eq!(storage.recent_date().unwrap(), 23456); assert_eq!(storage.recent_date().unwrap(), 23456);
} }
@ -84,7 +84,7 @@ fn three_files() {
); );
assert_eq!( assert_eq!(
dir.path().join("_filename").join("23456"), dir.path().join("_filename").join("23456"),
Path::new(&*storage.read_filename().unwrap()) Path::new(&storage.read_filename().unwrap())
); );
assert_eq!(storage.recent_date().unwrap(), 23456); assert_eq!(storage.recent_date().unwrap(), 23456);
} }