You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: skip read-only dirs and stop tmutil's POSIXError leaking into output
Go's module cache is deliberately 0555. A Time Machine exclusion is stored as
an xattr on the item itself, so a read-only directory can never take one —
tmutil fails with "Error (-20)" / EINVAL(22) after burning ~11s per call.
The failures were long attributed to the '@' in Go module version paths. That
was wrong: a writable path containing '@' excludes fine; permissions were
always the cause. Comments corrected and both cases now have regression tests.
- Pre-check writability and skip with an accurate message, before the ~11s call
- Silence tmutil's stdout too: it prints its POSIXError dump to stdout, not
stderr, so the existing 2>/dev/null never suppressed it
- Add ~/go/pkg/mod to ASIMOV_FIXED_DIRS — excludes the cache in one call and
lets the existing Layer 2 filter drop every vendor/ dir beneath it
- Mock tmutil now mirrors the real stream split (dump on stdout, error on
stderr) so the suite can actually catch this class of leak
- README: split Install into Stable / Beta / Quick start; refresh Credits for
the handover; document the Go cache and custom-GOPATH config
Copy file name to clipboardExpand all lines: CHANGELOG.md
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,10 +8,16 @@ This project adheres to [Semantic Versioning](http://semver.org/).
8
8
9
9
### Added
10
10
11
+
- Go's module cache (`~/go/pkg/mod`) is now one of the built-in global caches (opt-in via `[fixed_dirs] enabled = true`). Excluding the cache root covers every dependency inside it in a single `tmutil` call, instead of attempting each `vendor/` directory individually (~11s apiece, and doomed — see below). Using a custom `GOPATH`? Add it with `[fixed_dirs] extra`
12
+
11
13
### Changed
12
14
13
15
### Fixed
14
16
17
+
- Read-only directories are now detected and skipped up front with a clear `read-only, cannot be excluded` message, instead of burning ~11s on a `tmutil addexclusion` call that can never succeed. A Time Machine exclusion is stored as an extended attribute **on the item itself**, so a `0555` directory can never take one — Go's module cache is deliberately read-only, which is why its `vendor/` directories always failed
18
+
-`tmutil`'s `POSIXError(_nsError: …Code=22 "Invalid argument")` dump no longer leaks into Asimov's output. `tmutil` prints it to **stdout** (not stderr), so the existing `2>/dev/null` never suppressed it; both streams are now silenced and Asimov prints its own warning instead
19
+
- Corrected a long-standing misdiagnosis in the code comments: these failures were attributed to the `@` in Go module version paths. `@` is irrelevant — a writable path containing `@` excludes fine. Read-only permissions were always the cause (regression tests now cover both)
That's it — Asimov installs to `~/.local/bin` and runs at midday, every day. See [other install methods](#other-install-methods) for Homebrew and source installs.
36
+
Installs to `~/.local/bin`. Feedback and bug reports very welcome — [open an issue](https://github.com/AsimovMac/asimov/issues).
37
+
38
+
### Quick start
39
+
40
+
```sh
41
+
asimov --dry-run # preview what would be excluded — changes nothing
42
+
asimov # apply
43
+
```
44
+
45
+
That's it. Asimov then runs itself once a day, every day. Add `--stats` to either command to see sizes and how much space you're saving.
46
+
47
+
See [other install methods](#other-install-methods) to build from source.
26
48
27
49
## What you'll see
28
50
@@ -79,7 +101,7 @@ This means Asimov never touches a folder that just happens to share a common nam
**Don't see your tool?** You can teach Asimov your own directory + sentinel pairs in a couple of lines — no need to wait for a release. See [Add your own patterns](#add-your-own-patterns).
85
107
@@ -146,17 +168,11 @@ Global tool caches in your home directory (`~/.cache`, `~/.gradle/caches`, …)
146
168
[fixed_dirs]
147
169
enabled = true # exclude the built-in global caches
148
170
extra = ~/my-build-cache # plus any paths you name (always excluded when they exist)
171
+
extra = ~/golang/pkg/mod # e.g. a Go module cache under a custom GOPATH
149
172
```
150
173
151
174
## Other install methods
152
175
153
-
**Homebrew** — the tap currently tracks the last stable (`0.8.0`), not the `0.9.0` beta:
154
-
155
-
```sh
156
-
brew install django23/tap/asimov
157
-
brew services start django23/tap/asimov
158
-
```
159
-
160
176
**From source:**
161
177
162
178
```sh
@@ -179,7 +195,11 @@ See [UPGRADING.md](UPGRADING.md) for migrating from v0.4.x or the original `stev
179
195
180
196
## Credits
181
197
182
-
Asimov was created by [Steve Grunwell](https://github.com/stevegrunwell) and maintained at [`stevegrunwell/asimov`](https://github.com/stevegrunwell/asimov) through v0.3.0. Versions since `0.4.0` add performance improvements, config-file support, and expanded ecosystem coverage.
198
+
Asimov was created by **[Steve Grunwell](https://github.com/stevegrunwell)**, who built and maintained it at `stevegrunwell/asimov` from 2018 through v0.3.0 — the version most people know it by. Thank you, Steve, for the years of work and for [handing it on](https://github.com/AsimovMac/asimov/issues/99) so carefully.
199
+
200
+
The project now lives at [`AsimovMac/asimov`](https://github.com/AsimovMac/asimov) (the original repo, transferred — the old URL still redirects here), maintained by [@django23](https://github.com/django23). Releases from `v0.4.0` onward add expanded ecosystem coverage, a config file, and the caching that took typical runs from ~75s to ~1–2s.
201
+
202
+
Built on the contributions of everyone who filed issues and PRs over the years. Asimov is, and stays, MIT-licensed and community-driven.
0 commit comments