//! Debian build types (`dpkg-buildpackage -b/-B/-A/-S/-g/-G/--build=...`) //! and their mapping to `debian/rules` targets. /// Build type bit flags, mirroring `Dpkg::BuildTypes`. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct BuildType(u8); /// Source build component (`-S`, `--build=source`). pub const SOURCE: BuildType = BuildType(0x1); /// Arch-dependent binary build component (`-B`, `--build=any`). pub const ARCH_DEP: BuildType = BuildType(0x2); /// Arch-independent binary build component (`-A`, `--build=all`). pub const ARCH_INDEP: BuildType = BuildType(0x4); /// Any binary component. pub const BINARY: BuildType = BuildType(ARCH_DEP.0 | ARCH_INDEP.0); /// Normal full build: source + binaries (`-F`, default). pub const FULL: BuildType = BuildType(SOURCE.0 | BINARY.0); /// Source + arch-dependent (`-G`). pub const SOURCE_ARCH_DEP: BuildType = BuildType(SOURCE.0 | ARCH_DEP.0); /// Source + arch-indep (`-g`). pub const SOURCE_ARCH_INDEP: BuildType = BuildType(SOURCE.0 | ARCH_INDEP.0); impl BuildType { /// Construct from raw bits. pub const fn from_bits(bits: u8) -> Self { BuildType(bits) } /// Raw bits. pub const fn bits(self) -> u8 { self.0 } /// True if any of `other`'s components are set. pub fn has_any(self, other: BuildType) -> bool { self.0 & other.0 != 0 } /// True if all of `other`'s components are set. pub fn has_all(self, other: BuildType) -> bool { self.0 & other.0 == other.0 } /// True if none of `other`'s components are set. pub fn has_none(self, other: BuildType) -> bool { self.0 & other.0 == 0 } /// Parse a comma-separated `--build=[,...]` option value. /// /// Valid components: `full`, `source`, `binary`, `any`, `all`. pub fn from_options(value: &str) -> Result { let mut result = BuildType(0); for part in value.split(',') { match part.trim() { "full" => result = FULL, "source" => result = BuildType(result.0 | SOURCE.0), "binary" => result = BuildType(result.0 | BINARY.0), "any" => result = BuildType(result.0 | ARCH_DEP.0), "all" => result = BuildType(result.0 | ARCH_INDEP.0), other => return Err(format!("unknown build type component '{}'", other)), } } if result.0 == 0 { return Err("empty build type".to_string()); } Ok(result) } /// Canonical comma-separated representation (as passed to /// `dpkg-genchanges --build=` / `dpkg-genbuildinfo --build=`). pub fn to_options(self) -> String { let mut parts = Vec::new(); if self.has_any(SOURCE) { parts.push("source"); } if self.has_all(BINARY) { parts.push("binary"); } else { if self.has_any(ARCH_DEP) { parts.push("any"); } if self.has_any(ARCH_INDEP) { parts.push("all"); } } parts.join(",") } /// The `debian/rules` build target for this type: /// `build`, `build-arch` or `build-indep`. pub fn build_target(self) -> &'static str { if self.has_all(BINARY) || self.has_none(BINARY) { "build" } else if self.has_any(ARCH_DEP) { "build-arch" } else { "build-indep" } } /// The `debian/rules` binary target for this type: /// `binary`, `binary-arch` or `binary-indep`. pub fn binary_target(self) -> &'static str { if self.has_all(BINARY) || self.has_none(BINARY) { "binary" } else if self.has_any(ARCH_DEP) { "binary-arch" } else { "binary-indep" } } /// The architecture suffix used in artifact file names: /// host arch, `all` or `source`. pub fn arch_suffix(self, host_arch: &str) -> &str { if self.has_any(ARCH_DEP) { host_arch } else if self.has_any(ARCH_INDEP) { "all" } else { "source" } } } #[cfg(test)] mod tests { use super::*; #[test] fn parse_options() { assert_eq!(BuildType::from_options("full").unwrap(), FULL); assert_eq!(BuildType::from_options("source").unwrap(), SOURCE); assert_eq!( BuildType::from_options("source,any").unwrap(), SOURCE_ARCH_DEP ); assert_eq!(BuildType::from_options("any,all").unwrap(), BINARY); assert!(BuildType::from_options("bogus").is_err()); } #[test] fn roundtrip_options() { for t in [FULL, SOURCE, BINARY, SOURCE_ARCH_DEP, SOURCE_ARCH_INDEP] { assert_eq!(BuildType::from_options(&t.to_options()).unwrap(), t); } } #[test] fn targets() { assert_eq!(FULL.build_target(), "build"); assert_eq!(FULL.binary_target(), "binary"); assert_eq!(ARCH_DEP.build_target(), "build-arch"); assert_eq!(ARCH_DEP.binary_target(), "binary-arch"); assert_eq!(ARCH_INDEP.build_target(), "build-indep"); assert_eq!(ARCH_INDEP.binary_target(), "binary-indep"); assert_eq!(SOURCE.arch_suffix("amd64"), "source"); assert_eq!(ARCH_DEP.arch_suffix("amd64"), "amd64"); assert_eq!(ARCH_INDEP.arch_suffix("amd64"), "all"); } }