Releases: n36l3c7/hosts-cli
Release list
hosts 1.1.0
check can now repair what it finds, for the findings where the repair is not a
guess.
Added
-
check --fixrepairs five of the eleven rules:duplicate-entry, by removing
the later line;duplicate-name, by taking the redundant name off the line
and dropping the line if that leaves it with nothing but an address;
missing-loopbackandmissing-loopback6, by adding the entry above the
first entry the file has, or at the end when it has none; and
missing-trailing-newline.The other six are left alone deliberately, and that line is the feature. An
address or a name that does not parse cannot be repaired without inventing
one.conflicting-ipis the one that tempts: two lines send a name to two
addresses, and which of them is wanted is knowledge the file does not contain.
control-characteris left because stripping bytes out of a line in silence
would destroy the evidence of what happened to it.It is a write like the others: it takes the lock before the read, backs up
first, honours--dry-runand--no-backup, and asks before touching more
than one line unless--yesis given. A file with nothing to fix is not
written to at all. A line the fix did not touch is byte for byte what it was,
which is the existing guarantee rather than a new one. -
summary.fixedin the JSON output ofcheck, counting what was repaired,
and always present so the shape of the document does not depend on the flags.
The schema version stays at 1: fields are added within a version, and a
reader should ignore what it does not recognise.--fixwith--dry-runis
refused under--json, because the preview is a diff on standard output and
would leave the document unparseable. -
A fuzzing pass over the fix itself: hostile input is fixed, the result is
still a file the program reads, and fixing it a second time changes nothing. -
A recorded demonstration, in the README and at the top of the documentation
site: anadd, twormand thelsbetween each.demo/session.shruns the
commands it prints, against a scratch file rather than/etc/hostsso that
recording needs no privilege, anddemo/record.shturns it into
docs/demo.gif. Keeping the recipe in the repository means the picture can be
regenerated when output changes instead of quietly going stale.
Changed
-
After a fix the file is read and scanned again rather than the earlier
findings being renumbered onto it. Removing lines moves everything below them,
so a leftover finding would otherwise have been reported against a line that
is now something else, and a message naming another line would have named the
wrong one. Scanning again makes every number and message right by
construction, and reports anything a fix itself introduced. -
The documentation site leads with what the program is for. It gained an
opening statement, the demonstration, the apt command with a button that
copies it, and a navigation bar that follows the page and links to the
sections, in place of three links to other pages. The stylesheet is still one
hand-written file with no external asset and no font loaded from anywhere
else. Every documented section is unchanged. -
The workflows use actions that run on Node 24. The ones in use targeted Node
20, which the runners have deprecated and were forcing onto 24 anyway: they
worked, and one day they would not have.checkoutwent to v7 and the two
Pages actions to v5, further along than expected, so the versions were
looked up and the moving major tags checked rather than guessed at.
Fixed
-
The navigation bar of the documentation site stays on screen. It was the last
child of the header, and a sticky element is confined to its containing block,
so it came unstuck the moment the header scrolled past. -
Every released version is installable from the apt repository, not only the
most recent one.dpkg-scanpackagesreports one version per package unless
told otherwise, so earlier.debfiles were being published and then left
out of the index: present but not installable, which is not what "the index
is rebuilt from every release" was meant to mean.
hosts 1.0.1
Verification of what 1.0.0 already claimed, and one claim that turned out not
to be true.
Fixed
- Concurrent writers no longer lose each other's work. The lock was taken
inside the write, after the file had already been read, so two writers each
computed their change from the same starting point and the second one
discarded the first. Serialising the writes prevented nothing, the rename
having already made those indivisible: the update that got lost was lost
during the read. The lock is now taken before the file is read and held
until the new content is in place. 0.2.0 documented the protection this
provides; it did not provide it. hosts editholds that lock for as long as the editor is open, so another
writer waits and then fails saying so rather than quietly discarding one of
the two changes.- The apt index is rebuilt after a release again. It was chained to the
release event, which a release created by a workflow using the built-in
token never raises: GitHub suppresses those so that workflows cannot
trigger each other in a loop. It now chains to the release workflow itself,
which is the mechanism meant for it. The index for 1.0.0 was published by
running the workflow by hand.
Added
- Tests that kill a write partway through, at a different point on each pass,
and require the file to hold either the whole of the old content or the
whole of the new one. That guarantee is the one the whole program rests on
and had only ever been reasoned about. - A test that runs two writers at once against a file large enough for the
race to be certain rather than merely possible. It is what found the lock
defect above. - Tests that put the parser against input it was not written for: control
bytes, addresses and names that nearly parse, lines of only whitespace, and
a very long line. Three invariants are checked, the strongest being that
exportgives back exactly the bytes that were read. The generator is
seeded so a failure can be reproduced. Nothing was found, which is also
information. - A portability job that runs the whole suite on Debian 11 and 12 and Ubuntu
22.04 and 24.04, as an ordinary user rather than as root so that the tests
about refused permissions do not skip themselves. Everything had until now
only ever run on one Ubuntu, which left every assumption aboutstat,
date,realpath,sync,flockandinstalluntested.
Changed
- The README no longer implies bash 4.4 is tested. It is the documented floor;
what the suite runs against is bash 5.1 and 5.2, because nothing still
supported ships 4.4. - A test no longer expects a file to come out mode 644. Debian defaults to a
umask of 022 and Ubuntu to 002, so the same fixture is 644 on one and 664 on
the other; the sidecar records the mode the file actually has, which is what
the test now checks. The portability job found this on its first run, which
is the sort of thing it was added for.
hosts 1.0.0
The first release that can be installed with apt, and the point from which
the interface is a promise.
Nothing in the program itself changed from 0.6.0. What changed is that there
is now a way to install it that does not begin with cloning a repository, and
a commitment about what will not break.
Added
- A Debian package,
hosts-cli, holding the command, the man page and the
completions for bash and zsh.make debbuilds it from the same artifacts
make installuses. - An APT repository published on GitHub Pages, signed, and rebuilt from the
packages attached to every GitHub Release so that it holds no state of its
own and cannot drift from what was published. - A release workflow that runs on a tag, refuses to continue when the tag and
theVERSIONfile disagree, installs the package it just built and uses it
before publishing anything, and takes the release notes from this file.
Changed
- GitHub Pages is deployed by a workflow rather than from the
docsfolder of
the branch, because an APT repository contains a binary and committing one
would put it in the history for good. - The following are now covered by semantic versioning, and breaking any of
them costs a major version: the exit codes 0 to 8; the tab separated output
ofls,search,check,backup ls,profile lsandflush, the number
of fields included; the JSON schema; the rule identifiers ofcheck; the
environment variables and the layout of the backup and profile stores,
sidecar format included.