Most notably, this adds a defaults.toml
file which sets the ignore_kinds field. This allows the ignore_kinds field to easily integrate into the configuration layering system, which greatly simplifies the code.
2ZKE4XMJ3Z3IBFJCJCXQ6E76T3QEVBB2VEZCY7ZD4EMRJ2BHKBTQC
HGJETVANHD25AZLOPYYEXCMLZHZWZ2NAKI33XQ7F43XM3UZVQNOQC
U2KAO5VITQW4WW5FVAFJYDV4YNS6NRRZJO5W6VHCS5WR4A23Z2NQC
GYGLQPVXZHCXO62KMR62GBKBGB5EXIC2GYPM53LJFXRKPGBJAARQC
GKSVBEUW7Q2M4QPKPHOUPGP36AMXMJVGX7KCSNYXEFQZOURGBSMQC
SXEYMYF7P4RZMZ46WPL4IZUTSQ2ATBWYZX7QNVMS3SGOYXYOHAGQC
BZSC7VMYSFRXDHDDAMCDR6X67FN5VWIBOSE76BQLX7OCVOJFUA3AC
H72JG6HLA7U3XFOUMWF6F3NFSWK5B6ZM6J5ZTILRSXBA7IM6H75AC
CB7UPUQFOUH6M32KXQZL25EV4IH3XSK56RG3OYNRZBBFEABSNCXQC
UAXGGNAZFUQX2XTVNITFZG54E2W5V4RKJUGEKN7WD2HDLVT5QG6QC
YW6NICQV5LF4V2G77F2RG2ICODTQ2CKIEVBFIQEDATL5I5PFVRKQC
CCLLB7OIFNFYJZTG3UCI7536TOCWSCSXR67VELSB466R24WLJSDAC
QCPIBC6MDPFE42KWELKZQ3ORNEOPSBXR7C7H6Z3ZT62RNVBFN73QC
Q7CHNDXNVJCBL2DK7LYZ6KSRFN4KO6TXKEP3GIWDJHB6JPSE3FUQC
OPC2VAZDO4HL6K4BBNQP5A5YD2DI6UYI7O7ZQWAGLU7Z662PEOBAC
OMTQVGUEGSDJLMQULVJBZUZGHVH5YUABMELWPTD6CQ66P7OACYMAC
Z4PPQZUGHT5F5VFFBQBIW2J3OLHP4SF33QMT6POFCX6JS7L6G7GQC
HM6QW3CYVZVXOM2K3OT7SQFQGJG3GCDLNYIYAUDEVSJCVCSUZ4CQC
L4JXJHWXYNCL4QGJXNKKTOKKTAXKKXBJUUY7HFZGEUZ5A2V5H34QC
7UU3TV5W23QA7LLRBSBXEYPRMIVXPW4FNENEEE7ZEJYXDLXHVX4AC
pub const CONFIG_FILE: &str = "config";
const DEFAULT_IGNORE: [&[u8]; 2] = [b".git", b".DS_Store"];
// Static KV map of names for project kinds |-> elements
// that should go in the `.ignore` file by default.
const IGNORE_KINDS: &[(&[&str], &[&[u8]])] = &[
(&["rust"], &[b"/target", b"Cargo.lock"]),
(&["node", "nodejs"], &[b"node_modules"]),
(&["lean"], &[b"/build"]),
];
init_dot_ignore(config, &cur, kind)?;
let dot_ignore_path = cur.join(".ignore");
// Initialize the `.ignore` file, if it doesn't already exist
if !dot_ignore_path.exists() {
let mut dot_ignore_file = File::create_new(&dot_ignore_path)?;
let file_contents = config.dot_ignore_contents(kind)?;
dot_ignore_file.write_all(file_contents.as_bytes())?;
}
}
}
}
/// Create and populate an initial `.ignore` file for the repository.
/// The default elements are defined in the constant [`DEFAULT_IGNORE`].
fn init_dot_ignore(
config: &pijul_config::Config,
base_path: &Path,
kind: Option<&str>,
) -> Result<(), anyhow::Error> {
use std::io::Write;
let dot_ignore_path = base_path.join(".ignore");
// Don't replace/modify an existing `.ignore` file.
if dot_ignore_path.exists() {
Ok(())
} else {
let mut dot_ignore = std::fs::OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(dot_ignore_path)?;
for default_ignore in DEFAULT_IGNORE.iter() {
dot_ignore.write_all(default_ignore)?;
dot_ignore.write_all(b"\n")?;
/// if `kind` matches any of the known project kinds, add the associated
/// .ignore entries to the default `.ignore` file.
fn ignore_specific(
config: &pijul_config::Config,
dot_ignore: &mut std::fs::File,
kind: Option<&str>,
) -> Result<(), anyhow::Error> {
use std::io::Write;
if let Some(kind) = kind {
if let Some(kinds) = config.ignore_kinds.get(kind) {
for entry in kinds.iter() {
writeln!(dot_ignore, "{}", entry)?;
}
return Ok(());
}
let entries = IGNORE_KINDS
.iter()
.find(|(names, _)| names.iter().any(|x| kind.eq_ignore_ascii_case(x)))
.into_iter()
.flat_map(|(_, v)| v.iter());
for entry in entries {
dot_ignore.write_all(entry)?;
dot_ignore.write_all(b"\n")?;
}
}
Ok(())
}
// Find any extra lines to add to the `.ignore`, if they exist
let extra_ignore_lines = match ignore_kind {
Some(kind) => match self.ignore_kinds.get(kind) {
Some(extra_ignore_lines) => extra_ignore_lines.iter(),
None => {
return Err(anyhow::anyhow!(
"Unable to find specific ignore kind: {kind}"
));
}
},
None => [].iter(),
};
// Merge the default and specific ignore lines
let mut ignore_lines = default_ignore_lines
.iter()
.chain(extra_ignore_lines)
.map(|line| line.as_str())
.collect::<Vec<_>>()
.join("\n");
// Add a newline at the end of the file
if !ignore_lines.is_empty() {
ignore_lines.push('\n');
}
Ok(ignore_lines)
}
# Default configuration values
[ignore_kinds]
default = [".git", ".DS_Store"]
rust = ["/target", "Cargo.lock"]
node = ["nodejs", "node_modules"]
lean = ["/build"]