Skip to content
This repository was archived by the owner on Mar 27, 2024. It is now read-only.

Commit 676578a

Browse files
committed
feat: support ermerge packages analyzer
Signed-off-by: Lexus Lee <[email protected]>
1 parent aae5709 commit 676578a

File tree

7 files changed

+196
-0
lines changed

7 files changed

+196
-0
lines changed

differs/differs.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const rpmAnalyzer = "rpm"
3636
const rpmLayerAnalyzer = "rpmlayer"
3737
const pipAnalyzer = "pip"
3838
const nodeAnalyzer = "node"
39+
const emergeAnalyzer = "emerge"
3940

4041
type DiffRequest struct {
4142
Image1 pkgutil.Image
@@ -67,6 +68,7 @@ var Analyzers = map[string]Analyzer{
6768
rpmLayerAnalyzer: RPMLayerAnalyzer{},
6869
pipAnalyzer: PipAnalyzer{},
6970
nodeAnalyzer: NodeAnalyzer{},
71+
emergeAnalyzer: EmergeAnalyzer{},
7072
}
7173

7274
var LayerAnalyzers = [...]string{layerAnalyzer, sizeLayerAnalyzer, aptLayerAnalyzer, rpmLayerAnalyzer}

differs/emerge_diff.go

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
Copyright 2018 Google, Inc. All rights reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package differs
18+
19+
import (
20+
"io/ioutil"
21+
"os"
22+
"path/filepath"
23+
"strconv"
24+
"strings"
25+
26+
pkgutil "github.com/GoogleContainerTools/container-diff/pkg/util"
27+
"github.com/GoogleContainerTools/container-diff/util"
28+
"github.com/sirupsen/logrus"
29+
)
30+
31+
//Emerge package database location
32+
const emergePkgFile string = "/var/db/pkg"
33+
34+
type EmergeAnalyzer struct {
35+
}
36+
37+
func (em EmergeAnalyzer) Name() string {
38+
return "EmergeAnalyzer"
39+
}
40+
41+
// Diff compares the packages installed by emerge.
42+
func (em EmergeAnalyzer) Diff(image1, image2 pkgutil.Image) (util.Result, error) {
43+
diff, err := singleVersionDiff(image1, image2, em)
44+
return diff, err
45+
}
46+
47+
func (em EmergeAnalyzer) Analyze(image pkgutil.Image) (util.Result, error) {
48+
analysis, err := singleVersionAnalysis(image, em)
49+
return analysis, err
50+
}
51+
52+
func (em EmergeAnalyzer) getPackages(image pkgutil.Image) (map[string]util.PackageInfo, error) {
53+
var path string
54+
path = image.FSPath
55+
switch path {
56+
case "":
57+
path = emergePkgFile
58+
default:
59+
path = filepath.Join(path, emergePkgFile)
60+
}
61+
packages := make(map[string]util.PackageInfo)
62+
if _, err := os.Stat(path); err != nil {
63+
// invalid image directory path
64+
logrus.Errorf("Invalid image directory path %s", path)
65+
return packages, err
66+
}
67+
68+
contents, err := ioutil.ReadDir(path)
69+
if err != nil {
70+
logrus.Errorf("Non-content in image directory path %s", path)
71+
return packages, err
72+
}
73+
74+
for i := 0; i < len(contents); i++ {
75+
c := contents[i]
76+
pkgPrefix := c.Name()
77+
pkgContents, err := ioutil.ReadDir(filepath.Join(path, pkgPrefix))
78+
if err != nil {
79+
return packages, err
80+
}
81+
for j := 0; j < len(pkgContents); j++ {
82+
c := pkgContents[j]
83+
pkgRawName := c.Name()
84+
// in usual, name of package installed by emerge is formatted as '{pkgName}-{version}' e.g.(pymongo-3.9.0)
85+
s := strings.Split(pkgRawName, "-")
86+
if len(s) != 2 {
87+
continue
88+
}
89+
pkgName, version := s[0], s[1]
90+
pkgPath := filepath.Join(path, pkgPrefix, pkgRawName, "SIZE")
91+
size, err := getPkgSize(pkgPath)
92+
if err != nil {
93+
return packages, err
94+
}
95+
currPackage := util.PackageInfo{Version: version, Size: size}
96+
fullPackageName := strings.Join([]string{pkgPrefix, pkgName}, "/")
97+
packages[fullPackageName] = currPackage
98+
}
99+
}
100+
101+
return packages, nil
102+
}
103+
104+
// emerge will count the total size of a package and store it as a SIZE file in pkg metadata directory
105+
// getPkgSize read this SIZE file of a given package
106+
func getPkgSize(pkgPath string) (int64, error) {
107+
var sizeFile *os.File
108+
var err error
109+
sizeFile, err = os.Open(pkgPath)
110+
if err != nil {
111+
logrus.Debugf("unable to open SIZE file for pkg %s", pkgPath)
112+
return 0, err
113+
}
114+
defer sizeFile.Close()
115+
fileBody, err := ioutil.ReadAll(sizeFile)
116+
if err != nil {
117+
logrus.Debugf("unable to read SIZE file for pkg %s", pkgPath)
118+
return 0, err
119+
}
120+
strFileBody := strings.Replace(string(fileBody), "\n", "", -1)
121+
size, _ := strconv.ParseInt(strFileBody, 10, 64)
122+
return size, nil
123+
}

differs/emerge_diff_test.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
Copyright 2018 Google, Inc. All rights reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package differs
18+
19+
import (
20+
"reflect"
21+
"testing"
22+
23+
pkgutil "github.com/GoogleContainerTools/container-diff/pkg/util"
24+
"github.com/GoogleContainerTools/container-diff/util"
25+
)
26+
27+
func TestGetEmergePackages(t *testing.T) {
28+
testCases := []struct {
29+
descrip string
30+
path string
31+
expected map[string]util.PackageInfo
32+
err bool
33+
}{
34+
{
35+
descrip: "no directory",
36+
path: "testDirs/notThere",
37+
expected: map[string]util.PackageInfo{},
38+
err: true,
39+
},
40+
{
41+
descrip: "no packages",
42+
path: "testDirs/noPackages",
43+
expected: map[string]util.PackageInfo{},
44+
},
45+
{
46+
descrip: "packages in expected location",
47+
path: "testDirs/packageEmerge",
48+
expected: map[string]util.PackageInfo{
49+
"dev-python/pkg1": {Version: "0.0.1", Size: 167112},
50+
"dev-python/pkg2": {Version: "0.0.2", Size: 167112},
51+
"sys-libs/pkg3": {Version: "0.0.3", Size: 167112}},
52+
},
53+
}
54+
for _, test := range testCases {
55+
d := EmergeAnalyzer{}
56+
image := pkgutil.Image{FSPath: test.path}
57+
packages, err := d.getPackages(image)
58+
if err != nil && !test.err {
59+
t.Errorf("Got unexpected error: %s", err)
60+
}
61+
if err == nil && test.err {
62+
t.Errorf("Expected error but got none.")
63+
}
64+
if !reflect.DeepEqual(packages, test.expected) {
65+
t.Errorf("Expected: %v but got: %v", test.expected, packages)
66+
}
67+
}
68+
}

differs/testDirs/noPackages/var/db/pkg/dir/file

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
167112
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
167112
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
167112

0 commit comments

Comments
 (0)