Artifact 256fa3a1df7504171cecffaf30cfa95c33d842fe1b12237be53e375f3ed9e60b:
- File
internal/manifest/timestamp_test.go
— part of check-in
[fa1895d56b]
at
2026-10-18 18:15:05
on branch main
— fix(manifest): record check-in and tag times to the millisecond (#440)
Fossil and zit write D cards with exactly three fractional digits. go-libfossil wrote whatever precision the time carried, and the default clock time carries nanoseconds: legal under artifact-format ยง4.6.4, but zit cannot read a D card with more than three digits (danmestas/zit#244), so zit could not open a repository go-libfossil had committed to.
Checkin and AddTag now truncate the time to the millisecond, whether the caller supplied it or the clock did. Parsed artifacts are untouched: the marshaller still keeps any precision it read, so existing artifacts round-trip byte for byte. (user: [email protected], size: 1375) [annotate] [blame] [check-ins using] [more...]
package manifest import ( "regexp" "testing" "time" "github.com/danmestas/go-libfossil/internal/content" ) // dCardMillis is the D card fossil and zit write: whole seconds plus exactly // three fractional digits. var dCardMillis = regexp.MustCompile(`(?m)^D \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}$`) // TestCheckinWritesMillisecondTimestamps commits once with a caller time // carrying nanoseconds and once with no time (the clock default), and reads // back each manifest's D card. Both must carry milliseconds, as fossil and // zit write them; finer digits are legal but zit cannot read them. func TestCheckinWritesMillisecondTimestamps(t *testing.T) { r := setupTestRepo(t) cases := []struct { name string when time.Time }{ {"caller time with nanoseconds", time.Date(2024, 1, 15, 10, 30, 0, 123456789, time.UTC)}, {"default clock time", time.Time{}}, } for i, c := range cases { rid, _, err := Checkin(r, CheckinOpts{ Files: []File{{Name: "f.txt", Content: []byte{byte('a' + i)}}}, Comment: c.name, User: "testuser", Time: c.when, }) if err != nil { t.Fatalf("%s: Checkin: %v", c.name, err) } data, err := content.Expand(r.DB(), rid) if err != nil { t.Fatalf("%s: Expand: %v", c.name, err) } if !dCardMillis.Match(data) { t.Fatalf("%s: D card is not millisecond precision:\n%s", c.name, data) } } }