Conversation
…zz suites; leave out an entry without a name
…r prefix, as bsdtar writes it
… archive as nested
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
Closes #69. Part 2 of #76 (more archive formats), after gzip (#80).
TabularFile.OpenandArchiveCursornow read a.tarand a.tar.gz/.tgzas one workbook, exactly as a zip: the sheets of every csv, xlsx and ods file inside, in path order, each with its entry's path asSource.Spec:
docs/superpowers/specs/2026-10-03-tar-design.md. Plan:docs/superpowers/plans/2026-10-03-tar.md.TabularFormat.Tar(for.tarand.tar.gzalike).ArchiveCursor(stream, …)tells zip, tar and tar.gz apart by their bytes; a tar header is known by its magic and checksum, raw or as the first decompressed block of a gzip.ArchiveCursorrefactored over an internalArchiveContainer—ZipContainer(today's code, moved),TarContainer,TarGzContainer. Its judging, skipping, bounds and sheet logic is shared; 7z (Read 7z archives #75) will plug in the same way. Zip behaviour is unchanged: every existing test passes untouched..tar: indexed in one pass over the headers (TarReaderskips data by seeking); entries are read in place through a seekable window, workbooks included — nothing is copied. The end-of-archive zero block is checked (a seekableTarReaderdoes not), so a tar cut at an entry boundary is refused..tar.gz: one decompression pass lists the sheets; reading a sheet decompresses again up to it, continuing forward when the sheet lies further on. Memory stays flat. A pass that reaches the end reads the gzip stream to its end, so the whole-file CRC is checked.._files are left out;.gzentries skip asCompressed, a zip or tar inside asNestedArchive. A tar holding a GNU sparse file is refused asformat.unsupported—TarReaderthrows at the sparse header, so nothing after it can be reached.TarReaderquirk worked around: on .NET 8 and 10 it drops the ustar prefix of a PAX entry that has nopathrecord — which is how bsdtar (the tar of macOS and Windows) writes every path that fits the ustar fields, so a path over 100 characters lost its folders. The prefix is joined from the raw header.TarEntry.DataOffsetis .NET 9+; the fallback sits in one helper under#ifand goes when net8 is dropped at the .NET 11 release.format.truncated/format.corrupt; bounds as for zip (MaxEntries,MaxUncompressedBytes— for a tar.gz counted as it is decompressed,MaxEmbeddedWorkbookBytes).Performance (5M-row csv, 572 MB; Release, each in its own process, machine under load):
A tar.gz pays two decompressions (listing, then reading). 20 csv files of 50,000 rows in one tar.gz: stored in path order, read 1.46 s / analysis 3.92 s; stored in reverse path order — one restart per sheet, the worst case — 4.33 s / 6.76 s. Row and cell counts equal across csv, zip, tar and tar.gz.
Tests: every tar format (ustar, PAX, GNU), long paths, every entry type, cuts of
.tarand.tar.gz, missing end marker, damaged headers, a tar.gz stored out of path order read back and forth, bounds, detection near-misses, a bsdtar-style PAX entry, zip/tar/tar.gz profiling alike, analysis → plan → import; tar in the stream-ownership, cancellation and API-contract suites; a tar / tar.gz fuzz case (20,000 cases run locally, which found the nameless-entry case on net8, fixed). Checked by hand against real archives made by macOStar(bsdtar).Checklist
dotnet buildanddotnet testpass on net8.0 and net10.0 with zero warnings. (2572 tests, rebased on main)ErrorCodesand the guide's error-code table agree. (no new codes)TabularFormat.Tar; a consumer's exhaustive switch overTabularFormatneeds the new member)src/.