Parents and children of check-in [ddc4b5396d]
|
2026-10-12
| ||
| 18:07 |
fix(sync): handle unknown, error and pull-only cards per the draft (#300) (#341)
The server ignored reply-only cards a client should never send and the client read on past cards that end a reply. On the server, a client-sent error or message card -- reply-only cards fossil's page_xfer has no branch for -- now answers "bad command" and resets the reply, not silence. A push card from a requester who may read but not write answers "message pull only - not authorized to push", as fossil does, rather than a refusal, so the pull proceeds. To reach that branch the client now sends its pull card before its push card, fossil's order: the server's read-vs-pull-only decision turns on having seen the pull card first. On the client, an error card ends the reply-card loop (§10.1): the cards before it stand, those after it are not read. A "message pull only ..." (§10.2) stops the client pushing -- it keeps pulling but answers no further gimme and drops its push card one request later, matching fossil clearing SYNC_PUSH after it has already emitted the next request's header. Behavior change worth a look: a first --private pull against a server that denies private content (no 'x') now receives no content that session, because the denial error ends the reply-card loop before the server's inventory, as fossil's client does. The private blob still never reaches an unauthorized client. TestSyncPrivateEndToEnd/no_x_capability is updated to this. check-in: c9436f82cc user: [email protected] tags: main, trunk | |
| 18:01 |
fix(xfer): follow the draft's card grammar, not whole-message failure (#299) (#340)
The card decoder refused a card by failing the entire message: the server answered HTTP 400 where §5.2 has it emit "bad command" and parse on, and the client dropped a whole reply including its valid prefix. The decoder now yields a bad-command card for a line no rule accepts (an unknown operator, a bare pragma, a gimme with a surplus token, a config with a signed size) and a bad-file card for a file/cfile/uvfile line it cannot frame. The server resets its reply, emits the matching error (bad command, or the handler's "malformed file line" and the like) and either parses on (bad command) or stops (bad file), as fossil's page_xfer does; the client ends the reply-card loop, keeping the cards decoded before the bad one; a clone treats it as a non-retryable protocol error. Tokens are split on ASCII whitespace only, within fossil's six-token window (blob_tokenize over aToken[6]): a no-break space no longer separates tokens, and a seventh token is ignored rather than rejected, so igot and private tolerate a surplus token. A full cfile's USIZE is carried through as metadata, not checked against the inflated size (the hash binds the content instead), and the byte after a config payload is consumed whatever it is, both matching fossil's xfer_accept_compressed_file and page_xfer. This also resolves the bad-command cases tracked in #300 (sync.5.2.bad-command, .bad-command-resets, .unknown-prefix, sync.10.1.bad-command-keeps-mutations), whose marks are removed here. check-in: ddc4b5396d user: [email protected] tags: main, trunk | |
| 17:52 |
fix(deck): enforce card legality, required cards and per-type semantics (#273) (#339)
deck.Parse determined an artifact's type but then checked nothing against it, so a card a type disallows, a required card left out, or a tag that breaks a per-type semantic rule all parsed. Add deck/legality.go with fossil's manifestCardTypes table (allowed and required cards per type) and the §5.4 semantic checks: a control artifact's tags may not target itself, a technote's tags are all self-referential singletons, and a forum post carries at most one of an H or I card and at most one parent. Parse now determines the type (inferType gains the B, J and Q type-setters it was missing and falls back to a control artifact, not an empty check-in, when nothing sets a type and there is no comment or parent), then applies legality and the semantic checks. A missing Z card is now caught by the universal required-card rule. Several internal/manifest and internal/deck tests built incomplete artifacts fossil also rejects -- a cluster with a D card, a forum post with both an H and an I card, control-shaped D/U/Z artifacts with no T card, and single-card fixtures missing their type's required cards. Frame each as a valid artifact of its type; the behavior each test pins is unchanged. This also makes two repostate conformance cases conform: the technote with a non-self tag is now rejected at parse (not by a later isArtifact gate), and the opaque-control rebuild case. Their marks are removed in conformance/repostate_gaps_test.go. check-in: 7b8f655da6 user: [email protected] tags: main, trunk | |