Skip to content

Commit 5c45513

Browse files
committed
Auto merge of #9469 - PaulDance:fossil-local-settings, r=ehuss
Fix #4482 and #9449: set Fossil ignore and clean settings locally This aims to close #4482 and close #9449. Context: currently, the Fossil extension for `cargo new` would call `fossil settings [...]` in order to configure the created repository to ignore and allow cleaning the `target` build directory. However, as #9449 shows, it is ran from the CWD, which is probably outside of the repo, therefore it modifies global settings instead of local ones. This PR fixes that by writing the settings to local versioned files as the issue recommends. Furthermore, as #9449 notes, configuring the repository's ignore settings only in `util::vcs::FossilRepo::init` means it is not done when the repository is not new and makes it harder to maintain equivalent support for VCS ignore system implementations. It also completely ignores the `--lib` CLI option which adds `Cargo.lock` to the ignore list for Git and Mercurial. Therefore, the following modifications have been performed, using [the Fossil documentation](https://fossil-scm.org/home/doc/trunk/www/globs.md) as a reference for the ignore syntax: * All settings logic has been removed from `FossilRepo::init`. * `ops::cargo_new::IgnoreList::push` now requires a third argument for Fossil-specific glob syntax that is stored in a new `fossil_ignore` field. * `IgnoreList::format_new` uses the `fossil_ignore` field when needed just like any other VCS. * `IgnoreList::format_existing` handles Fossil separately for a few operations as its glob syntax does not support comments, so any lines starting with `#` cannot be included: the configurations can only be merged here. * `write_ignore_file` has been modified a bit as well to enable writing to two files for Fossil specifically in order to keep supporting its cleaning feature. The return type of the function is now `CargoResult<()>` instead `CargoResult<String>`: it makes the implementation easier and as the return value was actually not used, I figured it would be okay to do so, plus that return value would not make too much sense anymore for Fossil because of the two possibly different file contents. * `mk` has been updated to provide the correct ignore glob to `IgnoreList::push` for Fossil.
2 parents 5b37ab3 + 6801c49 commit 5c45513

File tree

2 files changed

+56
-51
lines changed

2 files changed

+56
-51
lines changed

src/cargo/ops/cargo_new.rs

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,8 @@ struct IgnoreList {
517517
ignore: Vec<String>,
518518
/// mercurial formatted entries
519519
hg_ignore: Vec<String>,
520+
/// Fossil-formatted entries.
521+
fossil_ignore: Vec<String>,
520522
}
521523

