use crate::Error;
use breezyshim::branch::Branch;
use breezyshim::workingtree::PyWorkingTree;
use debian_analyzer::debhelper::maximum_debhelper_compat_version;
use debian_analyzer::editor::{Editor, TreeEditor};
use debian_analyzer::lintian::latest_standards_version;
use debian_analyzer::relations::{ensure_exact_version, ensure_relation, ensure_some_version};
use debian_control::fields::MultiArch;
use debian_control::lossless::relations::Relations;
use debian_control::lossless::{Control, Source};
use debversion::Version;
use ognibuild::buildsystem::BuildSystem;
use ognibuild::debian::upstream_deps::get_project_wide_deps;
use ognibuild::session::Session;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use upstream_ontologist::UpstreamMetadata;
struct ProcessorContext<'a> {
session: &'a dyn Session,
wt: &'a dyn PyWorkingTree,
subpath: PathBuf,
debian_path: PathBuf,
upstream_version: String,
metadata: &'a UpstreamMetadata,
compat_release: String,
buildsystem: Box<dyn BuildSystem>,
_buildsystem_subpath: PathBuf,
maintainer: Option<String>,
_kickstart_from_dist: Option<Box<dyn FnOnce(&dyn PyWorkingTree, &Path) -> Result<(), Error>>>,
}
impl<'a> ProcessorContext<'a> {
fn kickstart_tree(&mut self, sourceful: bool) -> Result<(), Error> {
if sourceful {
if let Some(kickstart_fn) = self._kickstart_from_dist.take() {
kickstart_fn(self.wt, &self.subpath)?;
} else {
log::debug!("No kickstart_from_dist function provided, skipping dist import");
}
} else {
self.wt
.branch()
.generate_revision_history(&breezyshim::RevisionId::null())
.unwrap();
if !self.wt.has_filename(&self.subpath) {
self.wt.mkdir(&self.subpath)?;
}
if !self.wt.is_versioned(&self.subpath) {
self.wt.add(&[&self.subpath])?;
}
}
Ok(())
}
fn create_control_file(&self) -> Result<TreeEditor<'_, Control>, Error> {
Ok(TreeEditor::<Control>::new(
self.wt,
&self.debian_path.join("control"),
false,
true,
)?)
}
fn bootstrap_debhelper(
&self,
source: &mut Source,
config: DebhelperConfig,
) -> Result<(), Error> {
bootstrap_debhelper(
self.wt,
&self.debian_path,
source,
&self.compat_release,
config,
)
}
fn get_project_wide_deps(&self) -> (Relations, Relations) {
let (build_deps, test_deps) =
get_project_wide_deps(self.session, self.buildsystem.as_ref());
let mut build_ret = Relations::new();
for dep in build_deps {
let rs: Relations = dep.into();
for rel in rs.entries() {
ensure_relation(&mut build_ret, rel);
}
}
let mut test_ret = Relations::new();
for dep in test_deps {
let rs: Relations = dep.into();
for rel in rs.entries() {
ensure_relation(&mut test_ret, rel);
}
}
(build_ret, test_ret)
}
}
fn enable_dh_addon(source: &mut Source, addon: &str) {
let mut build_depends = source.build_depends().unwrap_or_default();
ensure_some_version(&mut build_depends, &format!("dh-sequence-{}", addon));
source.set_build_depends(&build_depends);
}
fn import_build_deps(source: &mut Source, new_build_deps: &Relations) {
let mut build_depends = source.build_depends().unwrap_or_default();
for build_dep in new_build_deps.entries() {
for rel in build_dep.relations() {
ensure_relation(&mut build_depends, rel.into());
}
}
source.set_build_depends(&build_depends);
}
fn debhelper_rules<F: std::io::Write>(
f: &mut F,
buildsystem: Option<&str>,
build_directory: Option<&str>,
env: HashMap<&str, &str>,
) -> std::io::Result<()> {
f.write_all(b"#!/usr/bin/make -f\n")?;
f.write_all(b"%:\n")?;
f.write_all(b"\tdh $@")?;
if let Some(buildsystem) = buildsystem {
f.write_all(format!(" --buildsystem={}", buildsystem).as_bytes())?;
}
if let Some(build_directory) = build_directory {
f.write_all(format!(" --builddirectory={}", build_directory).as_bytes())?;
}
f.write_all(b"\n")?;
for (key, value) in env {
f.write_all(format!("export {}={}\n", key, value).as_bytes())?;
}
Ok(())
}
#[derive(Debug, Default)]
struct DebhelperConfig<'a> {
addons: Vec<&'a str>,
env: HashMap<&'a str, &'a str>,
buildsystem: Option<&'a str>,
build_directory: Option<&'a str>,
}
fn bootstrap_debhelper(
wt: &dyn PyWorkingTree,
debian_path: &Path,
source: &mut Source,
compat_release: &str,
config: DebhelperConfig,
) -> Result<(), Error> {
let mut build_depends = source.build_depends().unwrap_or_default();
ensure_exact_version(
&mut build_depends,
"debhelper-compat",
&maximum_debhelper_compat_version(compat_release)
.to_string()
.parse::<Version>()
.unwrap(),
None,
);
source.set_build_depends(&build_depends);
for addon in config.addons.iter() {
enable_dh_addon(source, addon);
}
let mut f = Vec::new();
debhelper_rules(
&mut f,
config.buildsystem,
config.build_directory,
config.env,
)?;
wt.put_file_bytes_non_atomic(&debian_path.join("rules"), &f)?;
Ok(())
}
fn process_setup_py(context: &mut ProcessorContext) -> Result<(), Error> {
context.kickstart_tree(true)?;
let mut control = context.create_control_file()?;
let upstream_name = match context.metadata.name() {
Some(name) => name,
None => {
return Err(Error::MissingUpstreamInfo(
"unable to determine name from setup.py for the python3 project".to_string(),
))
}
};
let source_name = crate::names::python_source_package_name(upstream_name);
let mut source = control.add_source(&source_name);
if let Some(ref maintainer) = context.maintainer {
source.set_maintainer(maintainer);
}
source.set_rules_requires_root(false);
source.set_standards_version(&latest_standards_version().to_string());
context.bootstrap_debhelper(
&mut source,
DebhelperConfig {
buildsystem: Some("pybuild"),
addons: vec!["python3"],
..Default::default()
},
)?;
source.set_testsuite("autopkgtest-pkg-python");
let python3_support = check_python3_support(context.wt, &context.subpath)?;
if !python3_support {
log::warn!("Project may not support Python 3, but proceeding with Python 3 packaging");
}
let mut build_depends = source.build_depends().unwrap_or_default();
ensure_relation(&mut build_depends, "python3-all".parse().unwrap());
ensure_relation(&mut build_depends, "python3-setuptools".parse().unwrap());
source.set_build_depends(&build_depends);
let (build_deps, test_deps) = context.get_project_wide_deps();
import_build_deps(&mut source, &build_deps);
import_build_deps(&mut source, &test_deps);
let binary_name = crate::names::python_binary_package_name(upstream_name);
let mut binary = control.add_binary(&binary_name);
binary.set_architecture(Some("all"));
binary
.as_mut_deb822()
.insert("Depends", "${python3:Depends}");
control.commit()?;
Ok(())
}
fn process_maven(context: &mut ProcessorContext) -> Result<(), Error> {
context.kickstart_tree(true)?;
let mut control = context.create_control_file()?;
let upstream_name = match context.metadata.name() {
Some(name) => name,
None => {
return Err(Error::MissingUpstreamInfo(
"unable to determine the artifactId from pom.xml for the java project".to_string(),
))
}
};
let mut source = control.add_source(upstream_name);
source.set_rules_requires_root(false);
source.set_standards_version(&latest_standards_version().to_string());
context.bootstrap_debhelper(
&mut source,
DebhelperConfig {
buildsystem: Some("maven"),
..Default::default()
},
)?;
let (build_deps, _test_deps) = context.get_project_wide_deps();
import_build_deps(&mut source, &build_deps);
let mut binary = control.add_binary(&format!("lib{}-java", upstream_name));
binary.set_architecture(Some("all"));
binary.set_depends(Some(&"${java:Depends}".parse().unwrap()));
control.commit()?;
Ok(())
}
fn process_npm(context: &mut ProcessorContext) -> Result<(), Error> {
context.kickstart_tree(true)?;
let mut control = context.create_control_file()?;
let upstream_name = match context.metadata.name() {
Some(name) => name
.trim_end_matches("@")
.replace(['/', '_'], "-")
.replace("@", "")
.to_lowercase(),
None => {
return Err(Error::MissingUpstreamInfo(
"unable to determine the name from package.json for the node project".to_string(),
))
}
};
let mut source = control.add_source(&format!("node-{}", upstream_name));
if let Some(ref maintainer) = context.maintainer {
source.set_maintainer(maintainer);
}
context.bootstrap_debhelper(
&mut source,
DebhelperConfig {
addons: vec!["nodejs"],
..Default::default()
},
)?;
source.set_rules_requires_root(false);
source.set_standards_version(&latest_standards_version().to_string());
let (build_deps, _test_deps) = context.get_project_wide_deps();
import_build_deps(&mut source, &build_deps);
let mut binary = control.add_binary(&format!("node-{}", upstream_name));
binary.set_architecture(Some("all"));
source.set_testsuite("autopkgtest-pkg-nodejs");
control.commit()?;
Ok(())
}
fn process_dist_zilla(context: &mut ProcessorContext) -> Result<(), Error> {
context.kickstart_tree(true)?;
let mut control = context.create_control_file()?;
let upstream_name = match context.metadata.name() {
Some(name) => name,
None => {
return Err(Error::MissingUpstreamInfo(
"unable to determine the name in dist.ini for the perl project".to_string(),
))
}
};
let mut source = control.add_source(&crate::names::perl_package_name(upstream_name));
if let Some(ref maintainer) = context.maintainer {
source.set_maintainer(maintainer);
}
source.set_rules_requires_root(false);
source.set_testsuite("autopkgtest-pkg-perl");
source.set_standards_version(&latest_standards_version().to_string());
let (build_deps, _test_deps) = context.get_project_wide_deps();
import_build_deps(&mut source, &build_deps);
context.bootstrap_debhelper(
&mut source,
DebhelperConfig {
addons: vec!["dist-zilla"],
..Default::default()
},
)?;
let binary_name = source.name().unwrap();
let mut binary = control.add_binary(&binary_name);
binary.set_architecture(Some("all"));
binary.set_depends(Some(&"${perl:Depends}".parse().unwrap()));
control.commit()?;
Ok(())
}
fn process_perl_build_tiny(context: &mut ProcessorContext) -> Result<(), Error> {
context.kickstart_tree(true)?;
let mut control = context.create_control_file()?;
let upstream_name = match context.metadata.name() {
Some(name) => name,
None => {
return Err(Error::MissingUpstreamInfo(
"unable to determine the name in dist.ini for the perl project".to_string(),
))
}
};
let mut source = control.add_source(&crate::names::perl_package_name(upstream_name));
if let Some(ref maintainer) = context.maintainer {
source.set_maintainer(maintainer);
}
source.set_rules_requires_root(false);
source.set_testsuite("autopkgtest-pkg-perl");
source.set_standards_version(&latest_standards_version().to_string());
source.set_build_depends(&"libmodule-build-perl".parse().unwrap());
let (build_deps, _test_deps) = context.get_project_wide_deps();
import_build_deps(&mut source, &build_deps);
context.bootstrap_debhelper(&mut source, DebhelperConfig::default())?;
let binary_name = source.name().unwrap();
let mut binary = control.add_binary(&binary_name);
binary.set_architecture(Some("all"));
binary.set_depends(Some(&"${perl:Depends}".parse().unwrap()));
control.commit()?;
Ok(())
}
fn process_golang(context: &mut ProcessorContext) -> Result<(), Error> {
context.kickstart_tree(true)?;
let mut control = context.create_control_file()?;
let repository_url = match context.metadata.repository() {
Some(url) => url.parse::<url::Url>().unwrap(),
None => {
return Err(Error::MissingUpstreamInfo(
"no upstream or origin url is associated with the go project".to_string(),
))
}
};
let godebname = crate::names::go_base_name(
&[repository_url.host_str().unwrap(), repository_url.path()].concat(),
);
let mut source = control.add_source(&format!("golang-{}", godebname));
if let Some(ref maintainer) = context.maintainer {
source.set_maintainer(maintainer);
}
source.set_rules_requires_root(false);
source.set_standards_version(&latest_standards_version().to_string());
source.as_mut_deb822().insert(
"XS-Go-Import-Path",
&crate::names::go_import_path_from_repo(&repository_url),
);
if let Some(url) = context.metadata.repository() {
source.set_vcs_browser(Some(url));
}
source.set_section(Some("devel"));
let (build_deps, _test_deps) = context.get_project_wide_deps();
import_build_deps(&mut source, &build_deps);
source.set_testsuite("autopkgtest-pkg-go");
let mut dh_env = HashMap::new();
if context.wt.has_filename(&context.subpath.join("examples")) {
dh_env.insert("DH_GOLANG_EXCLUDES", "examples/");
}
context.bootstrap_debhelper(
&mut source,
DebhelperConfig {
addons: vec!["golang"],
buildsystem: Some("golang"),
build_directory: Some("_build"),
env: dh_env,
},
)?;
let mut binary = control.add_binary(&format!("golang-{}-dev", godebname));
binary.set_architecture(Some("all"));
binary.set_multi_arch(Some(MultiArch::Foreign));
control.commit()?;
Ok(())
}
fn process_r(context: &mut ProcessorContext) -> Result<(), Error> {
context.kickstart_tree(true)?;
let mut control = context.create_control_file()?;
let archive = match context.metadata.archive() {
Some("CRAN") => "cran",
Some("Bioconductor") => "bioc",
_ => "other",
};
let mut source = control.add_source(&format!(
"r-{}-{}",
archive,
context.metadata.name().unwrap().to_lowercase()
));
if let Some(ref maintainer) = context.maintainer {
source.set_maintainer(maintainer);
}
source.set_rules_requires_root(false);
source.set_build_depends(&"dh-r, r-base-dev".parse().unwrap());
source.set_standards_version(&latest_standards_version().to_string());
source.set_testsuite("autopkgtest-pkg-r");
let (build_deps, _test_deps) = context.get_project_wide_deps();
import_build_deps(&mut source, &build_deps);
context.bootstrap_debhelper(
&mut source,
DebhelperConfig {
buildsystem: Some("R"),
..Default::default()
},
)?;
let mut binary = control.add_binary(&format!(
"r-{}-{}",
archive,
context.metadata.name().unwrap().to_lowercase()
));
binary.set_architecture(Some("any"));
binary.set_depends(Some(
&"${R:Depends}, ${shlibs:Depends}, ${misc:Depends}"
.parse()
.unwrap(),
));
binary.set_recommends(Some(&"${R:Recommends}".parse().unwrap()));
binary.set_suggests(Some(&"${R:Suggests}".parse().unwrap()));
control.commit()?;
Ok(())
}
fn process_octave(context: &mut ProcessorContext) -> Result<(), Error> {
context.kickstart_tree(true)?;
let mut control = context.create_control_file()?;
let mut source = control.add_source(&format!(
"octave-{}",
context.metadata.name().unwrap().to_lowercase()
));
if let Some(ref maintainer) = context.maintainer {
source.set_maintainer(maintainer);
}
source.set_rules_requires_root(false);
source.set_build_depends(&"dh-octave".parse().unwrap());
source.set_standards_version(&latest_standards_version().to_string());
let (build_deps, _test_deps) = context.get_project_wide_deps();
import_build_deps(&mut source, &build_deps);
context.bootstrap_debhelper(
&mut source,
DebhelperConfig {
buildsystem: Some("octave"),
addons: vec!["octave"],
..Default::default()
},
)?;
let mut binary = control.add_binary(&format!(
"octave-{}",
context.metadata.name().unwrap().to_lowercase()
));
binary.set_architecture(Some("all"));
binary.set_depends(Some(&"${octave:Depends}, ${misc:Depends}".parse().unwrap()));
binary.set_description(Some("${octave:Upstream-Description}"));
control.commit()?;
Ok(())
}
fn process_default(context: &mut ProcessorContext) -> Result<(), Error> {
context.kickstart_tree(true)?;
let mut control = context.create_control_file()?;
let upstream_name = context.metadata.name().unwrap();
let source_name =
crate::names::upstream_name_to_debian_source_name(upstream_name).ok_or_else(|| {
Error::MissingUpstreamInfo(format!(
"Unable to determine source package name for {}",
upstream_name
))
})?;
let mut source = control.add_source(&source_name);
if let Some(ref maintainer) = context.maintainer {
source.set_maintainer(maintainer);
}
source.set_rules_requires_root(false);
source.set_standards_version(&latest_standards_version().to_string());
let (build_deps, _test_deps) = context.get_project_wide_deps();
import_build_deps(&mut source, &build_deps);
context.bootstrap_debhelper(&mut source, DebhelperConfig::default())?;
let binary_name = source.name().unwrap();
let mut binary = control.add_binary(&binary_name);
binary.set_architecture(Some("any"));
control.commit()?;
Ok(())
}
fn process_cmake(context: &mut ProcessorContext) -> Result<(), Error> {
context.kickstart_tree(true)?;
let mut control = context.create_control_file()?;
let upstream_name = context.metadata.name().unwrap_or("unknown");
let source_name = crate::names::upstream_name_to_debian_source_name(upstream_name)
.unwrap_or_else(|| upstream_name.to_string());
let mut source = control.add_source(&source_name);
if let Some(ref maintainer) = context.maintainer {
source.set_maintainer(maintainer);
}
source.set_standards_version(&latest_standards_version().to_string());
source.set_rules_requires_root(false);
let mut build_depends = Relations::new();
ensure_some_version(&mut build_depends, "cmake");
source.set_build_depends(&build_depends);
context.bootstrap_debhelper(
&mut source,
DebhelperConfig {
buildsystem: Some("cmake"),
..Default::default()
},
)?;
let (additional_build_deps, _test_deps) = context.get_project_wide_deps();
import_build_deps(&mut source, &additional_build_deps);
let binary_name = source.name().unwrap();
let mut binary = control.add_binary(&binary_name);
binary.set_architecture(Some("any"));
control.commit()?;
Ok(())
}
fn process_make(context: &mut ProcessorContext) -> Result<(), Error> {
context.kickstart_tree(true)?;
let mut control = context.create_control_file()?;
let upstream_name = context.metadata.name().unwrap_or("unknown");
let source_name = crate::names::upstream_name_to_debian_source_name(upstream_name)
.unwrap_or_else(|| upstream_name.to_string());
let mut source = control.add_source(&source_name);
if let Some(ref maintainer) = context.maintainer {
source.set_maintainer(maintainer);
}
source.set_standards_version(&latest_standards_version().to_string());
source.set_rules_requires_root(false);
context.bootstrap_debhelper(
&mut source,
DebhelperConfig {
buildsystem: Some("makefile"),
..Default::default()
},
)?;
let (additional_build_deps, _test_deps) = context.get_project_wide_deps();
import_build_deps(&mut source, &additional_build_deps);
let binary_name = source.name().unwrap();
let mut binary = control.add_binary(&binary_name);
binary.set_architecture(Some("any"));
control.commit()?;
Ok(())
}
fn process_cargo(context: &mut ProcessorContext) -> Result<(), Error> {
context.kickstart_tree(false)?;
let cratename = match context
.metadata
.get("Cargo-Crate")
.and_then(|v| v.datum.as_str())
{
Some(cratename) => cratename.to_string(),
None => context.metadata.name().unwrap().replace("_", "-"),
};
use semver::Version as VersionInfo;
let base_version = crate::names::debian_to_upstream_version(&context.upstream_version);
let version_to_use = if base_version == "0" || base_version.contains("git") {
context.metadata.version().unwrap_or("0.0.0")
} else {
base_version
};
let desired_version = VersionInfo::parse(version_to_use).map_err(|e| {
Error::Other(format!(
"Invalid semver version '{}': {}",
version_to_use, e
))
})?;
let rt = tokio::runtime::Runtime::new().unwrap();
let data = rt
.block_on(upstream_ontologist::providers::rust::load_crate_info(
&cratename,
))
.map_err(|e| {
Error::MissingUpstreamInfo(format!(
"Unable to load crate info for {}: {}",
cratename, e
))
})?
.ok_or(Error::MissingUpstreamInfo(format!(
"crates.io has no crate {}",
cratename
)))?;
let mut features = None;
let mut crate_version = None;
let mut semver_suffix = false;
for version_info in data.versions {
let available_version = &version_info.num;
if (available_version.major, available_version.minor)
> (desired_version.major, desired_version.minor)
{
semver_suffix = true;
break;
}
if VersionInfo::parse(&debian_analyzer::debcargo::unmangle_debcargo_version(
&context.upstream_version,
))
.unwrap()
== version_info.num
{
crate_version = Some(version_info.num);
features = Some(version_info.features.clone());
}
}
let mut control = debian_analyzer::debcargo::DebcargoEditor::new();
control.cargo = Some(debian_analyzer::debcargo::toml_edit::DocumentMut::new());
control.cargo.as_mut().unwrap()["package"]["name"] =
debian_analyzer::debcargo::toml_edit::value(cratename);
if let Some(crate_version) = crate_version {
control.cargo.as_mut().unwrap()["package"]["version"] =
debian_analyzer::debcargo::toml_edit::value(crate_version.to_string());
}
if let Some(features) = features {
let features_section = control.cargo.as_mut().unwrap()["features"]
.as_table_mut()
.unwrap();
for (feature, reqs) in features.iter() {
features_section[feature] = debian_analyzer::debcargo::toml_edit::value(
debian_analyzer::debcargo::toml_edit::Array::new(),
);
for req in reqs.iter() {
features_section[feature].as_array_mut().unwrap().push(
debian_analyzer::debcargo::toml_edit::Value::from(req.to_string()),
);
}
}
}
control.debcargo["semver_suffix"] = debian_analyzer::debcargo::toml_edit::value(semver_suffix);
control.debcargo["overlay"] = debian_analyzer::debcargo::toml_edit::value(".");
control.commit()?;
Ok(())
}
pub fn process(
session: &dyn Session,
wt: &dyn PyWorkingTree,
subpath: PathBuf,
debian_path: PathBuf,
upstream_version: String,
metadata: &UpstreamMetadata,
compat_release: String,
buildsystem: Box<dyn BuildSystem>,
buildsystem_subpath: PathBuf,
maintainer: Option<String>,
_kickstart_from_dist: Option<Box<dyn FnOnce(&dyn PyWorkingTree, &Path) -> Result<(), Error>>>,
) -> Result<(), Error> {
let bs_name = buildsystem.name().to_string();
let mut context = ProcessorContext {
session,
wt,
subpath,
debian_path,
upstream_version,
metadata,
compat_release,
buildsystem,
_buildsystem_subpath: buildsystem_subpath,
maintainer,
_kickstart_from_dist,
};
match bs_name.as_str() {
"setup.py" => process_setup_py(&mut context),
"node" => process_npm(&mut context),
"gradle" => process_maven(&mut context), "Dist::Zilla" => process_dist_zilla(&mut context),
"Module::Build::Tiny" => process_perl_build_tiny(&mut context),
"cargo" => process_cargo(&mut context),
"golang" => process_golang(&mut context),
"R" => process_r(&mut context),
"octave" => process_octave(&mut context),
"cmake" => process_cmake(&mut context),
"make" => process_make(&mut context), _ => process_default(&mut context),
}
}
fn check_python3_support(wt: &dyn PyWorkingTree, subpath: &Path) -> Result<bool, Error> {
let setup_py_path = subpath.join("setup.py");
if wt.has_filename(&setup_py_path) {
match wt.get_file_text(&setup_py_path) {
Ok(content) => {
let content_str = String::from_utf8_lossy(&content);
if content_str.contains("Programming Language :: Python :: 3")
|| content_str.contains("python_requires") && content_str.contains(">=3")
{
return Ok(true);
}
if content_str.contains("python_requires")
&& (content_str.contains(">=2.7") || content_str.contains(">=2.6"))
{
return Ok(true); }
}
Err(_) => {} }
}
let pyproject_path = subpath.join("pyproject.toml");
if wt.has_filename(&pyproject_path) {
match wt.get_file_text(&pyproject_path) {
Ok(content) => {
let content_str = String::from_utf8_lossy(&content);
if content_str.contains("python") && content_str.contains(">=3") {
return Ok(true);
}
}
Err(_) => {} }
}
let tox_path = subpath.join("tox.ini");
if wt.has_filename(&tox_path) {
match wt.get_file_text(&tox_path) {
Ok(content) => {
let content_str = String::from_utf8_lossy(&content);
if content_str.contains("py3") || content_str.contains("python3") {
return Ok(true);
}
}
Err(_) => {} }
}
Ok(true)
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
#[test]
fn test_debhelper_rules() {
let mut output = Vec::new();
debhelper_rules(&mut output, None, None, HashMap::new()).unwrap();
let rules_content = String::from_utf8(output).unwrap();
assert!(rules_content.contains("#!/usr/bin/make -f"));
assert!(rules_content.contains("%:\n\tdh $@\n"));
assert!(!rules_content.contains("--buildsystem="));
let mut output = Vec::new();
debhelper_rules(&mut output, Some("python"), None, HashMap::new()).unwrap();
let rules_content = String::from_utf8(output).unwrap();
assert!(rules_content.contains("dh $@ --buildsystem=python"));
let mut output = Vec::new();
let mut env = HashMap::new();
env.insert("TEST_VAR", "test-value");
env.insert("ANOTHER_VAR", "another-value");
debhelper_rules(&mut output, None, None, env).unwrap();
let rules_content = String::from_utf8(output).unwrap();
assert!(rules_content.contains("export TEST_VAR=test-value"));
assert!(rules_content.contains("export ANOTHER_VAR=another-value"));
}
#[test]
fn test_enable_dh_addon() {
let mut control = debian_control::lossless::Control::new();
let mut source = control.add_source("test-package");
enable_dh_addon(&mut source, "python3");
let build_deps = source.build_depends().unwrap();
let deps_string = build_deps.to_string();
assert!(deps_string.contains("dh-sequence-python3"));
enable_dh_addon(&mut source, "nodejs");
let build_deps = source.build_depends().unwrap();
let deps_string = build_deps.to_string();
assert!(deps_string.contains("dh-sequence-python3"));
assert!(deps_string.contains("dh-sequence-nodejs"));
}
#[test]
fn test_import_build_deps() {
let mut control = debian_control::lossless::Control::new();
let mut source = control.add_source("test-package");
source.set_build_depends(&"debhelper-compat (= 13)".parse().unwrap());
let new_build_deps: debian_control::lossless::relations::Relations =
"python3-all, dh-python".parse().unwrap();
import_build_deps(&mut source, &new_build_deps);
let build_deps = source.build_depends().unwrap();
let deps_string = build_deps.to_string();
assert!(deps_string.contains("debhelper-compat (= 13)"));
assert!(deps_string.contains("python3-all"));
assert!(deps_string.contains("dh-python"));
let versioned_deps: debian_control::lossless::relations::Relations =
"python3-all (>= 3.9)".parse().unwrap();
import_build_deps(&mut source, &versioned_deps);
let build_deps = source.build_depends().unwrap();
let deps_string = build_deps.to_string();
assert!(deps_string.contains("python3-all (>= 3.9)"));
}
#[test]
fn test_debhelper_config() {
let config = DebhelperConfig {
addons: vec!["python3", "nodejs"],
env: {
let mut env = HashMap::new();
env.insert("TEST_VAR", "test-value");
env
},
buildsystem: Some("pybuild"),
build_directory: None,
};
assert_eq!(config.addons.len(), 2);
assert_eq!(config.addons[0], "python3");
assert_eq!(config.addons[1], "nodejs");
assert_eq!(config.env.get("TEST_VAR"), Some(&"test-value"));
assert_eq!(config.buildsystem, Some("pybuild"));
let default_config = DebhelperConfig::default();
assert!(default_config.addons.is_empty());
assert!(default_config.env.is_empty());
assert_eq!(default_config.buildsystem, None);
assert_eq!(default_config.build_directory, None);
}
}