38 Commits

Author SHA1 Message Date
benvin f9cfe081c8 Merge pull request 'Load the working tree, not an installed arti-pack' (#9) from benvin/hermetic-test-harness into main
ci/woodpecker/tag/release Pipeline was successful
Reviewed-on: #9
v0.2.1
2026-09-12 12:54:45 +10:00
unkin-agent 1568334840 Load the working tree, not an installed arti-pack
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
Neovim's runtimepath searcher outranks package.path, so `make test` on a
machine with arti-pack installed tests the installed copy.

- Give the repository the first package loader slot in the test harness
- Run the suite under `nvim --clean` so site packages stay off the rtp
- Assert modules resolve inside the repository, even with a copy on the rtp
2026-09-12 12:52:55 +10:00
benvin c4eb84b34f Merge pull request 'Fetch the ref and url the spec actually names' (#8) from benvin/url-significant-refs into main
Reviewed-on: #8
2026-09-12 09:49:42 +10:00
unkin-agent e5a260ad25 Fetch the ref and url the spec actually names
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
A ref goes into the archive URL verbatim and an explicit url goes to curl
as a positional, so both could name one thing and fetch another.

- reject "#", "?", "%", "[", "]", "{" and "}" in a tag or branch, which
  curl or the server would turn into a different path
- pass "--" before the url so curl cannot read it as an option
- document the ref rules in README and the help file
2026-09-12 01:04:53 +10:00
benvin c06ac229af Merge pull request 'Install plugins from a branch' (#7) from benvin/branch-specs into main
Reviewed-on: #7
2026-09-12 00:44:59 +10:00
unkin-agent 3716131e56 Say the recorded digest is not a file checksum
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
sha256() refuses binary input, so the archive is hashed in its base64
form. Comparing it against sha256sum reads as corruption.
2026-09-12 00:23:08 +10:00
unkin-agent 3c73a83602 Reject a NUL byte in every ref that reaches curl
A NUL truncates a string when vim.system marshals argv, so the URL curl
fetches diverges from the ref that was validated, locked and displayed.
The whitespace class does not cover it.

- reject a NUL in tag, branch, the "as" directory name, an explicit url
  and the registry
- cover a NUL in the middle, at the end, and alone for each
2026-09-12 00:23:08 +10:00
unkin-agent 460dc2c5c8 Install plugins from a branch
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
Many upstream plugins publish no tags at all, so a tag-only installer cannot
manage them.

- Add a branch spec field, mutually exclusive with tag and validated the same way
- Build archive/refs/heads/<branch> URLs for branch specs
- Refetch a branch only on :ArtiPackUpdate or a forced sync, never from cache
- Record the branch, archive digest and fetch time in the lockfile
- Report a branch plugin as tracked and fetched, never as up to date
2026-09-12 00:08:18 +10:00
benvin f1b454a4eb Merge pull request 'Publish from an image that trusts the internal CA' (#6) from benvin/publish-internal-ca into main
ci/woodpecker/tag/release Pipeline was successful
Reviewed-on: #6
v0.1.0
2026-09-11 23:30:52 +10:00
unkin-agent 5b589f7e4d Publish from an image that trusts the internal CA
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
The publish step's https PUT cannot run on alpine, which has no internal CA.
Switch it to almalinux9-base, matching the rest of the estate.
2026-09-11 23:25:38 +10:00
benvin 3aa9a617b4 Merge pull request 'Cover the DEFLATE path and stop malformed zips raising' (#5) from benvin/deflate-tests into main
Reviewed-on: #5
2026-09-11 22:31:01 +10:00
unkin-agent 15383b8cce Bound every test with a wall-clock timeout
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
A runaway test spins at full CPU instead of failing, stalling the whole
run. A debug hook enforces a per-test deadline; the JIT stays off so the
hook is reachable from compiled code.
2026-09-11 00:00:20 +10:00
unkin-agent 27b182f1c3 Report a directory that collides with a file
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
vim.fn.mkdir raises when a path component is an existing file, and an
archive can arrange that by shipping a file and then a path under it.
Return nil, err from mkdirp and propagate it.
2026-09-10 23:30:48 +10:00
unkin-agent 11c8fbf485 Aim the truncated-directory test at the raising path
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
A record whose name is cut short already reported; the raise needed a
zero-length name and a directory offset pointing into the trailing
comment. Build that case instead.
2026-09-10 23:27:22 +10:00
unkin-agent 78a5df6cf3 Test the DEFLATE path with real compressed fixtures
The fixture builder only produced stored entries, so the vendored inflate
never ran under test. Add a small DEFLATE encoder and drive zip and
tar.gz entries through it: round-trips for fixed and dynamic huffman,
empty and large payloads, plus wrong CRC, wrong stated size, truncated
and corrupted streams, and a traversal name on a compressed entry.

Also cover the central directory and local header truncations that used
to raise.
2026-09-10 23:27:22 +10:00
unkin-agent 407ad8093f Report malformed zip headers instead of raising
A central directory record or local header cut short of its length fields
made zip_entries and zip_data do arithmetic on nil, so the parse raised
where every other failure returns nil, err. Bound both against the buffer
first. A pax record claiming a zero length no longer spins forever.
2026-09-10 23:27:22 +10:00
benvin 04506285df Merge pull request 'Extract archives in pure Lua with a vendored zzlib' (#4) from benvin/vendor-zzlib into main
Reviewed-on: #4
2026-09-10 23:18:12 +10:00
unkin-agent 5809a843c8 Extract archives in pure Lua
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Installing a plugin no longer needs unzip or tar on PATH, and entry paths
are vetted in Lua instead of trusting an external tool.

Add arti-pack.archive: a zip reader over zzlib's inflate and a tar reader
over its gunzip.
Reject absolute, parent-walking, backslashed and NUL-bearing entry names,
and any entry that is not a regular file or directory.
Verify every zip entry's CRC32 and size, and fail the install on mismatch.
Carry only the executable bit from archive modes.
Replace fs.extract_cmd with fs.extract and call it synchronously.
Drop unzip from the test pipeline and the stated requirements.
2026-09-10 22:48:25 +10:00
unkin-agent bae3a517f7 Vendor zzlib for pure-Lua DEFLATE
Add zzlib (codeberg.org/zerkman/zzlib @ 9c39321, WTFPL) under
lua/arti-pack/vendor. Namespace its submodule requires and re-export
crc32; the inflate backends are unmodified.

Exclude the vendor directory from luacheck and stylua.
2026-09-10 22:40:41 +10:00
benvin 7dd8888692 Merge pull request 'Gate pull requests on stylua formatting' (#3) from benvin/stylua-check into main
Reviewed-on: #3
2026-09-10 21:50:38 +10:00
unkin-agent 73960b03e2 Gate pull requests on stylua formatting
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
- add a fmt-check make target running stylua --check over lua, tests and plugin
- add a fmt step to the lint pipeline fetching pinned stylua v2.5.2
- verify the download against its sha256 before use
2026-09-09 23:29:48 +10:00
unkin-agent 167a529cec Format the tree with stylua 2026-09-09 23:28:52 +10:00
benvin 9a88afcd84 Merge pull request 'Publish tagged source zips on release' (#2) from benvin/release-pipeline into main
Reviewed-on: #2
2026-09-09 23:22:42 +10:00
benvin c7da77a588 Merge pull request 'Add arti-pack plugin manager scaffold' (#1) from benvin/scaffold into main
Reviewed-on: #1
2026-09-09 23:19:48 +10:00
unkin-agent 0db490bdf3 Merge branch 'benvin/scaffold' into benvin/release-pipeline
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
2026-09-09 22:57:01 +10:00
unkin-agent e61e950d30 Trim whitespace out of the registry and spec urls
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
A registry with a stray space or newline passed validation and was
concatenated verbatim into the archive URL, so curl saw the malformed
address instead of the user seeing the required-registry error. Trim the
value before matching and reject any whitespace left inside it; apply the
same to a spec's explicit url.
2026-09-09 22:56:18 +10:00
unkin-agent d3f8074940 Merge remote-tracking branch 'origin/benvin/scaffold' into benvin/release-pipeline
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
2026-09-09 22:44:45 +10:00
unkin-agent c75a866c02 Require an explicit registry instead of defaulting to one
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
The shipped default named one private, internet-unreachable host, so an
unconfigured install failed against a server it could never reach rather
than saying what to set.

- drop the registry default and make the option required
- reject a non-string, empty, or non-http(s) registry with the option name
  and how to set it
- ask for a registry only when a run has to resolve one, so clean, list,
  and specs with an explicit url keep working without it
2026-09-09 22:44:33 +10:00
unkin-agent 9b33f27d47 Use a placeholder host in the install instructions
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
The install snippets named one specific artifact repository by hostname.

- fetch the release zip from a placeholder host under the same tag-archive
  path shape
2026-09-09 22:35:54 +10:00
unkin-agent b520b862e9 Merge branch 'benvin/scaffold' into benvin/release-pipeline 2026-09-09 22:35:10 +10:00
unkin-agent 7def2a28a9 Describe arti-pack against any artifact repository
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
The docs described one specific deployment by hostname, reading as though
arti-pack only works there. It works against any HTTP artifact repository that
serves a tag archive at a stable URL.

- describe the registry as any HTTP artifact repository, with Artifactory as
  the worked example
- use a placeholder host in every configuration and URL example
- state that registry must be set, since the shipped default is site-specific
2026-09-09 22:35:00 +10:00
unkin-agent 3dc6409628 Assert the release zip's shape before publishing
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Uploads are immutable, so a malformed archive cannot be replaced at its
version path. verify-package checks the zip has one top-level directory,
carries lua/, plugin/, doc/ and README.md, and leaks no dev or CI files.
2026-09-09 21:17:21 +10:00
unkin-agent 8f49c50ef3 Drop the redundant safe.directory config from the package step
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
2026-09-09 21:08:22 +10:00
unkin-agent 2960321b0b Publish tagged source zips to artifactapi
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
Add a tag-triggered release pipeline and a package target that builds the
archive shape arti-pack's own installer consumes.
2026-09-09 21:06:09 +10:00
unkin-agent 11ce1fed9d Save the lockfile through a temp file and a rename
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
An interrupted save could leave a truncated lock.json.
2026-09-08 23:32:04 +10:00
unkin-agent 3190b30e97 Abort clean when a plugin spec fails to parse
An unparseable entry dropped out of the wanted set, so clean deleted the
directory and lock entry of a plugin the user still has configured.

Add tests/init_spec.lua covering setup, sync, clean and list.
2026-09-08 23:32:04 +10:00
unkin-agent 46517953e5 Add arti-pack plugin manager scaffold
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
- add lua modules for spec parsing, lock state, fs helpers and the installer
- add ArtiPackSync/ArtiPackClean/ArtiPackList commands and help doc
- add headless nvim test harness and specs
- add make test/lint/fmt/pre-commit and patch/minor/major bump targets
- add woodpecker test, lint and pre-commit pipelines
2026-09-08 23:22:15 +10:00
gitadmin 0d53991048 Initial commit 2026-09-08 23:00:07 +10:00