522524
impl IgnoreList {
@@ -525,22 +527,25 @@ impl IgnoreList {
525527
IgnoreList {
526528
ignore: Vec::new(),
527529
hg_ignore: Vec::new(),
530+
fossil_ignore: Vec::new(),
528531
}
529532
}
530533

531-
/// add a new entry to the ignore list. Requires two arguments with the
532-
/// entry in two different formats. One for "git style" entries and one for
533-
/// "mercurial like" entries.
534-
fn push(&mut self, ignore: &str, hg_ignore: &str) {
534+
/// Add a new entry to the ignore list. Requires three arguments with the
535+
/// entry in possibly three different formats. One for "git style" entries,
536+
/// one for "mercurial style" entries and one for "fossil style" entries.
537+
fn push(&mut self, ignore: &str, hg_ignore: &str, fossil_ignore: &str) {
535538
self.ignore.push(ignore.to_string());
536539
self.hg_ignore.push(hg_ignore.to_string());
540+
self.fossil_ignore.push(fossil_ignore.to_string());
537541
}
538542

539543
/// Return the correctly formatted content of the ignore file for the given
540544
/// version control system as `String`.
541545
fn format_new(&self, vcs: VersionControl) -> String {
542546
let ignore_items = match vcs {
543547
VersionControl::Hg => &self.hg_ignore,
548+
VersionControl::Fossil => &self.fossil_ignore,
544549
_ => &self.ignore,
545550
};
546551

@@ -557,20 +562,30 @@ impl IgnoreList {
557562

558563
let ignore_items = match vcs {
559564
VersionControl::Hg => &self.hg_ignore,
565+
VersionControl::Fossil => &self.fossil_ignore,
560566
_ => &self.ignore,
561567
};
562568

563-
let mut out = "\n\n# Added by cargo\n".to_string();
564-
if ignore_items
565-
.iter()
566-
.any(|item| existing_items.contains(item))
567-
{
568-
out.push_str("#\n# already existing elements were commented out\n");
569+
let mut out = String::new();
570+
571+
// Fossil does not support `#` comments.
572+
if vcs != VersionControl::Fossil {
573+
out.push_str("\n\n# Added by cargo\n");
574+
if ignore_items
575+
.iter()
576+
.any(|item| existing_items.contains(item))
577+
{
578+
out.push_str("#\n# already existing elements were commented out\n");
579+
}
580+
out.push('\n');
569581
}
570-
out.push('\n');
571582

572583
for item in ignore_items {
573584
if existing_items.contains(item) {
585+
if vcs == VersionControl::Fossil {
586+
// Just merge for Fossil.
587+
continue;
588+
}
574589
out.push('#');
575590
}
576591
out.push_str(item);
@@ -584,30 +599,35 @@ impl IgnoreList {
584599
/// Writes the ignore file to the given directory. If the ignore file for the
585600
/// given vcs system already exists, its content is read and duplicate ignore
586601
/// file entries are filtered out.
587-
fn write_ignore_file(
588-
base_path: &Path,
589-
list: &IgnoreList,
590-
vcs: VersionControl,
591-
) -> CargoResult<String> {
592-
let fp_ignore = match vcs {
593-
VersionControl::Git => base_path.join(".gitignore"),
594-
VersionControl::Hg => base_path.join(".hgignore"),
595-
VersionControl::Pijul => base_path.join(".ignore"),
596-
VersionControl::Fossil => return Ok("".to_string()),
597-
VersionControl::NoVcs => return Ok("".to_string()),
598-
};
602+
fn write_ignore_file(base_path: &Path, list: &IgnoreList, vcs: VersionControl) -> CargoResult<()> {
603+
// Fossil only supports project-level settings in a dedicated subdirectory.
604+
if vcs == VersionControl::Fossil {
605+
paths::create_dir_all(base_path.join(".fossil-settings"))?;
606+
}
599607

600-
let ignore: String = match paths::open(&fp_ignore) {
601-
Err(err) => match err.downcast_ref::<std::io::Error>() {
602-
Some(io_err) if io_err.kind() == ErrorKind::NotFound => list.format_new(vcs),
603-
_ => return Err(err),
604-
},
605-
Ok(file) => list.format_existing(BufReader::new(file), vcs),
606-
};
608+
for fp_ignore in match vcs {
609+
VersionControl::Git => vec![base_path.join(".gitignore")],
610+
VersionControl::Hg => vec![base_path.join(".hgignore")],
611+
VersionControl::Pijul => vec![base_path.join(".ignore")],
612+
// Fossil has a cleaning functionality configured in a separate file.
613+
VersionControl::Fossil => vec![
614+
base_path.join(".fossil-settings/ignore-glob"),
615+
base_path.join(".fossil-settings/clean-glob"),
616+
],
617+
VersionControl::NoVcs => return Ok(()),
618+
} {
619+
let ignore: String = match paths::open(&fp_ignore) {
620+
Err(err) => match err.downcast_ref::<std::io::Error>() {
621+
Some(io_err) if io_err.kind() == ErrorKind::NotFound => list.format_new(vcs),
622+
_ => return Err(err),
623+
},
624+
Ok(file) => list.format_existing(BufReader::new(file), vcs),
625+
};
607626

608-
paths::append(&fp_ignore, ignore.as_bytes())?;
627+
paths::append(&fp_ignore, ignore.as_bytes())?;
628+
}
609629

610-
Ok(ignore)
630+
Ok(())
611631
}
612632

613633
/// Initializes the correct VCS system based on the provided config.
@@ -650,12 +670,12 @@ fn mk(config: &Config, opts: &MkOptions<'_>) -> CargoResult<()> {
650670
let name = opts.name;
651671
let cfg = config.get::<CargoNewConfig>("cargo-new")?;
652672

653-
// Using the push method with two arguments ensures that the entries for
654-
// both `ignore` and `hgignore` are in sync.
673+
// Using the push method with multiple arguments ensures that the entries
674+
// for all mutually-incompatible VCS in terms of syntax are in sync.
655675
let mut ignore = IgnoreList::new();
656-
ignore.push("/target", "^target/");
676+
ignore.push("/target", "^target/", "target");
657677
if !opts.bin {
658-
ignore.push("Cargo.lock", "glob:Cargo.lock");
678+
ignore.push("Cargo.lock", "glob:Cargo.lock", "Cargo.lock,*/Cargo.lock");
659679
}
660680

661681
let vcs = opts.version_control.unwrap_or_else(|| {

src/cargo/util/vcs.rs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -95,21 +95,6 @@ impl FossilRepo {
9595
.arg(db_fname)
9696
.exec()?;
9797

98-
// set `target` as ignoreable and cleanable
99-
ProcessBuilder::new("fossil")
100-
.cwd(cwd)
101-
.arg("settings")
102-
.arg("ignore-glob")
103-
.arg("target")
104-
.exec()?;
105-
106-
ProcessBuilder::new("fossil")
107-
.cwd(cwd)
108-
.arg("settings")
109-
.arg("clean-glob")
110-
.arg("target")
111-
.exec()?;
112-
11398
Ok(FossilRepo)
11499
}
115100
}

0 commit comments

Comments
 (0)