Artifact c209912b17e492a65d589a7f75ee3699a78c24ccab045fa3a1168ea3b266ab77:
- File
internal/sync/version.go
— part of check-in
[707ffd05a2]
at
2026-10-17 20:57:59
on branch feat/submanifest-reader
— feat(sync): carry sub-manifest trees safely (draft-fossil-submanifests-00)
Gate, announce and configure sub-manifest transfer the way zit does, so the two implementations interoperate and no fossil release is handed a tree it cannot read.
- 7.2 gate: once the repository has stored an S-bearing artifact, a tree manifest or sub-manifest is withheld from a peer announcing a release below 2.29.0, zit's threshold, with one explicit error card per reply and never by omission. The server applies it to gimme answers and clone batches; the client to gimmes on push, recording each withheld artifact in the result. - This library reads trees, so it announces 22900 in client-version and server-version; a peer holding trees refuses them to anything lower. No fossil release gates any behaviour between 22800 and 22900. - A ci-lock reply carries pragma avoid-submanifests, where avoid-delta-manifests goes, while enable-submanifests is off. - 6.3: the three settings are /project members on the server, which also answers zit's reqconfig /config with them. Clone asks for them as zit's clone does, once, in its cleanup round with zit's scalar marker; fossil answers that with nothing. A reply's settings are staged and applied all or none.
The examined-blob table's old revision is dropped only when present, so a sweep pays no extra write. (user: [email protected], size: 3314) [annotate] [blame] [check-ins using]
package sync import ( "strconv" "github.com/danmestas/go-libfossil/internal/xfer" ) // The fossil release whose protocol this library speaks (§9.1), and that // release's check-in date and time. The version it announces is // announcedVersion (submanifest.go), which the date and time accompany. const ( releaseVersion = 22800 releaseDate = "20260315" releaseTime = "120000" ) // sha3Version is the first fossil release that accepts SHA3 artifact names. // Content named by SHA3 is withheld from a peer older than this (§7.6). const sha3Version = 20000 // sha1NameLen is the length of a SHA1 artifact name; any longer name is SHA3. const sha1NameLen = 40 // versionPragma is the pragma that announces this library's release: name is // "client-version" or "server-version". func versionPragma(name string) *xfer.PragmaCard { return &xfer.PragmaCard{ Name: name, Values: []string{strconv.Itoa(announcedVersion), releaseDate, releaseTime}, } } // peerVersion reads the VERSION of a client-version or server-version pragma // as fossil's atoi does: leading digits, and 0 when there are none. func peerVersion(c *xfer.PragmaCard) int { if len(c.Values) == 0 { panic("sync.peerVersion: pragma has no VERSION") } return leadingInt(c.Values[0]) } // privateIGotDate is the first peer check-in date that is told, with igot // HASH 1, of private content it asked for outside a private sync (§8.6). An // older peer treats a private igot it may not sync as an error, so it is told // nothing (fossil's send_file, src/xfer.c). const privateIGotDate = 20200413 // peerDate reads the DATE of a client-version or server-version pragma as // fossil's page_xfer and client_sync do: only when the pragma carries both // DATE and TIME, by atoi, and 0 when it does not, which no date gate passes. func peerDate(c *xfer.PragmaCard) int { if len(c.Values) < 3 { return 0 } return leadingInt(c.Values[1]) } // leadingInt reads s as fossil's atoi reads a pragma token: its leading // digits, and 0 when there are none or they overflow an int. func leadingInt(s string) int { n := 0 for n < len(s) && s[n] >= '0' && s[n] <= '9' { n++ } v, err := strconv.Atoi(s[:n]) if err != nil { return 0 } return v } // loginCookieGate reports whether a server-version names a release that // reads a login card from the x-f-l-c cookie: 2.27 or later, built at or // after 2025-07-27 11:05:00, as fossil's xfer_xflc_check decides (§6.5). A // server-version without DATE and TIME does not pass. func loginCookieGate(c *xfer.PragmaCard) bool { if len(c.Values) < 3 { return false } date, _ := strconv.Atoi(c.Values[1]) clock, _ := strconv.Atoi(c.Values[2]) return peerVersion(c) >= 22700 && (date > 20250727 || (date == 20250727 && clock >= 110500)) } // sha3Barred reports whether content named name is withheld from a peer of // the given release: a SHA3 name, to a peer older than SHA3 support (§7.6). func sha3Barred(name string, version int) bool { return len(name) > sha1NameLen && version < sha3Version } // sha3Refusal is the error card that takes the place of SHA3 content withheld // from an older peer, worded as fossil's xfer_cannot_send_sha3_error words it. func sha3Refusal() *xfer.ErrorCard { return &xfer.ErrorCard{Message: "Fossil version 2.0 or later required."} }