Skip to content

Commit 8b2082b

Browse files
committed
Auto merge of #5943 - dwijnand:fix-allow-staged, r=alexcrichton
Add `--allow-staged` to `cargo fix` Fixes #5737 This is @jljusten's branch, adapted to the testsuite changes in master. Submitted as an alternative to #5910 to expedite #5737 resolution in time for Edition RC 1.
2 parents b1209f8 + 8c2d0df commit 8b2082b

File tree

3 files changed

+79
-18
lines changed

3 files changed

+79
-18
lines changed

Diff for: src/bin/cargo/commands/fix.rs

+6
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ pub fn cli() -> App {
6666
.long("allow-dirty")
6767
.help("Fix code even if the working directory is dirty"),
6868
)
69+
.arg(
70+
Arg::with_name("allow-staged")
71+
.long("allow-staged")
72+
.help("Fix code even if the working directory has staged changes"),
73+
)
6974
.after_help(
7075
"\
7176
This Cargo subcommmand will automatically take rustc's suggestions from
@@ -135,6 +140,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
135140
compile_opts: opts,
136141
allow_dirty: args.is_present("allow-dirty"),
137142
allow_no_vcs: args.is_present("allow-no-vcs"),
143+
allow_staged: args.is_present("allow-staged"),
138144
broken_code: args.is_present("broken-code"),
139145
})?;
140146
Ok(())

Diff for: src/cargo/ops/fix.rs

+32-13
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub struct FixOptions<'a> {
3333
pub compile_opts: CompileOptions<'a>,
3434
pub allow_dirty: bool,
3535
pub allow_no_vcs: bool,
36+
pub allow_staged: bool,
3637
pub broken_code: bool,
3738
}
3839

@@ -87,39 +88,57 @@ fn check_version_control(opts: &FixOptions) -> CargoResult<()> {
8788
error pass `--allow-no-vcs`")
8889
}
8990

90-
if opts.allow_dirty {
91+
if opts.allow_dirty && opts.allow_staged {
9192
return Ok(())
9293
}
9394

9495
let mut dirty_files = Vec::new();
96+
let mut staged_files = Vec::new();
9597
if let Ok(repo) = git2::Repository::discover(config.cwd()) {
96-
let mut opts = git2::StatusOptions::new();
97-
opts.include_ignored(false);
98-
for status in repo.statuses(Some(&mut opts))?.iter() {
99-
if status.status() != git2::Status::CURRENT {
100-
if let Some(path) = status.path() {
101-
dirty_files.push(path.to_string());
102-
}
98+
let mut repo_opts = git2::StatusOptions::new();
99+
repo_opts.include_ignored(false);
100+
for status in repo.statuses(Some(&mut repo_opts))?.iter() {
101+
if let Some(path) = status.path() {
102+
match status.status() {
103+
git2::Status::CURRENT => (),
104+
git2::Status::INDEX_NEW |
105+
git2::Status::INDEX_MODIFIED |
106+
git2::Status::INDEX_DELETED |
107+
git2::Status::INDEX_RENAMED |
108+
git2::Status::INDEX_TYPECHANGE =>
109+
if !opts.allow_staged {
110+
staged_files.push(path.to_string())
111+
},
112+
_ =>
113+
if !opts.allow_dirty {
114+
dirty_files.push(path.to_string())
115+
},
116+
};
103117
}
104118

105119
}
106120
}
107121

108-
if dirty_files.is_empty() {
122+
if dirty_files.is_empty() && staged_files.is_empty() {
109123
return Ok(())
110124
}
111125

112126
let mut files_list = String::new();
113127
for file in dirty_files {
114128
files_list.push_str(" * ");
115129
files_list.push_str(&file);
116-
files_list.push_str("\n");
130+
files_list.push_str(" (dirty)\n");
131+
}
132+
for file in staged_files {
133+
files_list.push_str(" * ");
134+
files_list.push_str(&file);
135+
files_list.push_str(" (staged)\n");
117136
}
118137

119-
bail!("the working directory of this project is detected as dirty, and \
138+
bail!("the working directory of this project has uncommitted changes, and \
120139
`cargo fix` can potentially perform destructive changes; if you'd \
121-
like to suppress this error pass `--allow-dirty`, or commit the \
122-
changes to these files:\n\
140+
like to suppress this error pass `--allow-dirty`, `--allow-staged`, \
141+
or commit the changes to these files:\n\
123142
\n\
124143
{}\n\
125144
", files_list);

Diff for: tests/testsuite/fix.rs

+41-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use support::git;
66
use support::is_nightly;
77
use support::{basic_manifest, project};
88

9+
use std::io::Write;
10+
911
#[test]
1012
fn do_not_fix_broken_builds() {
1113
let p = project()
@@ -725,19 +727,53 @@ fn warns_about_dirty_working_directory() {
725727
.with_status(101)
726728
.with_stderr(
727729
"\
728-
error: the working directory of this project is detected as dirty, and `cargo \
729-
fix` can potentially perform destructive changes; if you'd like to \
730-
suppress this error pass `--allow-dirty`, or commit the changes to \
731-
these files:
730+
error: the working directory of this project has uncommitted changes, \
731+
and `cargo fix` can potentially perform destructive changes; if you'd \
732+
like to suppress this error pass `--allow-dirty`, `--allow-staged`, or \
733+
commit the changes to these files:
732734
733-
* src/lib.rs
735+
* src/lib.rs (dirty)
734736
735737
736738
",
737739
).run();
738740
p.cargo("fix --allow-dirty").run();
739741
}
740742

743+
#[test]
744+
fn warns_about_staged_working_directory() {
745+
let p = project().file("src/lib.rs", "pub fn foo() {}").build();
746+
747+
let repo = git2::Repository::init(&p.root()).unwrap();
748+
let mut cfg = t!(repo.config());
749+
t!(cfg.set_str("user.email", "[email protected]"));
750+
t!(cfg.set_str("user.name", "Foo Bar"));
751+
drop(cfg);
752+
git::add(&repo);
753+
git::commit(&repo);
754+
File::create(&p.root().join("src/lib.rs"))
755+
.unwrap()
756+
.write_all("pub fn bar() {}".to_string().as_bytes())
757+
.unwrap();
758+
git::add(&repo);
759+
760+
p.cargo("fix")
761+
.with_status(101)
762+
.with_stderr(
763+
"\
764+
error: the working directory of this project has uncommitted changes, \
765+
and `cargo fix` can potentially perform destructive changes; if you'd \
766+
like to suppress this error pass `--allow-dirty`, `--allow-staged`, or \
767+
commit the changes to these files:
768+
769+
* src/lib.rs (staged)
770+
771+
772+
",
773+
).run();
774+
p.cargo("fix --allow-staged").run();
775+
}
776+
741777
#[test]
742778
fn does_not_warn_about_clean_working_directory() {
743779
let p = project().file("src/lib.rs", "pub fn foo() {}").build();

0 commit comments

Comments
 (0)