Skip to content

Commit

Permalink
Refactor some code
Browse files Browse the repository at this point in the history
  • Loading branch information
azeemsgoogle committed Jan 31, 2022
1 parent fae5ff3 commit e52bb08
Show file tree
Hide file tree
Showing 8 changed files with 343 additions and 288 deletions.
5 changes: 3 additions & 2 deletions checks/binary_artifact_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func TestBinaryArtifacts(t *testing.T) {
}{
{
name: "Jar file",
inputFolder: "file://testdata/binaryartifacts/jars",
inputFolder: "testdata/binaryartifacts/jars",
err: nil,
expected: checker.CheckResult{
Score: 9,
Expand All @@ -46,7 +46,7 @@ func TestBinaryArtifacts(t *testing.T) {
},
{
name: "non binary file",
inputFolder: "file://testdata/licensedir/withlicense",
inputFolder: "testdata/licensedir/withlicense",
err: nil,
expected: checker.CheckResult{
Score: 10,
Expand All @@ -61,6 +61,7 @@ func TestBinaryArtifacts(t *testing.T) {

logger := log.NewLogger(log.DebugLevel)

// TODO: Use gMock instead of Localdir here.
ctrl := gomock.NewController(t)
repo, err := localdir.MakeLocalDirRepo(tt.inputFolder)

Expand Down
5 changes: 3 additions & 2 deletions checks/license_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func TestLicenseFileSubdirectory(t *testing.T) {
}{
{
name: "With LICENSE",
inputFolder: "file://testdata/licensedir/withlicense",
inputFolder: "testdata/licensedir/withlicense",
expected: scut.TestReturn{
Error: nil,
Score: checker.MaxResultScore,
Expand All @@ -128,7 +128,7 @@ func TestLicenseFileSubdirectory(t *testing.T) {
},
{
name: "Without LICENSE",
inputFolder: "file://testdata/licensedir/withoutlicense",
inputFolder: "testdata/licensedir/withoutlicense",
expected: scut.TestReturn{
Error: nil,
Score: checker.MinResultScore,
Expand All @@ -143,6 +143,7 @@ func TestLicenseFileSubdirectory(t *testing.T) {

logger := log.NewLogger(log.DebugLevel)

// TODO: Use gMock instead of Localdir here.
ctrl := gomock.NewController(t)
repo, err := localdir.MakeLocalDirRepo(tt.inputFolder)

Expand Down
6 changes: 3 additions & 3 deletions clients/localdir/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,21 @@ func TestClient_CreationAndCaching(t *testing.T) {
{
name: "invalid fullpath",
outputFiles: []string{},
inputFolder: "file:///invalid/fullpath",
inputFolder: "invalid/fullpath",
err: os.ErrNotExist,
},
{
name: "invalid relative path",
outputFiles: []string{},
inputFolder: "file://invalid/relative/path",
inputFolder: "invalid/relative/path",
err: os.ErrNotExist,
},
{
name: "repo 0",
outputFiles: []string{
"file0", "dir1/file1", "dir1/dir2/file2",
},
inputFolder: "file://testdata/repo0",
inputFolder: "testdata/repo0",
err: nil,
},
}
Expand Down
13 changes: 2 additions & 11 deletions clients/localdir/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,11 @@ import (
"fmt"
"os"
"path"
"strings"

clients "github.com/ossf/scorecard/v4/clients"
)

var (
errNotDirectory = errors.New("not a directory")
errInvalidURI = errors.New("invalid URI")
)

var filePrefix = "file://"
var errNotDirectory = errors.New("not a directory")

type repoLocal struct {
path string
Expand Down Expand Up @@ -78,10 +72,7 @@ func (r *repoLocal) AppendMetadata(m ...string) {

// MakeLocalDirRepo returns an implementation of clients.Repo interface.
func MakeLocalDirRepo(pathfn string) (clients.Repo, error) {
if !strings.HasPrefix(pathfn, filePrefix) {
return nil, fmt.Errorf("%w", errInvalidURI)
}
p := path.Clean(pathfn[len(filePrefix):])
p := path.Clean(pathfn)
repo := &repoLocal{
path: p,
}
Expand Down
30 changes: 30 additions & 0 deletions cmd/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2020 Security Scorecard Authors
//
// 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 cmd implements Scorecard commandline.
package cmd

var (
flagRepo string
flagLocal string
flagChecksToRun []string
flagMetadata []string
flagLogLevel string
flagFormat string
flagNPM string
flagPyPI string
flagRubyGems string
flagShowDetails bool
flagPolicyFile string
)
156 changes: 156 additions & 0 deletions cmd/package_managers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// Copyright 2020 Security Scorecard Authors
//
// 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 cmd implements Scorecard commandline.
package cmd

import (
"encoding/json"
"fmt"
"net/http"
"time"

sce "github.com/ossf/scorecard/v4/errors"
)

type packageMangerResponse struct {
associatedRepo string
exists bool
}

// TODO(#1568): Add unit tests for this.
func fetchGitRepositoryFromPackageManagers(npm, pypi, rubygems string) (packageMangerResponse, error) {
if npm != "" {
gitRepo, err := fetchGitRepositoryFromNPM(npm)
return packageMangerResponse{
exists: true,
associatedRepo: gitRepo,
}, err
}
if pypi != "" {
gitRepo, err := fetchGitRepositoryFromPYPI(pypi)
return packageMangerResponse{
exists: true,
associatedRepo: gitRepo,
}, err
}
if rubygems != "" {
gitRepo, err := fetchGitRepositoryFromRubyGems(rubygems)
return packageMangerResponse{
exists: true,
associatedRepo: gitRepo,
}, err
}

return packageMangerResponse{}, nil
}

type npmSearchResults struct {
Objects []struct {
Package struct {
Links struct {
Repository string `json:"repository"`
} `json:"links"`
} `json:"package"`
} `json:"objects"`
}

type pypiSearchResults struct {
Info struct {
ProjectUrls struct {
Source string `json:"Source"`
} `json:"project_urls"`
} `json:"info"`
}

type rubyGemsSearchResults struct {
SourceCodeURI string `json:"source_code_uri"`
}

// Gets the GitHub repository URL for the npm package.
// nolint: noctx
func fetchGitRepositoryFromNPM(packageName string) (string, error) {
npmSearchURL := "https://registry.npmjs.org/-/v1/search?text=%s&size=1"
const timeout = 10
client := &http.Client{
Timeout: timeout * time.Second,
}
resp, err := client.Get(fmt.Sprintf(npmSearchURL, packageName))
if err != nil {
return "", sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to get npm package json: %v", err))
}

defer resp.Body.Close()
v := &npmSearchResults{}
err = json.NewDecoder(resp.Body).Decode(v)
if err != nil {
return "", sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to parse npm package json: %v", err))
}
if len(v.Objects) == 0 {
return "", sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("could not find source repo for npm package: %s", packageName))
}
return v.Objects[0].Package.Links.Repository, nil
}

// Gets the GitHub repository URL for the pypi package.
// nolint: noctx
func fetchGitRepositoryFromPYPI(packageName string) (string, error) {
pypiSearchURL := "https://pypi.org/pypi/%s/json"
const timeout = 10
client := &http.Client{
Timeout: timeout * time.Second,
}
resp, err := client.Get(fmt.Sprintf(pypiSearchURL, packageName))
if err != nil {
return "", sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to get pypi package json: %v", err))
}

defer resp.Body.Close()
v := &pypiSearchResults{}
err = json.NewDecoder(resp.Body).Decode(v)
if err != nil {
return "", sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to parse pypi package json: %v", err))
}
if v.Info.ProjectUrls.Source == "" {
return "", sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("could not find source repo for pypi package: %s", packageName))
}
return v.Info.ProjectUrls.Source, nil
}

// Gets the GitHub repository URL for the rubygems package.
// nolint: noctx
func fetchGitRepositoryFromRubyGems(packageName string) (string, error) {
rubyGemsSearchURL := "https://rubygems.org/api/v1/gems/%s.json"
const timeout = 10
client := &http.Client{
Timeout: timeout * time.Second,
}
resp, err := client.Get(fmt.Sprintf(rubyGemsSearchURL, packageName))
if err != nil {
return "", sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to get ruby gem json: %v", err))
}

defer resp.Body.Close()
v := &rubyGemsSearchResults{}
err = json.NewDecoder(resp.Body).Decode(v)
if err != nil {
return "", sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to parse ruby gem json: %v", err))
}
if v.SourceCodeURI == "" {
return "", sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("could not find source repo for ruby gem: %v", err))
}
return v.SourceCodeURI, nil
}
Loading

0 comments on commit e52bb08

Please sign in to comment.