Skip to content

Commit

Permalink
Add method to look up Go paths without using Go
Browse files Browse the repository at this point in the history
  • Loading branch information
greysteil committed Oct 25, 2018
1 parent 26a6545 commit bd4a9c0
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 1 deletion.
3 changes: 2 additions & 1 deletion lib/dependabot/metadata_finders/go/dep.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ def look_up_source
return look_up_git_dependency_source if git_dependency?

path_str = (specified_source_string || dependency.name)
url = Dependabot::Utils::Go::PathConverter.git_url_for_path(path_str)
url = Dependabot::Utils::Go::PathConverter.
git_url_for_path_without_go_helper(path_str)
Source.from_url(url) if url
end

Expand Down
47 changes: 47 additions & 0 deletions lib/dependabot/utils/go/path_converter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,53 @@ def self.git_url_for_path(path)
args: { import: import_path }
)
end

# Used in dependabot-backend, which doesn't have access to any Go
# helpers.
# TODO: remove the need for this.
def self.git_url_for_path_without_go_helper(path)
# Save a query by manually converting golang.org/x names
tmp_path = path.gsub(%r{^golang\.org/x}, "github.com/golang")

# Currently, Dependabot::Source.new will return `nil` if it can't
# find a git SCH associated with a path. If it is ever extended to
# handle non-git sources we'll need to add an additional check here.
return Source.from_url(tmp_path).url if Source.from_url(tmp_path)
return "https://#{tmp_path}" if tmp_path.end_with?(".git")
return unless (metadata_response = fetch_path_metadata(path))

# Look for a GitHub, Bitbucket or GitLab URL in the response
metadata_response.scan(Dependabot::Source::SOURCE_REGEX) do
source_url = Regexp.last_match.to_s
return Source.from_url(source_url).url
end

# If none are found, parse the response and return the go-import path
doc = Nokogiri::XML(metadata_response)
doc.remove_namespaces!
import_details =
doc.xpath("//meta").
find { |n| n.attributes["name"]&.value == "go-import" }&.
attributes&.fetch("content")&.value&.split(/\s+/)
return unless import_details && import_details[1] == "git"

import_details[2]
end

def self.fetch_path_metadata(path)
# TODO: This is not robust! Instead, we should shell out to Go and
# use https://github.com/Masterminds/vcs.
response = Excon.get(
"https://#{path}?go-get=1",
idempotent: true,
**SharedHelpers.excon_defaults
)

return unless response.status == 200

response.body
end
private_class_method :fetch_path_metadata
end
end
end
Expand Down
43 changes: 43 additions & 0 deletions spec/dependabot/utils/go/path_converter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,47 @@
it { is_expected.to eq("https://github.com/drewolson/testflight") }
end
end

describe ".git_url_for_path_without_go_helper" do
subject { described_class.git_url_for_path_without_go_helper(path) }

let(:path) { "gopkg.in/guregu/null.v3" }

context "with a path that is immediately recognisable as a git source" do
let(:path) { "github.com/drewolson/testflight" }
it { is_expected.to eq("https://github.com/drewolson/testflight") }
end

context "with a golang.org path" do
let(:path) { "golang.org/x/tools" }
it { is_expected.to eq("https://github.com/golang/tools") }
end

context "with a path that ends in .git" do
let(:path) { "git.fd.io/govpp.git" }
it { is_expected.to eq("https://git.fd.io/govpp.git") }
end

context "with a vanity URL that needs to be fetched" do
let(:path) { "k8s.io/apimachinery" }

before do
stub_request(:get, "https://k8s.io/apimachinery?go-get=1").
to_return(status: 200, body: vanity_response)
end
let(:vanity_response) do
fixture("go", "repo_responses", "k8s_io_apimachinery.html")
end

it { is_expected.to eq("https://github.com/kubernetes/apimachinery") }

context "and returns a git source hosted with an unknown provider" do
let(:vanity_response) do
fixture("go", "repo_responses", "unknown_git_source.html")

it { is_expected.to eq("https://sf.com/kubernetes/apimachinery") }
end
end
end
end
end

0 comments on commit bd4a9c0

Please sign in to comment.