~bigbes/sr-ht-dolt

3843eb55 — Eugene Blikh 3 days ago
remoteapi: prove an empty store takes an unrelated first push

This file had not compiled since the logrus->slog migration removed the
package-level `logger` its serve goroutines still called. The
`integration` build tag keeps it out of every default build, test and vet
run, so nothing ever said so — the suite simply never ran again.

With it compiling, add the scenario the storage layer's contract is
actually about: a database provisioned empty ahead of its first push (the
web create form, or git.sr.ht's hook through /internal/repos) accepts a
push from a local database with a root commit of its own, with no
--force. Mutating the provisioning to InitStore fails it exactly as a
user hits it today: "unknown push error; no common ancestor".
a674ddb1 — Eugene Blikh 3 days ago
ci: publish the apk into artifacts.sr.ht as well

The abuild output goes on to the S3 bucket phoebe re-indexes, and now also to
the ~bigbes/main channel of artifacts.sr.ht, which indexes and signs it in the
same request. One PUT per file with the shared working token; a 409 says the
job ran twice and is a warning rather than a failure.
60fdb6dd — Eugene Blikh 5 days ago
beads: show the stored rows behind an issue on its detail pane

Every field on the detail pane is a reading of a row: the Issue struct names
the columns bd surfaces and drops the rest, humanizeEvent turns two JSON blobs
into a sentence, an Edge keeps an id and a type out of a dependency row. A
reading that went wrong looks exactly like one that did not, so the detail modes
now carry the rows they were built from — the issue's own row first, then the
rows belonging to it in labels, dependencies, comments and events, in the order
the tables were read and the columns came back in. custom_statuses is read for
the lane and is deliberately absent: its rows describe the tracker's statuses,
not this issue. Related tables are capped at RawMax rows and counted whole, so a
busy issue's audit log cannot turn the pane into a second page.

A raw view may not report an absent cell and an empty string as the same thing,
which is the one place cell()'s flattening of a real NULL to "" is wrong.
rowCells.isNull is now the single site that decides, shared by cell and the raw
row, so the two can never disagree; RawCell carries Null beside Value and drops
browse's "NULL" text, which would have put the collision straight back.

The section renders as a collapsed <details> in the stream layout's Past Stand
idiom — it is a check on the rendering, not the reason a reader came. Values are
escaped and deliberately not run through beadLinks.Text: a linkifier rewrites
what it is given, and a value that has been rewritten is no longer the value
that is stored. A cell holding no value renders as a NULL chip, a cell storing
those four characters as the text it stores, an empty one as (empty); a long
value scrolls inside its own cell.
07c2a63f — Eugene Blikh 5 days ago
mcpsrv: list_issues names every clipped table it drew from

Data.Truncated/ShownOf only ever meant the issues/dependencies read that
decides list_issues' total and truncated, so a clipped labels table took
label pills off every card and narrowed the label filter in silence, and a
clipped custom_statuses table could put a card in the wrong lane with
table_truncated still reading false.

list_issues now carries beads.Data.Clipped as clipped: one entry per
clipped table in read order, named, with the rows read against the rows
that exist and what that specific clip costs this listing. table_truncated
and table_total are unchanged; clipped is additive, an empty list on a
complete read.
bbaaa1f7 — Eugene Blikh 5 days ago
web: the milestones page says when its rollup is partial

MilestoneView has carried the clip since ebbd30f and list_milestones has
reported it since a419499; milestones.html rendered nothing, so the page
was the last surface presenting a partial rollup as whole-tracker
arithmetic. Every number on it is a rollup — "1/4 done", "1995 of 2000
issues carry no milestone label" — and arithmetic over the rows that were
read renders exactly like arithmetic over the tracker.

The notice is the detail pane's, word for word and class for class: it is
the same fact about the same read, and a second phrasing for it would be
a second style. It sits above the rollup and outside the
milestones/no-milestones branch, because "No milestones." over a clipped
read is the reading most easily mistaken for a fact about the tracker.

A milestone can lose members here rather than merely undercount them —
membership comes from labels — so the fixture makes that concrete: m1 has
five members, one of them past the cap, and the page counts four while
saying why.
96b5e53f — Eugene Blikh 5 days ago
beads: the board names every clipped table it draws from

The board raised its truncation flag for a clipped issues or dependencies
table and for nothing else, so a clipped labels table took the pills off
every card and the options out of the label filter in silence, and a
clipped custom_statuses table could put a card in the wrong lane with the
counts still reading as facts.

The flag could not grow to hold that. It is paired with a count line —
"the first N of M issues" — so it can only mean the reads that decide N
and M; widening it would have made a bool that means four different
things and a number that no longer follows from it. Data.Truncated and
ShownOf are therefore byte-for-byte what they were (mcpsrv's list_issues
reads them as they are), and the wider fact is a new field: Clipped, one
entry per clipped table the board reads, in read order, each naming the
table, the rows read against the rows that exist, and what the board lost
by the rest.

The banner follows. The count line now prints only when the issues read
was actually short — "the first 4 of 4 issues" was a wrong sentence, not
a warning — and every other clipped table gets its own line beneath it.
The detail pane keeps its single sentence from 82d997d; a pane that never
drew a lane has no use for a board's list.

TestBoardTruncationIsUnchanged is now TestBoardTruncationFlagIsUnchanged:
the flag is what it was, which is the claim that survives. Its "comments
does not flip the board" subtest survives as "a clip in a table the board
does not read" and now also asserts comments reaches neither the flag nor
the list, plus a new subtest pinning that labels and custom_statuses are
reported without touching the flag.
a1fe404f — Eugene Blikh 5 days ago
docs: spell out the clipped-read answers
82d997d2 — Eugene Blikh 5 days ago
web: the detail pane says when its read was clipped

The board has always carried a truncation banner; the detail pane it
shares a template with carried nothing, so an issue assembled from
tables clipped at 2000 rows looked complete, and an id in the tail of a
big tracker was answered "Issue not found." — which the page cannot
know.

Two lines, both in the banner's idiom. A pane built from a clipped read
says so and names the tracker's true size when the issues table itself
was cut; a miss over such a read says the id was not among the rows
read, which is not the same as saying it does not exist. A complete read
keeps the plain "Issue not found.", and the board's own banner is
untouched.
a4194995 — Eugene Blikh 5 days ago
mcpsrv: report the projection's clip on get_issue and list_milestones

Max clips every table read at 2000 rows. list_issues has always said so
(table_truncated, table_total); the other two answers computed over the
same read said nothing, so a rollup over a prefix of the tracker read as
arithmetic about the whole of it, and an id in the tail of a big tracker
was answered "no such issue" — a claim neither read can support.

get_issue now carries the two fields on every answer and splits the
miss: a complete read keeps the plain refusal, a clipped one says the id
was not among the rows read, names the cap and the true total, and ships
the payload (issue: null beside table_truncated) so the two misses are
one field apart rather than one adjective apart. list_milestones carries
the same two fields.
8dfe078b — Eugene Blikh 5 days ago
beads: report a clipped read from the remaining projections
f91a2e80 — Eugene Blikh 5 days ago
docs: read_rows answers strings or null
c82f106f — Eugene Blikh 5 days ago
beads: stop flattening a stored NULL string
63073508 — Eugene Blikh 5 days ago
mcpsrv: answer a real NULL as null
35875ff7 — Eugene Blikh 5 days ago
web: stop printing store paths to the owner
11c622f3 — Eugene Blikh 5 days ago
web: stop printing browse errors to the reader

The overview rendered the browse layer's own error text into the page, under
"Could not read history: " — dolt internals and the store's path on our disk,
which nothing else on this surface discloses and which a reader can do nothing
with.

The page now carries a fixed sentence and the reason goes to the log with the
database id (slog + scribe.Err). The view field is a bool rather than a message,
so no error string can reach the template by being assigned to it later. The
empty-database state the page already reported ("No commits.") is untouched:
that is a fact about the database, not a failure.
bee20506 — Eugene Blikh 5 days ago
web: tell a database outage from a missing database

loadRepoForBrowse turned any error from GetRepoByOwnerAndName into a 404, so a
metadata store that could not answer told every reader on the instance that
their database does not exist — for as long as Postgres was down, in the voice
reserved for "there is nothing here". loadRepoForAdmin did the same on the
settings page.

Both classify through repoLookupFailed now: db.ErrNotFound keeps the 404, and
it stays the same 404 the visibility rule renders for a PRIVATE database the
caller may not see, so a masked database and a missing one remain
indistinguishable. Anything else is a 500 through the shared error page, with
the cause logged (slog + scribe.Err) and never rendered.
ebbd30fe — Eugene Blikh 5 days ago
beads: report a clipped read from every projection
c1d1a17e — Eugene Blikh 5 days ago
mcpsrv: name the cursor a commit-log miss was asked about
5b00a516 — Eugene Blikh 5 days ago
browse: say which cells are actually NULL
cdb9195f — Eugene Blikh 5 days ago
mcpsrv: a bad commit-log cursor is a miss, not a fault
Next