Skip to content

Commit 6487422

Browse files
scampitopecongiro
authored andcommitted
fix print-config minimal option (#3687)
1 parent 0e6896b commit 6487422

File tree

2 files changed

+141
-45
lines changed

2 files changed

+141
-45
lines changed

src/bin/main.rs

Lines changed: 64 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use env_logger;
2-
#[macro_use]
3-
extern crate failure;
2+
use failure::{err_msg, format_err, Error as FailureError, Fail};
3+
use io::Error as IoError;
44

55
use rustfmt_nightly as rustfmt;
66

@@ -10,12 +10,10 @@ use std::io::{self, stdout, Read, Write};
1010
use std::path::{Path, PathBuf};
1111
use std::str::FromStr;
1212

13-
use failure::err_msg;
14-
1513
use getopts::{Matches, Options};
1614

1715
use crate::rustfmt::{
18-
load_config, CliOptions, Color, Config, Edition, EmitMode, ErrorKind, FileLines, FileName,
16+
load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName,
1917
FormatReportFormatterBuilder, Input, Session, Verbosity,
2018
};
2119

@@ -49,20 +47,37 @@ enum Operation {
4947
},
5048
/// Print the help message.
5149
Help(HelpOp),
52-
// Print version information
50+
/// Print version information
5351
Version,
5452
/// Output default config to a file, or stdout if None
55-
ConfigOutputDefault {
56-
path: Option<String>,
57-
},
53+
ConfigOutputDefault { path: Option<String> },
5854
/// Output current config (as if formatting to a file) to stdout
59-
ConfigOutputCurrent {
60-
path: Option<String>,
61-
},
55+
ConfigOutputCurrent { path: Option<String> },
6256
/// No file specified, read from stdin
63-
Stdin {
64-
input: String,
65-
},
57+
Stdin { input: String },
58+
}
59+
60+
/// Rustfmt operations errors.
61+
#[derive(Fail, Debug)]
62+
pub enum OperationError {
63+
/// An unknown help topic was requested.
64+
#[fail(display = "Unknown help topic: `{}`.", _0)]
65+
UnknownHelpTopic(String),
66+
/// An unknown print-config option was requested.
67+
#[fail(display = "Unknown print-config option: `{}`.", _0)]
68+
UnknownPrintConfigTopic(String),
69+
/// Attempt to generate a minimal config from standard input.
70+
#[fail(display = "The `--print-config=minimal` option doesn't work with standard input.")]
71+
MinimalPathWithStdin,
72+
/// An io error during reading or writing.
73+
#[fail(display = "io error: {}", _0)]
74+
IoError(IoError),
75+
}
76+
77+
impl From<IoError> for OperationError {
78+
fn from(e: IoError) -> OperationError {
79+
OperationError::IoError(e)
80+
}
6681
}
6782

6883
/// Arguments to `--help`
@@ -156,7 +171,7 @@ fn is_nightly() -> bool {
156171
}
157172

