refactoring archive indexing

Signed-off-by: Kudryavcev Nikolay <kydry.nikolau@gmail.com>
This commit is contained in:
Kudryavcev Nikolay
2025-06-29 19:39:00 +03:00
parent 40df2d0d91
commit c8fbd613eb
3 changed files with 47 additions and 37 deletions
+27 -23
View File
@@ -16,8 +16,8 @@ import (
type archiveAccessPath struct {
realPath string
accessPath string
archiveDepth int
archiveRealPath string
archiveDepth int
}
const (
@@ -100,7 +100,11 @@ func (r *Directory) buildIndex() error {
func (r *Directory) buildArchiveIndex(archiveTempDir string, archives []string, maxArchiveIndexDepth int) error {
archivesToIndex := make([]archiveAccessPath, len(archives))
for i, archive := range archives {
archivesToIndex[i] = archiveAccessPath{realPath: archive, accessPath: archive, archiveRealPath: archive}
archivesToIndex[i] = archiveAccessPath{
realPath: archive,
accessPath: archive,
archiveRealPath: archive,
}
}
loop:
@@ -119,59 +123,59 @@ loop:
continue
}
archivePath, err := os.MkdirTemp(archiveTempDir, archiveContentTempPathPattern)
envelopedUnarchiver, err := archiver.ByExtension(currentArchivePath.archiveRealPath)
if err != nil {
return fmt.Errorf("could not determine archive envelope type: %w", err)
}
unarchiver, ok := envelopedUnarchiver.(archiver.Unarchiver)
if !ok {
return fmt.Errorf("unarchiver %T is not an archiver", envelopedUnarchiver)
}
archiveDestinationTempDir, err := os.MkdirTemp(archiveTempDir, archiveContentTempPathPattern)
if err != nil {
return fmt.Errorf("unable to create tempdir for archive processing: %w", err)
}
archiveRealPath, err := filepath.EvalSymlinks(archivePath)
archiveDestinationPath, err := filepath.EvalSymlinks(archiveDestinationTempDir)
if err != nil {
var pathErr *os.PathError
if errors.As(err, &pathErr) {
// we can't index the path, but we shouldn't consider this to be fatal
// TODO: known-unknowns
log.WithFields("archivePath", archivePath, "error", err).Trace("unable to evaluate symlink while indexing branch")
return nil
log.WithFields("archivePath", archiveDestinationTempDir, "error", err).Trace("unable to evaluate symlink while indexing branch")
continue
}
return err
}
envelopedUnarchiver, err := archiver.ByExtension(currentArchivePath.archiveRealPath)
if err != nil {
return err
if err = unarchiver.Unarchive(currentArchivePath.archiveRealPath, archiveDestinationPath); err != nil {
return fmt.Errorf("unable to unarchive nested file: %w", err)
}
unarchiver, ok := envelopedUnarchiver.(archiver.Unarchiver)
if !ok {
return ErrSkipPath
}
if err = unarchiver.Unarchive(currentArchivePath.archiveRealPath, archiveRealPath); err != nil {
return err
}
d, err := newFromDirectoryWithoutIndex(archiveRealPath, "")
d, err := newFromDirectoryWithoutIndex(archiveDestinationPath, "")
if err != nil {
return err
}
if err = d.buildIndex(); err != nil {
return err
return fmt.Errorf("unable to build index of archive: %w", err)
}
for _, archive := range d.indexer.archivePaths {
archivesToIndex = append(archivesToIndex, archiveAccessPath{
realPath: currentArchivePath.realPath,
accessPath: strings.Replace(archive, archiveRealPath, currentArchivePath.accessPath, 1),
archiveDepth: currentArchivePath.archiveDepth + 1,
accessPath: strings.Replace(archive, archiveDestinationPath, currentArchivePath.accessPath, 1),
archiveRealPath: archive,
archiveDepth: currentArchivePath.archiveDepth + 1,
})
}
d.chroot = r.chroot
d.realPath = currentArchivePath.realPath
d.accessPath = currentArchivePath.accessPath
d.tempDir = archiveRealPath
d.archiveRealPath = archiveDestinationPath
r.archives = append(r.archives, &d.filetreeResolver)
}
+18 -10
View File
@@ -21,10 +21,10 @@ type filetreeResolver struct {
index filetree.IndexReader
searchContext filetree.Searcher
realPath string
accessPath string
tempDir string
archives []*filetreeResolver
realPath string
accessPath string
archiveRealPath string
archives []*filetreeResolver
}
func (r *filetreeResolver) requestPath(userPath string) (string, error) {
@@ -33,8 +33,8 @@ func (r *filetreeResolver) requestPath(userPath string) (string, error) {
return "", err
}
if r.accessPath != "" && r.tempDir != "" {
return strings.Replace(requestPath, r.accessPath, r.tempDir, 1), nil
if r.accessPath != "" && r.archiveRealPath != "" {
return strings.Replace(requestPath, r.accessPath, r.archiveRealPath, 1), nil
}
return requestPath, nil
@@ -42,15 +42,19 @@ func (r *filetreeResolver) requestPath(userPath string) (string, error) {
// responsePath takes a path from the underlying fs domain and converts it to a path that is relative to the root of the file resolver.
func (r filetreeResolver) responsePath(path string) string {
if r.tempDir != "" && strings.HasPrefix(path, r.tempDir) {
if r.archiveRealPath != "" && strings.HasPrefix(path, r.archiveRealPath) {
path = r.realPath
}
return r.chroot.ToChrootPath(path)
}
func (r filetreeResolver) responseAccessPath(path string) string {
responsePath := strings.Replace(path, r.tempDir, r.accessPath, 1)
return r.chroot.ToChrootPath(responsePath)
if r.accessPath != "" && r.archiveRealPath != "" {
path = strings.Replace(path, r.archiveRealPath, r.accessPath, 1)
}
return r.chroot.ToChrootPath(path)
}
// HasPath indicates if the given path exists in the underlying source.
@@ -138,7 +142,11 @@ func (r filetreeResolver) requestGlob(pattern string) (string, error) {
return "", err
}
return strings.Replace(nativeGlob, r.accessPath, r.tempDir, 1), nil
if r.accessPath != "" && r.archiveRealPath != "" {
return strings.Replace(nativeGlob, r.accessPath, r.archiveRealPath, 1), nil
}
return nativeGlob, nil
}
// FilesByGlob returns all file.References that match the given path glob pattern from any layer in the image.
@@ -1664,6 +1664,7 @@ func TestFileResolver_AllLocations_errorOnDirRequest(t *testing.T) {
}
func TestFileResolver_AllLocations(t *testing.T) {
defer goleak.VerifyNone(t)
// Verify both the parent and the file itself are indexed
filePath := "./test-fixtures/system_paths/target/home/place"
parentPath, err := absoluteSymlinkFreePathToParent(filePath)
@@ -1685,11 +1686,10 @@ func TestFileResolver_AllLocations(t *testing.T) {
sort.Strings(pathsList)
assert.ElementsMatchf(t, expected, pathsList, "expected all paths to be indexed, but found different paths: \n%s", cmp.Diff(expected, paths.List()))
goleak.VerifyNone(t)
}
func Test_FileResolver_AllLocationsDoesNotLeakGoRoutine(t *testing.T) {
defer goleak.VerifyNone(t)
filePath := "./test-fixtures/system_paths/target/home/place"
parentPath, err := absoluteSymlinkFreePathToParent(filePath)
require.NoError(t, err)
@@ -1703,6 +1703,4 @@ func Test_FileResolver_AllLocationsDoesNotLeakGoRoutine(t *testing.T) {
break
}
cancel()
goleak.VerifyNone(t)
}