Skip to content

Commit 591b743

Browse files
committed
...
1 parent 5846e81 commit 591b743

File tree

6 files changed

+108
-103
lines changed

6 files changed

+108
-103
lines changed

Cargo.lock

-65
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ base64 = "0.9"
1212
bcrypt = "0.2"
1313
cache = { path = "components/cache" }
1414
diesel = { version = "1.3", features = ["mysql"] }
15-
embed = { git = "https://github.com/iptq/embed" }
1615
env_logger = "0.5"
1716
failure = "0.1.1"
1817
idna = "0.1"

src/cli/chal.rs

+76-33
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,9 @@ use std::path::PathBuf;
55
use toml;
66

77
use errors::{CustomError, DirError};
8+
use util::read_file;
89
use Error;
910

10-
lazy_static! {
11-
static ref REQUIRED_FIELDS: [&'static str; 3] = ["title", "description_file", "grader_file"];
12-
}
13-
1411
#[derive(Debug, StructOpt)]
1512
pub enum ChalCommand {
1613
/// Import challenges from a directory into the database
@@ -46,6 +43,20 @@ impl ChalImportCommand {
4643
};
4744
let path = entry.path();
4845

46+
match path
47+
.file_name()
48+
.and_then(|ostr| ostr.to_str())
49+
.and_then(|name| {
50+
if name.starts_with(".") {
51+
None
52+
} else {
53+
Some(())
54+
}
55+
}) {
56+
Some(_) => (),
57+
None => continue,
58+
}
59+
4960
// find problem.toml
5061
let problem_toml_path = path.join("problem.toml");
5162
if !problem_toml_path.exists() {
@@ -57,21 +68,7 @@ impl ChalImportCommand {
5768
}
5869

5970
// read the problem file
60-
let problem_contents = match {
61-
let mut file = match File::open(&problem_toml_path) {
62-
Ok(file) => file,
63-
Err(err) => {
64-
return Err(CustomError::new(format!("Error accessing file: {}", err)).into())
65-
}
66-
};
67-
let mut contents = String::new();
68-
match file.read_to_string(&mut contents) {
69-
Ok(_) => Ok::<_, Error>(contents),
70-
Err(err) => {
71-
Err(CustomError::new(format!("Error reading file: {}", err)).into())
72-
}
73-
}
74-
} {
71+
let problem_contents = match read_file(&problem_toml_path) {
7572
Ok(problem) => problem,
7673
Err(err) => {
7774
failed.push((Some(path), err));
@@ -102,31 +99,77 @@ impl ChalImportCommand {
10299
};
103100

104101
// check for the existence of required fields
105-
let mut flag = false;
106-
for field in REQUIRED_FIELDS.iter() {
107-
if !problem_toml.contains_key(field.to_owned()) {
102+
let title = match problem_toml.get("title") {
103+
Some(toml::Value::String(title)) => title,
104+
_ => {
108105
failed.push((
109106
Some(path),
110-
CustomError::new(format!(
111-
"problem.toml is missing required key '{}'",
112-
field
113-
)).into(),
107+
CustomError::new("String key 'title' not found.").into(),
114108
));
115-
flag = true;
116-
break;
109+
continue;
117110
}
118-
}
119-
if flag {
120-
continue;
121-
}
111+
};
112+
let description = match (
113+
problem_toml.get("description"),
114+
problem_toml.get("description_file"),
115+
) {
116+
(Some(_), Some(_)) => {
117+
failed.push((
118+
Some(path),
119+
CustomError::new("Cannot use both 'description' and 'description_file'.")
120+
.into(),
121+
));
122+
continue;
123+
}
124+
(Some(toml::Value::String(description)), None) => description.clone(),
125+
(None, Some(toml::Value::String(description_file))) => {
126+
match read_file(&description_file) {
127+
Ok(description) => description,
128+
Err(err) => {
129+
failed.push((Some(path), err.into()));
130+
continue;
131+
}
132+
}
133+
}
134+
_ => {
135+
failed.push((
136+
Some(path),
137+
CustomError::new("Neither 'description' nor 'description_file' found.")
138+
.into(),
139+
));
140+
continue;
141+
}
142+
};
143+
let grader = match problem_toml.get("grader") {
144+
Some(toml::Value::String(grader_path)) => {
145+
let path = PathBuf::from(&grader_path);
146+
if !path.exists() {
147+
failed.push((
148+
Some(path),
149+
CustomError::new("Grader file not found.").into(),
150+
));
151+
continue;
152+
}
153+
path
154+
}
155+
_ => {
156+
failed.push((
157+
Some(path),
158+
CustomError::new("String key 'grader' not found.").into(),
159+
));
160+
continue;
161+
}
162+
};
122163
}
123164

124165
if failed.len() > 0 {
125166
error!("Failed to load directories:");
126167
for (path, err) in failed {
127-
error!(" - {:?}: {}", path, err);
168+
error!(" - {:?}: {:?}", path, err);
128169
}
170+
return Err(CustomError::new("Failed to import some challenges.").into());
129171
}
172+
info!("Successfully imported all challenges.");
130173
Ok(())
131174
}
132175
}

src/errors.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,22 @@ use serde_json;
99
#[fail(display = "Error traversing the directory")]
1010
pub struct DirError(#[cause] pub io::Error);
1111

12+
#[derive(Debug, Fail)]
13+
#[fail(display = "Error accessing the file")]
14+
pub struct FileOpenError(#[cause] pub io::Error);
15+
16+
#[derive(Debug, Fail)]
17+
#[fail(display = "Error reading the file")]
18+
pub struct FileReadError(#[cause] pub io::Error);
19+
1220
#[derive(Debug)]
1321
pub struct CustomError(String);
1422

1523
macro_rules! error_derive_from {
1624
([$($error:path[$v:expr] => $into:ident,)*]) => {
1725
#[derive(Debug, Fail)]
1826
pub enum Error {
19-
#[fail(display = "")]
27+
#[fail(display = "{}", _0)]
2028
Custom(#[cause] CustomError),
2129
$(
2230
#[fail(display = $v)]
@@ -37,7 +45,9 @@ macro_rules! error_derive_from {
3745
error_derive_from!([
3846
rocket::error::LaunchError["Error launching Rocket application"] => RocketLaunch,
3947
serde_json::Error["Error during the serialization of JSON"] => JSONSerialization,
40-
DirError["Error traversing the directory"] => Dir,
48+
DirError[""] => Dir,
49+
FileOpenError[""] => FileOpen,
50+
FileReadError[""] => FileRead,
4151
]);
4252

4353
impl CustomError {

src/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ extern crate r2d2_diesel;
1515
extern crate base64;
1616
extern crate bcrypt;
1717
extern crate cache;
18-
#[macro_use]
19-
extern crate embed;
2018
extern crate env_logger;
2119
#[macro_use]
2220
extern crate failure;
@@ -47,6 +45,7 @@ mod errors;
4745
pub mod models;
4846
mod schema;
4947
mod tasks;
48+
mod util;
5049
pub mod web;
5150

5251
pub use challenge::Challenge;

src/util.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use std::fs::File;
2+
use std::io::Read;
3+
use std::path::Path;
4+
5+
use errors::{FileOpenError, FileReadError};
6+
use Error;
7+
8+
pub fn read_file(path: impl AsRef<Path>) -> Result<String, Error> {
9+
let mut file = match File::open(path.as_ref()) {
10+
Ok(file) => file,
11+
Err(err) => return Err(FileOpenError(err).into()),
12+
};
13+
let mut contents = String::new();
14+
15+
match file.read_to_string(&mut contents) {
16+
Ok(_) => Ok(contents),
17+
Err(err) => Err(FileReadError(err).into()),
18+
}
19+
}

0 commit comments

Comments
 (0)