tarutil: convert all filename specs to regexps

This removes the previous behaviour from tarutil to do simple prefix matching.
All places where the previous prefix-based matches were specified have been
updated to use a regexp instead, maintaining previous behaviour.
This commit is contained in:
Chris Northwood 2019-03-22 10:13:24 +00:00
parent afd7fe2554
commit a3a37072b5
12 changed files with 30 additions and 22 deletions

View File

@ -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"}
} }

View File

@ -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() {

View File

@ -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()

View File

@ -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 {

View File

@ -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}
} }

View File

@ -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`}
} }

View File

@ -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()

View File

@ -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"}
} }

View File

@ -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"}
} }

View File

@ -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`}
} }

View File

@ -80,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 match, err := regexp.MatchString("^"+s, filename); err == nil && match { if match, err := regexp.MatchString(s, filename); err == nil && match {
toBeExtracted = true toBeExtracted = true
break break
} }

View File

@ -57,7 +57,7 @@ func TestExtract(t *testing.T) {
} }
} }
func TestExtractGlob(t *testing.T) { func TestExtractRegex(t *testing.T) {
for _, filename := range testTarballs { for _, filename := range testTarballs {
f, err := os.Open(testfilepath(filename)) f, err := os.Open(testfilepath(filename))
assert.Nil(t, err) assert.Nil(t, err)