-
Notifications
You must be signed in to change notification settings - Fork 237
feat: support emerge packages analyzer #337
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,123 @@ | ||||||||||||||||||||||||
/* | ||||||||||||||||||||||||
Copyright 2018 Google, Inc. All rights reserved. | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
Licensed under the Apache License, Version 2.0 (the "License"); | ||||||||||||||||||||||||
you may not use this file except in compliance with the License. | ||||||||||||||||||||||||
You may obtain a copy of the License at | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
http://www.apache.org/licenses/LICENSE-2.0 | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
Unless required by applicable law or agreed to in writing, software | ||||||||||||||||||||||||
distributed under the License is distributed on an "AS IS" BASIS, | ||||||||||||||||||||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||||||||||||||||||||
See the License for the specific language governing permissions and | ||||||||||||||||||||||||
limitations under the License. | ||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
package differs | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
import ( | ||||||||||||||||||||||||
"io/ioutil" | ||||||||||||||||||||||||
"os" | ||||||||||||||||||||||||
"path/filepath" | ||||||||||||||||||||||||
"strconv" | ||||||||||||||||||||||||
"strings" | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
pkgutil "github.com/GoogleContainerTools/container-diff/pkg/util" | ||||||||||||||||||||||||
"github.com/GoogleContainerTools/container-diff/util" | ||||||||||||||||||||||||
"github.com/sirupsen/logrus" | ||||||||||||||||||||||||
) | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
//Emerge package database location | ||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
|
||||||||||||||||||||||||
const emergePkgFile string = "/var/db/pkg" | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
type EmergeAnalyzer struct { | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
Comment on lines
+34
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
|
||||||||||||||||||||||||
|
||||||||||||||||||||||||
func (em EmergeAnalyzer) Name() string { | ||||||||||||||||||||||||
return "EmergeAnalyzer" | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
// Diff compares the packages installed by emerge. | ||||||||||||||||||||||||
func (em EmergeAnalyzer) Diff(image1, image2 pkgutil.Image) (util.Result, error) { | ||||||||||||||||||||||||
diff, err := singleVersionDiff(image1, image2, em) | ||||||||||||||||||||||||
return diff, err | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
func (em EmergeAnalyzer) Analyze(image pkgutil.Image) (util.Result, error) { | ||||||||||||||||||||||||
analysis, err := singleVersionAnalysis(image, em) | ||||||||||||||||||||||||
return analysis, err | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
func (em EmergeAnalyzer) getPackages(image pkgutil.Image) (map[string]util.PackageInfo, error) { | ||||||||||||||||||||||||
var path string | ||||||||||||||||||||||||
path = image.FSPath | ||||||||||||||||||||||||
Comment on lines
+53
to
+54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: in go, it's more idiomatic to say:
Suggested change
|
||||||||||||||||||||||||
switch path { | ||||||||||||||||||||||||
case "": | ||||||||||||||||||||||||
path = emergePkgFile | ||||||||||||||||||||||||
default: | ||||||||||||||||||||||||
path = filepath.Join(path, emergePkgFile) | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
Comment on lines
+55
to
+60
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this switch statement is really a two-case if statement in disguise, so it decreases the readability. i think it's easier to read if you just say:
Suggested change
|
||||||||||||||||||||||||
packages := make(map[string]util.PackageInfo) | ||||||||||||||||||||||||
if _, err := os.Stat(path); err != nil { | ||||||||||||||||||||||||
// invalid image directory path | ||||||||||||||||||||||||
logrus.Errorf("Invalid image directory path %s", path) | ||||||||||||||||||||||||
return packages, err | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
contents, err := ioutil.ReadDir(path) | ||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||
logrus.Errorf("Non-content in image directory path %s", path) | ||||||||||||||||||||||||
return packages, err | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
for i := 0; i < len(contents); i++ { | ||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in go, you can iterate directly over the items in a slice:
Suggested change
|
||||||||||||||||||||||||
c := contents[i] | ||||||||||||||||||||||||
pkgPrefix := c.Name() | ||||||||||||||||||||||||
pkgContents, err := ioutil.ReadDir(filepath.Join(path, pkgPrefix)) | ||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||
return packages, err | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
for j := 0; j < len(pkgContents); j++ { | ||||||||||||||||||||||||
c := pkgContents[j] | ||||||||||||||||||||||||
pkgRawName := c.Name() | ||||||||||||||||||||||||
// in usual, name of package installed by emerge is formatted as '{pkgName}-{version}' e.g.(pymongo-3.9.0) | ||||||||||||||||||||||||
s := strings.Split(pkgRawName, "-") | ||||||||||||||||||||||||
if len(s) != 2 { | ||||||||||||||||||||||||
continue | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
pkgName, version := s[0], s[1] | ||||||||||||||||||||||||
pkgPath := filepath.Join(path, pkgPrefix, pkgRawName, "SIZE") | ||||||||||||||||||||||||
size, err := getPkgSize(pkgPath) | ||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||
return packages, err | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
currPackage := util.PackageInfo{Version: version, Size: size} | ||||||||||||||||||||||||
fullPackageName := strings.Join([]string{pkgPrefix, pkgName}, "/") | ||||||||||||||||||||||||
packages[fullPackageName] = currPackage | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
return packages, nil | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
// emerge will count the total size of a package and store it as a SIZE file in pkg metadata directory | ||||||||||||||||||||||||
// getPkgSize read this SIZE file of a given package | ||||||||||||||||||||||||
func getPkgSize(pkgPath string) (int64, error) { | ||||||||||||||||||||||||
var sizeFile *os.File | ||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps I am missing something, but can this just use os.Stat to get the file size? https://gist.github.com/miguelmota/08bca5febf2ce460a289ef14c7e9af4f If not, maybe a comment that says
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, this SIZE file and created by emerge, since emerge will count the total size of a package and store it as a SIZE file in packages metadata directory. So And it's quite complex using |
||||||||||||||||||||||||
var err error | ||||||||||||||||||||||||
sizeFile, err = os.Open(pkgPath) | ||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||
logrus.Debugf("unable to open SIZE file for pkg %s", pkgPath) | ||||||||||||||||||||||||
return 0, err | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
defer sizeFile.Close() | ||||||||||||||||||||||||
fileBody, err := ioutil.ReadAll(sizeFile) | ||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||
logrus.Debugf("unable to read SIZE file for pkg %s", pkgPath) | ||||||||||||||||||||||||
return 0, err | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
strFileBody := strings.Replace(string(fileBody), "\n", "", -1) | ||||||||||||||||||||||||
size, _ := strconv.ParseInt(strFileBody, 10, 64) | ||||||||||||||||||||||||
return size, nil | ||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/* | ||
Copyright 2018 Google, Inc. All rights reserved. | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package differs | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
|
||
pkgutil "github.com/GoogleContainerTools/container-diff/pkg/util" | ||
"github.com/GoogleContainerTools/container-diff/util" | ||
) | ||
|
||
func TestGetEmergePackages(t *testing.T) { | ||
testCases := []struct { | ||
descrip string | ||
path string | ||
expected map[string]util.PackageInfo | ||
err bool | ||
}{ | ||
{ | ||
descrip: "no directory", | ||
path: "testDirs/notThere", | ||
expected: map[string]util.PackageInfo{}, | ||
err: true, | ||
}, | ||
{ | ||
descrip: "no packages", | ||
path: "testDirs/noPackages", | ||
expected: map[string]util.PackageInfo{}, | ||
}, | ||
{ | ||
descrip: "packages in expected location", | ||
path: "testDirs/packageEmerge", | ||
expected: map[string]util.PackageInfo{ | ||
"dev-python/pkg1": {Version: "0.0.1", Size: 167112}, | ||
"dev-python/pkg2": {Version: "0.0.2", Size: 167112}, | ||
"sys-libs/pkg3": {Version: "0.0.3", Size: 167112}}, | ||
}, | ||
} | ||
for _, test := range testCases { | ||
d := EmergeAnalyzer{} | ||
image := pkgutil.Image{FSPath: test.path} | ||
packages, err := d.getPackages(image) | ||
if err != nil && !test.err { | ||
t.Errorf("Got unexpected error: %s", err) | ||
} | ||
if err == nil && test.err { | ||
t.Errorf("Expected error but got none.") | ||
} | ||
if !reflect.DeepEqual(packages, test.expected) { | ||
t.Errorf("Expected: %v but got: %v", test.expected, packages) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
167112 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
167112 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
167112 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these should be 2020. i'll merge this and fix myself, so we don't have to go back and forth.