Skip to content

Commit 3115481

Browse files
authored
Merge pull request #39 from devwhodevs/fix/system-ca-and-gitignore
fix: trust system CA for model downloads + optional .gitignore bypass
2 parents c2294e9 + bd4255c commit 3115481

5 files changed

Lines changed: 162 additions & 15 deletions

File tree

Cargo.lock

Lines changed: 71 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ tracing = "0.1"
2323
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
2424
tokenizers = { version = "0.22", default-features = false, features = ["fancy-regex"] }
2525
sha2 = "0.10"
26-
ureq = "2.12"
26+
ureq = { version = "2.12", features = ["native-certs"] }
2727
indicatif = "0.17"
2828
dialoguer = "0.12"
2929
console = "0.16"

src/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ pub struct Config {
123123
pub exclude: Vec<String>,
124124
/// Number of files to process per embedding batch.
125125
pub batch_size: usize,
126+
/// Honor `.gitignore` / `.ignore` files when walking the vault. Set false
127+
/// to index files those VCS rules would otherwise skip.
128+
pub respect_gitignore: bool,
126129
/// Whether intelligence features are enabled. None = not yet configured.
127130
pub intelligence: Option<bool>,
128131
/// Model override URIs.
@@ -149,6 +152,7 @@ impl Default for Config {
149152
top_n: 5,
150153
exclude: vec![".obsidian/".to_string()],
151154
batch_size: 64,
155+
respect_gitignore: true,
152156
intelligence: None,
153157
models: ModelConfig::default(),
154158
obsidian: ObsidianConfig::default(),

src/indexer.rs

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,31 @@ pub struct IndexFileResult {
3434

3535
/// Walk a vault directory and collect all `.md` file paths.
3636
///
37-
/// Uses the `ignore` crate so `.gitignore` rules are respected automatically.
38-
/// Additional exclude patterns (e.g. `.obsidian/`) are applied on top.
39-
pub fn walk_vault(path: &Path, exclude: &[String]) -> Result<Vec<PathBuf>> {
40-
let walker = WalkBuilder::new(path)
41-
.standard_filters(true) // respect .gitignore, .ignore, etc.
42-
.build();
37+
/// When `respect_gitignore` is true, the `ignore` crate honors `.gitignore` /
38+
/// `.ignore` rules (within a git repo, per the crate's `require_git` default).
39+
/// Set it false to index files those VCS rules would skip; hidden entries
40+
/// (`.git/`, dotfiles) and the explicit `exclude` patterns are always skipped.
41+
pub fn walk_vault(
42+
path: &Path,
43+
exclude: &[String],
44+
respect_gitignore: bool,
45+
) -> Result<Vec<PathBuf>> {
46+
let mut builder = WalkBuilder::new(path);
47+
if respect_gitignore {
48+
builder.standard_filters(true); // respect .gitignore, .ignore, hidden, etc.
49+
} else {
50+
// Stop honoring .gitignore / .ignore so VCS-ignored files get indexed,
51+
// but still skip hidden entries (.git/, dotfiles) and apply the
52+
// explicit exclude patterns below.
53+
builder
54+
.hidden(true)
55+
.parents(true)
56+
.git_ignore(false)
57+
.git_global(false)
58+
.git_exclude(false)
59+
.ignore(false);
60+
}
61+
let walker = builder.build();
4362

4463
let mut files = Vec::new();
4564
for entry in walker {
@@ -548,7 +567,7 @@ fn run_index_inner(
548567
}
549568

550569
// If rebuild, treat everything as new.
551-
let files = walk_vault(vault_path, &exclude)?;
570+
let files = walk_vault(vault_path, &exclude, config.respect_gitignore)?;
552571

553572
let (new_files, changed_files, deleted_files) = if rebuild {
554573
// On rebuild we skip diffing — all files are "new".
@@ -753,7 +772,7 @@ mod tests {
753772
write_file(root, "image.png", "not markdown");
754773
write_file(root, "readme.txt", "text file");
755774

756-
let files = walk_vault(root, &[]).unwrap();
775+
let files = walk_vault(root, &[], true).unwrap();
757776
assert_eq!(files.len(), 3, "expected 3 .md files, got {:?}", files);
758777
for f in &files {
759778
assert_eq!(f.extension().unwrap(), "md");
@@ -768,7 +787,7 @@ mod tests {
768787
write_file(root, ".obsidian/workspace.md", "obsidian internal");
769788
write_file(root, ".obsidian/plugins/plugin.md", "plugin data");
770789

771-
let files = walk_vault(root, &[".obsidian/".to_string()]).unwrap();
790+
let files = walk_vault(root, &[".obsidian/".to_string()], true).unwrap();
772791
assert_eq!(files.len(), 1, "expected 1 file, got {:?}", files);
773792
assert!(files[0].ends_with("note.md"));
774793
}
@@ -789,7 +808,7 @@ mod tests {
789808
write_file(root, "note.md", "# Note");
790809
write_file(root, "drafts/note.md", "# Draft");
791810

792-
let files = walk_vault(root, &[]).unwrap();
811+
let files = walk_vault(root, &[], true).unwrap();
793812
assert_eq!(
794813
files.len(),
795814
1,
@@ -799,6 +818,48 @@ mod tests {
799818
assert!(files[0].ends_with("note.md"));
800819
}
801820

821+
#[test]
822+
fn test_walk_gitignore_toggle() {
823+
let tmp = TempDir::new().unwrap();
824+
let root = tmp.path();
825+
826+
// Git repo so the ignore crate honors .gitignore (require_git default).
827+
std::process::Command::new("git")
828+
.args(["init"])
829+
.current_dir(root)
830+
.output()
831+
.expect("git init failed");
832+
833+
write_file(root, ".gitignore", "drafts/\n");
834+
write_file(root, "note.md", "# Note");
835+
write_file(root, "drafts/draft.md", "# Draft");
836+
837+
// respect_gitignore = true: the gitignored dir is skipped.
838+
let respected = walk_vault(root, &[], true).unwrap();
839+
assert_eq!(
840+
respected.len(),
841+
1,
842+
"gitignored dir should be skipped, got {:?}",
843+
respected
844+
);
845+
assert!(respected[0].ends_with("note.md"));
846+
847+
// respect_gitignore = false: the gitignored file is indexed too.
848+
let ignored = walk_vault(root, &[], false).unwrap();
849+
let names: Vec<String> = ignored
850+
.iter()
851+
.map(|f| f.file_name().unwrap().to_string_lossy().into_owned())
852+
.collect();
853+
assert_eq!(
854+
ignored.len(),
855+
2,
856+
"expected gitignored file to be included, got {:?}",
857+
ignored
858+
);
859+
assert!(names.contains(&"note.md".to_string()));
860+
assert!(names.contains(&"draft.md".to_string()));
861+
}
862+
802863
#[test]
803864
fn test_detect_new_files() {
804865
let tmp = TempDir::new().unwrap();
@@ -807,7 +868,7 @@ mod tests {
807868
write_file(root, "b.md", "# B");
808869

809870
let store = Store::open_memory().unwrap();
810-
let files = walk_vault(root, &[]).unwrap();
871+
let files = walk_vault(root, &[], true).unwrap();
811872
let (new, changed, deleted) = diff_vault(&files, root, &store).unwrap();
812873

813874
assert_eq!(new.len(), 2, "all files should be new");
@@ -835,7 +896,7 @@ mod tests {
835896
)
836897
.unwrap();
837898

838-
let files = walk_vault(root, &[]).unwrap();
899+
let files = walk_vault(root, &[], true).unwrap();
839900
let (new, changed, deleted) = diff_vault(&files, root, &store).unwrap();
840901

841902
assert_eq!(new.len(), 0);
@@ -878,7 +939,7 @@ mod tests {
878939
)
879940
.unwrap();
880941

881-
let files = walk_vault(root, &[]).unwrap();
942+
let files = walk_vault(root, &[], true).unwrap();
882943
let (new, changed, deleted) = diff_vault(&files, root, &store).unwrap();
883944

884945
assert_eq!(new.len(), 0);

src/main.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ enum Command {
3939
/// Rebuild the index from scratch.
4040
#[arg(long)]
4141
rebuild: bool,
42+
43+
/// Index files that `.gitignore` / `.ignore` would normally exclude.
44+
#[arg(long)]
45+
no_gitignore: bool,
4246
},
4347

4448
/// Search the indexed vault.
@@ -444,9 +448,16 @@ async fn main() -> Result<()> {
444448
let data_dir = Config::data_dir()?;
445449

446450
match cli.command {
447-
Command::Index { path, rebuild } => {
451+
Command::Index {
452+
path,
453+
rebuild,
454+
no_gitignore,
455+
} => {
448456
// Merge CLI vault path over config.
449457
cfg.merge_vault_path(path);
458+
if no_gitignore {
459+
cfg.respect_gitignore = false;
460+
}
450461

451462
// Fall back to current directory if neither CLI nor config provides a vault path.
452463
let vault_path = match &cfg.vault_path {

0 commit comments

Comments
 (0)