Drop mimeType and ctime from the manifest format (closes #235)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
Nothing goes in the 1.0 manifest that 1.0 does not read or write, and mfer never wrote either field. mf.proto now reserves the numbers 301 and 303 and both names in MFFilePath, and mf.pb.go is regenerated. The decoded-size check counts only file entries, hashes and timestamps, and counts a file entry, 16 bytes smaller without the two fields, at 160 bytes. export prints no ctime, and FileEntry loses the Ctime nothing set. FORMAT.md and the README no longer describe either field. The test of entries that decode too large gives each entry a second, empty hash: an entry with one hash and a modification time can no longer reach 8 times its size. Model: opus-5-5
This commit was merged in pull request #237.
This commit is contained in:
@@ -295,14 +295,17 @@ func TestDeserializeRefusesModeOutsidePermissionBits(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Entries of a path, a SHA-256 hash, an empty MIME type and empty
|
||||
// modification and change times are counted at 432 bytes each (176 + 112 +
|
||||
// 16 + 64 + 64) and take 52 bytes plus the path to encode. A one-character
|
||||
// path makes that 53 bytes, about 8.2 times: refused, and leaving any one of
|
||||
// the five uncounted, even the MIME type, brings it under 8. A two-character
|
||||
// path makes it 54 bytes, 8 times exactly: loaded. There is one entry for
|
||||
// each base-36 digit, and each entry's path is its number in base 36, padded
|
||||
// with zeros to that length, since a manifest lists a path only once.
|
||||
// Entries of a path, a SHA-256 hash, an empty second hash and an empty
|
||||
// modification time are counted at 448 bytes each (160 + 112 + 112 + 64)
|
||||
// and take 48 bytes plus the path to encode. A 7-character path makes that
|
||||
// 55 bytes, about 8.1 times: refused, and leaving any one of the four
|
||||
// uncounted, even the modification time, brings it under 8. An 8-character
|
||||
// path makes it 56 bytes, 8 times exactly: loaded. Without the second hash
|
||||
// an entry is never refused: it takes at least 47 bytes and is counted at
|
||||
// 336. There is one entry for each base-36 digit, enough that the 22 bytes
|
||||
// of the version and UUID change neither outcome, and each entry's path is
|
||||
// its number in base 36, padded with zeros to that length, since a manifest
|
||||
// lists a path only once.
|
||||
func TestDeserializeRefusesEntriesThatDecodeTooLarge(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -316,8 +319,8 @@ func TestDeserializeRefusesEntriesThatDecodeTooLarge(t *testing.T) {
|
||||
pathLen int
|
||||
refused bool
|
||||
}{
|
||||
{1, true},
|
||||
{2, false},
|
||||
{7, true},
|
||||
{8, false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -338,12 +341,10 @@ func TestDeserializeRefusesEntriesThatDecodeTooLarge(t *testing.T) {
|
||||
entry = protowire.AppendString(entry, path)
|
||||
entry = protowire.AppendTag(entry, 3, protowire.BytesType) // MFFilePath.hashes
|
||||
entry = protowire.AppendBytes(entry, checksum)
|
||||
entry = protowire.AppendTag(entry, 301, protowire.BytesType) // MFFilePath.mimeType
|
||||
entry = protowire.AppendTag(entry, 3, protowire.BytesType) // MFFilePath.hashes
|
||||
entry = protowire.AppendBytes(entry, nil)
|
||||
entry = protowire.AppendTag(entry, 302, protowire.BytesType) // MFFilePath.mtime
|
||||
entry = protowire.AppendBytes(entry, nil)
|
||||
entry = protowire.AppendTag(entry, 303, protowire.BytesType) // MFFilePath.ctime
|
||||
entry = protowire.AppendBytes(entry, nil)
|
||||
|
||||
inner = protowire.AppendTag(inner, 101, protowire.BytesType) // MFFile.files
|
||||
inner = protowire.AppendBytes(inner, entry)
|
||||
@@ -399,6 +400,44 @@ func TestDeserializeDropsUnknownFields(t *testing.T) {
|
||||
assert.Empty(t, m.Files()[0].ProtoReflect().GetUnknown())
|
||||
}
|
||||
|
||||
// A file entry holding fields 301 and 303, which mf.proto reserves, loads,
|
||||
// and the loaded entry keeps neither.
|
||||
func TestDeserializeDropsReservedFields(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
hash, err := multihash.Encode(make([]byte, sha256.Size), multihash.SHA2_256)
|
||||
require.NoError(t, err)
|
||||
|
||||
checksum, err := proto.Marshal(&MFFileChecksum{MultiHash: hash})
|
||||
require.NoError(t, err)
|
||||
|
||||
timestamp, err := proto.Marshal(&Timestamp{Seconds: 1})
|
||||
require.NoError(t, err)
|
||||
|
||||
entry := protowire.AppendTag(nil, 1, protowire.BytesType) // MFFilePath.path
|
||||
entry = protowire.AppendString(entry, "a")
|
||||
entry = protowire.AppendTag(entry, 3, protowire.BytesType) // MFFilePath.hashes
|
||||
entry = protowire.AppendBytes(entry, checksum)
|
||||
entry = protowire.AppendTag(entry, 301, protowire.BytesType) // reserved
|
||||
entry = protowire.AppendString(entry, "text/plain")
|
||||
entry = protowire.AppendTag(entry, 303, protowire.BytesType) // reserved
|
||||
entry = protowire.AppendBytes(entry, timestamp)
|
||||
|
||||
id := uuid.NewV4()
|
||||
inner := protowire.AppendTag(nil, 100, protowire.VarintType) // MFFile.version
|
||||
inner = protowire.AppendVarint(inner, uint64(MFFile_VERSION_ONE))
|
||||
inner = protowire.AppendTag(inner, 101, protowire.BytesType) // MFFile.files
|
||||
inner = protowire.AppendBytes(inner, entry)
|
||||
inner = protowire.AppendTag(inner, 102, protowire.BytesType) // MFFile.uuid
|
||||
inner = protowire.AppendBytes(inner, id[:])
|
||||
|
||||
m, err := NewManifestFromReader(bytes.NewReader(wrapInner(t, id, inner)))
|
||||
require.NoError(t, err)
|
||||
require.Len(t, m.Files(), 1)
|
||||
assert.Equal(t, "a", m.Files()[0].GetPath())
|
||||
assert.Empty(t, m.Files()[0].ProtoReflect().GetUnknown())
|
||||
}
|
||||
|
||||
// Many empty files with names of at most three characters and modification
|
||||
// times at the epoch make about the densest manifest mfer writes: it takes
|
||||
// about 7 times its size to decode, and still loads. A signature would not
|
||||
|
||||
Reference in New Issue
Block a user