Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --allow-staged to cargo fix #5943

Merged
merged 4 commits into from
Aug 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/bin/cargo/commands/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ pub fn cli() -> App {
.long("allow-dirty")
.help("Fix code even if the working directory is dirty"),
)
.arg(
Arg::with_name("allow-staged")
.long("allow-staged")
.help("Fix code even if the working directory has staged changes"),
)
.after_help(
"\
This Cargo subcommmand will automatically take rustc's suggestions from
Expand Down Expand Up @@ -135,6 +140,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
compile_opts: opts,
allow_dirty: args.is_present("allow-dirty"),
allow_no_vcs: args.is_present("allow-no-vcs"),
allow_staged: args.is_present("allow-staged"),
broken_code: args.is_present("broken-code"),
})?;
Ok(())
Expand Down
45 changes: 32 additions & 13 deletions src/cargo/ops/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub struct FixOptions<'a> {
pub compile_opts: CompileOptions<'a>,
pub allow_dirty: bool,
pub allow_no_vcs: bool,
pub allow_staged: bool,
pub broken_code: bool,
}

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

if opts.allow_dirty {
if opts.allow_dirty && opts.allow_staged {
return Ok(())
}

let mut dirty_files = Vec::new();
let mut staged_files = Vec::new();
if let Ok(repo) = git2::Repository::discover(config.cwd()) {
let mut opts = git2::StatusOptions::new();
opts.include_ignored(false);
for status in repo.statuses(Some(&mut opts))?.iter() {
if status.status() != git2::Status::CURRENT {
if let Some(path) = status.path() {
dirty_files.push(path.to_string());
}
let mut repo_opts = git2::StatusOptions::new();
repo_opts.include_ignored(false);
for status in repo.statuses(Some(&mut repo_opts))?.iter() {
if let Some(path) = status.path() {
match status.status() {
git2::Status::CURRENT => (),
git2::Status::INDEX_NEW |
git2::Status::INDEX_MODIFIED |
git2::Status::INDEX_DELETED |
git2::Status::INDEX_RENAMED |
git2::Status::INDEX_TYPECHANGE =>
if !opts.allow_staged {
staged_files.push(path.to_string())
},
_ =>
if !opts.allow_dirty {
dirty_files.push(path.to_string())
},
};
}

}
}

if dirty_files.is_empty() {
if dirty_files.is_empty() && staged_files.is_empty() {
return Ok(())
}

let mut files_list = String::new();
for file in dirty_files {
files_list.push_str(" * ");
files_list.push_str(&file);
files_list.push_str("\n");
files_list.push_str(" (dirty)\n");
}
for file in staged_files {
files_list.push_str(" * ");
files_list.push_str(&file);
files_list.push_str(" (staged)\n");
}

bail!("the working directory of this project is detected as dirty, and \
bail!("the working directory of this project has uncommitted changes, and \
`cargo fix` can potentially perform destructive changes; if you'd \
like to suppress this error pass `--allow-dirty`, or commit the \
changes to these files:\n\
like to suppress this error pass `--allow-dirty`, `--allow-staged`, \
or commit the changes to these files:\n\
\n\
{}\n\
", files_list);
Expand Down
46 changes: 41 additions & 5 deletions tests/testsuite/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use support::git;
use support::is_nightly;
use support::{basic_manifest, project};

use std::io::Write;

#[test]
fn do_not_fix_broken_builds() {
let p = project()
Expand Down Expand Up @@ -725,19 +727,53 @@ fn warns_about_dirty_working_directory() {
.with_status(101)
.with_stderr(
"\
error: the working directory of this project is detected as dirty, and `cargo \
fix` can potentially perform destructive changes; if you'd like to \
suppress this error pass `--allow-dirty`, or commit the changes to \
these files:
error: the working directory of this project has uncommitted changes, \
and `cargo fix` can potentially perform destructive changes; if you'd \
like to suppress this error pass `--allow-dirty`, `--allow-staged`, or \
commit the changes to these files:

* src/lib.rs
* src/lib.rs (dirty)


",
).run();
p.cargo("fix --allow-dirty").run();
}

#[test]
fn warns_about_staged_working_directory() {
let p = project().file("src/lib.rs", "pub fn foo() {}").build();

let repo = git2::Repository::init(&p.root()).unwrap();
let mut cfg = t!(repo.config());
t!(cfg.set_str("user.email", "foo@bar.com"));
t!(cfg.set_str("user.name", "Foo Bar"));
drop(cfg);
git::add(&repo);
git::commit(&repo);
File::create(&p.root().join("src/lib.rs"))
.unwrap()
.write_all("pub fn bar() {}".to_string().as_bytes())
.unwrap();
git::add(&repo);

p.cargo("fix")
.with_status(101)
.with_stderr(
"\
error: the working directory of this project has uncommitted changes, \
and `cargo fix` can potentially perform destructive changes; if you'd \
like to suppress this error pass `--allow-dirty`, `--allow-staged`, or \
commit the changes to these files:

* src/lib.rs (staged)


",
).run();
p.cargo("fix --allow-staged").run();
}

#[test]
fn does_not_warn_about_clean_working_directory() {
let p = project().file("src/lib.rs", "pub fn foo() {}").build();
Expand Down