1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use toml;
use super::util;
#[derive(Deserialize)]
pub struct Metadata {
pub repos: HashMap<String, Repo>,
pub proxy: Proxy,
}
#[derive(Deserialize)]
pub struct Repo {
pub vcs: String,
pub allow_sync: bool,
pub bare: bool,
pub use_proxy: bool,
pub topics: Vec<String>,
}
#[derive(Deserialize)]
pub struct Proxy {
pub scheme: String,
pub host: String,
pub port: u16,
}
pub fn load(path: &Path) -> Result<Metadata, String> {
let path_display = path.display();
let mut file = match File::open(&path) {
Ok(file) => file,
Err(err) => {
return Err(format!(
"Couldn't open {}: {}",
path_display,
err.to_string()
))
}
};
let mut content = String::new();
match file.read_to_string(&mut content) {
Ok(_) => {}
Err(err) => {
return Err(format!(
"Couldn't read {}: {}",
path_display,
err.to_string()
))
}
}
loads(&content)
}
pub fn loads(content: &str) -> Result<Metadata, String> {
let md: Metadata = match toml::from_str(&content) {
Ok(md) => md,
Err(err) => {
return Err(format!(
"Couldn't parse as toml format because of: {}",
err.to_string()
));
}
};
let mut urls_errors: HashMap<String, String> = HashMap::new();
for url in md.repos.keys() {
match util::validate_repo_url(url) {
Err(err) => {
urls_errors.insert(url.to_string(), err.to_string());
}
Ok(_) => {}
}
}
if !urls_errors.is_empty() {
for (url, error) in urls_errors {
println!("Url '{}' is unsupported because of: {}.", url, error);
}
Err("Unsupported repository urls found in metadata file.".to_string())
} else {
Ok(md)
}
}
#[cfg(test)]
mod tests {
extern crate tempfile;
use std::io::Write;
use std::path::Path;
use super::{load, loads};
static TEMP_CONTENT: &'static str = "
[repos.'https://github.com/org/repo.git']
vcs = 'git'
allow_sync = true
bare = false
use_proxy = false
topics = ['topic1', 'topic2']
[proxy]
scheme = 'socks5'
host = '127.0.0.1'
port = 1080
";
#[test]
fn md_loads() {
let md = loads(&TEMP_CONTENT).unwrap();
assert_eq!(md.proxy.scheme, "socks5");
assert_eq!(md.proxy.host, "127.0.0.1");
assert_eq!(md.proxy.port, 1080);
}
#[test]
fn md_load() {
let mut tmpfile = tempfile::NamedTempFile::new().unwrap();
write!(tmpfile, "{}", &TEMP_CONTENT).unwrap();
let path = tmpfile.path();
let filepath = Path::new(path);
let md = load(&filepath).unwrap();
assert_eq!(md.proxy.scheme, "socks5");
assert_eq!(md.proxy.host, "127.0.0.1");
assert_eq!(md.proxy.port, 1080);
}
}