Skip to main content

config_disassembler/
ignore_file.rs

1//! Shared ignore-file conventions for every subcommand.
2//!
3//! Every disassemble action accepts an `--ignore-path` flag pointing at a
4//! `.gitignore`-style file. When the flag is omitted we look for
5//! [`DEFAULT_IGNORE_FILENAME`] in the directory disassembly is run from,
6//! falling back to the legacy `.xmldisassemblerignore` filename for the
7//! `xml` subcommand only (with a deprecation warning) so existing setups
8//! keep working.
9
10use std::path::Path;
11
12/// Default ignore-file name used by every format. Can be overridden via
13/// the `--ignore-path` CLI flag.
14pub const DEFAULT_IGNORE_FILENAME: &str = ".cdignore";
15
16/// Legacy `xml-disassembler` ignore-file name. Kept as a fallback for the
17/// `xml` subcommand so users migrating from the standalone crate aren't
18/// silently broken.
19pub const LEGACY_XML_IGNORE_FILENAME: &str = ".xmldisassemblerignore";
20
21/// Resolve the ignore path for the `xml` subcommand.
22///
23/// * If the caller passed `--ignore-path`, return that unchanged.
24/// * Else if [`DEFAULT_IGNORE_FILENAME`] does not exist but
25///   [`LEGACY_XML_IGNORE_FILENAME`] does, log a deprecation warning and
26///   return the legacy filename so existing XML setups keep working.
27/// * Otherwise return [`DEFAULT_IGNORE_FILENAME`] (which the XML handler
28///   tolerates as missing).
29///
30/// `cwd` is the directory the existence checks are resolved against,
31/// normally the process working directory.
32pub fn resolve_xml_ignore_path<'a>(
33    explicit: Option<&'a str>,
34    cwd: &Path,
35) -> std::borrow::Cow<'a, str> {
36    if let Some(p) = explicit {
37        return std::borrow::Cow::Borrowed(p);
38    }
39    let new_default = cwd.join(DEFAULT_IGNORE_FILENAME);
40    if !new_default.exists() {
41        let legacy = cwd.join(LEGACY_XML_IGNORE_FILENAME);
42        if legacy.exists() {
43            log::warn!(
44                "{LEGACY_XML_IGNORE_FILENAME} is deprecated; rename it to {DEFAULT_IGNORE_FILENAME} or pass --ignore-path explicitly."
45            );
46            return std::borrow::Cow::Owned(LEGACY_XML_IGNORE_FILENAME.to_string());
47        }
48    }
49    std::borrow::Cow::Owned(DEFAULT_IGNORE_FILENAME.to_string())
50}
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55
56    #[test]
57    fn explicit_value_is_returned_unchanged() {
58        let cwd = std::env::current_dir().unwrap();
59        let resolved = resolve_xml_ignore_path(Some("custom/.ignore"), &cwd);
60        assert_eq!(resolved, "custom/.ignore");
61    }
62
63    #[test]
64    fn returns_default_when_neither_file_exists() {
65        let temp = tempfile::tempdir().unwrap();
66        let resolved = resolve_xml_ignore_path(None, temp.path());
67        assert_eq!(resolved, DEFAULT_IGNORE_FILENAME);
68    }
69
70    #[test]
71    fn falls_back_to_legacy_when_only_legacy_exists() {
72        let temp = tempfile::tempdir().unwrap();
73        std::fs::write(temp.path().join(LEGACY_XML_IGNORE_FILENAME), "").unwrap();
74        let resolved = resolve_xml_ignore_path(None, temp.path());
75        assert_eq!(resolved, LEGACY_XML_IGNORE_FILENAME);
76    }
77
78    #[test]
79    fn prefers_new_default_when_both_exist() {
80        let temp = tempfile::tempdir().unwrap();
81        std::fs::write(temp.path().join(DEFAULT_IGNORE_FILENAME), "").unwrap();
82        std::fs::write(temp.path().join(LEGACY_XML_IGNORE_FILENAME), "").unwrap();
83        let resolved = resolve_xml_ignore_path(None, temp.path());
84        assert_eq!(resolved, DEFAULT_IGNORE_FILENAME);
85    }
86}