Skip to content
Open
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Fixed

- Sentinel matches nested under directories configured with `[fixed_dirs] extra` are now
skipped, avoiding redundant per-directory Time Machine exclusions before the configured
parent directory is excluded ([#132](https://github.com/AsimovMac/asimov/issues/132)).

### Removed

## [0.12.0] — 2026-07-30
Expand Down
18 changes: 14 additions & 4 deletions lib/asimov/exclude.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,24 @@ exclude_paths_from_stdin() {
fi
verbose_timing "Filtered: ${#to_exclude[@]} new, ${already_excluded} already excluded"

# Layer 2: Filter descendants of ASIMOV_FIXED_DIRS — they'll be excluded
# unconditionally later, so calling tmutil on them individually is wasted (~11s each).
if [[ "$ASIMOV_CONFIG_FIXED_DIRS_ENABLED" == "true" && ${#to_exclude[@]} -gt 0 ]]; then
# Layer 2: Filter descendants of enabled built-in fixed dirs and configured
# extra fixed dirs — they'll be excluded unconditionally later, so calling
# tmutil on them individually is wasted (~11s each).
local -a effective_fixed_dirs=()
if [[ "$ASIMOV_CONFIG_FIXED_DIRS_ENABLED" == "true" ]]; then
effective_fixed_dirs=("${ASIMOV_FIXED_DIRS[@]}")
fi
local configured_fixed_dir
for configured_fixed_dir in ${ASIMOV_CONFIG_EXTRA_FIXED_DIRS[@]+"${ASIMOV_CONFIG_EXTRA_FIXED_DIRS[@]}"}; do
effective_fixed_dirs+=("$configured_fixed_dir")
done

if [[ ${#effective_fixed_dirs[@]} -gt 0 && ${#to_exclude[@]} -gt 0 ]]; then
local -a filtered_exclude=()
for path in "${to_exclude[@]}"; do
local under_fixed=false
local fixed_dir
for fixed_dir in "${ASIMOV_FIXED_DIRS[@]}"; do
for fixed_dir in "${effective_fixed_dirs[@]}"; do
if [[ "$path" == "${fixed_dir}/"* ]]; then
under_fixed=true
break
Expand Down
26 changes: 26 additions & 0 deletions tests/behavior.bats
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,32 @@ extra = ~/.cache-b"
assert_excluded "${HOME}/.cache-b"
}

@test "config: extra fixed dir suppresses nested sentinel exclusions when fixed dirs enabled" {
create_project ".custom-cache/My-Project" "package.json" "node_modules"
write_config "[fixed_dirs]
enabled = true
extra = ~/.custom-cache"

run_asimov --no-cache

assert_excluded "${HOME}/.custom-cache"
refute_excluded "${HOME}/.custom-cache/My-Project/node_modules"
[[ "$(count_exclusions)" -eq 1 ]]
}

@test "config: extra fixed dir suppresses nested sentinel exclusions when fixed dirs disabled" {
create_project ".custom-cache/My-Project" "package.json" "node_modules"
write_config "[fixed_dirs]
enabled = false
extra = ~/.custom-cache"

run_asimov --no-cache

assert_excluded "${HOME}/.custom-cache"
refute_excluded "${HOME}/.custom-cache/My-Project/node_modules"
[[ "$(count_exclusions)" -eq 1 ]]
}

@test "config: extra sentinel pair triggers exclusion" {
create_project "Code/My-Project" "custom.config" ".custom-deps"
write_config "[sentinels]
Expand Down