Skip to content

Commit eff70bc

Browse files
Remove the usage of pip-pop library (#468)
* Remove the usage of pip-grep tool * Add some fixes to address PR comments * Handle recursive requirements.txt files Co-authored-by: Andrew Meyer <[email protected]>
1 parent 9fee045 commit eff70bc

File tree

12 files changed

+514
-107
lines changed

12 files changed

+514
-107
lines changed

manifest.yml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,6 @@ dependencies:
5353
- cflinuxfs3
5454
source: https://files.pythonhosted.org/packages/88/d9/761f0b1e0551a3559afe4d34bd9bf68fc8de3292363b3775dda39b62ce84/pip-22.0.3.tar.gz
5555
source_sha256: f29d589df8c8ab99c060e68ad294c4a9ed896624f6368c5349d70aa581b333d0
56-
- name: pip-pop
57-
version: 0.1.5
58-
cf_stacks:
59-
- cflinuxfs3
60-
uri: https://buildpacks.cloudfoundry.org/dependencies/manual-binaries/pip-pop/pip-pop-0.1.5-b32efe86.tar.gz
61-
sha256: b32efe865fc6d956e3345690215bc92a7038acf728db228243097b254403048f
62-
source: https://github.com/cloudfoundry/pip-pop/archive/v0.1.5.tar.gz
63-
source_sha256: 879221acbf123fb24e4a91b3d02e400031f89799bb70316fd97f36d2307a8230
6456
- name: pipenv
6557
version: 2022.1.8
6658
uri: https://buildpacks.cloudfoundry.org/dependencies/pipenv/pipenv_2022.1.8_linux_noarch_cflinuxfs3_119108d6.tgz

src/python/finalize/cli/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import (
44
"io"
55
"io/ioutil"
66
"os"
7+
"time"
8+
79
"github.com/cloudfoundry/python-buildpack/src/python/finalize"
810
_ "github.com/cloudfoundry/python-buildpack/src/python/hooks"
911
"github.com/cloudfoundry/python-buildpack/src/python/pyfinder"
10-
"time"
12+
"github.com/cloudfoundry/python-buildpack/src/python/requirements"
1113

1214
"github.com/cloudfoundry/libbuildpack"
1315
)
@@ -55,6 +57,7 @@ func main() {
5557
Logfile: logfile,
5658
Command: &libbuildpack.Command{},
5759
ManagePyFinder: pyfinder.ManagePyFinder{},
60+
Requirements: requirements.Reqs{},
5861
}
5962

6063
if err := finalize.Run(&f); err != nil {

src/python/finalize/finalize.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ import (
1010
"regexp"
1111
"strings"
1212

13-
"github.com/cloudfoundry/libbuildpack"
1413
"github.com/kr/text"
14+
15+
"github.com/cloudfoundry/libbuildpack"
1516
)
1617

1718
type Manifest interface {
@@ -34,13 +35,19 @@ type ManagePyFinder interface {
3435
FindManagePy(dir string) (string, error)
3536
}
3637

38+
type Reqs interface {
39+
FindAnyPackage(buildDir string, searchedPackages ...string) (bool, error)
40+
FindStalePackages(oldRequirementsPath, newRequirementsPath string, excludedPackages ...string) ([]string, error)
41+
}
42+
3743
type Finalizer struct {
3844
Stager Stager
3945
Log *libbuildpack.Logger
4046
Logfile *os.File
4147
Manifest Manifest
4248
Command Command
4349
ManagePyFinder ManagePyFinder
50+
Requirements Reqs
4451
}
4552

4653
func Run(f *Finalizer) error {
@@ -67,7 +74,13 @@ func (f *Finalizer) HandleCollectstatic() error {
6774
if len(os.Getenv("DISABLE_COLLECTSTATIC")) > 0 {
6875
return nil
6976
}
70-
if err := f.Command.Execute(f.Stager.BuildDir(), os.Stdout, os.Stderr, "pip-grep", "-s", "requirements.txt", "django", "Django"); err != nil {
77+
78+
exists, err := f.Requirements.FindAnyPackage(f.Stager.BuildDir(), "django", "Django")
79+
if err != nil {
80+
return err
81+
}
82+
83+
if !exists {
7184
return nil
7285
}
7386

src/python/finalize/finalize_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ var _ = Describe("Finalize", func() {
3333
mockManifest *MockManifest
3434
mockCommand *MockCommand
3535
mockManagePyFinder *MockManagePyFinder
36+
mockRequirements *MockReqs
3637
)
3738

3839
BeforeEach(func() {
@@ -53,6 +54,7 @@ var _ = Describe("Finalize", func() {
5354
mockManifest = NewMockManifest(mockCtrl)
5455
mockCommand = NewMockCommand(mockCtrl)
5556
mockManagePyFinder = NewMockManagePyFinder(mockCtrl)
57+
mockRequirements = NewMockReqs(mockCtrl)
5658

5759
args := []string{buildDir, "", depsDir, depsIdx}
5860
stager := libbuildpack.NewStager(args, logger, &libbuildpack.Manifest{})
@@ -63,6 +65,7 @@ var _ = Describe("Finalize", func() {
6365
Log: logger,
6466
Command: mockCommand,
6567
ManagePyFinder: mockManagePyFinder,
68+
Requirements: mockRequirements,
6669
}
6770
})
6871

@@ -93,7 +96,7 @@ var _ = Describe("Finalize", func() {
9396
})
9497
Context("app uses Django", func() {
9598
BeforeEach(func() {
96-
mockCommand.EXPECT().Execute(buildDir, gomock.Any(), gomock.Any(), "pip-grep", "-s", "requirements.txt", "django", "Django").Return(nil)
99+
mockRequirements.EXPECT().FindAnyPackage(buildDir, "django", "Django").Return(true, nil)
97100
mockManagePyFinder.EXPECT().FindManagePy(buildDir).Return("/foo/bar/manage.py", nil)
98101
})
99102

@@ -118,7 +121,7 @@ var _ = Describe("Finalize", func() {
118121

119122
Context("app does not use Django", func() {
120123
BeforeEach(func() {
121-
mockCommand.EXPECT().Execute(buildDir, gomock.Any(), gomock.Any(), "pip-grep", "-s", "requirements.txt", "django", "Django").Return(fmt.Errorf("Not found"))
124+
mockRequirements.EXPECT().FindAnyPackage(buildDir, "django", "Django").Return(false, nil)
122125
})
123126

124127
It("does not run anything", func() {

src/python/finalize/mocks_test.go

Lines changed: 63 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package requirements
2+
3+
import (
4+
"io/ioutil"
5+
"path/filepath"
6+
"regexp"
7+
"strings"
8+
)
9+
10+
const requirementsParserRegex = `(?m)^[\w\-\w\[\]]+`
11+
12+
type Reqs struct{}
13+
14+
func (m Reqs) FindAnyPackage(buildDir string, searchedPackages ...string) (bool, error) {
15+
reqPackages, err := parseRequirementsWithoutVersion(filepath.Join(buildDir, "requirements.txt"))
16+
if err != nil {
17+
return false, err
18+
}
19+
20+
for _, searchedPackage := range searchedPackages {
21+
if containsPackage(reqPackages, searchedPackage) {
22+
return true, nil
23+
}
24+
}
25+
26+
return false, nil
27+
}
28+
29+
func (m Reqs) FindStalePackages(oldRequirementsPath, newRequirementsPath string, excludedPackages ...string) ([]string, error) {
30+
var stalePackages []string
31+
32+
oldPkgs, err := parseRequirements(oldRequirementsPath)
33+
if err != nil {
34+
return nil, err
35+
}
36+
37+
newPkgs, err := parseRequirements(newRequirementsPath)
38+
if err != nil {
39+
return nil, err
40+
}
41+
42+
for _, oldPkg := range oldPkgs {
43+
if !containsPackage(newPkgs, oldPkg) && !packageIsExcluded(excludedPackages, oldPkg) {
44+
stalePackages = append(stalePackages, oldPkg)
45+
}
46+
}
47+
48+
return stalePackages, nil
49+
}
50+
51+
func containsPackage(packages []string, searchedPackage string) bool {
52+
for _, pkg := range packages {
53+
if pkg == searchedPackage {
54+
return true
55+
}
56+
}
57+
return false
58+
}
59+
60+
func packageIsExcluded(excludedPackages []string, packageFullName string) bool {
61+
62+
regex := regexp.MustCompile(requirementsParserRegex)
63+
64+
packageWithoutVersion := regex.FindString(packageFullName)
65+
66+
for _, excludedPackage := range excludedPackages {
67+
if packageWithoutVersion == excludedPackage {
68+
return true
69+
}
70+
}
71+
72+
return false
73+
}
74+
75+
func parseRequirements(requirementsPath string) ([]string, error) {
76+
content, err := ioutil.ReadFile(requirementsPath)
77+
if err != nil {
78+
return nil, err
79+
}
80+
81+
requirements := strings.Split(string(content), "\n")
82+
83+
for _, requirement := range requirements {
84+
if strings.HasPrefix(requirement, "-r ") {
85+
requirement = strings.TrimPrefix(requirement, "-r ")
86+
nestedReqs, err := parseRequirements(strings.ReplaceAll(requirementsPath, filepath.Base(requirementsPath), requirement))
87+
if err != nil {
88+
return nil, err
89+
}
90+
91+
requirements = append(requirements, nestedReqs...)
92+
}
93+
}
94+
95+
return requirements, nil
96+
}
97+
98+
func parseRequirementsWithoutVersion(requirementsPath string) ([]string, error) {
99+
parsedRequirements, err := parseRequirements(requirementsPath)
100+
if err != nil {
101+
return nil, err
102+
}
103+
104+
regex := regexp.MustCompile(`(?m)^[\w\-\w\[\]]+`)
105+
return regex.FindAllString(strings.Join(parsedRequirements, "\n"), -1), nil
106+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package requirements_test
2+
3+
import (
4+
"testing"
5+
6+
. "github.com/onsi/ginkgo"
7+
. "github.com/onsi/gomega"
8+
)
9+
10+
func TestRequirements(t *testing.T) {
11+
RegisterFailHandler(Fail)
12+
RunSpecs(t, "Reqs Suite")
13+
}

0 commit comments

Comments
 (0)