Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ description = "Run pkg-config from declarative dependencies in Cargo.toml"
keywords = ["pkg-config", "build-dependencies", "build-depends", "manifest", "metadata"]

[dependencies]
error-chain = { version = "0.10", default-features = false }
anyhow = "1"
pkg-config = "0.3.8"
toml = { version = "0.2", default-features = false }
toml = { version = "0.5", default-features = false }

[dev-dependencies]
lazy_static = "1"
73 changes: 40 additions & 33 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,47 +12,44 @@

#![deny(missing_docs, warnings)]

#[macro_use]
extern crate error_chain;
extern crate anyhow;
extern crate pkg_config;
extern crate toml;

pub use anyhow::{Error, Result};

use anyhow::Context;
use pkg_config::{Config, Library};
use std::collections::HashMap;
use std::env;
use std::fs;
use std::io::Read;
use std::path::PathBuf;
use pkg_config::{Config, Library};
use std::path::Path;

error_chain! {
foreign_links {
PkgConfig(pkg_config::Error) #[doc="pkg-config error"];
}
const KEY: &str = "package.metadata.pkg-config";

fn get_pkgconfig_table(toml: &toml::Value) -> Option<&toml::Value> {
toml.get("package")?.get("metadata")?.get("pkg-config")
}

/// Probe all libraries configured in the Cargo.toml
/// `[package.metadata.pkg-config]` section.
pub fn probe() -> Result<HashMap<String, Library>> {
let dir = try!(env::var_os("CARGO_MANIFEST_DIR").ok_or("$CARGO_MANIFEST_DIR not set"));
let mut path = PathBuf::from(dir);
path.push("Cargo.toml");
let mut manifest = try!(fs::File::open(&path).chain_err(||
format!("Error opening {}", path.display())
));
let dir = env::var_os("CARGO_MANIFEST_DIR")
.ok_or_else(|| anyhow::anyhow!("$CARGO_MANIFEST_DIR not set"))?;
let path = Path::new(&dir).join("Cargo.toml");
let mut manifest_str = String::new();
try!(manifest.read_to_string(&mut manifest_str).chain_err(||
format!("Error reading {}", path.display())
));
let toml = try!(manifest_str.parse::<toml::Value>().map_err(|e|
format!("Error parsing TOML from {}: {:?}", path.display(), e)
));
let key = "package.metadata.pkg-config";
let meta = try!(toml.lookup(key).ok_or(
format!("No {} in {}", key, path.display())
));
let table = try!(meta.as_table().ok_or(
format!("{} not a table in {}", key, path.display())
));
fs::File::open(&path)
.with_context(|| format!("Error opening {}", path.display()))?
.read_to_string(&mut manifest_str)
.with_context(|| format!("Error reading {}", path.display()))?;
let toml = manifest_str
.parse::<toml::Value>()
.with_context(|| format!("Error parsing TOML from {}", path.display()))?;
let table = get_pkgconfig_table(&toml)
.with_context(|| format!("No {} key in {}", KEY, path.display()))?
.as_table()
.with_context(|| format!("{} not a table in {}", KEY, path.display()))?;
let mut libraries = HashMap::new();
for (name, value) in table {
let ref version = match value {
Expand All @@ -62,9 +59,19 @@ pub fn probe() -> Result<HashMap<String, Library>> {
let mut version = None;
for (tname, tvalue) in t {
match (tname.as_str(), tvalue) {
("feature", &toml::Value::String(ref s)) => { feature = Some(s); }
("version", &toml::Value::String(ref s)) => { version = Some(s); }
_ => bail!("Unexpected key {}.{}.{} type {}", key, name, tname, tvalue.type_str()),
("feature", &toml::Value::String(ref s)) => {
feature = Some(s);
}
("version", &toml::Value::String(ref s)) => {
version = Some(s);
}
_ => anyhow::bail!(
"Unexpected key {}.{}.{} type {}",
KEY,
name,
tname,
tvalue.type_str()
),
}
}
if let Some(feature) = feature {
Expand All @@ -73,11 +80,11 @@ pub fn probe() -> Result<HashMap<String, Library>> {
continue;
}
}
try!(version.ok_or(format!("No version in {}.{}", key, name)))
version.ok_or_else(|| anyhow::anyhow!("No version in {}.{}", KEY, name))?
}
_ => bail!("{}.{} not a string or table", key, name),
_ => anyhow::bail!("{}.{} not a string or table", KEY, name),
};
let library = try!(Config::new().atleast_version(&version).probe(name));
let library = Config::new().atleast_version(&version).probe(name)?;
libraries.insert(name.clone(), library);
}
Ok(libraries)
Expand Down
53 changes: 41 additions & 12 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@ lazy_static! {
static ref LOCK: Mutex<()> = Mutex::new(());
}

fn toml(path: &str) -> metadeps::Result<std::collections::HashMap<String, pkg_config::Library>> {
fn toml(
path: &str,
) -> Result<std::collections::HashMap<String, pkg_config::Library>, metadeps::Error> {
let _l = LOCK.lock();
env::set_var("PKG_CONFIG_PATH", &env::current_dir().unwrap().join("tests"));
env::set_var("CARGO_MANIFEST_DIR", &env::current_dir().unwrap().join("tests").join(path));
env::set_var(
"PKG_CONFIG_PATH",
&env::current_dir().unwrap().join("tests"),
);
env::set_var(
"CARGO_MANIFEST_DIR",
&env::current_dir().unwrap().join("tests").join(path),
);
env::set_var("CARGO_FEATURE_TEST_FEATURE", "");
metadeps::probe()
}
Expand All @@ -30,8 +38,11 @@ fn good() {

fn toml_err(path: &str, err_starts_with: &str) {
let err = toml(path).unwrap_err();
if !err.description().starts_with(err_starts_with) {
panic!("Expected error to start with: {:?}\nGot error: {:?}", err_starts_with, err);
if !format!("{}", err).starts_with(err_starts_with) {
panic!(
"Expected error to start with: {:?}\nGot error: {:?}",
err_starts_with, err
);
}
}

Expand All @@ -42,35 +53,53 @@ fn missing_file() {

#[test]
fn missing_key() {
toml_err("toml-missing-key", "No package.metadata.pkg-config in");
toml_err("toml-missing-key", "No package.metadata.pkg-config key in");
}

#[test]
fn not_table() {
toml_err("toml-not-table", "package.metadata.pkg-config not a table in");
toml_err(
"toml-not-table",
"package.metadata.pkg-config not a table in",
);
}

#[test]
fn version_missing() {
toml_err("toml-version-missing", "No version in package.metadata.pkg-config.testlib");
toml_err(
"toml-version-missing",
"No version in package.metadata.pkg-config.testlib",
);
}

#[test]
fn version_not_string() {
toml_err("toml-version-not-string", "package.metadata.pkg-config.testlib not a string or table");
toml_err(
"toml-version-not-string",
"package.metadata.pkg-config.testlib not a string or table",
);
}

#[test]
fn version_in_table_not_string() {
toml_err("toml-version-in-table-not-string", "Unexpected key package.metadata.pkg-config.testlib.version type integer");
toml_err(
"toml-version-in-table-not-string",
"Unexpected key package.metadata.pkg-config.testlib.version type integer",
);
}

#[test]
fn feature_not_string() {
toml_err("toml-feature-not-string", "Unexpected key package.metadata.pkg-config.testlib.feature type integer");
toml_err(
"toml-feature-not-string",
"Unexpected key package.metadata.pkg-config.testlib.feature type integer",
);
}

#[test]
fn unexpected_key() {
toml_err("toml-unexpected-key", "Unexpected key package.metadata.pkg-config.testlib.color type string");
toml_err(
"toml-unexpected-key",
"Unexpected key package.metadata.pkg-config.testlib.color type string",
);
}