use crate::errors::Error;
use crate::helpers::*;
use crate::types::*;
use log::{debug, info, warn};
use rayon::prelude::*;
use std::path::Path;
impl TmplBuilder {
pub fn new(pkg_name: &str) -> Self {
Self {
pkg_name: pkg_name.to_owned(),
pkg_type: None,
pkg_info: None,
}
}
pub fn from_pkg_info(pkg_info: PkgInfo) -> Self {
Self {
pkg_name: pkg_info.pkg_name.clone(),
pkg_type: None,
pkg_info: Some(pkg_info),
}
}
pub fn get_type(&mut self) -> Result<&mut Self, Error> {
self.pkg_type = Some(figure_out_provider(&self.pkg_name)?);
Ok(self)
}
pub fn set_type(&mut self, pkg_type: PkgType) -> &mut Self {
self.pkg_type = Some(pkg_type);
self
}
pub fn get_info(&mut self) -> Result<&mut Self, Error> {
if self.pkg_type.is_some() {
self.pkg_info = Some(get_pkginfo(&self.pkg_name, self.pkg_type.unwrap())?);
Ok(self)
} else {
Err(Error::TooLittleInfo(
"Can't get PkgInfo without setting/getting PkgType first!".to_string(),
))
}
}
pub fn set_info(&mut self, pkg_info: PkgInfo) -> &mut Self {
self.pkg_info = Some(pkg_info);
self
}
pub fn is_built_in(&self) -> Result<bool, Error> {
if self.pkg_type.is_some() {
let data: TomlData = toml::from_str(include_str!("data.toml")).unwrap();
let built_ins = BuiltInDeps {
perl: data.builtin.perl,
ruby: data.builtin.ruby,
};
if self.pkg_type.unwrap() == PkgType::Gem {
for x in built_ins.ruby {
if self.pkg_name == x {
info!(
"Gem {} is part of ruby, won't write a template for it!",
self.pkg_name
);
return Ok(true);
}
}
} else if self.pkg_type.unwrap() == PkgType::PerlDist {
let pkg_name = self.pkg_name.replace("::", "-");
for x in built_ins.perl {
if pkg_name == x {
info!(
"Perl distribution {} is part of perl, won't write a template for it!",
pkg_name
);
return Ok(true);
}
}
}
Ok(false)
} else {
Err(Error::TooLittleInfo(
"Can't check if Pkg is built in without setting/getting PkgType first!".to_string(),
))
}
}
pub fn gen_deps(&self, tmpl_path: Option<&str>) -> Result<Vec<Template>, Error> {
if self.pkg_info.is_some() {
let deps = self
.pkg_info
.as_ref()
.unwrap()
.dependencies
.as_ref()
.unwrap();
let mut run_vec = if let Some(run_deps) = &deps.run {
run_deps
.par_iter()
.filter(|x| x == &&"perl".to_string() || x == &&"ruby".to_string())
.collect::<Vec<&String>>()
} else {
Vec::new()
};
let mut make_vec = if let Some(make_deps) = &deps.make {
make_deps
.par_iter()
.filter(|x| x == &&"perl".to_string() || x == &&"ruby".to_string())
.collect::<Vec<&String>>()
} else {
Vec::new()
};
run_vec.append(&mut make_vec);
let mut tmpl_vec = Vec::new();
for x in run_vec {
let pkg_tainted = x.split('>').collect::<Vec<&str>>()[0]
.split('<')
.collect::<Vec<&str>>()[0];
let pkg = pkg_tainted.replace("perl-", "").replace("ruby-", "");
let mut tmpl_builder = Self::new(&pkg);
if tmpl_builder
.set_type(self.pkg_type.unwrap())
.is_built_in()?
{
debug!("Won't write template for built-in package {}", pkg);
continue;
} else if tmpl_path.is_some() {
let tmpl_path_exists = if self.pkg_type.unwrap() == PkgType::Gem {
Path::new(&format!(
"{}/ruby-{}/template",
tmpl_path.unwrap_or_default(),
pkg
))
.exists()
} else {
Path::new(&format!(
"{}/perl-{}/template",
tmpl_path.unwrap_or_default(),
pkg.replace("::", "-")
))
.exists()
};
if tmpl_path_exists {
continue;
}
}
tmpl_vec.push(tmpl_builder.get_info()?.generate(true)?);
tmpl_vec.append(
&mut Self::new(&pkg)
.set_type(self.pkg_type.unwrap())
.get_info()?
.gen_deps(tmpl_path)?,
)
}
Ok(tmpl_vec)
} else {
Err(Error::TooLittleInfo(
"Can't create Templates for deps without setting/getting PkgInfo of the package first!".to_string(),
))
}
}
pub fn update(&self, old_template: &Template, update_all: bool) -> Result<Template, Error> {
let pkg_info = if self.pkg_info.is_some() {
Ok(self.pkg_info.as_ref().unwrap())
} else {
Err(Error::TooLittleInfo(
"Can't update template without setting PkgInfo first!".to_string(),
))
}?;
info!("Updating template {}", &pkg_info.pkg_name);
let mut template_string = old_template.inner.clone();
let mut orig_vec = vec![
"version=",
"checksum=",
"distfiles=",
"homepage=",
"short_desc=",
"revision=",
]
.par_iter()
.map(|search_str| {
template_string
.lines()
.filter(|x| x.contains(search_str))
.map(|x| x)
.collect::<String>()
})
.collect::<Vec<String>>();
let orig_revision_string = orig_vec.pop().unwrap_or_else(|| "".to_string());
let orig_description_string = orig_vec.pop().unwrap_or_else(|| "".to_string());
let orig_homepage_string = orig_vec.pop().unwrap_or_else(|| "".to_string());
let orig_distfiles_string = orig_vec.pop().unwrap_or_else(|| "".to_string());
let orig_checksum_string = orig_vec.pop().unwrap_or_else(|| "".to_string());
let orig_ver_string = orig_vec.pop().unwrap_or_else(|| "".to_string());
if !(orig_ver_string == format!("version={}", &pkg_info.version)) {
template_string = template_string.replace(&orig_revision_string, "revision=1");
}
template_string =
template_string.replace(&orig_ver_string, &format!("version={}", &pkg_info.version));
if update_all {
template_string = template_string.replace(
&orig_checksum_string,
&format!("checksum={}", &pkg_info.sha),
);
if orig_homepage_string.is_empty() {
warn!("Couldn't find 'homepage' string and as such won't update it!");
} else {
template_string = template_string.replace(
&orig_homepage_string,
&format!("homepage=\"{}\"", &pkg_info.homepage),
);
}
if orig_distfiles_string.is_empty() {
warn!("Couldn't find 'distfiles' string and as such won't update it!");
} else {
template_string = template_string.replace(
&orig_distfiles_string,
&format!(
"distfiles=\"{}",
format!(
"{}\"",
&pkg_info
.download_url
.as_ref()
.unwrap_or(&orig_distfiles_string.replace("distfiles=\"", ""))
)
),
);
}
if orig_description_string.is_empty() {
warn!("Couldn't find 'description' string and as such won't update it!");
} else if pkg_info.description.is_some() {
template_string = template_string.replace(
&orig_description_string,
&format!("short_desc=\"{}\"", pkg_info.description.as_ref().unwrap()),
);
} else {
warn!("Couldn't determine field 'description'! Won't update it.",);
}
} else {
let tmpl_download_url = &orig_distfiles_string
.replace("distfiles=", "")
.replace("\"", "");
if pkg_info.download_url.as_ref().unwrap_or(&"".to_string()) == tmpl_download_url {
template_string = template_string.replace(
&orig_checksum_string,
&format!("checksum={}", &pkg_info.sha),
);
} else {
template_string = template_string.replace(
&orig_checksum_string,
&format!(
"checksum={}",
gen_checksum(&tmpl_download_url.replace("${version}", &pkg_info.version))?
),
);
};
}
Ok(Template {
inner: template_string.to_owned(),
name: pkg_info.pkg_name.clone(),
})
}
pub fn generate(&self, prefix: bool) -> Result<Template, Error> {
let pkg_info = if self.pkg_info.is_some() {
Ok(self.pkg_info.as_ref().unwrap())
} else {
Err(Error::TooLittleInfo(
"Can't write a new template without setting PkgInfo first!".to_string(),
))
}?;
let tmpl_type = self.pkg_type.unwrap();
let template_in = include_str!("template.in");
let maintainer = get_git_author()?;
let mut template_string = template_in
.replace("@version@", &pkg_info.version)
.replace("@maintainer@", &maintainer)
.replace("@pkgname@", &pkg_info.pkg_name)
.replace("@checksum@", &pkg_info.sha)
.replace("@homepage@", &pkg_info.homepage);
if pkg_info.description.is_some() {
let mut description = check_string_len(
&pkg_info.pkg_name,
&pkg_info.description.as_ref().unwrap(),
"description",
);
if description.chars().last().unwrap_or_default() == '.' {
description.pop();
}
template_string = template_string.replace("@description@", &description)
} else {
warn!(
"Couldn't determine field 'description'! Please add it to the template yourself.",
);
}
if pkg_info.license.is_some() {
let license_iter = pkg_info.license.as_ref().unwrap().par_iter();
let mut license = license_iter
.clone()
.take(1)
.map(|x| correct_license(x))
.collect::<String>();
license.push_str(
&license_iter
.skip(1)
.map(|x| format!(", {}", correct_license(x)))
.collect::<String>(),
);
template_string = template_string.replace("@license@", &license)
} else {
warn!("Couldn't determine field 'license'! Please add it to the template yourself.",);
}
if pkg_info.dependencies.is_some() {
let dependencies = pkg_info.dependencies.as_ref().unwrap();
if dependencies.host.is_some() {
let host_depends = gen_dep_string(dependencies.host.as_ref().unwrap(), tmpl_type);
template_string =
template_string.replace("@hostmakedepends@", &host_depends.trim_end());
} else {
template_string =
template_string.replace("\nhostmakedepends=\"@hostmakedepends@\"", "");
}
if dependencies.make.is_some() {
let make_depends = gen_dep_string(dependencies.make.as_ref().unwrap(), tmpl_type);
template_string =
template_string.replace("@makedepends@", &make_depends.trim_end());
} else {
template_string = template_string.replace("\nmakedepends=\"@makedepends@\"", "");
}
if dependencies.run.is_some() {
let run_depends = gen_dep_string(dependencies.run.as_ref().unwrap(), tmpl_type);
template_string = template_string.replace("@depends@", &run_depends.trim_end());
} else {
template_string = template_string.replace("\ndepends=\"@depends@\"", "");
}
} else {
template_string = template_string.replace("\ndepends=\"@depends@\"", "");
template_string = template_string.replace("\nmakedepends=\"@makedepends@\"", "");
template_string =
template_string.replace("\nhostmakedepends=\"@hostmakedepends@\"", "");
}
if pkg_info.download_url.is_some() {
template_string =
template_string.replace("@distfiles@", &pkg_info.download_url.as_ref().unwrap());
} else {
template_string = template_string.replace("\ndistfiles=\"@distfiles@\"", "")
}
if tmpl_type == PkgType::PerlDist {
template_string = template_string
.replace("@build_style@", "perl-module")
.replace("@archs@", "noarch");
} else if tmpl_type == PkgType::Gem {
template_string = template_string
.replace("@build_style@", "gem")
.replace("\nwrksrc=\"@wrksrc@\"", "")
.replace("\narchs=@archs@", "");
} else {
template_string = template_string
.replace("@pkgname@", &pkg_info.pkg_name)
.replace("\ndepends=\"@depends@\"", "")
.replace("@build_style@", "cargo")
.replace("\narchs=@archs@", "");
}
if prefix {
let prefix_str = if tmpl_type == PkgType::Crate {
"rust-"
} else {
"perl-"
};
let wrksrc = format!("${{pkgname/{}/}}-${{version}}", prefix_str);
template_string = template_string.replace("@wrksrc@", &wrksrc);
} else {
template_string = template_string.replace("\nwrksrc=\"@wrksrc@\"", "");
}
let license = &pkg_info.license.as_ref().unwrap_or(&Vec::new()).join(", ");
if license.contains(&"MIT".to_string())
|| license.contains(&"ISC".to_string())
|| license.contains(&"BSD".to_string())
{
template_string.push_str("\n\npost_install() {\n\tvlicense LICENSE\n}");
}
template_string.push_str("\n");
Ok(Template {
inner: template_string,
name: pkg_info.pkg_name.clone(),
})
}
}