Try to get rid of owned types
Inspired by https://www.youtube.com/watch?v=A4cKi7PTJSs. This turns a lot of cloning Strings and PathBufs into Rcs.
This commit is contained in:
parent
e3b425eb1c
commit
d091265d27
20 changed files with 343 additions and 232 deletions
|
|
@ -1,13 +1,24 @@
|
|||
use std::path::{Path as ActualPath, PathBuf};
|
||||
use std::path::{self, PathBuf};
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Path(PathBuf);
|
||||
pub struct Path(Rc<path::Path>);
|
||||
|
||||
// FIXME: This is a specialization since with Path: Into<PathBuf>
|
||||
impl Path {
|
||||
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
|
||||
//impl<T: Into<PathBuf>> From<T> for Path {
|
||||
//impl<T: AsRef<path::Path>> From<T> for Path {
|
||||
// fn from(v: T) -> Self {
|
||||
// Path(v.into())
|
||||
// Self(v.as_ref().into())
|
||||
// }
|
||||
//}
|
||||
|
||||
|
|
@ -15,7 +26,8 @@ macro_rules! path_from {
|
|||
( $t:ty ) => {
|
||||
impl From<$t> for Path {
|
||||
fn from(v: $t) -> Self {
|
||||
Self(v.into())
|
||||
let path: &path::Path = v.as_ref();
|
||||
Self(path.into())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -25,23 +37,35 @@ path_from!(String);
|
|||
path_from!(&str);
|
||||
path_from!(PathBuf);
|
||||
|
||||
impl From<Path> for PathBuf {
|
||||
impl From<Rc<path::Path>> for Path {
|
||||
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 {
|
||||
v.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<ActualPath> for Path {
|
||||
fn as_ref(&self) -> &ActualPath {
|
||||
&self.0
|
||||
impl From<&Path> for Rc<path::Path> {
|
||||
fn from(v: &Path) -> Self {
|
||||
v.0.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct UserName(pub String);
|
||||
pub struct UserName(pub Rc<str>);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ServiceName(pub String);
|
||||
pub struct ServiceName(pub Rc<str>);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DatabaseName(pub String);
|
||||
pub struct DatabaseName(pub Rc<str>);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::env;
|
|||
use std::process::exit;
|
||||
|
||||
pub fn schematics_main(run: &dyn Fn(bool) -> Result<(), ()>) {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let args: Box<[String]> = env::args().collect();
|
||||
let dry_run = match args.len() {
|
||||
1 => false,
|
||||
2 => {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ pub fn create_static_output(
|
|||
.to_str()
|
||||
.ok_or("Filename is not valid unicode")?
|
||||
.to_uppercase();
|
||||
let content = String::from_utf8(read_file(source_path)?)?;
|
||||
let file = read_file(source_path)?;
|
||||
let content = std::str::from_utf8(&file)?;
|
||||
let fence = content.chars().filter(|&c| c == '#').collect::<String>() + "#";
|
||||
|
||||
writeln!(
|
||||
|
|
|
|||
166
src/builder.rs
166
src/builder.rs
|
|
@ -41,7 +41,8 @@ use crate::templates::systemd::{
|
|||
};
|
||||
use crate::to_artifact::ToArtifact;
|
||||
use std::fmt::Display;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub trait ImplementationBuilder<R> {
|
||||
type Prerequisites: ToArtifact;
|
||||
|
|
@ -64,13 +65,13 @@ impl<D> ImplementationBuilder<Key<D>> for DefaultBuilder {
|
|||
type Prerequisites = ();
|
||||
fn prerequisites(_resource: &Key<D>) -> Self::Prerequisites {}
|
||||
|
||||
type Implementation = KeySymbol<StdCommandRunner, PathBuf>;
|
||||
type Implementation = KeySymbol<StdCommandRunner, Rc<Path>>;
|
||||
fn create(
|
||||
_resource: &Key<D>,
|
||||
target: &<Key<D> as Resource>::Artifact,
|
||||
(): <Self::Prerequisites as ToArtifact>::Artifact,
|
||||
) -> Self::Implementation {
|
||||
KeySymbol::new(StdCommandRunner, target.clone().into())
|
||||
KeySymbol::new(StdCommandRunner, target.clone_rc())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +81,7 @@ impl<D: Clone> ImplementationBuilder<Csr<D>> for DefaultBuilder {
|
|||
Key(resource.0.clone())
|
||||
}
|
||||
|
||||
type Implementation = CsrSymbol<StdCommandRunner, D, PathBuf, PathBuf>;
|
||||
type Implementation = CsrSymbol<StdCommandRunner, D, Rc<Path>, Rc<Path>>;
|
||||
fn create(
|
||||
resource: &Csr<D>,
|
||||
target: &<Csr<D> as Resource>::Artifact,
|
||||
|
|
@ -89,8 +90,8 @@ impl<D: Clone> ImplementationBuilder<Csr<D>> for DefaultBuilder {
|
|||
CsrSymbol::new(
|
||||
StdCommandRunner,
|
||||
resource.0.clone(),
|
||||
key.into(),
|
||||
target.clone().into(),
|
||||
key.clone_rc(),
|
||||
target.clone_rc(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -116,7 +117,7 @@ impl<D: Clone> ImplementationBuilder<Cert<D>> for DefaultBuilder {
|
|||
}
|
||||
|
||||
type Implementation =
|
||||
CertSymbol<SetuidCommandRunner<String>, SetuidCommandRunner<String>, D, PathBuf>;
|
||||
CertSymbol<SetuidCommandRunner<Rc<str>>, SetuidCommandRunner<Rc<str>>, D, Rc<Path>>;
|
||||
fn create(
|
||||
resource: &Cert<D>,
|
||||
target: &<Cert<D> as Resource>::Artifact,
|
||||
|
|
@ -125,11 +126,11 @@ impl<D: Clone> ImplementationBuilder<Cert<D>> for DefaultBuilder {
|
|||
CertSymbol::new(
|
||||
resource.0.clone(),
|
||||
SetuidCommandRunner::new(user_name.0),
|
||||
root_cert.into(),
|
||||
account_key.into(),
|
||||
challenges_dir.into(),
|
||||
csr.into(),
|
||||
target.clone().into(),
|
||||
root_cert.clone_rc(),
|
||||
account_key.clone_rc(),
|
||||
challenges_dir.clone_rc(),
|
||||
csr.clone_rc(),
|
||||
target.clone_rc(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -140,13 +141,13 @@ impl<D: Clone> ImplementationBuilder<CertChain<D>> for DefaultBuilder {
|
|||
(Cert(resource.0.clone()), AcmeRootCert)
|
||||
}
|
||||
|
||||
type Implementation = ConcatSymbol<[PathBuf; 2], PathBuf, PathBuf>;
|
||||
type Implementation = ConcatSymbol<[Rc<Path>; 2], Rc<Path>, Rc<Path>>;
|
||||
fn create(
|
||||
_resource: &CertChain<D>,
|
||||
target: &<CertChain<D> as Resource>::Artifact,
|
||||
(cert, root_cert): <Self::Prerequisites as ToArtifact>::Artifact,
|
||||
) -> Self::Implementation {
|
||||
ConcatSymbol::new([cert.into(), root_cert.into()], target.clone().into())
|
||||
ConcatSymbol::new([cert.clone_rc(), root_cert.clone_rc()], target.clone_rc())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -156,13 +157,13 @@ impl<D: Clone> ImplementationBuilder<KeyAndCertBundle<D>> for DefaultBuilder {
|
|||
(CertChain(resource.0.clone()), Key(resource.0.clone()))
|
||||
}
|
||||
|
||||
type Implementation = ConcatSymbol<[PathBuf; 2], PathBuf, PathBuf>;
|
||||
type Implementation = ConcatSymbol<[Rc<Path>; 2], Rc<Path>, Rc<Path>>;
|
||||
fn create(
|
||||
_resource: &KeyAndCertBundle<D>,
|
||||
target: &<KeyAndCertBundle<D> as Resource>::Artifact,
|
||||
(cert_chain, key): <Self::Prerequisites as ToArtifact>::Artifact,
|
||||
) -> Self::Implementation {
|
||||
ConcatSymbol::new([key.into(), cert_chain.into()], target.clone().into())
|
||||
ConcatSymbol::new([key.clone_rc(), cert_chain.clone_rc()], target.clone_rc())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -170,7 +171,7 @@ impl<P: AsRef<Path> + Clone> ImplementationBuilder<File<P>> for DefaultBuilder {
|
|||
type Prerequisites = ();
|
||||
fn prerequisites(_resource: &File<P>) -> Self::Prerequisites {}
|
||||
|
||||
type Implementation = FileSymbol<P, String>;
|
||||
type Implementation = FileSymbol<P, Rc<str>>;
|
||||
fn create(
|
||||
resource: &File<P>,
|
||||
_target: &<File<P> as Resource>::Artifact,
|
||||
|
|
@ -201,7 +202,7 @@ impl ImplementationBuilder<DefaultServer> for DefaultBuilder {
|
|||
}
|
||||
|
||||
type Implementation = (
|
||||
FileSymbol<PathBuf, String>,
|
||||
FileSymbol<Rc<Path>, Box<str>>,
|
||||
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
|
||||
);
|
||||
fn create(
|
||||
|
|
@ -211,8 +212,8 @@ impl ImplementationBuilder<DefaultServer> for DefaultBuilder {
|
|||
) -> Self::Implementation {
|
||||
(
|
||||
FileSymbol::new(
|
||||
target.clone().into(),
|
||||
nginx::default_server(challenges_snippet_path),
|
||||
target.clone_rc(),
|
||||
nginx::default_server(challenges_snippet_path).into(),
|
||||
),
|
||||
ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
|
||||
)
|
||||
|
|
@ -230,7 +231,7 @@ impl<D: AsRef<str> + Clone + Display> ImplementationBuilder<ServeCustom<D>> for
|
|||
}
|
||||
|
||||
type Implementation = (
|
||||
FileSymbol<PathBuf, String>,
|
||||
FileSymbol<Rc<Path>, Box<str>>,
|
||||
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
|
||||
);
|
||||
fn create(
|
||||
|
|
@ -240,8 +241,8 @@ impl<D: AsRef<str> + Clone + Display> ImplementationBuilder<ServeCustom<D>> for
|
|||
) -> Self::Implementation {
|
||||
(
|
||||
FileSymbol::new(
|
||||
target.clone().into(),
|
||||
nginx::server_config(&resource.0, cert, key, &resource.1, challenges_snippet_path),
|
||||
target.clone_rc(),
|
||||
nginx::server_config(&resource.0, cert, key, &resource.1, challenges_snippet_path).into(),
|
||||
),
|
||||
ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
|
||||
)
|
||||
|
|
@ -267,7 +268,7 @@ impl<D: Clone + Display, P: AsRef<Path>, C: Clone + Into<PhpFpmPoolConfig>>
|
|||
}
|
||||
|
||||
type Implementation = (
|
||||
FileSymbol<PathBuf, String>,
|
||||
FileSymbol<Rc<Path>, Box<str>>,
|
||||
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
|
||||
);
|
||||
fn create(
|
||||
|
|
@ -277,14 +278,15 @@ impl<D: Clone + Display, P: AsRef<Path>, C: Clone + Into<PhpFpmPoolConfig>>
|
|||
) -> Self::Implementation {
|
||||
(
|
||||
FileSymbol::new(
|
||||
target.clone().into(),
|
||||
target.clone_rc(),
|
||||
nginx::server_config(
|
||||
&resource.0,
|
||||
cert,
|
||||
key,
|
||||
nginx::php_snippet(resource.2, pool.0, &resource.1) + &resource.3,
|
||||
challenges_snippet_path,
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
|
||||
)
|
||||
|
|
@ -316,7 +318,7 @@ impl<D: Clone + Display, P: Clone + AsRef<Path>> ImplementationBuilder<ServeServ
|
|||
}
|
||||
|
||||
type Implementation = (
|
||||
FileSymbol<PathBuf, String>,
|
||||
FileSymbol<Rc<Path>, Box<str>>,
|
||||
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
|
||||
);
|
||||
fn create(
|
||||
|
|
@ -326,14 +328,15 @@ impl<D: Clone + Display, P: Clone + AsRef<Path>> ImplementationBuilder<ServeServ
|
|||
) -> Self::Implementation {
|
||||
(
|
||||
FileSymbol::new(
|
||||
target.clone().into(),
|
||||
target.clone_rc(),
|
||||
nginx::server_config(
|
||||
&resource.0,
|
||||
cert,
|
||||
key,
|
||||
nginx::proxy_snippet(&socket.0, &resource.3),
|
||||
challenges_snippet_path,
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
|
||||
)
|
||||
|
|
@ -351,7 +354,7 @@ impl<D: AsRef<str> + Clone + Display> ImplementationBuilder<ServeRedir<D>> for D
|
|||
}
|
||||
|
||||
type Implementation = (
|
||||
FileSymbol<PathBuf, String>,
|
||||
FileSymbol<Rc<Path>, Box<str>>,
|
||||
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
|
||||
);
|
||||
fn create(
|
||||
|
|
@ -361,14 +364,15 @@ impl<D: AsRef<str> + Clone + Display> ImplementationBuilder<ServeRedir<D>> for D
|
|||
) -> Self::Implementation {
|
||||
(
|
||||
FileSymbol::new(
|
||||
target.clone().into(),
|
||||
target.clone_rc(),
|
||||
nginx::server_config(
|
||||
&resource.0,
|
||||
cert,
|
||||
key,
|
||||
nginx::redir_snippet(resource.1.as_ref()),
|
||||
challenges_snippet_path,
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
|
||||
)
|
||||
|
|
@ -388,7 +392,7 @@ impl<D: AsRef<str> + Clone + Display, P: AsRef<Path>> ImplementationBuilder<Serv
|
|||
}
|
||||
|
||||
type Implementation = (
|
||||
FileSymbol<PathBuf, String>,
|
||||
FileSymbol<Rc<Path>, Box<str>>,
|
||||
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
|
||||
);
|
||||
fn create(
|
||||
|
|
@ -398,14 +402,15 @@ impl<D: AsRef<str> + Clone + Display, P: AsRef<Path>> ImplementationBuilder<Serv
|
|||
) -> Self::Implementation {
|
||||
(
|
||||
FileSymbol::new(
|
||||
target.clone().into(),
|
||||
target.clone_rc(),
|
||||
nginx::server_config(
|
||||
&resource.0,
|
||||
cert,
|
||||
key,
|
||||
nginx::static_snippet(resource.1.as_ref()),
|
||||
challenges_snippet_path,
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
|
||||
)
|
||||
|
|
@ -417,8 +422,8 @@ impl<D: Clone> ImplementationBuilder<PhpFpmPool<D>> for DefaultBuilder {
|
|||
fn prerequisites(_resource: &PhpFpmPool<D>) -> Self::Prerequisites {}
|
||||
|
||||
type Implementation = (
|
||||
FileSymbol<PathBuf, String>,
|
||||
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, String>,
|
||||
FileSymbol<Rc<Path>, Box<str>>,
|
||||
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, Rc<str>>,
|
||||
);
|
||||
fn create(
|
||||
resource: &PhpFpmPool<D>,
|
||||
|
|
@ -427,8 +432,8 @@ impl<D: Clone> ImplementationBuilder<PhpFpmPool<D>> for DefaultBuilder {
|
|||
) -> Self::Implementation {
|
||||
(
|
||||
FileSymbol::new(
|
||||
conf_path.clone().into(),
|
||||
php_fpm_pool_config(&user_name.0, socket_path, &resource.1),
|
||||
conf_path.clone_rc(),
|
||||
php_fpm_pool_config(&user_name.0, socket_path, &resource.1).into(),
|
||||
),
|
||||
ReloadServiceSymbol::new(StdCommandRunner, service_name.0.clone()),
|
||||
)
|
||||
|
|
@ -441,10 +446,10 @@ impl<D, P: AsRef<Path>> ImplementationBuilder<SystemdSocketService<D, P>> for De
|
|||
|
||||
type Implementation = (
|
||||
// First three could be parallel
|
||||
FileSymbol<PathBuf, String>,
|
||||
SystemdUserSessionSymbol<'static, String, StdCommandRunner>,
|
||||
OwnerSymbol<StdCommandRunner, StdCommandRunner, PathBuf, String>,
|
||||
UserServiceSymbol<'static, PathBuf, String>,
|
||||
FileSymbol<Rc<Path>, Box<str>>,
|
||||
SystemdUserSessionSymbol<'static, Rc<str>, StdCommandRunner>,
|
||||
OwnerSymbol<StdCommandRunner, StdCommandRunner, Box<Path>, Rc<str>>,
|
||||
UserServiceSymbol<'static, Rc<Path>, Rc<str>>,
|
||||
);
|
||||
fn create(
|
||||
resource: &SystemdSocketService<D, P>,
|
||||
|
|
@ -453,7 +458,7 @@ impl<D, P: AsRef<Path>> ImplementationBuilder<SystemdSocketService<D, P>> for De
|
|||
) -> Self::Implementation {
|
||||
(
|
||||
FileSymbol::new(
|
||||
conf_path.clone().into(),
|
||||
conf_path.clone_rc(),
|
||||
if resource.4 {
|
||||
systemd_nodejs_service(&resource.2, socket_path, &resource.3)
|
||||
} else {
|
||||
|
|
@ -463,15 +468,16 @@ impl<D, P: AsRef<Path>> ImplementationBuilder<SystemdSocketService<D, P>> for De
|
|||
&resource.3,
|
||||
"",
|
||||
)
|
||||
},
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
SystemdUserSessionSymbol::new(user_name.0.clone(), &StdCommandRunner),
|
||||
OwnerSymbol::new(
|
||||
conf_path.as_ref().parent().unwrap().to_path_buf(),
|
||||
conf_path.as_ref().parent().unwrap().into(),
|
||||
user_name.0.clone(),
|
||||
StdCommandRunner,
|
||||
),
|
||||
UserServiceSymbol::new(socket_path.clone().into(), user_name.0.clone(), resource.1),
|
||||
UserServiceSymbol::new(socket_path.clone_rc(), user_name.0.clone(), resource.1),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -516,7 +522,7 @@ impl<P: Clone + AsRef<Path>> ImplementationBuilder<StoredDirectory<P>> for Defau
|
|||
) -> Self::Implementation {
|
||||
SavedDirectorySymbol::new(
|
||||
resource.1.clone(),
|
||||
SimpleStorage::new(target.clone().into()),
|
||||
SimpleStorage::new(target.clone_rc()),
|
||||
StorageDirection::Store,
|
||||
StdCommandRunner,
|
||||
)
|
||||
|
|
@ -535,7 +541,7 @@ impl<P: Clone + AsRef<Path>> ImplementationBuilder<LoadedDirectory<P>> for Defau
|
|||
) -> Self::Implementation {
|
||||
SavedDirectorySymbol::new(
|
||||
resource.1.clone(),
|
||||
SimpleStorage::new(target.clone().into()),
|
||||
SimpleStorage::new(target.clone_rc()),
|
||||
StorageDirection::Load,
|
||||
StdCommandRunner,
|
||||
)
|
||||
|
|
@ -546,7 +552,7 @@ impl<D: Clone> ImplementationBuilder<UserForDomain<D>> for DefaultBuilder {
|
|||
type Prerequisites = ();
|
||||
fn prerequisites(_resource: &UserForDomain<D>) -> Self::Prerequisites {}
|
||||
|
||||
type Implementation = UserSymbol<String, StdCommandRunner>;
|
||||
type Implementation = UserSymbol<Rc<str>, StdCommandRunner>;
|
||||
fn create(
|
||||
_resource: &UserForDomain<D>,
|
||||
(user_name, _home_path): &<UserForDomain<D> as Resource>::Artifact,
|
||||
|
|
@ -560,7 +566,7 @@ impl ImplementationBuilder<User> for DefaultBuilder {
|
|||
type Prerequisites = ();
|
||||
fn prerequisites(_resource: &User) -> Self::Prerequisites {}
|
||||
|
||||
type Implementation = UserSymbol<String, StdCommandRunner>;
|
||||
type Implementation = UserSymbol<Rc<str>, StdCommandRunner>;
|
||||
fn create(
|
||||
resource: &User,
|
||||
(): &<User as Resource>::Artifact,
|
||||
|
|
@ -574,7 +580,7 @@ impl<P: AsRef<Path> + Clone> ImplementationBuilder<Owner<P>> for DefaultBuilder
|
|||
type Prerequisites = ();
|
||||
fn prerequisites(_resource: &Owner<P>) -> Self::Prerequisites {}
|
||||
|
||||
type Implementation = OwnerSymbol<StdCommandRunner, StdCommandRunner, P, String>;
|
||||
type Implementation = OwnerSymbol<StdCommandRunner, StdCommandRunner, P, Rc<str>>;
|
||||
fn create(
|
||||
resource: &Owner<P>,
|
||||
(): &<Owner<P> as Resource>::Artifact,
|
||||
|
|
@ -588,7 +594,7 @@ impl ImplementationBuilder<AcmeUser> for DefaultBuilder {
|
|||
type Prerequisites = ();
|
||||
fn prerequisites(_resource: &AcmeUser) -> Self::Prerequisites {}
|
||||
|
||||
type Implementation = UserSymbol<String, StdCommandRunner>;
|
||||
type Implementation = UserSymbol<Rc<str>, StdCommandRunner>;
|
||||
fn create(
|
||||
_resource: &AcmeUser,
|
||||
user_name: &<AcmeUser as Resource>::Artifact,
|
||||
|
|
@ -605,8 +611,8 @@ impl ImplementationBuilder<AcmeChallengesDir> for DefaultBuilder {
|
|||
}
|
||||
|
||||
type Implementation = (
|
||||
DirSymbol<PathBuf>,
|
||||
OwnerSymbol<StdCommandRunner, StdCommandRunner, PathBuf, String>,
|
||||
DirSymbol<Rc<Path>>,
|
||||
OwnerSymbol<StdCommandRunner, StdCommandRunner, Rc<Path>, Rc<str>>,
|
||||
);
|
||||
fn create(
|
||||
_resource: &AcmeChallengesDir,
|
||||
|
|
@ -614,8 +620,8 @@ impl ImplementationBuilder<AcmeChallengesDir> for DefaultBuilder {
|
|||
user_name: <Self::Prerequisites as ToArtifact>::Artifact,
|
||||
) -> Self::Implementation {
|
||||
(
|
||||
DirSymbol::new(target.clone().into()),
|
||||
OwnerSymbol::new(target.clone().into(), user_name.0, StdCommandRunner),
|
||||
DirSymbol::new(target.clone_rc()),
|
||||
OwnerSymbol::new(target.clone_rc(), user_name.0, StdCommandRunner),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -626,15 +632,15 @@ impl ImplementationBuilder<AcmeChallengesNginxSnippet> for DefaultBuilder {
|
|||
AcmeChallengesDir
|
||||
}
|
||||
|
||||
type Implementation = FileSymbol<PathBuf, String>;
|
||||
type Implementation = FileSymbol<Rc<Path>, Box<str>>;
|
||||
fn create(
|
||||
_resource: &AcmeChallengesNginxSnippet,
|
||||
target: &<AcmeChallengesNginxSnippet as Resource>::Artifact,
|
||||
challenges_dir: <Self::Prerequisites as ToArtifact>::Artifact,
|
||||
) -> Self::Implementation {
|
||||
FileSymbol::new(
|
||||
target.clone().into(),
|
||||
nginx::acme_challenges_snippet(challenges_dir),
|
||||
target.clone_rc(),
|
||||
nginx::acme_challenges_snippet(challenges_dir).into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -646,8 +652,8 @@ impl ImplementationBuilder<AcmeAccountKey> for DefaultBuilder {
|
|||
}
|
||||
|
||||
type Implementation = (
|
||||
KeySymbol<StdCommandRunner, PathBuf>,
|
||||
OwnerSymbol<StdCommandRunner, StdCommandRunner, PathBuf, String>,
|
||||
KeySymbol<StdCommandRunner, Rc<Path>>,
|
||||
OwnerSymbol<StdCommandRunner, StdCommandRunner, Rc<Path>, Rc<str>>,
|
||||
);
|
||||
fn create(
|
||||
_resource: &AcmeAccountKey,
|
||||
|
|
@ -655,8 +661,8 @@ impl ImplementationBuilder<AcmeAccountKey> for DefaultBuilder {
|
|||
user_name: <Self::Prerequisites as ToArtifact>::Artifact,
|
||||
) -> Self::Implementation {
|
||||
(
|
||||
KeySymbol::new(StdCommandRunner, target.clone().into()),
|
||||
OwnerSymbol::new(target.clone().into(), user_name.0, StdCommandRunner),
|
||||
KeySymbol::new(StdCommandRunner, target.clone_rc()),
|
||||
OwnerSymbol::new(target.clone_rc(), user_name.0, StdCommandRunner),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -665,13 +671,13 @@ impl ImplementationBuilder<AcmeRootCert> for DefaultBuilder {
|
|||
type Prerequisites = ();
|
||||
fn prerequisites(_resource: &AcmeRootCert) -> Self::Prerequisites {}
|
||||
|
||||
type Implementation = FileSymbol<PathBuf, &'static str>;
|
||||
type Implementation = FileSymbol<Rc<Path>, &'static str>;
|
||||
fn create(
|
||||
_resource: &AcmeRootCert,
|
||||
target: &<AcmeRootCert as Resource>::Artifact,
|
||||
(): <Self::Prerequisites as ToArtifact>::Artifact,
|
||||
) -> Self::Implementation {
|
||||
FileSymbol::new(target.clone().into(), LETS_ENCRYPT_R3)
|
||||
FileSymbol::new(target.clone_rc(), LETS_ENCRYPT_R3)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -679,7 +685,7 @@ impl<D> ImplementationBuilder<MariaDbUser<D>> for DefaultBuilder {
|
|||
type Prerequisites = ();
|
||||
fn prerequisites(_resource: &MariaDbUser<D>) -> Self::Prerequisites {}
|
||||
|
||||
type Implementation = MariaDbUserSymbol<'static, String, StdCommandRunner>;
|
||||
type Implementation = MariaDbUserSymbol<'static, Rc<str>, StdCommandRunner>;
|
||||
fn create(
|
||||
_resource: &MariaDbUser<D>,
|
||||
user_name: &<MariaDbUser<D> as Resource>::Artifact,
|
||||
|
|
@ -696,15 +702,15 @@ impl<D: Clone> ImplementationBuilder<MariaDbDatabase<D>> for DefaultBuilder {
|
|||
}
|
||||
|
||||
type Implementation = (
|
||||
MariaDbDatabaseSymbol<'static, String, SimpleStorage, StdCommandRunner>,
|
||||
MariaDbDumpSymbol<'static, String, StdCommandRunner, SimpleStorage>,
|
||||
MariaDbDatabaseSymbol<'static, Rc<str>, SimpleStorage, StdCommandRunner>,
|
||||
MariaDbDumpSymbol<'static, Rc<str>, StdCommandRunner, SimpleStorage>,
|
||||
);
|
||||
fn create(
|
||||
_resource: &MariaDbDatabase<D>,
|
||||
(db_name, _, data_path): &<MariaDbDatabase<D> as Resource>::Artifact,
|
||||
_: <Self::Prerequisites as ToArtifact>::Artifact,
|
||||
) -> Self::Implementation {
|
||||
let db_dump = SimpleStorage::new(data_path.clone().into());
|
||||
let db_dump = SimpleStorage::new(data_path.clone_rc());
|
||||
(
|
||||
MariaDbDatabaseSymbol::new(db_name.0.clone(), db_dump.clone(), &StdCommandRunner),
|
||||
MariaDbDumpSymbol::new(db_name.0.clone(), db_dump, &StdCommandRunner),
|
||||
|
|
@ -716,13 +722,13 @@ impl<D: Clone> ImplementationBuilder<PostgresqlDatabase<D>> for DefaultBuilder {
|
|||
type Prerequisites = ();
|
||||
fn prerequisites(_: &PostgresqlDatabase<D>) -> Self::Prerequisites {}
|
||||
|
||||
type Implementation = (PostgreSQLDatabaseSymbol<'static, String, String, StdCommandRunner>,);
|
||||
type Implementation = (PostgreSQLDatabaseSymbol<'static, Rc<str>, Rc<str>, StdCommandRunner>,);
|
||||
fn create(
|
||||
_resource: &PostgresqlDatabase<D>,
|
||||
(db_name, data_path): &<PostgresqlDatabase<D> as Resource>::Artifact,
|
||||
_: <Self::Prerequisites as ToArtifact>::Artifact,
|
||||
) -> Self::Implementation {
|
||||
let db_dump = SimpleStorage::new(data_path.clone().into());
|
||||
let db_dump = SimpleStorage::new(data_path.clone_rc());
|
||||
(PostgreSQLDatabaseSymbol::new(
|
||||
db_name.0.clone(),
|
||||
db_dump.read_filename().unwrap().to_str().unwrap().into(),
|
||||
|
|
@ -732,9 +738,9 @@ impl<D: Clone> ImplementationBuilder<PostgresqlDatabase<D>> for DefaultBuilder {
|
|||
}
|
||||
|
||||
impl<P: Clone + AsRef<Path>> ImplementationBuilder<WordpressPlugin<P>> for DefaultBuilder {
|
||||
type Prerequisites = Dir<PathBuf>;
|
||||
type Prerequisites = Dir<Rc<Path>>;
|
||||
fn prerequisites(resource: &WordpressPlugin<P>) -> Self::Prerequisites {
|
||||
Dir(resource.0.as_ref().join("wp-content/plugins"))
|
||||
Dir::new(resource.0.as_ref().join("wp-content/plugins"))
|
||||
}
|
||||
|
||||
type Implementation = WordpressPluginSymbol<'static, P, &'static str, StdCommandRunner>;
|
||||
|
|
@ -747,21 +753,21 @@ impl<P: Clone + AsRef<Path>> ImplementationBuilder<WordpressPlugin<P>> for Defau
|
|||
}
|
||||
}
|
||||
|
||||
impl<P: Clone + AsRef<Path>> ImplementationBuilder<WordpressTranslation<P>> for DefaultBuilder {
|
||||
type Prerequisites = Dir<PathBuf>;
|
||||
impl<P: AsRef<Path>> ImplementationBuilder<WordpressTranslation<P>> for DefaultBuilder {
|
||||
type Prerequisites = Dir<Rc<Path>>;
|
||||
fn prerequisites(resource: &WordpressTranslation<P>) -> Self::Prerequisites {
|
||||
Dir(resource.0.as_ref().join("wp-content/languages"))
|
||||
Dir::new(resource.0.as_ref().join("wp-content/languages"))
|
||||
}
|
||||
|
||||
type Implementation =
|
||||
WordpressTranslationSymbol<'static, &'static str, PathBuf, StdCommandRunner>;
|
||||
WordpressTranslationSymbol<'static, &'static str, Box<Path>, StdCommandRunner>;
|
||||
fn create(
|
||||
resource: &WordpressTranslation<P>,
|
||||
(): &<WordpressTranslation<P> as Resource>::Artifact,
|
||||
_: <Self::Prerequisites as ToArtifact>::Artifact,
|
||||
) -> Self::Implementation {
|
||||
WordpressTranslationSymbol::new(
|
||||
resource.0.as_ref().join("wp-content/languages"),
|
||||
(*resource.0.as_ref().join("wp-content/languages")).into(),
|
||||
resource.1,
|
||||
resource.2,
|
||||
&StdCommandRunner,
|
||||
|
|
@ -775,7 +781,7 @@ impl<D: Clone> ImplementationBuilder<Cron<D>> for DefaultBuilder {
|
|||
UserForDomain(resource.0.clone())
|
||||
}
|
||||
|
||||
type Implementation = CronSymbol<'static, String, String, StdCommandRunner>;
|
||||
type Implementation = CronSymbol<'static, Box<str>, Rc<str>, StdCommandRunner>;
|
||||
fn create(
|
||||
resource: &Cron<D>,
|
||||
(): &<Cron<D> as Resource>::Artifact,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ fn check_success(output: Output) -> Result<Output, Box<dyn Error>> {
|
|||
if output.status.success() {
|
||||
Ok(output)
|
||||
} else {
|
||||
Err(String::from_utf8(output.stderr)?.into())
|
||||
Err(std::str::from_utf8(&output.stderr)?.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ struct TempSetEnv<'a> {
|
|||
}
|
||||
|
||||
impl<'a> TempSetEnv<'a> {
|
||||
fn new(name: &'a str, new_value: String) -> TempSetEnv<'a> {
|
||||
fn new(name: &'a str, new_value: impl AsRef<OsStr>) -> TempSetEnv<'a> {
|
||||
let old_value = env::var(name);
|
||||
env::set_var(name, new_value);
|
||||
TempSetEnv {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ use crate::resources::{
|
|||
use crate::to_artifact::ToArtifact;
|
||||
use std::fmt::Display;
|
||||
use std::marker::PhantomData;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub trait Policy {
|
||||
#[must_use]
|
||||
|
|
@ -21,13 +22,13 @@ pub trait Policy {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
fn user_home(user_name: &str) -> PathBuf {
|
||||
Path::new("/home").join(user_name)
|
||||
fn user_home(user_name: &str) -> Rc<Path> {
|
||||
Path::new("/home").join(user_name).into()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
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)
|
||||
fn user_name_for_domain(domain_name: &'_ str) -> Rc<str> {
|
||||
domain_name.split('.').rev().fold(String::new(), |result, part| if result.is_empty() { result } else { result + "_" } + part).into()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
|
|
@ -36,8 +37,8 @@ pub trait Policy {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
fn path_for_data(name: impl Display) -> PathBuf {
|
||||
Path::new("/root/data").join(format!("_{name}"))
|
||||
fn path_for_data(name: impl Display) -> Rc<Path> {
|
||||
Path::new("/root/data").join(format!("_{name}")).into()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -59,37 +60,37 @@ pub struct DefaultLocator<P = DefaultPolicy> {
|
|||
}
|
||||
|
||||
impl<P, D: AsRef<str>> ResourceLocator<Key<D>> for DefaultLocator<P> {
|
||||
type Prerequisites = Dir<PathBuf>;
|
||||
type Prerequisites = Dir<Rc<Path>>;
|
||||
fn locate(resource: &Key<D>) -> (<Key<D> as Resource>::Artifact, Self::Prerequisites) {
|
||||
(
|
||||
PathArtifact::from(format!("/etc/ssl/private/{}.key", resource.0.as_ref())),
|
||||
Dir("/etc/ssl/private".into()),
|
||||
Dir::new("/etc/ssl/private"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, D: AsRef<str>> ResourceLocator<Csr<D>> for DefaultLocator<P> {
|
||||
type Prerequisites = Dir<PathBuf>;
|
||||
type Prerequisites = Dir<Rc<Path>>;
|
||||
fn locate(resource: &Csr<D>) -> (<Csr<D> as Resource>::Artifact, Self::Prerequisites) {
|
||||
(
|
||||
PathArtifact::from(format!("/etc/ssl/local_certs/{}.csr", resource.0.as_ref())),
|
||||
Dir("/etc/ssl/local_certs".into()),
|
||||
Dir::new("/etc/ssl/local_certs"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, D: AsRef<str>> ResourceLocator<Cert<D>> for DefaultLocator<P> {
|
||||
type Prerequisites = Dir<PathBuf>;
|
||||
type Prerequisites = Dir<Rc<Path>>;
|
||||
fn locate(resource: &Cert<D>) -> (<Cert<D> as Resource>::Artifact, Self::Prerequisites) {
|
||||
(
|
||||
PathArtifact::from(format!("/etc/ssl/local_certs/{}.crt", resource.0.as_ref())),
|
||||
Dir("/etc/ssl/local_certs".into()),
|
||||
Dir::new("/etc/ssl/local_certs"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, D: AsRef<str>> ResourceLocator<CertChain<D>> for DefaultLocator<P> {
|
||||
type Prerequisites = Dir<PathBuf>;
|
||||
type Prerequisites = Dir<Rc<Path>>;
|
||||
fn locate(
|
||||
resource: &CertChain<D>,
|
||||
) -> (<CertChain<D> as Resource>::Artifact, Self::Prerequisites) {
|
||||
|
|
@ -98,13 +99,13 @@ impl<P, D: AsRef<str>> ResourceLocator<CertChain<D>> for DefaultLocator<P> {
|
|||
"/etc/ssl/local_certs/{}.chained.crt",
|
||||
resource.0.as_ref()
|
||||
)),
|
||||
Dir("/etc/ssl/local_certs".into()),
|
||||
Dir::new("/etc/ssl/local_certs"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, D: AsRef<str>> ResourceLocator<KeyAndCertBundle<D>> for DefaultLocator<P> {
|
||||
type Prerequisites = Dir<PathBuf>;
|
||||
type Prerequisites = Dir<Rc<Path>>;
|
||||
fn locate(
|
||||
resource: &KeyAndCertBundle<D>,
|
||||
) -> (
|
||||
|
|
@ -116,34 +117,34 @@ impl<P, D: AsRef<str>> ResourceLocator<KeyAndCertBundle<D>> for DefaultLocator<P
|
|||
"/etc/ssl/private/{}.with_key.crt",
|
||||
resource.0.as_ref()
|
||||
)),
|
||||
Dir("/etc/ssl/private".into()),
|
||||
Dir::new("/etc/ssl/private"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<POLICY, P: AsRef<Path>> ResourceLocator<File<P>> for DefaultLocator<POLICY> {
|
||||
type Prerequisites = Dir<PathBuf>;
|
||||
type Prerequisites = Dir<Rc<Path>>;
|
||||
fn locate(resource: &File<P>) -> (<File<P> as Resource>::Artifact, Self::Prerequisites) {
|
||||
((), Dir(resource.0.as_ref().parent().unwrap().into()))
|
||||
((), Dir::new(resource.0.as_ref().parent().unwrap()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, POLICY, P: AsRef<Path>> ResourceLocator<GitCheckout<'a, P>> for DefaultLocator<POLICY> {
|
||||
type Prerequisites = Dir<PathBuf>;
|
||||
type Prerequisites = Dir<Rc<Path>>;
|
||||
fn locate(
|
||||
resource: &GitCheckout<'a, P>,
|
||||
) -> (
|
||||
<GitCheckout<'a, P> as Resource>::Artifact,
|
||||
Self::Prerequisites,
|
||||
) {
|
||||
((), Dir(resource.0.as_ref().parent().unwrap().into()))
|
||||
((), Dir::new(resource.0.as_ref().parent().unwrap()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<POLICY, P: Clone + AsRef<Path>> ResourceLocator<Dir<P>> for DefaultLocator<POLICY> {
|
||||
type Prerequisites = Option<Dir<PathBuf>>;
|
||||
type Prerequisites = Option<Dir<Rc<Path>>>;
|
||||
fn locate(resource: &Dir<P>) -> (<Dir<P> as Resource>::Artifact, Self::Prerequisites) {
|
||||
((), resource.0.as_ref().parent().map(|p| Dir(p.into())))
|
||||
((), resource.0.as_ref().parent().map(Dir::new))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -173,7 +174,7 @@ impl<POLICY: Policy, P: AsRef<Path>> ResourceLocator<StoredDirectory<P>>
|
|||
impl<POLICY: Policy, P: AsRef<Path>> ResourceLocator<LoadedDirectory<P>>
|
||||
for DefaultLocator<POLICY>
|
||||
{
|
||||
type Prerequisites = Dir<PathBuf>;
|
||||
type Prerequisites = Dir<Rc<Path>>;
|
||||
fn locate(
|
||||
resource: &LoadedDirectory<P>,
|
||||
) -> (
|
||||
|
|
@ -182,13 +183,13 @@ impl<POLICY: Policy, P: AsRef<Path>> ResourceLocator<LoadedDirectory<P>>
|
|||
) {
|
||||
(
|
||||
PathArtifact::from(POLICY::path_for_data(resource.0)),
|
||||
Dir(resource.1.as_ref().parent().unwrap().into()),
|
||||
Dir::new(resource.1.as_ref().parent().unwrap()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Policy> ResourceLocator<AcmeAccountKey> for DefaultLocator<P> {
|
||||
type Prerequisites = Dir<PathBuf>;
|
||||
type Prerequisites = Dir<Rc<Path>>;
|
||||
fn locate(
|
||||
_resource: &AcmeAccountKey,
|
||||
) -> (<AcmeAccountKey as Resource>::Artifact, Self::Prerequisites) {
|
||||
|
|
@ -207,7 +208,7 @@ impl<P: Policy> ResourceLocator<AcmeUser> for DefaultLocator<P> {
|
|||
}
|
||||
|
||||
impl<P: Policy> ResourceLocator<AcmeChallengesDir> for DefaultLocator<P> {
|
||||
type Prerequisites = Dir<PathBuf>;
|
||||
type Prerequisites = Dir<Rc<Path>>;
|
||||
fn locate(
|
||||
_resource: &AcmeChallengesDir,
|
||||
) -> (
|
||||
|
|
@ -236,7 +237,7 @@ impl<P: Policy> ResourceLocator<AcmeChallengesNginxSnippet> for DefaultLocator<P
|
|||
}
|
||||
|
||||
impl<P: Policy> ResourceLocator<AcmeRootCert> for DefaultLocator<P> {
|
||||
type Prerequisites = Dir<PathBuf>;
|
||||
type Prerequisites = Dir<Rc<Path>>;
|
||||
fn locate(
|
||||
_resource: &AcmeRootCert,
|
||||
) -> (<AcmeRootCert as Resource>::Artifact, Self::Prerequisites) {
|
||||
|
|
@ -370,7 +371,7 @@ impl<D: Clone + AsRef<str>, P: Policy> ResourceLocator<PhpFpmPool<D>> for Defaul
|
|||
php_version, user.0
|
||||
)),
|
||||
user,
|
||||
ServiceNameArtifact(format!("php{php_version}-fpm")),
|
||||
ServiceNameArtifact(format!("php{php_version}-fpm").into()),
|
||||
),
|
||||
(),
|
||||
)
|
||||
|
|
@ -380,7 +381,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>>
|
||||
for DefaultLocator<POLICY>
|
||||
{
|
||||
type Prerequisites = Dir<PathBuf>;
|
||||
type Prerequisites = Dir<Rc<Path>>;
|
||||
fn locate(
|
||||
resource: &SystemdSocketService<D, P>,
|
||||
) -> (
|
||||
|
|
@ -396,7 +397,7 @@ impl<D: Clone + AsRef<str>, P, POLICY: Policy> ResourceLocator<SystemdSocketServ
|
|||
PathArtifact::from(service_dir_path.join(format!("{}.service", resource.1))),
|
||||
user_name,
|
||||
),
|
||||
Dir(service_dir_path),
|
||||
Dir::new(service_dir_path),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use crate::artifacts::{
|
|||
};
|
||||
use crate::templates::php::FpmPoolConfig;
|
||||
use std::hash::Hash;
|
||||
use std::path::PathBuf;
|
||||
use std::path::Path;
|
||||
|
||||
pub trait Resource {
|
||||
type Artifact;
|
||||
|
|
@ -41,23 +41,41 @@ impl<D> Resource for KeyAndCertBundle<D> {
|
|||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||
pub struct File<P>(pub P, pub String);
|
||||
pub struct File<P>(pub P, pub Rc<str>);
|
||||
impl<P> Resource for File<P> {
|
||||
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)]
|
||||
pub struct GitCheckout<'a, P>(pub P, pub &'a str, pub &'a str);
|
||||
impl<'a, P> Resource for GitCheckout<'a, P> {
|
||||
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)]
|
||||
pub struct Dir<P>(pub P);
|
||||
impl<P> Resource for Dir<P> {
|
||||
type Artifact = ();
|
||||
}
|
||||
|
||||
impl Dir<Rc<Path>> {
|
||||
pub fn new(p: impl AsRef<Path>) -> Self {
|
||||
Self(p.as_ref().into())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||
pub struct UserForDomain<D>(pub D);
|
||||
impl<D> Resource for UserForDomain<D> {
|
||||
|
|
@ -106,10 +124,11 @@ impl<P> Resource for LoadedDirectory<P> {
|
|||
type Artifact = PathArtifact;
|
||||
}
|
||||
|
||||
pub fn get_saved_directory<P: Clone>(
|
||||
pub fn get_saved_directory(
|
||||
storage_name: &'static str,
|
||||
target: P,
|
||||
) -> (StoredDirectory<P>, LoadedDirectory<P>) {
|
||||
target: impl Into<Rc<Path>>,
|
||||
) -> (StoredDirectory<Rc<Path>>, LoadedDirectory<Rc<Path>>) {
|
||||
let target = target.into();
|
||||
(
|
||||
StoredDirectory(storage_name, target.clone()),
|
||||
LoadedDirectory(storage_name, target),
|
||||
|
|
@ -117,7 +136,7 @@ pub fn get_saved_directory<P: Clone>(
|
|||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||
pub struct User(pub String);
|
||||
pub struct User(pub Rc<str>);
|
||||
impl Resource for User {
|
||||
type Artifact = ();
|
||||
}
|
||||
|
|
@ -134,20 +153,32 @@ impl<P> Resource for NpmInstall<P> {
|
|||
type Artifact = ();
|
||||
}
|
||||
|
||||
impl NpmInstall<Rc<Path>> {
|
||||
pub fn new(path: impl Into<Rc<Path>>) -> Self {
|
||||
Self(path.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||
pub struct Owner<P>(pub String, pub P);
|
||||
pub struct Owner<P>(pub Rc<str>, pub P);
|
||||
impl<P> Resource for Owner<P> {
|
||||
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)]
|
||||
pub struct ServeCustom<D>(pub D, pub String);
|
||||
pub struct ServeCustom<D>(pub D, pub Rc<str>);
|
||||
impl<D> Resource for ServeCustom<D> {
|
||||
type Artifact = PathArtifact;
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||
pub struct ServePhp<D, P, C>(pub D, pub P, pub &'static str, pub String, pub C);
|
||||
pub struct ServePhp<D, P, C>(pub D, pub P, pub &'static str, pub Rc<str>, pub C);
|
||||
impl<D, P, C> Resource for ServePhp<D, P, C> {
|
||||
type Artifact = PathArtifact;
|
||||
}
|
||||
|
|
@ -158,6 +189,25 @@ 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> {
|
||||
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)]
|
||||
pub struct ServeRedir<D>(pub D, pub D);
|
||||
|
|
@ -171,6 +221,12 @@ impl<D, P> Resource for ServeStatic<D, P> {
|
|||
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)]
|
||||
pub struct DefaultServer;
|
||||
impl Resource for DefaultServer {
|
||||
|
|
@ -213,14 +269,26 @@ impl<P> Resource for WordpressPlugin<P> {
|
|||
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)]
|
||||
pub struct WordpressTranslation<P>(pub P, pub &'static str, pub &'static str);
|
||||
impl<P> Resource for WordpressTranslation<P> {
|
||||
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)]
|
||||
pub struct Cron<D>(pub D, pub String);
|
||||
pub struct Cron<D>(pub D, pub Rc<str>);
|
||||
impl<D> Resource for Cron<D> {
|
||||
type Artifact = ();
|
||||
}
|
||||
|
|
@ -287,38 +355,38 @@ default_resources!(
|
|||
Cron: Cron<D>,
|
||||
Csr: Csr<D>,
|
||||
DefaultServer: DefaultServer,
|
||||
Dir: Dir<PathBuf>,
|
||||
File: File<PathBuf>,
|
||||
GitCheckout: GitCheckout<'a, PathBuf>,
|
||||
Dir: Dir<Rc<Path>>,
|
||||
File: File<Rc<Path>>,
|
||||
GitCheckout: GitCheckout<'a, Rc<Path>>,
|
||||
Key: Key<D>,
|
||||
KeyAndCertBundle: KeyAndCertBundle<D>,
|
||||
LoadedDirectory: LoadedDirectory<PathBuf>,
|
||||
LoadedDirectory: LoadedDirectory<Rc<Path>>,
|
||||
MariaDbDatabase: MariaDbDatabase<D>,
|
||||
MariaDbUser: MariaDbUser<D>,
|
||||
PostgresqlDatabase: PostgresqlDatabase<D>,
|
||||
SystemdSocketService: SystemdSocketService<D, PathBuf>,
|
||||
NpmInstall: NpmInstall<PathBuf>,
|
||||
Owner: Owner<PathBuf>,
|
||||
SystemdSocketService: SystemdSocketService<D, Rc<Path>>,
|
||||
NpmInstall: NpmInstall<Rc<Path>>,
|
||||
Owner: Owner<Rc<Path>>,
|
||||
PhpFpmPool: PhpFpmPool<D>,
|
||||
ServeCustom: ServeCustom<D>,
|
||||
ServeService: ServeService<D, PathBuf>,
|
||||
ServePhp: ServePhp<D, PathBuf, FpmPoolConfig>,
|
||||
ServeService: ServeService<D, Rc<Path>>,
|
||||
ServePhp: ServePhp<D, Rc<Path>, FpmPoolConfig>,
|
||||
ServeRedir: ServeRedir<D>,
|
||||
ServeStatic: ServeStatic<D, PathBuf>,
|
||||
StoredDirectory: StoredDirectory<PathBuf>,
|
||||
ServeStatic: ServeStatic<D, Rc<Path>>,
|
||||
StoredDirectory: StoredDirectory<Rc<Path>>,
|
||||
User: User,
|
||||
UserForDomain: UserForDomain<D>,
|
||||
WordpressPlugin: WordpressPlugin<PathBuf>,
|
||||
WordpressTranslation: WordpressTranslation<PathBuf>,
|
||||
WordpressPlugin: WordpressPlugin<Rc<Path>>,
|
||||
WordpressTranslation: WordpressTranslation<Rc<Path>>,
|
||||
);
|
||||
|
||||
pub fn serve_php<D, P: Into<PathBuf>, C: Into<FpmPoolConfig>>(
|
||||
pub fn serve_php<D, C: Into<FpmPoolConfig>>(
|
||||
domain: D,
|
||||
path: P,
|
||||
path: impl Into<Rc<Path>>,
|
||||
root_filename: &'static str,
|
||||
nginx_config: impl Into<String>,
|
||||
nginx_config: impl Into<Rc<str>>,
|
||||
pool_config: C,
|
||||
) -> ServePhp<D, PathBuf, FpmPoolConfig> {
|
||||
) -> ServePhp<D, Rc<Path>, FpmPoolConfig> {
|
||||
ServePhp(
|
||||
domain,
|
||||
path.into(),
|
||||
|
|
|
|||
|
|
@ -1,49 +1,46 @@
|
|||
use std::error::Error;
|
||||
use std::fs::read_dir;
|
||||
use std::path::PathBuf;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
pub trait Storage {
|
||||
fn write_filename(&self) -> PathBuf;
|
||||
fn read_filename(&self) -> Result<PathBuf, Box<dyn Error>>;
|
||||
fn write_filename(&self) -> Box<Path>;
|
||||
fn read_filename(&self) -> Result<Box<Path>, Box<dyn Error>>;
|
||||
fn recent_date(&self) -> Result<u64, Box<dyn Error>>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SimpleStorage(PathBuf);
|
||||
pub struct SimpleStorage(Rc<Path>);
|
||||
|
||||
impl SimpleStorage {
|
||||
#[must_use]
|
||||
pub const fn new(base: PathBuf) -> Self {
|
||||
pub const fn new(base: Rc<Path>) -> Self {
|
||||
Self(base)
|
||||
}
|
||||
|
||||
fn get_path(&self, date: Option<u64>) -> PathBuf {
|
||||
match date {
|
||||
Some(d) => self.0.join(d.to_string()),
|
||||
None => self.0.clone(),
|
||||
}
|
||||
fn get_path(&self, date: u64) -> Box<Path> {
|
||||
self.0.join(date.to_string()).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Storage for SimpleStorage {
|
||||
fn write_filename(&self) -> PathBuf {
|
||||
self.get_path(Some(
|
||||
fn write_filename(&self) -> Box<Path> {
|
||||
self.get_path(
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs(),
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
fn read_filename(&self) -> Result<PathBuf, Box<dyn Error>> {
|
||||
Ok(self.get_path(Some(self.recent_date()?)))
|
||||
fn read_filename(&self) -> Result<Box<Path>, Box<dyn Error>> {
|
||||
Ok(self.get_path(self.recent_date()?))
|
||||
}
|
||||
|
||||
fn recent_date(&self) -> Result<u64, Box<dyn Error>> {
|
||||
let dir = self.get_path(None);
|
||||
read_dir(dir)?
|
||||
read_dir(&self.0)?
|
||||
.map(|entry| {
|
||||
entry
|
||||
.ok()
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ impl<_C: CommandRunner, C: Borrow<_C>, D: AsRef<str>, P: AsRef<Path>> Symbol for
|
|||
{
|
||||
Ok(false)
|
||||
} else {
|
||||
Err(String::from_utf8(output.stderr)?.into())
|
||||
Err(std::str::from_utf8(&output.stderr)?.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ pub struct Cron<'r, C, U, R> {
|
|||
command_runner: &'r R,
|
||||
}
|
||||
|
||||
impl<'r, U, R> Cron<'r, String, U, R> {
|
||||
impl<'r, U, R> Cron<'r, Box<str>, U, R> {
|
||||
pub fn new<C: AsRef<str>>(user: U, content: C, command_runner: &'r R) -> Self {
|
||||
Self {
|
||||
user,
|
||||
content: String::from(content.as_ref()) + "\n",
|
||||
content: (String::from(content.as_ref()) + "\n").into(),
|
||||
command_runner,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,15 +42,14 @@ impl<P: AsRef<Path>, C: CommandRunner> Symbol for GitSubmodules<'_, P, C> {
|
|||
if !self.target.as_ref().exists() {
|
||||
return Ok(false);
|
||||
}
|
||||
let output = String::from_utf8(
|
||||
self
|
||||
._run_in_target_repo(args!["submodule", "status"])
|
||||
.await?,
|
||||
)?;
|
||||
Ok(
|
||||
output
|
||||
.lines()
|
||||
.all(|line| line.is_empty() || line.starts_with(' ')),
|
||||
std::str::from_utf8(
|
||||
&self
|
||||
._run_in_target_repo(args!["submodule", "status"])
|
||||
.await?,
|
||||
)?
|
||||
.lines()
|
||||
.all(|line| line.is_empty() || line.starts_with(' ')),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ impl<T: AsRef<Path>, C: CommandRunner> Symbol for Install<'_, T, C> {
|
|||
.await?;
|
||||
Ok(
|
||||
result.status.success()
|
||||
&& !String::from_utf8(result.stdout)
|
||||
&& !std::str::from_utf8(&result.stdout)
|
||||
.unwrap()
|
||||
.contains("(empty)"),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ impl<_C: CommandRunner, C: Borrow<_C>, P: AsRef<Path>, S: Storage> Symbol
|
|||
],
|
||||
)
|
||||
.await?;
|
||||
let modified_date = u64::from_str(String::from_utf8(output)?.trim_end())?;
|
||||
let modified_date = u64::from_str(std::str::from_utf8(&output)?.trim_end())?;
|
||||
if if self.dir == StorageDirection::Store {
|
||||
modified_date > dump_date
|
||||
} else {
|
||||
|
|
@ -84,13 +84,17 @@ impl<_C: CommandRunner, C: Borrow<_C>, P: AsRef<Path>, S: Storage> Symbol
|
|||
.borrow()
|
||||
.run_with_args(
|
||||
"diff",
|
||||
args!["-rq", self.storage.read_filename()?, self.path.as_ref()],
|
||||
args![
|
||||
"-rq",
|
||||
self.storage.read_filename()?.as_os_str(),
|
||||
self.path.as_ref()
|
||||
],
|
||||
)
|
||||
.await?;
|
||||
match output.status.code() {
|
||||
Some(0) => Ok(true),
|
||||
Some(1) => Ok(false),
|
||||
_ => Err(String::from_utf8(output.stderr)?.into()),
|
||||
_ => Err(std::str::from_utf8(&output.stderr)?.into()),
|
||||
}
|
||||
} else {
|
||||
Ok(true)
|
||||
|
|
@ -109,7 +113,11 @@ impl<_C: CommandRunner, C: Borrow<_C>, P: AsRef<Path>, S: Storage> Symbol
|
|||
.borrow()
|
||||
.run_successfully(
|
||||
"cp",
|
||||
args!["-a", self.storage.read_filename()?, self.path.as_ref()],
|
||||
args![
|
||||
"-a",
|
||||
self.storage.read_filename()?.as_os_str(),
|
||||
self.path.as_ref()
|
||||
],
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
|
|
@ -118,7 +126,11 @@ impl<_C: CommandRunner, C: Borrow<_C>, P: AsRef<Path>, S: Storage> Symbol
|
|||
.borrow()
|
||||
.run_successfully(
|
||||
"cp",
|
||||
args!["-a", self.path.as_ref(), self.storage.write_filename()],
|
||||
args![
|
||||
"-a",
|
||||
self.path.as_ref(),
|
||||
self.storage.write_filename().as_os_str()
|
||||
],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@ impl<S: AsRef<Path>, U: AsRef<str>> UserService<'_, S, U> {
|
|||
loop {
|
||||
let result = self.command_runner.run_with_args("systemctl", args).await?;
|
||||
if result.status.success() {
|
||||
return Ok(String::from_utf8(result.stdout)?.trim_end().to_string());
|
||||
return Ok(std::str::from_utf8(&result.stdout)?.trim_end().to_string());
|
||||
}
|
||||
let raw_stderr = String::from_utf8(result.stderr)?;
|
||||
let raw_stderr = std::str::from_utf8(&result.stderr)?;
|
||||
let stderr = raw_stderr.trim_end();
|
||||
if stderr != "Failed to connect to bus: No such file or directory" {
|
||||
return Err(stderr.into());
|
||||
|
|
@ -61,8 +61,8 @@ impl<S: AsRef<Path>, U: AsRef<str>> UserService<'_, S, U> {
|
|||
"ActiveState=active" => return Ok(true),
|
||||
"ActiveState=failed" => {
|
||||
return Err(
|
||||
String::from_utf8(
|
||||
self
|
||||
std::str::from_utf8(
|
||||
&self
|
||||
.command_runner
|
||||
.get_output(
|
||||
"journalctl",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use std::error::Error;
|
|||
use std::fs::File as FsFile;
|
||||
use std::io;
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Plugin<'a, P, N, R> {
|
||||
|
|
@ -24,12 +24,13 @@ impl<'a, P: AsRef<Path>, N: AsRef<str>, R> Plugin<'a, P, N, R> {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_path(&self) -> PathBuf {
|
||||
fn get_path(&self) -> Box<Path> {
|
||||
self
|
||||
.base
|
||||
.as_ref()
|
||||
.join("wp-content/plugins")
|
||||
.join(self.name.as_ref())
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -41,8 +42,8 @@ impl<P: AsRef<Path>, N: AsRef<str>, R: CommandRunner> Symbol for Plugin<'_, P, N
|
|||
return Ok(false);
|
||||
}
|
||||
let path = base_path.join(self.name.as_ref().to_owned() + ".php");
|
||||
let mut version = String::new();
|
||||
let mut plugin_uri = String::new();
|
||||
let mut version: Option<Box<str>> = None;
|
||||
let mut plugin_uri: Option<Box<str>> = None;
|
||||
match FsFile::open(path) {
|
||||
Err(e) => {
|
||||
// Check if file exists
|
||||
|
|
@ -56,11 +57,12 @@ impl<P: AsRef<Path>, N: AsRef<str>, R: CommandRunner> Symbol for Plugin<'_, P, N
|
|||
let reader = BufReader::new(file);
|
||||
let regex = Regex::new("(?m)^(Plugin URI|Version): (.+)$")?;
|
||||
for content in reader.lines() {
|
||||
for matches in regex.captures_iter(&(content?)) {
|
||||
let content = content?;
|
||||
for matches in regex.captures_iter(&content) {
|
||||
if &matches[1] == "Plugin URI" {
|
||||
plugin_uri = matches[2].to_string();
|
||||
plugin_uri = Some(matches[2].into());
|
||||
} else {
|
||||
version = matches[2].to_string();
|
||||
version = Some(matches[2].into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -75,14 +77,14 @@ impl<P: AsRef<Path>, N: AsRef<str>, R: CommandRunner> Symbol for Plugin<'_, P, N
|
|||
format!(
|
||||
r###"plugins={{"plugins":{{"{0}/{0}.php":{{"Version":"{1}", "PluginURI":"{2}"}}}}}}"###,
|
||||
self.name.as_ref(),
|
||||
version,
|
||||
plugin_uri
|
||||
version.as_deref().unwrap_or_default(),
|
||||
plugin_uri.as_deref().unwrap_or_default()
|
||||
),
|
||||
"https://api.wordpress.org/plugins/update-check/1.1/",
|
||||
],
|
||||
)
|
||||
.await?;
|
||||
Ok(String::from_utf8(upstream)?.contains(r###""plugins":[]"###))
|
||||
Ok(std::str::from_utf8(&upstream)?.contains(r###""plugins":[]"###))
|
||||
}
|
||||
|
||||
async fn execute(&self) -> Result<(), Box<dyn Error>> {
|
||||
|
|
@ -97,7 +99,7 @@ impl<P: AsRef<Path>, N: AsRef<str>, R: CommandRunner> Symbol for Plugin<'_, P, N
|
|||
.await?;
|
||||
self
|
||||
.command_runner
|
||||
.run_successfully("rm", args!["-rf", self.get_path()])
|
||||
.run_successfully("rm", args!["-rf", self.get_path().as_os_str()])
|
||||
.await?;
|
||||
self
|
||||
.command_runner
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use std::fs::File as FsFile;
|
|||
use std::io;
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Translation<'a, C, D, R> {
|
||||
|
|
@ -30,7 +29,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> {
|
||||
fn get_pairs(&self) -> Vec<(String, PathBuf)> {
|
||||
fn get_pairs(&self) -> impl Iterator<Item = (Box<str>, Box<Path>)> + '_ {
|
||||
let version_x = self
|
||||
.version
|
||||
.trim_end_matches(|c: char| c.is_ascii_digit())
|
||||
|
|
@ -42,21 +41,19 @@ impl<C: AsRef<str>, D: AsRef<Path>, R: CommandRunner> Translation<'_, C, D, R> {
|
|||
} else {
|
||||
locale.to_lowercase().replace('_', "-")
|
||||
};
|
||||
let mut res = vec![];
|
||||
for &(in_slug, out_slug) in &[
|
||||
[
|
||||
("", ""),
|
||||
("cc/", "continents-cities-"),
|
||||
("admin/", "admin-"),
|
||||
("admin/network/", "admin-network-"),
|
||||
] {
|
||||
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}"),
|
||||
[self.path.as_ref(), format!("{}{}.{}", out_slug, self.locale.as_ref(), format).as_ref()].iter().collect()
|
||||
));
|
||||
].into_iter().flat_map(move |(in_slug, out_slug)|{
|
||||
["po", "mo"].map(|format|
|
||||
(
|
||||
format!("https://translate.wordpress.org/projects/wp/{version_x}/{in_slug}{path_locale}/default/export-translations?format={format}").into(),
|
||||
self.path.as_ref().join(format!("{}{}.{}", out_slug, self.locale.as_ref(), format)).into()
|
||||
))
|
||||
}
|
||||
}
|
||||
res
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +77,7 @@ impl<C: AsRef<str>, D: AsRef<Path>, R: CommandRunner> Symbol for Translation<'_,
|
|||
let reader = BufReader::new(file);
|
||||
for content in reader.lines() {
|
||||
if let Some(match_result) = match_date.captures(&content?) {
|
||||
newest = max(newest, match_result[1].to_string());
|
||||
newest = max(newest, match_result[1].into());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -99,7 +96,7 @@ impl<C: AsRef<str>, D: AsRef<Path>, R: CommandRunner> Symbol for Translation<'_,
|
|||
)],
|
||||
)
|
||||
.await?;
|
||||
Ok(String::from_utf8(upstream)?.contains(&format!(
|
||||
Ok(std::str::from_utf8(&upstream)?.contains(&format!(
|
||||
r###"language":"{}","version":"{}","updated":"{}"###,
|
||||
self.locale.as_ref(),
|
||||
self.version,
|
||||
|
|
@ -111,7 +108,10 @@ impl<C: AsRef<str>, D: AsRef<Path>, R: CommandRunner> Symbol for Translation<'_,
|
|||
for (source, target) in self.get_pairs() {
|
||||
self
|
||||
.command_runner
|
||||
.run_successfully("curl", args!["--compressed", "-o", target, source,])
|
||||
.run_successfully(
|
||||
"curl",
|
||||
args!["--compressed", "-o", target.as_os_str(), source.as_ref(),],
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::path::Path;
|
|||
#[derive(Clone, Debug, PartialEq, Hash, Eq)]
|
||||
pub struct FpmPoolConfig {
|
||||
max_children: NonZeroUsize,
|
||||
custom: Option<String>,
|
||||
custom: Option<Box<str>>,
|
||||
}
|
||||
|
||||
impl Display for FpmPoolConfig {
|
||||
|
|
@ -27,7 +27,7 @@ impl From<usize> for FpmPoolConfig {
|
|||
}
|
||||
|
||||
impl FpmPoolConfig {
|
||||
pub fn new(max_children: NonZeroUsize, custom: impl Into<String>) -> Self {
|
||||
pub fn new(max_children: NonZeroUsize, custom: impl Into<Box<str>>) -> Self {
|
||||
Self {
|
||||
max_children,
|
||||
custom: Some(custom.into()),
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use schematics::symbols::file::File as FileSymbol;
|
|||
use schematics::symbols::Symbol;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::Path;
|
||||
use tempfile::{tempdir, TempDir};
|
||||
|
||||
fn get_dir(content: Option<&str>) -> TempDir {
|
||||
|
|
@ -19,8 +19,8 @@ fn get_dir(content: Option<&str>) -> TempDir {
|
|||
tmp_dir
|
||||
}
|
||||
|
||||
fn get_symbol(path: &Path) -> FileSymbol<PathBuf, &str> {
|
||||
FileSymbol::new(path.join("filename"), "target content")
|
||||
fn get_symbol(path: &Path) -> FileSymbol<Box<Path>, &str> {
|
||||
FileSymbol::new(path.join("filename").into(), "target content")
|
||||
}
|
||||
|
||||
// Normal cases
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use schematics::SymbolRunner;
|
|||
use slog::{info, Logger as SlogLogger};
|
||||
use std::error::Error;
|
||||
use std::fmt::Debug;
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -60,7 +61,7 @@ fn test(
|
|||
#[test]
|
||||
fn can_create_an_acme_user() {
|
||||
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
|
||||
.pop()
|
||||
|
|
@ -133,8 +134,8 @@ fn can_create_an_acme_cert() {
|
|||
#[test]
|
||||
fn can_create_a_git_checkout() {
|
||||
let mut result = test(1, |setup| {
|
||||
run(setup.add(GitCheckout(
|
||||
"/tmp/somepath".into(),
|
||||
run(setup.add(GitCheckout::new(
|
||||
"/tmp/somepath".as_ref() as &Path,
|
||||
"/tmp/some_src_repo",
|
||||
"master",
|
||||
)))
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ fn get_dir<'a, I: IntoIterator<Item = &'a &'a str>>(content: I) -> TempDir {
|
|||
}
|
||||
|
||||
fn get_storage(path: &Path) -> SimpleStorage {
|
||||
SimpleStorage::new(path.join("_filename"))
|
||||
SimpleStorage::new(path.join("_filename").into())
|
||||
}
|
||||
|
||||
// Normal cases
|
||||
|
|
@ -33,7 +33,7 @@ fn single_file() {
|
|||
);
|
||||
assert_eq!(
|
||||
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);
|
||||
}
|
||||
|
|
@ -50,7 +50,7 @@ fn two_files() {
|
|||
);
|
||||
assert_eq!(
|
||||
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);
|
||||
}
|
||||
|
|
@ -67,7 +67,7 @@ fn another_two_files() {
|
|||
);
|
||||
assert_eq!(
|
||||
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);
|
||||
}
|
||||
|
|
@ -84,7 +84,7 @@ fn three_files() {
|
|||
);
|
||||
assert_eq!(
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue