cur_path: Path) -> CargoResult<Vec<SourceId>> {
debug!("loaded config; configs={}", configs);
- let config_paths = configs.find_equiv(&"paths").map(|v| v.clone());
- let config_paths = config_paths.unwrap_or_else(|| ConfigValue::new());
-
+ let config_paths = match configs.find_equiv(&"paths") {
+ Some(cfg) => cfg,
+ None => return Ok(Vec::new())
+ };
let paths = try!(config_paths.list().chain_error(|| {
- internal("invalid configuration for the key `path`")
+ internal("invalid configuration for the key `paths`")
}));
- // Make sure we don't override the local package, even if it's in the list
- // of override paths
- paths.iter().filter(|p| {
- cur_path != os::make_absolute(&Path::new(p.as_slice()))
- }).map(|p| SourceId::for_path(&Path::new(p.as_slice()))).collect()
+ paths.iter().map(|&(ref s, ref p)| {
+ // The path listed next to the string is the config file in which the
+ // key was located, so we want to pop off the `.cargo/config` component
+ // to get the directory containing the `.cargo` folder.
+ p.dir_path().dir_path().join(s.as_slice())
+ }).filter(|p| {
+ // Make sure we don't override the local package, even if it's in the
+ // list of override paths.
+ cur_path != *p
+ }).map(|p| SourceId::for_path(&p)).collect()
}
fn scrape_target_config(config: &mut Config,
Some(ar) => {
config.set_ar(try!(ar.string().chain_error(|| {
internal("invalid configuration for key `ar`")
- })).to_string());
+ })).ref0().to_string());
}
}
Some(linker) => {
config.set_linker(try!(linker.string().chain_error(|| {
internal("invalid configuration for key `ar`")
- })).to_string());
+ })).ref0().to_string());
}
}
}
#[deriving(Eq,PartialEq,Clone,Decodable)]
-pub enum ConfigValueValue {
- String(String),
- List(Vec<String>),
+pub enum ConfigValue {
+ String(String, Path),
+ List(Vec<(String, Path)>),
Table(HashMap<String, ConfigValue>),
}
-impl fmt::Show for ConfigValueValue {
+impl fmt::Show for ConfigValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
- String(ref string) => write!(f, "{}", string),
- List(ref list) => write!(f, "{}", list),
+ String(ref string, ref path) => {
+ write!(f, "{} (from {})", string, path.display())
+ }
+ List(ref list) => {
+ try!(write!(f, "["));
+ for (i, &(ref s, ref path)) in list.iter().enumerate() {
+ if i > 0 { try!(write!(f, ", ")); }
+ try!(write!(f, "{} (from {})", s, path.display()));
+ }
+ write!(f, "]")
+ }
Table(ref table) => write!(f, "{}", table),
}
}
}
-impl<E, S: Encoder<E>> Encodable<S, E> for ConfigValueValue {
+impl<E, S: Encoder<E>> Encodable<S, E> for ConfigValue {
fn encode(&self, s: &mut S) -> Result<(), E> {
match *self {
- String(ref string) => string.encode(s),
- List(ref list) => list.encode(s),
+ String(ref string, _) => string.encode(s),
+ List(ref list) => {
+ let list: Vec<&String> = list.iter().map(|s| s.ref0()).collect();
+ list.encode(s)
+ }
Table(ref table) => table.encode(s),
}
}
}
-#[deriving(Eq,PartialEq,Clone,Decodable)]
-pub struct ConfigValue {
- value: ConfigValueValue,
- path: Vec<Path>
-}
-
impl ConfigValue {
- pub fn new() -> ConfigValue {
- ConfigValue { value: List(vec!()), path: vec!() }
- }
-
- pub fn get_value(&self) -> &ConfigValueValue {
- &self.value
- }
-
fn from_toml(path: &Path, toml: toml::Value) -> CargoResult<ConfigValue> {
- let value = match toml {
- toml::String(val) => String(val),
+ match toml {
+ toml::String(val) => Ok(String(val, path.clone())),
toml::Array(val) => {
- List(try!(result::collect(val.move_iter().map(|toml| {
+ Ok(List(try!(result::collect(val.move_iter().map(|toml| {
match toml {
- toml::String(val) => Ok(val),
+ toml::String(val) => Ok((val, path.clone())),
_ => Err(internal("")),
}
- }))))
+ })))))
}
toml::Table(val) => {
- Table(try!(result::collect(val.move_iter().map(|(key, value)| {
+ Ok(Table(try!(result::collect(val.move_iter().map(|(key, value)| {
let value = raw_try!(ConfigValue::from_toml(path, value));
Ok((key, value))
- }))))
+ })))))
}
_ => return Err(internal(""))
- };
-
- Ok(ConfigValue { value: value, path: vec![path.clone()] })
+ }
}
fn merge(&mut self, from: ConfigValue) -> CargoResult<()> {
- let ConfigValue { value, path } = from;
- match (&mut self.value, value) {
- (&String(ref mut old), String(ref mut new)) => {
- mem::swap(old, new);
- self.path = path;
- }
+ match (self, from) {
+ (me @ &String(..), from @ String(..)) => *me = from,
(&List(ref mut old), List(ref mut new)) => {
- old.extend(mem::replace(new, Vec::new()).move_iter());
- self.path.extend(path.move_iter());
+ let new = mem::replace(new, Vec::new());
+ old.extend(new.move_iter());
}
(&Table(ref mut old), Table(ref mut new)) => {
let new = mem::replace(new, HashMap::new());
|_, new| new);
try!(err);
}
- self.path.extend(path.move_iter());
}
(expected, found) => {
return Err(internal(format!("expected {}, but found {}",
Ok(())
}
- pub fn string(&self) -> CargoResult<&str> {
- match self.value {
- Table(_) => Err(internal("expected a string, but found a table")),
- List(_) => Err(internal("expected a string, but found a list")),
- String(ref s) => Ok(s.as_slice()),
+ pub fn string(&self) -> CargoResult<(&str, &Path)> {
+ match *self {
+ Table(..) => Err(internal("expected a string, but found a table")),
+ List(..) => Err(internal("expected a string, but found a list")),
+ String(ref s, ref p) => Ok((s.as_slice(), p)),
}
}
pub fn table(&self) -> CargoResult<&HashMap<String, ConfigValue>> {
- match self.value {
- String(_) => Err(internal("expected a table, but found a string")),
- List(_) => Err(internal("expected a table, but found a list")),
+ match *self {
+ String(..) => Err(internal("expected a table, but found a string")),
+ List(..) => Err(internal("expected a table, but found a list")),
Table(ref table) => Ok(table),
}
}
- pub fn list(&self) -> CargoResult<&[String]> {
- match self.value {
- String(_) => Err(internal("expected a list, but found a string")),
- Table(_) => Err(internal("expected a list, but found a table")),
+ pub fn list(&self) -> CargoResult<&[(String, Path)]> {
+ match *self {
+ String(..) => Err(internal("expected a list, but found a string")),
+ Table(..) => Err(internal("expected a list, but found a table")),
List(ref list) => Ok(list.as_slice()),
}
}
-}
-impl ConfigValueValue {
- fn desc(&self) -> &'static str {
+ pub fn desc(&self) -> &'static str {
match *self {
Table(..) => "table",
List(..) => "array",
}
}
-impl<E, S: Encoder<E>> Encodable<S, E> for ConfigValue {
- fn encode(&self, s: &mut S) -> Result<(), E> {
- s.emit_map(2, |s| {
- raw_try!(s.emit_map_elt_key(0, |s| "value".encode(s)));
- raw_try!(s.emit_map_elt_val(0, |s| self.value.encode(s)));
- Ok(())
- })
- }
-}
-
-impl fmt::Show for ConfigValue {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let paths: Vec<String> = self.path.iter().map(|p| {
- p.display().to_string()
- }).collect();
- write!(f, "{} (from {})", self.value, paths)
- }
-}
-
pub fn get_config(pwd: Path, key: &str) -> CargoResult<ConfigValue> {
find_in_tree(&pwd, |file| extract_config(file, key)).map_err(|_|
human(format!("`{}` not found in your configuration", key)))
}
pub fn all_configs(pwd: Path) -> CargoResult<HashMap<String, ConfigValue>> {
- let mut cfg = ConfigValue { value: Table(HashMap::new()), path: Vec::new() };
+ let mut cfg = Table(HashMap::new());
try!(walk_tree(&pwd, |mut file| {
let path = file.path().clone();
}).map_err(|_| human("Couldn't load Cargo configuration")));
- match cfg.value {
+ match cfg {
Table(map) => Ok(map),
_ => unreachable!(),
}