diff --git a/src/lib.rs b/src/lib.rs index 88dd310..32da0b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,6 +71,7 @@ use std::error; use std::ffi::{OsStr, OsString}; use std::fmt; use std::io; +use std::ops::{Bound, RangeBounds}; use std::path::{PathBuf, Path}; use std::process::{Command, Output}; use std::str; @@ -84,10 +85,11 @@ pub fn target_supported() -> bool { (host == target || env::var_os("PKG_CONFIG_ALLOW_CROSS").is_some()) } -#[derive(Clone, Default)] +#[derive(Clone)] pub struct Config { statik: Option, - atleast_version: Option, + min_version: Bound, + max_version: Bound, extra_args: Vec, cargo_metadata: bool, env_metadata: bool, @@ -264,7 +266,8 @@ impl Config { pub fn new() -> Config { Config { statik: None, - atleast_version: None, + min_version: Bound::Unbounded, + max_version: Bound::Unbounded, extra_args: vec![], print_system_libs: true, cargo_metadata: true, @@ -283,7 +286,33 @@ impl Config { /// Indicate that the library must be at least version `vers`. pub fn atleast_version(&mut self, vers: &str) -> &mut Config { - self.atleast_version = Some(vers.to_string()); + self.min_version = Bound::Included(vers.to_string()); + self.max_version = Bound::Unbounded; + self + } + + /// Indicate that the library must be equal to version `vers`. + pub fn exactly_version(&mut self, vers: &str) -> &mut Config { + self.min_version = Bound::Included(vers.to_string()); + self.max_version = Bound::Included(vers.to_string()); + self + } + + /// Indicate that the library's version must be in `range`. + pub fn range_version<'a, R>(&mut self, range: R) -> &mut Config + where + R: RangeBounds<&'a str> + { + self.min_version = match range.start_bound() { + Bound::Included(vers) => Bound::Included(vers.to_string()), + Bound::Excluded(vers) => Bound::Excluded(vers.to_string()), + Bound::Unbounded => Bound::Unbounded, + }; + self.max_version = match range.end_bound() { + Bound::Included(vers) => Bound::Included(vers.to_string()), + Bound::Excluded(vers) => Bound::Excluded(vers.to_string()), + Bound::Unbounded => Bound::Unbounded, + }; self } @@ -408,10 +437,24 @@ impl Config { if self.print_system_libs { cmd.env("PKG_CONFIG_ALLOW_SYSTEM_LIBS", "1"); } - if let Some(ref version) = self.atleast_version { - cmd.arg(&format!("{} >= {}", name, version)); - } else { - cmd.arg(name); + cmd.arg(name); + match self.min_version { + Bound::Included(ref version) => { + cmd.arg(&format!("{} >= {}", name, version)); + } + Bound::Excluded(ref version) => { + cmd.arg(&format!("{} > {}", name, version)); + } + _ => (), + } + match self.max_version { + Bound::Included(ref version) => { + cmd.arg(&format!("{} <= {}", name, version)); + } + Bound::Excluded(ref version) => { + cmd.arg(&format!("{} < {}", name, version)); + } + _ => (), } cmd } @@ -438,6 +481,22 @@ impl Config { } } + +// Implement Default manualy since Bound does not implement Default. +impl Default for Config { + fn default() -> Config { + Config { + statik: None, + min_version: Bound::Unbounded, + max_version: Bound::Unbounded, + extra_args: vec![], + print_system_libs: false, + cargo_metadata: false, + env_metadata: false, + } + } +} + impl Library { fn new() -> Library { Library { diff --git a/tests/test.rs b/tests/test.rs index fad0fcf..cbdc7f4 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -116,3 +116,115 @@ fn version() { reset(); assert_eq!(&find("foo").unwrap().version[..], "3.10.0.SVN"); } + +#[test] +fn atleast_version_ok() { + let _g = LOCK.lock(); + reset(); + pkg_config::Config::new().atleast_version("3.10").probe("foo").unwrap(); +} + +#[test] +#[should_panic] +fn atleast_version_ng() { + let _g = LOCK.lock(); + reset(); + pkg_config::Config::new().atleast_version("3.11").probe("foo").unwrap(); +} + +#[test] +fn exactly_version_ok() { + let _g = LOCK.lock(); + reset(); + pkg_config::Config::new().exactly_version("3.10.0.SVN").probe("foo").unwrap(); +} + +#[test] +#[should_panic] +fn exactly_version_ng() { + let _g = LOCK.lock(); + reset(); + pkg_config::Config::new().exactly_version("3.10.0").probe("foo").unwrap(); +} + +#[test] +fn range_version_range_ok() { + let _g = LOCK.lock(); + reset(); + pkg_config::Config::new().range_version("4.2.0".."4.4.0").probe("escape").unwrap(); +} + +#[test] +#[should_panic] +fn range_version_range_ng() { + let _g = LOCK.lock(); + reset(); + pkg_config::Config::new().range_version("4.0.0".."4.2.0").probe("escape").unwrap(); +} + +#[test] +fn range_version_range_inclusive_ok() { + let _g = LOCK.lock(); + reset(); + pkg_config::Config::new().range_version("4.0.0"..="4.2.0").probe("escape").unwrap(); +} + +#[test] +#[should_panic] +fn range_version_range_inclusive_ng() { + let _g = LOCK.lock(); + reset(); + pkg_config::Config::new().range_version("3.8.0"..="4.0.0").probe("escape").unwrap(); +} + +#[test] +fn range_version_range_from_ok() { + let _g = LOCK.lock(); + reset(); + pkg_config::Config::new().range_version("4.0.0"..).probe("escape").unwrap(); +} + +#[test] +#[should_panic] +fn range_version_range_from_ng() { + let _g = LOCK.lock(); + reset(); + pkg_config::Config::new().range_version("4.4.0"..).probe("escape").unwrap(); +} + +#[test] +fn range_version_range_to_ok() { + let _g = LOCK.lock(); + reset(); + pkg_config::Config::new().range_version(.."4.4.0").probe("escape").unwrap(); +} + +#[test] +#[should_panic] +fn range_version_range_to_ng() { + let _g = LOCK.lock(); + reset(); + pkg_config::Config::new().range_version(.."4.2.0").probe("escape").unwrap(); +} + +#[test] +fn range_version_range_to_inclusive_ok() { + let _g = LOCK.lock(); + reset(); + pkg_config::Config::new().range_version(..="4.2.0").probe("escape").unwrap(); +} + +#[test] +#[should_panic] +fn range_version_range_to_inclusive_ng() { + let _g = LOCK.lock(); + reset(); + pkg_config::Config::new().range_version(..="4.0.0").probe("escape").unwrap(); +} + +#[test] +fn range_version_full() { + let _g = LOCK.lock(); + reset(); + pkg_config::Config::new().range_version(..).probe("escape").unwrap(); +}