package bundle import ( "archive/zip" "context" "io" "os" "path/filepath" "strings" "github.com/pkg/errors" "gitlab.com/wpetit/goweb/logger" ) type ZipBundle struct { archivePath string } func (b *ZipBundle) File(filename string) (io.ReadCloser, os.FileInfo, error) { reader, err := b.openArchive() if err != nil { return nil, nil, err } ctx := logger.With( context.Background(), logger.F("filename", filename), ) logger.Debug(ctx, "opening file") f, err := reader.Open(filename) if err != nil { return nil, nil, errors.WithStack(err) } stat, err := f.Stat() if err != nil { return nil, nil, errors.WithStack(err) } return f, stat, nil } func (b *ZipBundle) Dir(dirname string) ([]os.FileInfo, error) { reader, err := b.openArchive() if err != nil { return nil, err } defer func() { if err := reader.Close(); err != nil { panic(errors.WithStack(err)) } }() files := make([]os.FileInfo, 0) ctx := context.Background() for _, f := range reader.File { if !strings.HasPrefix(f.Name, dirname) { continue } relPath, err := filepath.Rel(dirname, f.Name) if err != nil { return nil, errors.Wrap(err, "could not get relative path") } logger.Debug( ctx, "checking file prefix", logger.F("dirname", dirname), logger.F("filename", f.Name), logger.F("relpath", relPath), ) if relPath == filepath.Base(f.Name) { files = append(files, f.FileInfo()) } } return files, nil } func (b *ZipBundle) openArchive() (*zip.ReadCloser, error) { zr, err := zip.OpenReader(b.archivePath) if err != nil { return nil, errors.Wrapf(err, "could not decompress '%v'", b.archivePath) } return zr, nil } func NewZipBundle(archivePath string) *ZipBundle { return &ZipBundle{ archivePath: archivePath, } }