Merge pull request #749 from cnorthwood/tarutil-glob
tarutil: allow file names to be specified by regexp
This commit is contained in:
commit
4af5afe305
@ -90,5 +90,5 @@ func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.LayerFeature, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l lister) RequiredFilenames() []string {
|
func (l lister) RequiredFilenames() []string {
|
||||||
return []string{"lib/apk/db/installed"}
|
return []string{"^lib/apk/db/installed"}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ var (
|
|||||||
type lister struct{}
|
type lister struct{}
|
||||||
|
|
||||||
func (l lister) RequiredFilenames() []string {
|
func (l lister) RequiredFilenames() []string {
|
||||||
return []string{"var/lib/dpkg/status"}
|
return []string{"^var/lib/dpkg/status"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -35,10 +35,11 @@ type Lister interface {
|
|||||||
// ListFeatures produces a list of Features present in an image layer.
|
// ListFeatures produces a list of Features present in an image layer.
|
||||||
ListFeatures(tarutil.FilesMap) ([]database.LayerFeature, error)
|
ListFeatures(tarutil.FilesMap) ([]database.LayerFeature, error)
|
||||||
|
|
||||||
// RequiredFilenames returns the list of files required to be in the FilesMap
|
// RequiredFilenames returns a list of patterns for filenames that will
|
||||||
// provided to the ListFeatures method.
|
// be in the FilesMap provided to the ListFeatures method.
|
||||||
//
|
//
|
||||||
// Filenames must not begin with "/".
|
// The patterns are expressed as regexps, and will be matched against
|
||||||
|
// full paths that do not include the leading "/".
|
||||||
RequiredFilenames() []string
|
RequiredFilenames() []string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,8 +103,9 @@ func ListFeatures(files tarutil.FilesMap, toUse []database.Detector) ([]database
|
|||||||
return features, nil
|
return features, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequiredFilenames returns all files required by the give extensions. Any
|
// RequiredFilenames returns all file patterns that will be passed to the
|
||||||
// extension metadata that has non feature-detector type will be skipped.
|
// given extensions. These patterns are expressed as regexps. Any extension
|
||||||
|
// metadata that has non feature-detector type will be skipped.
|
||||||
func RequiredFilenames(toUse []database.Detector) (files []string) {
|
func RequiredFilenames(toUse []database.Detector) (files []string) {
|
||||||
listersM.RLock()
|
listersM.RLock()
|
||||||
defer listersM.RUnlock()
|
defer listersM.RUnlock()
|
||||||
|
@ -46,7 +46,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l lister) RequiredFilenames() []string {
|
func (l lister) RequiredFilenames() []string {
|
||||||
return []string{"var/lib/rpm/Packages"}
|
return []string{"^var/lib/rpm/Packages"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isIgnored(packageName string) bool {
|
func isIgnored(packageName string) bool {
|
||||||
|
@ -62,5 +62,5 @@ func (d detector) Detect(files tarutil.FilesMap) (*database.Namespace, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d detector) RequiredFilenames() []string {
|
func (d detector) RequiredFilenames() []string {
|
||||||
return []string{alpineReleasePath}
|
return []string{"^" + alpineReleasePath}
|
||||||
}
|
}
|
||||||
|
@ -88,5 +88,5 @@ func (d detector) Detect(files tarutil.FilesMap) (*database.Namespace, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d detector) RequiredFilenames() []string {
|
func (d detector) RequiredFilenames() []string {
|
||||||
return []string{"etc/apt/sources.list"}
|
return []string{`^etc/apt/sources\.list`}
|
||||||
}
|
}
|
||||||
|
@ -39,10 +39,11 @@ type Detector interface {
|
|||||||
// layer.
|
// layer.
|
||||||
Detect(tarutil.FilesMap) (*database.Namespace, error)
|
Detect(tarutil.FilesMap) (*database.Namespace, error)
|
||||||
|
|
||||||
// RequiredFilenames returns the list of files required to be in the FilesMap
|
// RequiredFilenames returns a list of patterns for filenames that will
|
||||||
// provided to the Detect method.
|
// be in the FilesMap provided to the Detect method.
|
||||||
//
|
//
|
||||||
// Filenames must not begin with "/".
|
// The patterns are expressed as regexps, and will be matched against
|
||||||
|
// full paths that do not include the leading "/".
|
||||||
RequiredFilenames() []string
|
RequiredFilenames() []string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,8 +109,9 @@ func Detect(files tarutil.FilesMap, toUse []database.Detector) ([]database.Layer
|
|||||||
return namespaces, nil
|
return namespaces, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequiredFilenames returns all files required by the give extensions. Any
|
// RequiredFilenames returns all file patterns that will be passed to the
|
||||||
// extension metadata that has non namespace-detector type will be skipped.
|
// given extensions. These patterns are expressed as regexps. Any extension
|
||||||
|
// metadata that has non namespace-detector type will be skipped.
|
||||||
func RequiredFilenames(toUse []database.Detector) (files []string) {
|
func RequiredFilenames(toUse []database.Detector) (files []string) {
|
||||||
detectorsM.RLock()
|
detectorsM.RLock()
|
||||||
defer detectorsM.RUnlock()
|
defer detectorsM.RUnlock()
|
||||||
|
@ -94,5 +94,5 @@ func (d detector) Detect(files tarutil.FilesMap) (*database.Namespace, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *detector) RequiredFilenames() []string {
|
func (d *detector) RequiredFilenames() []string {
|
||||||
return []string{"etc/lsb-release"}
|
return []string{"^etc/lsb-release"}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,8 @@ var (
|
|||||||
osReleaseOSRegexp = regexp.MustCompile(`^ID=(.*)`)
|
osReleaseOSRegexp = regexp.MustCompile(`^ID=(.*)`)
|
||||||
osReleaseVersionRegexp = regexp.MustCompile(`^VERSION_ID=(.*)`)
|
osReleaseVersionRegexp = regexp.MustCompile(`^VERSION_ID=(.*)`)
|
||||||
|
|
||||||
|
filenames = []string{"etc/os-release", "usr/lib/os-release"}
|
||||||
|
|
||||||
// blacklistFilenames are files that should exclude this detector.
|
// blacklistFilenames are files that should exclude this detector.
|
||||||
blacklistFilenames = []string{
|
blacklistFilenames = []string{
|
||||||
"etc/oracle-release",
|
"etc/oracle-release",
|
||||||
@ -57,7 +59,7 @@ func (d detector) Detect(files tarutil.FilesMap) (*database.Namespace, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, filePath := range d.RequiredFilenames() {
|
for _, filePath := range filenames {
|
||||||
f, hasFile := files[filePath]
|
f, hasFile := files[filePath]
|
||||||
if !hasFile {
|
if !hasFile {
|
||||||
continue
|
continue
|
||||||
@ -100,5 +102,5 @@ func (d detector) Detect(files tarutil.FilesMap) (*database.Namespace, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d detector) RequiredFilenames() []string {
|
func (d detector) RequiredFilenames() []string {
|
||||||
return []string{"etc/os-release", "usr/lib/os-release"}
|
return []string{"^(etc|usr/lib)/os-release"}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,8 @@ var (
|
|||||||
oracleReleaseRegexp = regexp.MustCompile(`(?P<os>Oracle) (Linux Server release) (?P<version>[\d]+)`)
|
oracleReleaseRegexp = regexp.MustCompile(`(?P<os>Oracle) (Linux Server release) (?P<version>[\d]+)`)
|
||||||
centosReleaseRegexp = regexp.MustCompile(`(?P<os>[^\s]*) (Linux release|release) (?P<version>[\d]+)`)
|
centosReleaseRegexp = regexp.MustCompile(`(?P<os>[^\s]*) (Linux release|release) (?P<version>[\d]+)`)
|
||||||
redhatReleaseRegexp = regexp.MustCompile(`(?P<os>Red Hat Enterprise Linux) (Client release|Server release|Workstation release) (?P<version>[\d]+)`)
|
redhatReleaseRegexp = regexp.MustCompile(`(?P<os>Red Hat Enterprise Linux) (Client release|Server release|Workstation release) (?P<version>[\d]+)`)
|
||||||
|
|
||||||
|
filenames = []string{"etc/oracle-release", "etc/centos-release", "etc/redhat-release", "etc/system-release"}
|
||||||
)
|
)
|
||||||
|
|
||||||
type detector struct{}
|
type detector struct{}
|
||||||
@ -42,7 +44,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d detector) Detect(files tarutil.FilesMap) (*database.Namespace, error) {
|
func (d detector) Detect(files tarutil.FilesMap) (*database.Namespace, error) {
|
||||||
for _, filePath := range d.RequiredFilenames() {
|
for _, filePath := range filenames {
|
||||||
f, hasFile := files[filePath]
|
f, hasFile := files[filePath]
|
||||||
if !hasFile {
|
if !hasFile {
|
||||||
continue
|
continue
|
||||||
@ -83,5 +85,5 @@ func (d detector) Detect(files tarutil.FilesMap) (*database.Namespace, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d detector) RequiredFilenames() []string {
|
func (d detector) RequiredFilenames() []string {
|
||||||
return []string{"etc/oracle-release", "etc/centos-release", "etc/redhat-release", "etc/system-release"}
|
return []string{`^etc/(oracle|centos|redhat|system)-release`}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -50,7 +51,8 @@ var (
|
|||||||
type FilesMap map[string][]byte
|
type FilesMap map[string][]byte
|
||||||
|
|
||||||
// ExtractFiles decompresses and extracts only the specified files from an
|
// ExtractFiles decompresses and extracts only the specified files from an
|
||||||
// io.Reader representing an archive.
|
// io.Reader representing an archive. The files to be extracted are specified
|
||||||
|
// by regexp
|
||||||
func ExtractFiles(r io.Reader, filenames []string) (FilesMap, error) {
|
func ExtractFiles(r io.Reader, filenames []string) (FilesMap, error) {
|
||||||
data := make(map[string][]byte)
|
data := make(map[string][]byte)
|
||||||
|
|
||||||
@ -78,7 +80,7 @@ func ExtractFiles(r io.Reader, filenames []string) (FilesMap, error) {
|
|||||||
// Determine if we should extract the element
|
// Determine if we should extract the element
|
||||||
toBeExtracted := false
|
toBeExtracted := false
|
||||||
for _, s := range filenames {
|
for _, s := range filenames {
|
||||||
if strings.HasPrefix(filename, s) {
|
if match, err := regexp.MatchString(s, filename); err == nil && match {
|
||||||
toBeExtracted = true
|
toBeExtracted = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,26 @@ func TestExtract(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExtractRegex(t *testing.T) {
|
||||||
|
for _, filename := range testTarballs {
|
||||||
|
f, err := os.Open(testfilepath(filename))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
data, err := ExtractFiles(f, []string{`.+\.txt`})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
if c, n := data["test/test.txt"]; !n {
|
||||||
|
assert.Fail(t, "test/test.txt should have been extracted")
|
||||||
|
} else {
|
||||||
|
assert.NotEqual(t, 0, len(c) > 0, "test/test.txt file is empty")
|
||||||
|
}
|
||||||
|
if _, n := data["test.txt"]; !n {
|
||||||
|
assert.Fail(t, "test.txt should also have been extracted")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestExtractUncompressedData(t *testing.T) {
|
func TestExtractUncompressedData(t *testing.T) {
|
||||||
for _, filename := range testTarballs {
|
for _, filename := range testTarballs {
|
||||||
f, err := os.Open(testfilepath(filename))
|
f, err := os.Open(testfilepath(filename))
|
||||||
|
Loading…
Reference in New Issue
Block a user