Skip to content

Commit

Permalink
Change Go modules package selectors for go list
Browse files Browse the repository at this point in the history
Without module mode being enabled (`-m`), the "all" selector isn't
targeting the correct packages. The documentation for "all" states:

> "all" expands to all packages found in all the GOPATH trees

This could feasibly select all packages on the local system. Instead,
the "./..." selector is being used. This has the added benefit of being
the same selector used by some of the other Go package managers.

As the "./..." selector will only select packages in and beneath the
current directory, the "-deps" flag has been added to also select
dependencies of those packages, while the .DepOnly field ensures that
local packages are not unnecessarily listed.

Finally, the -mod=readonly flag has been added to explicitly ignore the
vendor directory. The issue appears to be that each package of a module
gets listed as the module's install path. This causes the LICENSE files
to not be found (because they are at a higher path than the imported
package).
  • Loading branch information
miquella committed Jul 8, 2020
1 parent 34361fd commit dffae4a
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 28 deletions.
11 changes: 8 additions & 3 deletions lib/license_finder/package_managers/go_modules.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,16 @@ def current_packages
def packages_info
Dir.chdir(project_path) do
# Explanations:
# * Only list dependencies (packages not listed in the project directory)
# (.DepOnly)
# * Ignore standard library packages
# (not .Standard)
# * Replacement modules are respected
# (or .Module.Replace .Module)
# * Module cache directory or (vendored) package directory
# (or $mod.Dir .Dir)
format_str = \
'{{ if not .Standard }}'\
'{{ if and (.DepOnly) (not .Standard) }}'\
'{{ $mod := (or .Module.Replace .Module) }}'\
'{{ $mod.Path }},{{ $mod.Version }},{{ or $mod.Dir .Dir }}'\
'{{ end }}'
Expand All @@ -49,8 +51,11 @@ def packages_info
#
# Instead, the owning module is listed for each imported package. This better
# matches the implementation of other Go package managers.
info_output, stderr, _status = Cmd.run("GO111MODULE=on go list -f '#{format_str}' all")
info_output, _stderr, _status = Cmd.run("GO111MODULE=on go list -mod=mod -f '#{format_str}' all") if stderr =~ Regexp.compile("can't compute 'all' using the vendor directory")
#
# TODO: Figure out a way to make the vendor directory work (i.e. remove the
# -mod=readonly flag). Each of the imported packages gets listed separatly,
# confusing the issue as to which package is the root of the module.
info_output, _stderr, _status = Cmd.run("GO111MODULE=on go list -mod=readonly -deps -f '#{format_str}' ./...")

# Since many packages may belong to a single module, #uniq is used to deduplicate
info_output.split("\n").uniq
Expand Down
27 changes: 2 additions & 25 deletions spec/lib/license_finder/package_managers/go_modules_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module LicenseFinder
let(:src_path) { '/workspace/code' }
let(:mod_path) { "#{src_path}/go.mod" }
let(:vendor_path) { "#{src_path}/vendor" }
let(:go_list_format) { '{{ if not .Standard }}{{ $mod := (or .Module.Replace .Module) }}{{ $mod.Path }},{{ $mod.Version }},{{ or $mod.Dir .Dir }}{{ end }}' }
let(:go_list_format) { '{{ if and (.DepOnly) (not .Standard) }}{{ $mod := (or .Module.Replace .Module) }}{{ $mod.Path }},{{ $mod.Version }},{{ or $mod.Dir .Dir }}{{ end }}' }
let(:go_list_string) do
"foo,,/workspace/code/\ngopkg.in/check.v1,v0.0.0-20161208181325-20d25e280405,"\
"/workspace/LicenseFinder/features/fixtures/go_modules/vendor/gopkg.in/check.v1\n"\
Expand All @@ -26,7 +26,7 @@ module LicenseFinder
FileUtils.mkdir_p(vendor_path)
File.write(mod_path, content)

allow(SharedHelpers::Cmd).to receive(:run).with("GO111MODULE=on go list -f '#{go_list_format}' all").and_return(go_list_string)
allow(SharedHelpers::Cmd).to receive(:run).with("GO111MODULE=on go list -mod=readonly -deps -f '#{go_list_format}' ./...").and_return(go_list_string)
end

after do
Expand Down Expand Up @@ -56,29 +56,6 @@ module LicenseFinder

expect(packages.first.package_manager).to eq 'Go'
end

context 'when compute is not allowed on vendor' do
before do
allow(SharedHelpers::Cmd).to receive(:run)
.with("GO111MODULE=on go list -f '#{go_list_format}' all")
.and_return(['', "go list -m: can't compute 'all' using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)\n", 1])
allow(SharedHelpers::Cmd).to receive(:run)
.with("GO111MODULE=on go list -mod=mod -f '#{go_list_format}' all")
.and_return(go_list_string)
end

it 'finds all the packages all go.mod files' do
packages = subject.current_packages

expect(packages.length).to eq 2

expect(packages.first.name).to eq 'gopkg.in/check.v1'
expect(packages.first.version).to eq 'v0.0.0-20161208181325-20d25e280405'

expect(packages.last.name).to eq 'gopkg.in/yaml.v2'
expect(packages.last.version).to eq 'v2.2.1'
end
end
end

describe '.takes_priority_over' do
Expand Down

0 comments on commit dffae4a

Please sign in to comment.