Skip to content

Commit 13e107e

Browse files
authored
feat(mro): Improve martian_make_mro (#498)
Include the filename in the error message of martian_make_mro. Use current_executable in get_generator_name. Deref symlinks in current_executable.
1 parent ac52194 commit 13e107e

File tree

3 files changed

+42
-48
lines changed

3 files changed

+42
-48
lines changed

martian/src/lib.rs

Lines changed: 35 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,23 @@
33
//!
44
//! ## Documentation
55
//! For a guide style documentation and examples, visit: [https://martian-lang.github.io/martian-rust/](https://martian-lang.github.io/martian-rust/#/)
6-
//!
76
87
pub use anyhow::Error;
9-
use anyhow::{format_err, Context};
8+
use anyhow::{ensure, Context, Result};
109
use backtrace::Backtrace;
1110
use log::{error, info};
12-
1311
use std::collections::HashMap;
1412
use std::fmt::Write as FmtWrite;
1513
use std::fs::File;
1614
use std::io::Write as IoWrite;
1715
use std::os::unix::io::{FromRawFd, IntoRawFd};
1816
use std::path::Path;
19-
2017
use std::{io, panic};
2118
use time::format_description::modifier::{Day, Hour, Minute, Month, Second, Year};
2219
use time::format_description::FormatItem::Literal;
2320
use time::format_description::{Component, FormatItem};
2421
use time::OffsetDateTime;
22+
use utils::current_executable;
2523

2624
mod metadata;
2725
pub use metadata::*;
@@ -42,15 +40,15 @@ pub use log::LevelFilter;
4240
pub use mro::*;
4341
pub mod prelude;
4442

45-
pub fn initialize(args: Vec<String>) -> Result<Metadata, Error> {
43+
pub fn initialize(args: Vec<String>) -> Result<Metadata> {
4644
let mut md = Metadata::new(args);
4745
md.update_jobinfo()?;
4846

4947
Ok(md)
5048
}
5149

5250
#[cold]
53-
fn write_errors(msg: &str, is_assert: bool) -> Result<(), Error> {
51+
fn write_errors(msg: &str, is_assert: bool) -> Result<()> {
5452
let mut err_file: File = unsafe { File::from_raw_fd(4) };
5553

5654
// We want to aggressively avoid allocations here if we can, since one
@@ -79,7 +77,7 @@ fn write_errors(msg: &str, is_assert: bool) -> Result<(), Error> {
7977
// We could use the proc macro, but then we'd need
8078
// to compile the proc macro crate, which would slow down build times
8179
// significantly for very little benefit in readability.
82-
pub(crate) const DATE_FORMAT: &[FormatItem] = &[
80+
pub(crate) const DATE_FORMAT: &[FormatItem<'_>] = &[
8381
FormatItem::Component(Component::Year(Year::default())),
8482
Literal(b"-"),
8583
FormatItem::Component(Component::Month(Month::default())),
@@ -195,13 +193,13 @@ fn martian_entry_point<S: std::hash::BuildHasher>(
195193
};
196194

197195
// Get the stage implementation
198-
let _stage = stage_map.get(&md.stage_name).ok_or_else(
196+
let stage = stage_map.get(&md.stage_name).with_context(
199197
#[cold]
200-
|| format_err!("Couldn't find requested Martian stage: {}", md.stage_name),
198+
|| format!("Couldn't find requested Martian stage: {}", md.stage_name),
201199
);
202200

203201
// special handler for non-existent stage
204-
let stage = match _stage {
202+
let stage = match stage {
205203
Ok(s) => s,
206204
Err(e) => {
207205
let _ = write_errors(&format!("{e:?}"), false);
@@ -286,48 +284,43 @@ fn report_error(md: &mut Metadata, e: &Error, is_assert: bool) {
286284
let _ = write_errors(&format!("{e:#}"), is_assert);
287285
}
288286

287+
/// Return the environment variable CARGO_PKG_NAME or the current executable name.
289288
fn get_generator_name() -> String {
290-
std::env::var("CARGO_BIN_NAME")
291-
.or_else(|_| std::env::var("CARGO_CRATE_NAME"))
292-
.or_else(|_| std::env::var("CARGO_PKG_NAME"))
293-
.unwrap_or_else(|_| {
294-
option_env!("CARGO_BIN_NAME")
295-
.or(option_env!("CARGO_CRATE_NAME"))
296-
.unwrap_or("martian-rust")
297-
.into()
298-
})
289+
std::env::var("CARGO_PKG_NAME").unwrap_or_else(|_| current_executable())
299290
}
300291

292+
/// Write MRO to filename or stdout.
301293
pub fn martian_make_mro(
302294
header_comment: &str,
303-
file_name: Option<impl AsRef<Path>>,
295+
filename: Option<impl AsRef<Path>>,
304296
rewrite: bool,
305297
mro_registry: Vec<StageMro>,
306-
) -> Result<(), Error> {
307-
if let Some(ref f) = file_name {
308-
let file_path = f.as_ref();
309-
if file_path.is_dir() {
310-
return Err(format_err!(
311-
"Error! Path {} is a directory!",
312-
file_path.display()
313-
));
314-
}
315-
if file_path.exists() && !rewrite {
316-
return Err(format_err!(
317-
"File {} exists. You need to explicitly mention if it is okay to rewrite.",
318-
file_path.display()
319-
));
320-
}
298+
) -> Result<()> {
299+
if let Some(filename) = &filename {
300+
let filename = filename.as_ref();
301+
ensure!(
302+
!filename.is_dir(),
303+
"Path {} is a directory",
304+
filename.display()
305+
);
306+
ensure!(
307+
rewrite || !filename.exists(),
308+
"File {} exists. Use --rewrite to overwrite it.",
309+
filename.display()
310+
);
321311
}
322312

323-
let final_mro_string = make_mro_string(header_comment, &mro_registry);
324-
match file_name {
325-
Some(f) => {
326-
let mut output = File::create(f)?;
327-
output.write_all(final_mro_string.as_bytes())?;
313+
let mro = make_mro_string(header_comment, &mro_registry);
314+
match filename {
315+
Some(filename) => {
316+
let filename = filename.as_ref();
317+
File::create(filename)
318+
.with_context(|| filename.display().to_string())?
319+
.write_all(mro.as_bytes())
320+
.with_context(|| filename.display().to_string())?;
328321
}
329322
None => {
330-
print!("{final_mro_string}");
323+
print!("{mro}");
331324
}
332325
}
333326
Ok(())
@@ -361,8 +354,7 @@ pub fn make_mro_string(header_comment: &str, mro_registry: &[StageMro]) -> Strin
361354
header_comment
362355
.lines()
363356
.all(|line| line.trim_end().is_empty() || line.starts_with('#')),
364-
"All non-empty header lines must start with '#', but got\n{}",
365-
header_comment
357+
"All non-empty header lines must start with '#', but got\n{header_comment}"
366358
);
367359
format!(
368360
"{}

martian/src/metadata.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ impl Metadata {
179179

180180
/// Update the Martian journal -- so that Martian knows what we've updated
181181
fn update_journal(&self, name: &str) -> Result<()> {
182-
let journal_name: Cow<str> = if self.stage_type != "main" {
182+
let journal_name: Cow<'_, str> = if self.stage_type != "main" {
183183
format!("{}_{name}", self.stage_type).into()
184184
} else {
185185
name.into()

martian/src/utils.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,14 @@ pub fn to_camel_case(stage_name: &str) -> String {
5252
/// Parse the `env::args()` and return the name of the
5353
/// current executable as a String
5454
pub fn current_executable() -> String {
55-
let args: Vec<_> = std::env::args().collect();
56-
std::path::Path::new(&args[0])
55+
Path::new(&std::env::args().next().unwrap())
56+
.canonicalize()
57+
.unwrap()
5758
.file_name()
5859
.unwrap()
59-
.to_string_lossy()
60-
.into_owned()
60+
.to_str()
61+
.unwrap()
62+
.to_string()
6163
}
6264

6365
/// Given a filename and an extension, return the filename with the correct extension.

0 commit comments

Comments
 (0)