158173
// Returned i32 is an exit code
159-
fn execute(opts: &Options) -> Result<i32, failure::Error> {
174+
fn execute(opts: &Options) -> Result<i32, FailureError> {
160175
let matches = opts.parse(env::args().skip(1))?;
161176
let options = GetOptsOptions::from_matches(&matches)?;
162177

@@ -210,7 +225,7 @@ fn execute(opts: &Options) -> Result<i32, failure::Error> {
210225
}
211226
}
212227

213-
fn format_string(input: String, options: GetOptsOptions) -> Result<i32, failure::Error> {
228+
fn format_string(input: String, options: GetOptsOptions) -> Result<i32, FailureError> {
214229
// try to read config from local directory
215230
let (mut config, _) = load_config(Some(Path::new(".")), Some(options.clone()))?;
216231

@@ -243,7 +258,7 @@ fn format(
243258
files: Vec<PathBuf>,
244259
minimal_config_path: Option<String>,
245260
options: &GetOptsOptions,
246-
) -> Result<i32, failure::Error> {
261+
) -> Result<i32, FailureError> {
247262
options.verify_file_lines(&files);
248263
let (config, config_path) = load_config(None, Some(options.clone()))?;
249264

@@ -385,7 +400,7 @@ fn print_version() {
385400
println!("rustfmt {}", version_info);
386401
}
387402

388-
fn determine_operation(matches: &Matches) -> Result<Operation, ErrorKind> {
403+
fn determine_operation(matches: &Matches) -> Result<Operation, OperationError> {
389404
if matches.opt_present("h") {
390405
let topic = matches.opt_str("h");
391406
if topic == None {
@@ -395,22 +410,25 @@ fn determine_operation(matches: &Matches) -> Result<Operation, ErrorKind> {
395410
} else if topic == Some("file-lines".to_owned()) {
396411
return Ok(Operation::Help(HelpOp::FileLines));
397412
} else {
398-
println!("Unknown help topic: `{}`\n", topic.unwrap());
399-
return Ok(Operation::Help(HelpOp::None));
413+
return Err(OperationError::UnknownHelpTopic(topic.unwrap()));
400414
}
401415
}
416+
let mut free_matches = matches.free.iter();
402417

403418
let mut minimal_config_path = None;
404-
if let Some(ref kind) = matches.opt_str("print-config") {
405-
let path = matches.free.get(0).cloned();
406-
if kind == "default" {
407-
return Ok(Operation::ConfigOutputDefault { path });
408-
} else if kind == "current" {
409-
return Ok(Operation::ConfigOutputCurrent { path });
410-
} else if kind == "minimal" {
411-
minimal_config_path = path;
412-
if minimal_config_path.is_none() {
413-
println!("WARNING: PATH required for `--print-config minimal`");
419+
if let Some(kind) = matches.opt_str("print-config") {
420+
let path = free_matches.next().cloned();
421+
match kind.as_str() {
422+
"default" => return Ok(Operation::ConfigOutputDefault { path }),
423+
"current" => return Ok(Operation::ConfigOutputCurrent { path }),
424+
"minimal" => {
425+
minimal_config_path = path;
426+
if minimal_config_path.is_none() {
427+
eprintln!("WARNING: PATH required for `--print-config minimal`.");
428+
}
429+
}
430+
_ => {
431+
return Err(OperationError::UnknownPrintConfigTopic(kind));
414432
}
415433
}
416434
}
@@ -419,17 +437,7 @@ fn determine_operation(matches: &Matches) -> Result<Operation, ErrorKind> {
419437
return Ok(Operation::Version);
420438
}
421439

422-
// if no file argument is supplied, read from stdin
423-
if matches.free.is_empty() {
424-
let mut buffer = String::new();
425-
io::stdin().read_to_string(&mut buffer)?;
426-
427-
return Ok(Operation::Stdin { input: buffer });
428-
}
429-
430-
let files: Vec<_> = matches
431-
.free
432-
.iter()
440+
let files: Vec<_> = free_matches
433441
.map(|s| {
434442
let p = PathBuf::from(s);
435443
// we will do comparison later, so here tries to canonicalize first
@@ -438,6 +446,17 @@ fn determine_operation(matches: &Matches) -> Result<Operation, ErrorKind> {
438446
})
439447
.collect();
440448

449+
// if no file argument is supplied, read from stdin
450+
if files.is_empty() {
451+
if minimal_config_path.is_some() {
452+
return Err(OperationError::MinimalPathWithStdin);
453+
}
454+
let mut buffer = String::new();
455+
io::stdin().read_to_string(&mut buffer)?;
456+
457+
return Ok(Operation::Stdin { input: buffer });
458+
}
459+
441460
Ok(Operation::Format {
442461
files,
443462
minimal_config_path,
@@ -464,7 +483,7 @@ struct GetOptsOptions {
464483
}
465484

466485
impl GetOptsOptions {
467-
pub fn from_matches(matches: &Matches) -> Result<GetOptsOptions, failure::Error> {
486+
pub fn from_matches(matches: &Matches) -> Result<GetOptsOptions, FailureError> {
468487
let mut options = GetOptsOptions::default();
469488
options.verbose = matches.opt_present("verbose");
470489
options.quiet = matches.opt_present("quiet");
@@ -598,15 +617,15 @@ impl CliOptions for GetOptsOptions {
598617
}
599618
}
600619

601-
fn edition_from_edition_str(edition_str: &str) -> Result<Edition, failure::Error> {
620+
fn edition_from_edition_str(edition_str: &str) -> Result<Edition, FailureError> {
602621
match edition_str {
603622
"2015" => Ok(Edition::Edition2015),
604623
"2018" => Ok(Edition::Edition2018),
605624
_ => Err(format_err!("Invalid value for `--edition`")),
606625
}
607626
}
608627

609-
fn emit_mode_from_emit_str(emit_str: &str) -> Result<EmitMode, failure::Error> {
628+
fn emit_mode_from_emit_str(emit_str: &str) -> Result<EmitMode, FailureError> {
610629
match emit_str {
611630
"files" => Ok(EmitMode::Files),
612631
"stdout" => Ok(EmitMode::Stdout),

tests/rustfmt/main.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//! Integration tests for rustfmt.
2+
3+
use std::env;
4+
use std::fs::remove_file;
5+
use std::path::Path;
6+
use std::process::Command;
7+
8+
/// Run the rustfmt executable and return its output.
9+
fn rustfmt(args: &[&str]) -> (String, String) {
10+
let mut bin_dir = env::current_exe().unwrap();
11+
bin_dir.pop(); // chop off test exe name
12+
if bin_dir.ends_with("deps") {
13+
bin_dir.pop();
14+
}
15+
let cmd = bin_dir.join(format!("rustfmt{}", env::consts::EXE_SUFFIX));
16+
17+
// Ensure the rustfmt binary runs from the local target dir.
18+
let path = env::var_os("PATH").unwrap_or_default();
19+
let mut paths = env::split_paths(&path).collect::<Vec<_>>();
20+
paths.insert(0, bin_dir);
21+
let new_path = env::join_paths(paths).unwrap();
22+
23+
match Command::new(&cmd).args(args).env("PATH", new_path).output() {
24+
Ok(output) => (
25+
String::from_utf8(output.stdout).expect("utf-8"),
26+
String::from_utf8(output.stderr).expect("utf-8"),
27+
),
28+
Err(e) => panic!("failed to run `{:?} {:?}`: {}", cmd, args, e),
29+
}
30+
}
31+
32+
macro_rules! assert_that {
33+
($args:expr, $check:ident $check_args:tt) => {
34+
let (stdout, stderr) = rustfmt($args);
35+
if !stdout.$check$check_args && !stderr.$check$check_args {
36+
panic!(
37+
"Output not expected for rustfmt {:?}\n\
38+
expected: {}{}\n\
39+
actual stdout:\n{}\n\
40+
actual stderr:\n{}",
41+
$args,
42+
stringify!($check),
43+
stringify!($check_args),
44+
stdout,
45+
stderr
46+
);
47+
}
48+
};
49+
}
50+
51+
#[test]
52+
fn print_config() {
53+
assert_that!(
54+
&["--print-config", "unknown"],
55+
starts_with("Unknown print-config option")
56+
);
57+
assert_that!(&["--print-config", "default"], contains("max_width = 100"));
58+
assert_that!(&["--print-config", "minimal"], contains("PATH required"));
59+
assert_that!(
60+
&["--print-config", "minimal", "minimal-config"],
61+
contains("doesn't work with standard input.")
62+
);
63+
64+
let (stdout, stderr) = rustfmt(&[
65+
"--print-config",
66+
"minimal",
67+
"minimal-config",
68+
"src/shape.rs",
69+
]);
70+
assert!(
71+
Path::new("minimal-config").exists(),
72+
"stdout:\n{}\nstderr:\n{}",
73+
stdout,
74+
stderr
75+
);
76+
remove_file("minimal-config").unwrap();
77+
}

0 commit comments

Comments
 (0)