Skip to content

Commit

Permalink
Add file related failure to project Error enum
Browse files Browse the repository at this point in the history
  • Loading branch information
lpil committed Dec 20, 2019
1 parent 128df13 commit 87aa490
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 46 deletions.
71 changes: 71 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,51 @@ pub enum Error {
},

DependencyCycle,

FileIO {
kind: FileKind,
action: FileIOAction,
path: PathBuf,
err: Option<String>,
},
}

#[derive(Debug, PartialEq)]
pub enum FileIOAction {
Open,
Read,
Parse,
Create,
WriteTo,
FindParent,
}

impl FileIOAction {
fn text(&self) -> &'static str {
match self {
FileIOAction::Open => "open",
FileIOAction::Read => "read",
FileIOAction::Parse => "parse",
FileIOAction::Create => "create",
FileIOAction::WriteTo => "write to",
FileIOAction::FindParent => "find the parent of",
}
}
}

#[derive(Debug, PartialEq)]
pub enum FileKind {
File,
Directory,
}

impl FileKind {
fn text(&self) -> &'static str {
match self {
FileKind::File => "file",
FileKind::Directory => "directory",
}
}
}

fn write_project(mut buffer: &mut Buffer, d: ProjectErrorDiagnostic) {
Expand Down Expand Up @@ -105,6 +150,7 @@ cannot import them. Perhaps move the `{}` module to the src directory.",
)
.unwrap();
}

Error::DuplicateModule {
module,
first,
Expand All @@ -125,6 +171,31 @@ Second: {}",
write_project(buffer, diagnostic);
}

Error::FileIO {
kind,
action,
path,
err,
} => {
let err = match err {
Some(e) => format!("\n\nThe error message was:\n {}\n", e),
None => "".to_string(),
};
let diagnostic = ProjectErrorDiagnostic {
title: "File IO failure".to_string(),
label: format!(
"An error occurred while trying to {} the {}
{}.{}
",
action.text(),
kind.text(),
path.to_string_lossy(),
err,
),
};
write_project(buffer, diagnostic);
}

Error::Type { path, src, error } => match error {
UnknownLabel {
label,
Expand Down
94 changes: 48 additions & 46 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,63 +117,65 @@ fn command_build(root: String) -> Result<(), Error> {

for crate::project::Compiled { files, .. } in compiled {
for crate::project::OutputFile { text, path } in files {
let dir_path = path
.parent()
.unwrap_or_else(|| panic!("getting output file directory {:?}", path));
std::fs::create_dir_all(dir_path).unwrap_or_else(|e| {
panic!(
"creating output file directory {:?}: {:?}",
dir_path,
e.to_string()
)
});

let mut f = File::create(&path)
.unwrap_or_else(|e| panic!("creating output file {:?}: {:?}", path, e.to_string()));
f.write_all(text.as_bytes()).unwrap_or_else(|e| {
panic!("writing to output file {:?}: {:?}", path, e.to_string())
});
let dir_path = path.parent().ok_or_else(|| Error::FileIO {
action: error::FileIOAction::FindParent,
kind: error::FileKind::Directory,
path: path.clone(),
err: None,
})?;

std::fs::create_dir_all(dir_path).map_err(|e| Error::FileIO {
action: error::FileIOAction::Create,
kind: error::FileKind::Directory,
path: dir_path.to_path_buf(),
err: Some(e.to_string()),
})?;

let mut f = File::create(&path).map_err(|e| Error::FileIO {
action: error::FileIOAction::Create,
kind: error::FileKind::File,
path: path.clone(),
err: Some(e.to_string()),
})?;

f.write_all(text.as_bytes()).map_err(|e| Error::FileIO {
action: error::FileIOAction::WriteTo,
kind: error::FileKind::File,
path: path.clone(),
err: Some(e.to_string()),
})?;
}
}

println!("Done!");
Ok(())
}

fn read_project_config(root: &str) -> Result<ProjectConfig, ()> {
fn die(message: String) -> ! {
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
let mut stderr = StandardStream::stderr(ColorChoice::Always);

// Write "error: " in red
stderr
.set_color(
ColorSpec::new()
.set_fg(Some(Color::Red))
.set_intense(true)
.set_bold(true),
)
.unwrap();
write!(&mut stderr, "error: ").unwrap();

// Write error message in white
stderr.reset().unwrap();
writeln!(&mut stderr, "{}", message).unwrap();

std::process::exit(1);
}

fn read_project_config(root: &str) -> Result<ProjectConfig, Error> {
use std::io::Read;
let config_path = PathBuf::from(root).join("gleam.toml");
let mut file = File::open(config_path)
.unwrap_or_else(|e| die(format!("could not open gleam.toml: {}", e.to_string())));

let mut toml = String::new();
file.read_to_string(&mut toml)
.unwrap_or_else(|e| die(format!("could not read gleam.toml: {}", e.to_string())));
let mut file = File::open(&config_path).map_err(|e| Error::FileIO {
action: error::FileIOAction::Open,
kind: error::FileKind::File,
path: config_path.clone(),
err: Some(e.to_string()),
})?;

let project_config = toml::from_str(&toml)
.unwrap_or_else(|e| die(format!("could not parse gleam.toml: {}", e.to_string())));
let mut toml = String::new();
file.read_to_string(&mut toml).map_err(|e| Error::FileIO {
action: error::FileIOAction::Read,
kind: error::FileKind::File,
path: config_path.clone(),
err: Some(e.to_string()),
})?;

let project_config = toml::from_str(&toml).map_err(|e| Error::FileIO {
action: error::FileIOAction::Parse,
kind: error::FileKind::File,
path: config_path.clone(),
err: Some(e.to_string()),
})?;

Ok(project_config)
}

0 comments on commit 87aa490

Please sign in to comment.