zit 0.3.13 adds the write side of attachments. zit could read attachment
artifacts — A cards fold, zit artifact describes them, sync carries them
— but could not author one. Every other authoring path quarry uses is a
zit verb; attachments now are too, so the artifact format is written in one
place.
No artifact, tag namespace, sync message, or on-disk format changed. One
new repository setting, attachment-size-limit, is carried in the config
frame under a new key; older zit reads a repository that sets it without
complaint and simply does not honour it.
zit attach add / rm / list (zit#186)
zit attach add TARGET FILE [--name NAME] [--comment TEXT] [--mimetype TYPE]
[--user NAME] [-R repo] # FILE may be - for stdin
zit attach rm TARGET NAME [--user NAME] [-R repo]
zit attach list [TARGET] [-R repo]
addstores FILE as a blob, then an attachment artifact carrying oneA NAME TARGET SOURCEcard plusC(when given),D,N(when given),U,Z— both written in the same commit, so an attachment can never name bytes the store does not hold. It prints the artifact's hash, then the blob's, on two lines. NAME defaults to FILE's final path component; a directory prefix is always discarded, as the format requires. TARGET is a ticket, technote, or forum post's hash (full or abbreviated) or a wiki page's name, checked for shape only — an unresolved target is recorded as a generic reference. An empty file is refused, as fossil refuses it.rmwrites an A card with no source for (TARGET, NAME): the association ends under the format's latest-wins rule; nothing leaves the store.listprints the live attachments — the newest A card per name, a sourceless one meaning gone — asNAME SIZE MIMETYPE BLOB DATE USER, with the target as a first column when listing the whole repository.
The cap. attachment-size-limit is fossil's setting, honoured the way
fossil reads it — a byte count, checked before the blob is written, 0
meaning unlimited — with one difference: unset, zit's default is 1 MiB,
not unlimited. A blob in the DAG travels to every clone for ever, and a
default that lets a first-time user attach a 400 MB recording is the wrong
default. add refuses over the limit naming the size and the limit;
zit settings attachment-size-limit N raises it.
Interop. A zit-authored attachment pushed to a real fossil server
crosslinks as a live attachment on its target with zit's blob as its
source — fossil's attachment table says so, and the smoke suite now
checks it on every run (scenario S15).
The quarry attachment stub (zit#187)
quarry never attaches file bytes to a hosted repository; it attaches a small text blob naming the bytes by SHA-256, size, type and name, so the A card stays a valid fossil artifact and the store stays small. zit now recognises that shape:
zit attach listshows it asNAME SIZE TYPE external:sha256:…, with the size and type it points at rather than the stub's own bytes.zit artifact HASHon the blob adds anattachment-stub:line.- The size cap applies to the blob actually stored, so a stub always passes. Nothing write-side changed; a client that does not recognise a stub sees a small text file under the attachment's name.
Compatibility
- Fossil RFC revision 00 remains the target; the attachment artifact is written in the form the format specifies and fossil's own reader crosslinks it.
- The new setting lives in the config frame under a fresh key, read as "unset" by any zit that predates it.
attachis a machine verb: unlisted inzit help's command list likewiki,ticket,forumandtechnote, documented byzit help attachand in the command reference.
Qualification
zig build test, e2e (including the new attach test: add/list/replace/
rm, the size limit and its lifting, stdin, a wiki-name target, prefix
stripping, and the stub), smoke (Fossil interop against a real fossil,
now including S15), muscle (41 differential steps), git-import-e2e,
git-export-e2e, and dst, plus the three-runner CI battery.