Skip to content

Commit

Permalink
Handle Gemfiles without Gemfile.lock
Browse files Browse the repository at this point in the history
  • Loading branch information
sfowl committed Nov 13, 2023
1 parent 4e86e79 commit dff8928
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 23 deletions.
107 changes: 107 additions & 0 deletions internal/scan/gemfile-parser.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
require 'bundler'


def get_lockfile_deps(lockfile, deps = nil)
lockfileParser = Bundler::LockfileParser.new(lockfile)
rvalue = []

lockfileParser.specs.each do |spec|
if deps
if deps.include?(spec.name)
rvalue.append(spec)
end
else
rvalue.append(spec)
end
end

return rvalue
end

def get_paths()
dir = "."
if ARGV.length > 0
dir = ARGV[0]
end

gemfilePath = File.join(dir, "Gemfile")
lockfilePath = File.join(dir, "Gemfile.lock")

return gemfilePath, lockfilePath
end


def get_gemfiles(gemfilePath, lockfilePath)
gemfile = nil
lockfile = nil
if File.exist? File.expand_path gemfilePath
gemfile = Bundler.read_file(gemfilePath)
end
if File.exist? File.expand_path lockfilePath
lockfile = Bundler.read_file(lockfilePath)
end

return gemfile, lockfile
end

def print_spec_recursive(dep, all_specs)
all_specs.each do |spec|
if spec.name == dep.name
puts "#{spec.name} #{spec.version}"
spec.dependencies.each do |spec2|
print_spec_recursive(spec2, all_specs)
end
end
end
end


gemfilePath, lockfilePath = get_paths()
gemfile, lockfile = get_gemfiles(gemfilePath, lockfilePath)

exclude_groups = [
:development,
:guard,
:packaging,
:release,
:system_tests,
:test,
]

if gemfile
if lockfile
gemfileParser = Bundler::Definition.build(gemfilePath, lockfilePath, nil)
else
gemfileParser = Bundler::Definition.build(gemfilePath, '', nil)
end

# First get runtime deps from Gemfile
runtime_deps = []
gemfileParser.dependencies.each do |dep|
# puts dep
if dep.should_include?
if !exclude_groups.any? { |g| dep.groups.include?(g) }
# puts "#{dep.name} #{dep.groups}"
runtime_deps.append(dep.name)
end
end
end

# Then compare with lockfile to get more specific version info and transitive deps
if lockfile
runtime_specs = get_lockfile_deps(lockfile, runtime_deps)
all_specs = get_lockfile_deps(lockfile, nil)
runtime_specs.each do |spec|
puts "#{spec.name} #{spec.version}"
spec.dependencies.each do |dep2|
print_spec_recursive(dep2, all_specs)
end
end
else
# if no lockfile then just print deps without version info
runtime_deps.each do |r|
puts "#{r}"
end
end

end
12 changes: 0 additions & 12 deletions internal/scan/gemlock-parser.rb

This file was deleted.

20 changes: 9 additions & 11 deletions internal/scan/ruby.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (
log "github.com/sirupsen/logrus"
)

//go:embed gemlock-parser.rb
var gemlockScriptData []byte
//go:embed gemfile-parser.rb
var gemfileScriptData []byte

//go:embed gemspec-parser.rb
var gemSpecScriptData []byte
Expand All @@ -24,9 +24,9 @@ type Script struct {
Data []byte
}

var gemLockParser = Script{
Name: "gemlock-parser.rb",
Data: gemlockScriptData,
var gemFileParser = Script{
Name: "gemfile-parser.rb",
Data: gemfileScriptData,
}

var gemSpecParser = Script{
Expand Down Expand Up @@ -68,18 +68,16 @@ func GetRubyDeps(path string) (map[string]string, error) {
if err != nil {
log.Errorf("couldn't create %s: %v", lockPath, err)
log.Debugf("bundle lock output: %v", string(data))
return nil, err
}
log.Debugf("Created %s", lockPath)
} else {
log.Errorf("Unexpected error: %v", err)
return nil, err
}
}
return runRubyParser(gemLockParser, lockPath)
return runRubyParser(gemFileParser, baseDir)
}

func runRubyParser(script Script, lockPath string) (map[string]string, error) {
func runRubyParser(script Script, target string) (map[string]string, error) {
gathered := make(map[string]string)

g, err := os.CreateTemp("", script.Name)
Expand All @@ -93,8 +91,8 @@ func runRubyParser(script Script, lockPath string) (map[string]string, error) {
log.Errorf("Could not write ruby script to %s: %s", g.Name(), err)
return gathered, err
}
dir := filepath.Dir(lockPath)
name := filepath.Base(lockPath)
dir := filepath.Dir(target)
name := filepath.Base(target)
args := []string{fmt.Sprintf("--chdir=%s", dir), "ruby", g.Name(), name}
log.Debugf("Running env %v", args)
cmd := exec.Command("env", args...)
Expand Down

0 comments on commit dff8928

Please sign in to comment.