Skip to content

refactor: split asimov into a launcher, a library, and data files - #126

Merged
django23 merged 1 commit into
mainfrom
refactor/modular-layout
Jul 30, 2026
Merged

refactor: split asimov into a launcher, a library, and data files#126
django23 merged 1 commit into
mainfrom
refactor/modular-layout

Conversation

@django23

Copy link
Copy Markdown
Collaborator

The single 1645-line script becomes three things: a launcher, a library, and data files.

bin/asimov              # launcher: version, self-locate, probe, source, dispatch
lib/asimov/*.sh         # 11 modules, largest ~330 lines
data/*.tsv              # sentinels, fixed dirs, skip paths

Installed, the library and data land at <prefix>/libexec/asimov and <prefix>/share/asimov. The launcher resolves its own physical path through symlinks (as Homebrew creates) and probes for both that layout and the repo layout, so ./bin/asimov works straight from a checkout. ASIMOV_LIB and ASIMOV_DATA override the probe.

Data entities

Sentinels, fixed directories and skip paths are tab-separated records that carry their ecosystem or owning tool as a real field, rather than as a trailing bash comment:

node_modules	package.json	javascript	npm, Yarn
DerivedData	*.xcodeproj	swift	Xcode DerivedData

Adding a pattern is now a one-line data edit with no bash syntax involved. tests/data.bats enforces the schema (tabs not spaces, no duplicates, paths relative to the root) and proves a contributor-added sentinel is honoured without touching a script.

Behaviour

Unchanged. All 219 pre-existing tests pass untouched under bash 5 and bash 3.2; only tests/test_helper.bash moved, to point at bin/asimov.

Three things are more than a pure move:

  • sentinel_active_pairs() replaces two drifted copies of the config disabled/extra filtering (build_find_vendor_params and discover_new_paths_via_mdfind each had their own).
  • A duplicated dead if [[ ! -s "$uncached_file" ]] block in the discovery path is gone.
  • doctor gains a Data section reporting loaded counts, and checks the data files before loading them so a broken install is diagnosed rather than aborted on.

Notes for review

  • bash 3.2: readonly ARR=(...) inside a function is local under 3.2 and global under 5. Arrays are assigned at file scope; readonly is scalars only.
  • Linting is whole-program: make lint runs shellcheck -x --source-path=. bin/asimov, which follows the explicit source lines. That is why the sources are written one per line rather than looped — a loop hides the module bodies and every cross-module variable looks undefined.
  • The version stays in bin/asimov, because doctor reads other installs' versions by grepping their launcher rather than executing them.
  • Release assets become asimov-X.Y.Z.tar.gz instead of a bare script; scripts/install-remote.sh downloads a tarball.

Verified

  • make check — 232 tests, shellcheck clean
  • make test-system-bash — same 232 under bash 3.2
  • Installed to a throwaway prefix, ran through a symlink, uninstalled clean
  • Data files diffed against the old arrays: identical sets

Not in this PR

The homebrew-core formula still does bin.install buildpath/"asimov". That needs updating before the next release tag — see the discussion on the issue.

The single 1645-line script becomes bin/asimov (launcher), lib/asimov/*.sh
(eleven modules, none over ~320 lines), and data/*.tsv (the directory lists).

Installed, the library and data live at <prefix>/libexec/asimov and
<prefix>/share/asimov. The launcher resolves its own physical path through
symlinks, as Homebrew creates, and probes for both that layout and the repo
layout, so ./bin/asimov works straight from a checkout. ASIMOV_LIB and
ASIMOV_DATA override the probe.

Sentinels, fixed directories and skip paths are now tab-separated records
carrying their ecosystem or owning tool as a real field, loaded into parallel
arrays (bash 3.2 has no associative arrays). sentinel_active_pairs() applies
the config disabled/extra lists once and is the single source of active pairs
for both find and Spotlight discovery, replacing the two copies of that
filtering that had drifted apart.

Behaviour is unchanged: all 219 existing tests pass untouched under bash 5 and
bash 3.2. Adds tests/data.bats (13 tests) covering the record schemas and the
loader, including a missing data file and a contributor-added sentinel.

Sources are listed one per line rather than looped so that
'shellcheck -x --source-path=. bin/asimov' checks the whole program as a single
unit; linting a module alone reports false unused-variable warnings.
@django23
django23 merged commit 25677dc into main Jul 30, 2026
5 checks passed
@django23
django23 deleted the refactor/modular-layout branch July 30, 2026 13:06
django23 added a commit to lunaluxie/asimov that referenced this pull request Jul 30, 2026
…yout

The monolithic `asimov` is gone as of AsimovMac#126, so this resolves the
modify/delete conflict by re-landing the feature where it now belongs:

- lib/asimov/config.sh parses `skip_paths:extra`
- lib/asimov/data.sh appends those paths to ASIMOV_SKIP_PATHS in
  load_skip_paths, after the data/skip-paths.tsv rows. load_config runs
  before load_data, so the array is complete by the time scan.sh and
  discover.sh read it, and neither needs to know about the config
- lib/asimov/doctor.sh accepts the section and its one key

Tests and docs carried over unchanged. 238 tests pass under bash 5 and
under the system bash 3.2.
django23 added a commit to aditya-arcot/asimov that referenced this pull request Jul 30, 2026
…d-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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant