Skip to content

Commit e661d07

Browse files
committed
Merge origin/main into pr-121, porting the Vagrant cache to data/fixed-dirs.tsv
The monolithic `asimov` is gone as of AsimovMac#126, so the ASIMOV_FIXED_DIRS entry becomes a row in data/fixed-dirs.tsv, placed in the file's alphabetical order rather than appended. Test, README table and CHANGELOG entry carry over unchanged.
2 parents bf104cd + 25677dc commit e661d07

29 files changed

Lines changed: 2245 additions & 1693 deletions

.github/workflows/release.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,20 @@ jobs:
3737
NOTES_FILE=$(mktemp)
3838
awk '/^## \['"$BASE_VERSION"'\]/{found=1; next} found && /^## /{exit} found{print}' CHANGELOG.md > "$NOTES_FILE"
3939
40+
# Asimov is a launcher plus a library and data files, so the asset is a
41+
# tarball of all three rather than a single script. It unpacks to
42+
# asimov-<version>/{bin,lib,data} and installs with scripts/install.sh.
43+
STAGE="asimov-${FULL_VERSION}"
44+
mkdir -p "$STAGE"
45+
cp -a bin lib data scripts LICENSE README.md CHANGELOG.md \
46+
com.stevegrunwell.asimov.plist "$STAGE/"
47+
TARBALL="${STAGE}.tar.gz"
48+
tar -czf "$TARBALL" "$STAGE"
49+
4050
gh release create "$TAG" \
4151
--title "Asimov $TAG" \
4252
--notes-file "$NOTES_FILE" \
4353
$PRERELEASE_FLAG \
44-
asimov
54+
"$TARBALL"
4555
46-
rm -f "$NOTES_FILE"
56+
rm -rf "$NOTES_FILE" "$STAGE" "$TARBALL"

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,15 @@ This project adheres to [Semantic Versioning](http://semver.org/).
1212
when you opt in with `[fixed_dirs] enabled = true`
1313
([#117](https://github.com/AsimovMac/asimov/issues/117)).
1414

15+
- `asimov doctor` now checks the data files and reports how many sentinels and fixed directories are loaded, so an incomplete install is diagnosed rather than just failing.
16+
1517
### Changed
1618

19+
- **Asimov is no longer a single file.** The launcher lives at `bin/asimov`, the logic in `lib/asimov/*.sh`, and the directory lists in `data/*.tsv`. Installed, those become `<prefix>/bin/asimov`, `<prefix>/libexec/asimov/` and `<prefix>/share/asimov/`. Behaviour is unchanged; every existing test passes untouched.
20+
- Sentinels, fixed directories and skip paths are now tab-separated data files instead of bash arrays. Each record carries its ecosystem or owning tool as a real field, so adding a pattern is a one-line edit with no bash syntax involved.
21+
- The remote installer (`scripts/install-remote.sh`) downloads a tarball instead of a single script, and installs under `~/.local`.
22+
- Release assets are now `asimov-<version>.tar.gz` rather than a bare `asimov` script.
23+
1724
### Fixed
1825

1926
### Removed

CONTRIBUTING.md

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,22 @@ The main script supports `--help`, `--version`, `--dry-run`, `--verbose`, and `-
5858

5959
## Adding a new dependency pattern
6060

61-
This is the most common type of contribution. To add a new ecosystem or dependency directory:
61+
This is the most common type of contribution, and it needs no bash: sentinels live in a data file.
6262

63-
1. **Add the sentinel pair** to the `ASIMOV_VENDOR_DIR_SENTINELS` array in [`asimov`](asimov) — one `'directory sentinel'` entry per pattern.
64-
2. **Add a test** in [`tests/sentinels.bats`](tests/sentinels.bats) using `create_project` to build the fixture. Keep this file in sync with `ASIMOV_VENDOR_DIR_SENTINELS` (one test per sentinel pair).
63+
1. **Add a row** to [`data/sentinels.tsv`](data/sentinels.tsv) — one per pattern, fields separated by a **tab**.
64+
2. **Add a test** in [`tests/sentinels.bats`](tests/sentinels.bats) using `create_project` to build the fixture. Keep this file in sync with `data/sentinels.tsv` (one test per row).
6565
3. **Run `make check`** to verify your changes pass tests and linting.
6666
4. **Add a changelog entry** under the `[Unreleased]` section in [`CHANGELOG.md`](CHANGELOG.md).
6767

68-
**Example sentinel entry:**
68+
**Example sentinel row** (`dir`, `sentinel`, `ecosystem`, `note`):
6969

70-
```bash
71-
'.zig-cache build.zig' # Zig build cache
70+
```tsv
71+
.zig-cache build.zig zig build cache
7272
```
7373

74-
This means: exclude `.zig-cache/` only when `build.zig` exists in the same directory.
74+
This means: exclude `.zig-cache/` only when `build.zig` exists in the same directory. Glob metacharacters are allowed in the sentinel, e.g. `DerivedData *.xcodeproj`.
75+
76+
The same applies to global caches ([`data/fixed-dirs.tsv`](data/fixed-dirs.tsv)) and skipped directories ([`data/skip-paths.tsv`](data/skip-paths.tsv)). Paths in those two are **relative to the home directory** — write `.npm/_cacache`, not `~/.npm/_cacache`.
7577

7678
## Commit conventions
7779

@@ -105,10 +107,28 @@ type(scope): short description
105107
## Project structure
106108

107109
```
108-
asimov # Main bash script
110+
bin/asimov # Launcher: finds the library and data, then runs it
111+
lib/asimov/
112+
bootstrap.sh # Colours, constants, root and state-path resolution
113+
config.sh # ~/.config/asimov/config
114+
data.sh # Loaders for the data/ entities
115+
cache.sh # ~/.cache/asimov state and the path cache
116+
scan.sh # Which dirs to scan, and the find expression
117+
discover.sh # Spotlight top-up on a cached run
118+
exclude.sh # tmutil addexclusion, with its filters
119+
report.sh # Usage, size formatting, run summary
120+
prune.sh # The prune subcommand
121+
doctor.sh # The doctor subcommand
122+
main.sh # Argument parsing and dispatch
123+
data/
124+
sentinels.tsv # Directory + sentinel pairs
125+
fixed-dirs.tsv # Global tool caches, always excluded
126+
skip-paths.tsv # Directories never descended into
109127
tests/
110128
sentinels.bats # Tests for each dependency pattern
111129
behavior.bats # Tests for edge cases and general behavior
130+
cache.bats # Tests for the path cache
131+
doctor.bats # Tests for the doctor subcommand
112132
format.bats # Unit tests for format_size_kb()
113133
plist.bats # Tests for the LaunchAgent plist
114134
test_helper.bash # Shared setup/teardown and assertions
@@ -121,13 +141,24 @@ scripts/
121141
Makefile # Build targets (test, lint, check, install, uninstall)
122142
```
123143

144+
Installed, the three top-level pieces land under one prefix: `<prefix>/bin/asimov`,
145+
`<prefix>/libexec/asimov/` and `<prefix>/share/asimov/`. The launcher resolves its
146+
own physical path (through symlinks, as Homebrew creates) and probes for both that
147+
layout and the repo layout, so `./bin/asimov` works straight from a checkout.
148+
`ASIMOV_LIB` and `ASIMOV_DATA` override the probe.
149+
150+
**Linting is whole-program.** `make lint` runs `shellcheck -x --source-path=. bin/asimov`,
151+
which follows the `source` lines into every module. Running shellcheck on a module by
152+
itself reports false "unused variable" and "referenced but not assigned" warnings,
153+
because no single module is a complete program.
154+
124155
## Releasing (maintainers)
125156

126157
**The pipeline, end to end:**
127158

128159
1. **Develop** on a branch → **PR into `main`**. CI (macOS 14 + 15) must pass; commits must be signed.
129160
2. **Merge** to `main`.
130-
3. **`make release`** tags `vX.Y.Z` (signed) → GitHub Actions publishes the release + `asimov` binary.
161+
3. **`make release`** tags `vX.Y.Z` (signed) → GitHub Actions publishes the release + the `asimov-X.Y.Z.tar.gz` asset.
131162
4. **Homebrew** autobumps `brew install asimov` on its own (~3h later). Nothing to do.
132163

133164
Version = SemVer: new feature → **minor**, bug fix → **patch**. Pre-releases: `make release-beta` (GitHub pre-release; Homebrew ignores it). Details below.

Makefile

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ help: ## Show this help
1414
@grep -E '(^[a-zA-Z0-9_-]+:.*?##.*$$)|(^##)' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}{printf "\033[32m%-30s\033[0m %s\n", $$1, $$2}' | sed -e 's/\[32m##/[33m/'
1515

1616
version: ## Print asimov version
17-
@./asimov --version
17+
@./bin/asimov --version
1818

1919
exclusions: ## List all paths excluded from Time Machine
2020
@sudo mdfind "com_apple_backup_excludeItem = 'com.apple.backupd'"
@@ -38,7 +38,8 @@ test-system-bash: ## Run Bats tests under the macOS system bash (3.2), as shippe
3838
@$(MAKE) --no-print-directory test BASH_BIN=/bin/bash
3939

4040
lint: ## Run Shellcheck on all shell scripts
41-
@shellcheck asimov scripts/install.sh scripts/install-remote.sh scripts/uninstall.sh scripts/prep-release.sh scripts/test.sh tests/test_helper.bash tests/bin/run-tests.sh tests/bin/tmutil tests/bin/mdfind tests/bin/launchctl
41+
@shellcheck -x --source-path=. bin/asimov
42+
@shellcheck scripts/install.sh scripts/install-remote.sh scripts/uninstall.sh scripts/prep-release.sh scripts/test.sh tests/test_helper.bash tests/bin/run-tests.sh tests/bin/tmutil tests/bin/mdfind tests/bin/launchctl
4243

4344
check: test lint ## Run tests and linting
4445

@@ -49,7 +50,7 @@ bench:
4950
@bash -c 'time HOME="$(CURDIR)/tests/fixture" /tmp/asimov-v042 --dry-run'
5051
@echo ""
5152
@echo "=== v0.5.x (directory=tests/fixture) ==="
52-
@bash -c 'time HOME="$(CURDIR)/tests/fixture" ./asimov --dry-run "$(CURDIR)/tests/fixture"'
53+
@bash -c 'time HOME="$(CURDIR)/tests/fixture" ./bin/asimov --dry-run "$(CURDIR)/tests/fixture"'
5354
@rm -f /tmp/asimov-v042
5455

5556
## bench-home: Compare dry-run scan timing: current vs v0.4.2, against real home directory
@@ -59,7 +60,7 @@ bench-home:
5960
@bash -c 'time /tmp/asimov-v042 --dry-run'
6061
@echo ""
6162
@echo "=== v0.5.x (full home) ==="
62-
@bash -c 'time ./asimov --dry-run'
63+
@bash -c 'time ./bin/asimov --dry-run'
6364
@rm -f /tmp/asimov-v042
6465

6566

@@ -86,7 +87,7 @@ release: check ## Tag and push a stable release — GitHub Actions will create t
8687
if [ -n "$$(git status --porcelain)" ]; then echo "error: working tree not clean"; exit 1; fi; \
8788
BRANCH=$$(git rev-parse --abbrev-ref HEAD); \
8889
if [ "$$BRANCH" != "main" ]; then echo "error: releases must be tagged from main (on $$BRANCH)"; exit 1; fi; \
89-
VERSION=$$(./asimov --version); \
90+
VERSION=$$(./bin/asimov --version); \
9091
TAG="v$$VERSION"; \
9192
if git rev-parse "$$TAG" >/dev/null 2>&1; then echo "error: $$TAG already exists"; exit 1; fi; \
9293
echo "Tagging $$TAG (signed)..."; \
@@ -98,7 +99,7 @@ release: check ## Tag and push a stable release — GitHub Actions will create t
9899
release-beta: check ## Tag and push a beta pre-release — GitHub Actions will create the pre-release
99100
@set -e; \
100101
if [ -n "$$(git status --porcelain)" ]; then echo "error: working tree not clean"; exit 1; fi; \
101-
VERSION=$$(./asimov --version); \
102+
VERSION=$$(./bin/asimov --version); \
102103
BETA_NUM=1; \
103104
while git tag | grep -q "^v$$VERSION-beta\.$$BETA_NUM$$"; do \
104105
BETA_NUM=$$((BETA_NUM + 1)); \

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ brew services start asimov
3030
curl -fsSL https://raw.githubusercontent.com/AsimovMac/asimov/main/scripts/install-remote.sh | bash
3131
```
3232

33-
Installs `v0.10.0` to `~/.local/bin`. Found a bug? [Open an issue](https://github.com/AsimovMac/asimov/issues).
33+
Installs to `~/.local` (`bin/asimov`, plus its library and data files under `libexec/` and `share/`). Found a bug? [Open an issue](https://github.com/AsimovMac/asimov/issues).
3434

3535
### Quick start
3636

@@ -286,10 +286,10 @@ cd asimov && make install
286286
## Uninstall
287287

288288
```sh
289-
rm ~/.local/bin/asimov # curl install
290-
brew uninstall asimov # Homebrew
291-
launchctl bootout gui/$(id -u)/com.stevegrunwell.asimov # stop schedule
292-
make uninstall # source install
289+
rm -rf ~/.local/bin/asimov ~/.local/libexec/asimov ~/.local/share/asimov # curl install
290+
brew uninstall asimov # Homebrew
291+
launchctl bootout gui/$(id -u)/com.stevegrunwell.asimov # stop schedule
292+
make uninstall # source install
293293
```
294294

295295
## Upgrading

0 commit comments

Comments
 (0)