1use fnv::FnvHashMap;
7use lazy_static;
8use regex::Regex;
9use std::fs::File;
10use std::io;
11use std::io::prelude::*;
12use std::path;
13
14lazy_static::lazy_static! {
19 static ref EXACT: Regex = Regex::new(r"[^#]\b(?P<type>setup(Optional|Required))[(](?P<product>[[:word:]]+?\b)\s+[-]j\s(?P<version>\S+?\b)[)]").unwrap();
22 static ref INEXACT: Regex = Regex::new(r"[^#]\b(?P<type>setup(Optional|Required))[(](?P<product>[[:word:]]+?\b)(?:\s(?P<version>\S+?\b)\s\[)?").unwrap();
24
25
26 static ref ENV_PREPEND: Regex = Regex::new(r"(envPrepend|pathPrepend)[(](?P<var>.+?)[,]\s(?P<target>.+?)[)]").unwrap();
28 static ref ENV_APPEND: Regex = Regex::new(r"(envAppend|pathAppend)[(](?P<var>.+?)[,]\s(?P<target>.+?)[)]").unwrap();
30}
31
32#[derive(Clone)]
36pub enum VersionType {
37 Exact,
38 Inexact,
39}
40
41#[derive(Debug, Clone)]
44pub enum EnvActionType {
45 Prepend,
46 Append,
47}
48
49#[derive(Debug, Clone)]
52pub struct Deps {
53 pub required: FnvHashMap<String, String>,
54 pub optional: FnvHashMap<String, String>,
55}
56
57#[derive(Debug, Clone)]
59pub struct Table {
60 pub name: String,
61 pub path: path::PathBuf,
62 pub product_dir: path::PathBuf,
63 pub exact: Option<Deps>,
64 pub inexact: Option<Deps>,
65 pub env_var: FnvHashMap<String, (EnvActionType, String)>,
66}
67
68impl Table {
69 pub fn new(
72 name: String,
73 path: path::PathBuf,
74 prod_dir: path::PathBuf,
75 ) -> Result<Table, io::Error> {
76 let mut f = File::open(path.clone())?;
77 let mut contents = String::new();
78 f.read_to_string(&mut contents)?;
79 let exact = Table::extract_setup(contents.as_str(), &*EXACT);
86 let inexact = Table::extract_setup(contents.as_str(), &*INEXACT);
88 let mut env_var = FnvHashMap::default();
89 let env_re_vec: Vec<&Regex> = vec![&*ENV_PREPEND, &*ENV_APPEND];
90 for (re, action) in env_re_vec
91 .iter()
92 .zip([EnvActionType::Prepend, EnvActionType::Append].iter())
93 {
94 for cap in re.captures_iter(contents.as_str()) {
95 let var = String::from(&cap["var"]);
96 let target = String::from(&cap["target"]);
97 let final_target = target.replace("${PRODUCT_DIR}", prod_dir.to_str().unwrap());
98 env_var.insert(var, (action.clone(), final_target));
99 }
100 }
101 Ok(Table {
102 name: name,
103 path: path,
104 product_dir: prod_dir,
105 exact: exact,
106 inexact: inexact,
107 env_var: env_var,
108 })
109 }
110
111 fn extract_setup(input: &str, re: &Regex) -> Option<Deps> {
114 let temp_string = input;
115 let mut required_map = FnvHashMap::default();
116 let mut optional_map = FnvHashMap::default();
117 for dep_cap in re.captures_iter(temp_string) {
118 let option_type = &dep_cap["type"];
119 let prod = &dep_cap["product"];
120 let vers = match dep_cap.name("version") {
121 Some(ver) => ver.as_str(),
122 None => "",
123 };
124 if option_type == "setupRequired" {
125 required_map.insert(String::from(prod), String::from(vers));
126 }
127 if option_type == "setupOptional" {
128 optional_map.insert(String::from(prod), String::from(vers));
129 }
130 }
131 Some(Deps {
132 required: required_map,
133 optional: optional_map,
134 })
135 }
136}