class Bibliothecary::Parsers::Go
Constants
- GOMOD_COMMENT_REGEXP
- GOMOD_DEP_REGEXP
- GOMOD_MULTILINE_DEP_REGEXP
- GOMOD_MULTILINE_END_REGEXP
- GOMOD_MULTILINE_START_REGEXP
- GOMOD_REPLACEMENT_SEPARATOR_REGEXP
- GOMOD_SINGLELINE_DEP_REGEXP
- GOSUM_REGEXP
- GPM_REGEXP
Public Class Methods
go_mod_category_relative_dep(category:, line:, match:)
click to toggle source
Returns our standard-ish dep Hash based on the category of dep matched (“require”, “replace”, etc.)
# File lib/bibliothecary/parsers/go.rb, line 223 def self.go_mod_category_relative_dep(category:, line:, match:) case category when "replace" replacement_dep = line.split(GOMOD_REPLACEMENT_SEPARATOR_REGEXP, 2).last replacement_match = replacement_dep.match(GOMOD_DEP_REGEXP) Dependency.new( original_name: match[:name], original_requirement: match[:requirement], name: replacement_match[:name], requirement: replacement_match[:requirement], type: "runtime", direct: !match[:indirect], ) when "retract" Dependency.new( name: match[:name], requirement: match[:requirement], type: "runtime", deprecated: true, direct: !match[:indirect], ) else Dependency.new( name: match[:name], requirement: match[:requirement], type: "runtime", direct: !match[:indirect], ) end end
map_dependencies(manifest, attr_name, dep_attr_name, version_attr_name, type)
click to toggle source
# File lib/bibliothecary/parsers/go.rb, line 212 def self.map_dependencies(manifest, attr_name, dep_attr_name, version_attr_name, type) manifest.fetch(attr_name,[]).map do |dependency| Dependency.new( name: dependency[dep_attr_name], requirement: dependency[version_attr_name], type: type, ) end end
mapping()
click to toggle source
# File lib/bibliothecary/parsers/go.rb, line 19 def self.mapping { # Go Modules (recommended) match_filename("go.mod") => { kind: "manifest", parser: :parse_go_mod, }, match_filename("go.sum") => { kind: "lockfile", parser: :parse_go_sum, }, # Glide (unmaintained: https://github.com/Masterminds/glide#go-modules) match_filename("glide.yaml") => { kind: "manifest", parser: :parse_glide_yaml, }, match_filename("glide.lock") => { kind: "lockfile", parser: :parse_glide_lockfile, }, # Godep (unmaintained: https://github.com/tools/godep) match_filename("Godeps/Godeps.json") => { kind: "manifest", parser: :parse_godep_json, }, match_filename("Godeps", case_insensitive: true) => { kind: "manifest", parser: :parse_gpm, }, # Govendor (unmaintained: https://github.com/kardianos/govendor) match_filename("vendor/manifest") => { kind: "manifest", parser: :parse_gb_manifest, }, match_filename("vendor/vendor.json") => { kind: "manifest", parser: :parse_govendor, }, # Go dep (deprecated: https://github.com/golang/dep#dep) match_filename("Gopkg.toml") => { kind: "manifest", parser: :parse_dep_toml, }, match_filename("Gopkg.lock") => { kind: "lockfile", parser: :parse_dep_lockfile, }, match_filename("go-resolved-dependencies.json") => { kind: "lockfile", parser: :parse_go_resolved, }, } end
parse_dep_lockfile(file_contents, options: {})
click to toggle source
# File lib/bibliothecary/parsers/go.rb, line 122 def self.parse_dep_lockfile(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument manifest = Tomlrb.parse file_contents map_dependencies(manifest, "projects", "name", "revision", "runtime") end
parse_dep_toml(file_contents, options: {})
click to toggle source
# File lib/bibliothecary/parsers/go.rb, line 117 def self.parse_dep_toml(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument manifest = Tomlrb.parse file_contents map_dependencies(manifest, "constraint", "name", "version", "runtime") end
parse_gb_manifest(file_contents, options: {})
click to toggle source
# File lib/bibliothecary/parsers/go.rb, line 112 def self.parse_gb_manifest(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument manifest = JSON.parse file_contents map_dependencies(manifest, "dependencies", "importpath", "revision", "runtime") end
parse_glide_lockfile(file_contents, options: {})
click to toggle source
# File lib/bibliothecary/parsers/go.rb, line 107 def self.parse_glide_lockfile(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument manifest = YAML.load file_contents map_dependencies(manifest, "imports", "name", "version", "runtime") end
parse_glide_yaml(file_contents, options: {})
click to toggle source
# File lib/bibliothecary/parsers/go.rb, line 101 def self.parse_glide_yaml(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument manifest = YAML.load file_contents map_dependencies(manifest, "import", "package", "version", "runtime") + map_dependencies(manifest, "devImports", "package", "version", "development") end
parse_go_mod(file_contents, options: {})
click to toggle source
# File lib/bibliothecary/parsers/go.rb, line 127 def self.parse_go_mod(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument categorized_deps = parse_go_mod_categorized_deps(file_contents) deps = categorized_deps["require"] .map do |dep| # NOTE: A "replace" directive doesn't add the dep to the module graph unless the original dep is also in a "require" directive, # so we need to track down replacements here and use those instead of the originals, if present. # # NOTE: The "replace" directive doesn't actually change the version reported from Go (e.g. "go mod graph"), it only changes # the *source code*. So by replacing the deps here, we're giving more honest results than you'd get when asking go # about the versions used. replaced_dep = categorized_deps["replace"] .find do |replacement_dep| replacement_dep.original_name == dep.name && (replacement_dep.original_requirement == "*" || replacement_dep.original_requirement == dep.requirement) end replaced_dep || dep end return deps end
parse_go_mod_categorized_deps(file_contents)
click to toggle source
# File lib/bibliothecary/parsers/go.rb, line 150 def self.parse_go_mod_categorized_deps(file_contents) current_multiline_category = nil # docs: https://go.dev/ref/mod#go-mod-file-require categorized_deps = { "require" => [], "exclude" => [], # these deps are not necessarily used by the module "replace" => [], # these deps are not necessarily used by the module "retract" => [], # TODO: these are not parsed correctly right now, but they shouldn't be returned in list of deps anyway. } file_contents .lines .map(&:strip) .reject { |line| line =~ /^#{GOMOD_COMMENT_REGEXP}/ } # ignore comment lines .each do |line| if line.match(GOMOD_MULTILINE_END_REGEXP) # detect the end of a multiline current_multiline_category = nil elsif (match = line.match(GOMOD_MULTILINE_START_REGEXP)) # or, detect the start of a multiline current_multiline_category = match[1] elsif (match = line.match(GOMOD_SINGLELINE_DEP_REGEXP)) # or, detect a singleline dep categorized_deps[match[:category]] << go_mod_category_relative_dep(category: match[:category], line: line, match: match) elsif (current_multiline_category && match = line.match(GOMOD_MULTILINE_DEP_REGEXP)) # otherwise, parse the multiline dep categorized_deps[current_multiline_category] << go_mod_category_relative_dep(category: current_multiline_category, line: line, match: match) end end categorized_deps end
parse_go_resolved(file_contents, options: {})
click to toggle source
# File lib/bibliothecary/parsers/go.rb, line 191 def self.parse_go_resolved(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument JSON.parse(file_contents) .select { |dep| dep["Main"] != "true" } .map do |dep| if dep["Replace"].is_a?(String) && dep["Replace"] != "<nil>" && dep["Replace"] != "" # NOTE: The "replace" directive doesn't actually change the version reported from Go (e.g. "go mod graph"), it only changes # the *source code*. So by replacing the deps here, we're giving more honest results than you'd get when asking go # about the versions used. name, requirement = dep["Replace"].split(" ", 2) requirement = "*" if requirement.to_s.strip == "" Dependency.new( name: name, requirement: requirement, original_name: dep["Path"], original_requirement: dep["Version"], type: dep.fetch("Scope") { "runtime" } ) else Dependency.new( name: dep["Path"], requirement: dep["Version"], type: dep.fetch("Scope") { "runtime" } ) end end end
parse_go_sum(file_contents, options: {})
click to toggle source
# File lib/bibliothecary/parsers/go.rb, line 177 def self.parse_go_sum(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument deps = [] file_contents.lines.map(&:strip).each do |line| if (match = line.match(GOSUM_REGEXP)) deps << Dependency.new( name: match[1].strip, requirement: match[2].strip.split("/").first, type: "runtime", ) end end deps.uniq end
parse_godep_json(file_contents, options: {})
click to toggle source
# File lib/bibliothecary/parsers/go.rb, line 77 def self.parse_godep_json(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument manifest = JSON.parse file_contents map_dependencies(manifest, "Deps", "ImportPath", "Rev", "runtime") end
parse_govendor(file_contents, options: {})
click to toggle source
# File lib/bibliothecary/parsers/go.rb, line 96 def self.parse_govendor(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument manifest = JSON.load file_contents map_dependencies(manifest, "package", "path", "revision", "runtime") end
parse_gpm(file_contents, options: {})
click to toggle source
# File lib/bibliothecary/parsers/go.rb, line 82 def self.parse_gpm(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument deps = [] file_contents.split("\n").each do |line| match = line.gsub(/(\#(.*))/, "").match(GPM_REGEXP) next unless match deps << Dependency.new( name: match[1].strip, requirement: match[2].strip, type: "runtime", ) end deps end