Skip to content
zit Artifact [5148784c22]
Login

Artifact [5148784c22]

Artifact 5148784c22cb07161622520094d05cbbf11b8780d39245c110486fd863292f96:


# zit 0.3.16

zit 0.3.16 makes the file-history index work on a submanifest repository, makes
`zit artifact` show a tree check-in's file set, and makes a saved login
authenticate the pushes that name no user, autosync included.

No artifact, tag namespace, sync message, or on-disk repository format changed.

## The file index on a tree-manifest store

0.3.14 gave `zit log CHECKIN PATH` an index and 0.3.15 made it durable. Neither
did anything for a submanifest repository. The change-set capture refused every
tree manifest as "unknown at this layer", so on such a store the index recorded
the whole log as unknown, was adopted as valid, and answered nothing; a PATH
query paid the build and then reconstructed each check-in anyway. The answer
was always right. The cost was 39 minutes a query on a pkgsrc mirror, and a
forge that warmed the index after every restart spent those minutes for
nothing.

Trees are now flattened inside the diff step's memo, through the same seam the
Repository facade already used, so the untouched diff machinery sees a flat
list. A tree that cannot be flattened — a sub-manifest absent, shunned or
corrupt — stays unknown, which is the honest degrade the old refusal was
protecting and the only case it still covers.

| pkgsrc submanifest mirror, 218,444 check-ins | before | after |
|---|---|---|
| check-ins unknown to the index | 218,048 | **0** |
| a PATH query, warm | ~39 min, every time | **1.09s** |
| a different path, same index | ~39 min | **1.14s** |
| index build | 39 min, never useful | 34.3 min, once |

Answers are identical to reconstruction, checked per path. On a 1029-check-in
tree store the warm query went from 0.68s to 0.18s; the same history minted flat
answers in 0.49s, so a tree store now gets what a flat store gets.

The index format bumps to version 3. A version-2 blob built before this change
recorded every tree check-in as unknown and would have been adopted as valid
forever; it is refused and rebuilt once. The build is proportional to files per
check-in rather than files changed, which on a wide tree is real work done once.
Making it proportional to what changed remains open.

The derive-time crosslink feed is deliberately not flattened: it runs on every
cold open, and flattening each tree there would move the whole build onto open.
A tree stays unknown in that feed, as it always was.

## `zit artifact` renders S cards

The card renderer had a lane per card letter and no S lane. A tree check-in
carries its entire file set by S cards and no F cards, so it printed as a
manifest with no files at all while `ls` on the same hash listed thousands. One
lane, in card order; an end-to-end test checks the rendered lines against
`--raw`, which always showed them.

## A saved login authenticates a push that names no user

`zit push --user U` saves the derived secret at 0600 so a later push needs no
password. But the credential resolver returned anonymous the moment `--user` was
absent, before consulting what was saved. Autosync invokes the push with no
arguments, so a clone whose peer requires a login for writes pulled
automatically and never pushed automatically, and logging in changed nothing.

With `--user` absent, the saved login now stands in. This is fossil's shape: a
remembered login authenticates every later sync. The branch never prompts —
there is no operator at a keyboard by definition — so with nothing saved the
push is anonymous as before. `push`, `sync` and `config pull` share the one
resolver, so all three gain it. `--user ""` still forces an anonymous push, and
an explicit `--user` keeps its precedence. The saved login is reused as it
stands: after a password change on the peer, pass `--user` again.

A unit test pins the resolver: with no `--user` and a login stored, it returns
that login without prompting; with nothing stored, or an explicit empty
`--user`, the push is anonymous.

This makes a no-user push carry the stored login. Whether that push then lands
on a *fossil* peer is a separate, pre-existing matter: an authenticated push to
fossil is currently refused even for a Setup user whose login the same peer
accepts for `config pull`. Against a `zit serve` peer the
point is moot — zit's server has no capability model and accepts anonymous
writes.

## Compatibility

- No on-disk repository or wire format changed; Fossil RFC revision 00 remains
  the target.
- `.zit-cache/finfo` is version 3. A version-2 file is ignored and rebuilt once;
  the cache is advisory and deleting it is always safe.
- A repository holding a saved login now authenticates pushes and syncs that
  name no user. Pass `--user ""` to push anonymously from such a repository.
- No other command or flag changed. `ZIT_FILEINDEX_WALK` now also prints
  `fileindex-unknown`; it is a diagnostic seam, not a supported interface.

## Qualification

`zig build test`, `e2e`, `smoke` (Fossil interop against a real `fossil`),
`muscle` (41 differential steps), `git-import-e2e`, `git-export-e2e`, `dst`,
and `cross`, plus the three-runner CI battery. Timings are release builds; the
pkgsrc figures are from the submanifest mirror in the benchmark corpus and the
before figures from the preceding binary on the same store.