fix: build ArchivePath from real paths, not access paths

each `ArchivePath` segment came from `loc.Path()`, so it was the link path when an archive was reached through a symlink and the real path otherwise. That depended on how discovery happened to find the archive. The package location said `store/3f9a1c` while the files inside the same jar were recorded under `...:app/lib/json-simple-1.1.1.jar`, so a consumer couldn't join a package to its files by prefix.

The chain for extracted files is now built from `RealPath`. `Traversal.Location` still carries the access path, so java's name check and `VirtualPath` metadata behave the same as before. The field comment and schema now say every segment has links resolved.

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
Alex Goodman
2026-09-24 11:26:38 -04:00
parent 5fc384dddb
commit f5bac4a026
6 changed files with 17 additions and 9 deletions
+3 -2
View File
@@ -161,8 +161,9 @@ func (c *archiveCataloger) processArchive(ctx context.Context, parentResolver fi
started := time.Now()
// extracted files keep the filesystem ID of where the archive was found; the nesting chain is
// carried separately as the archive path
archivePath := archive.VirtualPath(location)
// carried separately as the archive path. The chain names real paths, not the link the archive was
// reached by, so it is stable and joins to the archive's package location by prefix.
archivePath := archive.VirtualPath(file.NewLocationFromCoordinates(location.Coordinates))
extracted, err := archive.Extract(ctx, archiveContent, location.FileSystemID, archivePath, c.limiter, c.exclusions)
if errors.Is(err, archive.ErrDiskLimitReached) {
// nothing is released while this archive waits, so skip it rather than block the scan