Skip to content

feat: support extraction of multiple package types - #318

Open
upils wants to merge 22 commits into
canonical:mainfrom
upils:support-bin-extract
Open

upils wants to merge 22 commits into
canonical:mainfrom
upils:support-bin-extract

Conversation

@upils

@upils upils commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator
  • Have you signed the CLA?

Prepare the extraction path for upcoming bin packages (plain XZ-compressed
tarballs), which today cannot be handled because the tar walker is hard-wired
to the .deb container format.

tarball now consumes a PkgReader interface — a package that can provide
its tar stream, freshly and from the start, on every call. This keeps the
two-pass hard-link rewind inside tarball, shared by all formats, while
each format owns its container knowledge: deb.DataReader became
deb.Pkg.TarStream, and bin.Pkg is added under internal/bin.
Archive.Fetch now returns a PkgReader directly, so the package type is
transparent to the slicer.

The walker's tests use a minimal in-memory testutil.TestPkg double, so
tarball no longer depends on deb even in tests; the real implementations
keep their own extraction coverage, and the fake test archive now publishes
structurally real debs to match.

@upils upils added the Simple Nice for a quick look on a minute or two label Jul 31, 2026
@upils upils mentioned this pull request Jul 31, 2026
1 task
Comment thread internal/tarball/extract.go Outdated
)

// OpenTarFunc opens the uncompressed tar stream carried by a package, hiding
// the package format from Extract. An implementation may unwrap a container

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is documenting a "package" inside internal/tarball.

It's a bit late here so that doesn't help, but this PR seems to suffer a bit from lack of clarity and precision about the encapsulations it's introducing and changing. In theory, if you want to "extract bins", we shouldn't have to touch the interface of either deb or tarball.

Happy to be lessoned on what you had in mind, though.

@upils upils Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main goal of this PR is exactly to not have to touch the interface of either deb or tarball anymore in the future. But I think it is worth adapting it a bit right now when preparing for multiple tarball containers, rather than later.

So far the tarball extraction logic assumed a deb was extracted. The TarOpener abstracts how the container looks like (ar, etc.) and gives a io.ReadCloser to the tarball logic. deb.DataReader was also needlessly receiving a io.ReadSeeker when it only needs a io.Reader, so I refined it while defining the TarOpener interface.

As a result of these changes, tarball does not depend on deb anymore and the extraction logic does not assume it works on a deb either.

I have rework the documentation to avoid mixing independent concepts.

@upils upils changed the title feat: extract bins refactor: make tarball.Extract package-format agnostic Sep 3, 2026

@niemeyer niemeyer left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On last week's review and discussion on Tuesday I already provided some hints that this is not looking great. It seems to be the same as last week still, so still not looking great.

return nil, err
}
dataReader, err := deb.DataReader(pkgReader)
dataReader, err := deb.OpenTar(pkgReader)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not opening "a tar"... this is opening the deb's "data" payload, per implementation.

Comment thread internal/tarball/extract.go Outdated
}

func Extract(pkgReader io.ReadSeeker, options *ExtractOptions) (err error) {
func Extract(pkgReader io.ReadSeeker, opener TarOpener, options *ExtractOptions) (err error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would this take both an "opener" and a "reader"? This extracting pkgReader, right?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your analogy in the other comment clarified the issue with the approach.

Comment thread internal/tarball/extract.go Outdated
func extractData(pkgReader io.ReadSeeker, options *ExtractOptions) error {
dataReader, err := deb.DataReader(pkgReader)
func extractData(pkgReader io.ReadSeeker, opener TarOpener, options *ExtractOptions) error {
dataReader, err := opener(pkgReader)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a good encapsulation. Imagine I hand you my phone and a USB-C charging cable, and ask you "Paul, can you please connect my charging cable on my phone for me, I want to charge it.", how would that feel? That's what is going on here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That analogy was helpful, thanks. I have drastically redesigned the approach in this PR, so concerns are better separated. With the new PkgReader interface, the tarball pkg clearly defines what it needs to operate and the various package types (deb, bin) are handling package-specific knowledge.

@upils upils changed the title refactor: make tarball.Extract package-format agnostic feat: add package format support to tarball extraction Sep 8, 2026
@upils upils changed the title feat: add package format support to tarball extraction feat: support extraction of multiple package types Sep 14, 2026

func extractData(pkgReader io.ReadSeeker, options *ExtractOptions) error {
dataReader, err := deb.DataReader(pkgReader)
func extractEntries(pkg PkgReader, options *ExtractOptions) error {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Note to reviewer]: As you pointed out in another comment, I realized extractData was named because it extracted the content of the "data" container from a deb. With the current more generic approach, the existing name made little sense.
I also considered doExtract for the name but extractEntries is more precise.

Comment thread internal/bin/extract.go
@@ -0,0 +1,36 @@
package bin

@upils upils Sep 14, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Note to reviewer]: The introduction of this package can be done in a follow up PR if we want this one to focus on the reworked interface. I added it as this is rather small and it illustrates the work in this PR is not artificial.

Comment thread internal/tarball/extract.go Outdated
"github.com/canonical/chisel/internal/strdist"
)

// PkgReader provides the tar stream of a package. TarStream must

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Note to reviewer]: We may need to come up with a better name for this tarball package, as it does not deal with general tarballs. I suggest "pkgcontent". This is a compound but both pkg and content names had good pros but still cons if used alone.

If we proceed, we should do that in a follow-up to keep this PR focused on the introduced interface.

Version: "1.1",
Arch: "amd64",
SHA256: "1f08ef04cfe7a8087ee38a1ea35fa1810246648136c3c42d5a61ad6503d85e05",
SHA256: "ff175644a17301e047ac757681f6e16b1c410228d9fe50441bba8438a7c45fa2",

@upils upils Sep 14, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Note to reviewer]: These hashes changed because the shape of the input in the test changed. A simple []byte cannot be used anymore as the testarchive.Package now expects a valid package, providing extractable content. However the actual content of the input package did not change, so this is a benign change.

@upils upils removed the Simple Nice for a quick look on a minute or two label Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants