bibliothecary 8.7.4 → 8.7.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +21 -4
- data/.rubocop.yml +32 -941
- data/Gemfile +1 -1
- data/Rakefile +10 -0
- data/bibliothecary.gemspec +2 -2
- data/lib/bibliothecary/analyser.rb +6 -6
- data/lib/bibliothecary/cli.rb +8 -8
- data/lib/bibliothecary/configuration.rb +8 -8
- data/lib/bibliothecary/file_info.rb +2 -2
- data/lib/bibliothecary/multi_parsers/bundler_like_manifest.rb +1 -1
- data/lib/bibliothecary/multi_parsers/cyclonedx.rb +16 -17
- data/lib/bibliothecary/multi_parsers/dependencies_csv.rb +16 -16
- data/lib/bibliothecary/multi_parsers/json_runtime.rb +3 -3
- data/lib/bibliothecary/multi_parsers/spdx.rb +14 -14
- data/lib/bibliothecary/parsers/bower.rb +7 -7
- data/lib/bibliothecary/parsers/cargo.rb +15 -15
- data/lib/bibliothecary/parsers/carthage.rb +16 -16
- data/lib/bibliothecary/parsers/clojars.rb +7 -7
- data/lib/bibliothecary/parsers/cocoapods.rb +20 -20
- data/lib/bibliothecary/parsers/conda.rb +9 -9
- data/lib/bibliothecary/parsers/cpan.rb +12 -12
- data/lib/bibliothecary/parsers/cran.rb +12 -12
- data/lib/bibliothecary/parsers/dub.rb +8 -8
- data/lib/bibliothecary/parsers/elm.rb +8 -8
- data/lib/bibliothecary/parsers/go.rb +147 -67
- data/lib/bibliothecary/parsers/hackage.rb +13 -13
- data/lib/bibliothecary/parsers/haxelib.rb +4 -4
- data/lib/bibliothecary/parsers/hex.rb +11 -11
- data/lib/bibliothecary/parsers/julia.rb +4 -4
- data/lib/bibliothecary/parsers/maven.rb +88 -89
- data/lib/bibliothecary/parsers/meteor.rb +4 -4
- data/lib/bibliothecary/parsers/npm.rb +31 -31
- data/lib/bibliothecary/parsers/nuget.rb +44 -44
- data/lib/bibliothecary/parsers/packagist.rb +14 -14
- data/lib/bibliothecary/parsers/pub.rb +13 -13
- data/lib/bibliothecary/parsers/pypi.rb +71 -71
- data/lib/bibliothecary/parsers/rubygems.rb +15 -15
- data/lib/bibliothecary/parsers/shard.rb +13 -13
- data/lib/bibliothecary/parsers/swift_pm.rb +6 -6
- data/lib/bibliothecary/purl_util.rb +1 -1
- data/lib/bibliothecary/runner.rb +4 -4
- data/lib/bibliothecary/version.rb +1 -1
- data/lib/bibliothecary.rb +3 -3
- data/lib/sdl_parser.rb +5 -5
- metadata +2 -2
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "gemnasium/parser"
|
2
|
+
require "yaml"
|
3
3
|
|
4
4
|
module Bibliothecary
|
5
5
|
module Parsers
|
@@ -13,58 +13,58 @@ module Bibliothecary
|
|
13
13
|
def self.mapping
|
14
14
|
{
|
15
15
|
match_filename("Podfile") => {
|
16
|
-
kind:
|
17
|
-
parser: :parse_podfile
|
16
|
+
kind: "manifest",
|
17
|
+
parser: :parse_podfile,
|
18
18
|
},
|
19
19
|
match_extension(".podspec") => {
|
20
|
-
kind:
|
20
|
+
kind: "manifest",
|
21
21
|
parser: :parse_podspec,
|
22
|
-
can_have_lockfile: false
|
22
|
+
can_have_lockfile: false,
|
23
23
|
},
|
24
24
|
match_filename("Podfile.lock") => {
|
25
|
-
kind:
|
26
|
-
parser: :parse_podfile_lock
|
25
|
+
kind: "lockfile",
|
26
|
+
parser: :parse_podfile_lock,
|
27
27
|
},
|
28
28
|
match_extension(".podspec.json") => {
|
29
|
-
kind:
|
29
|
+
kind: "manifest",
|
30
30
|
parser: :parse_json_manifest,
|
31
|
-
can_have_lockfile: false
|
32
|
-
}
|
31
|
+
can_have_lockfile: false,
|
32
|
+
},
|
33
33
|
}
|
34
34
|
end
|
35
35
|
|
36
36
|
add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
|
37
37
|
|
38
|
-
def self.parse_podfile_lock(file_contents, options: {})
|
38
|
+
def self.parse_podfile_lock(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
39
39
|
manifest = YAML.load file_contents
|
40
|
-
manifest[
|
40
|
+
manifest["PODS"].map do |row|
|
41
41
|
pod = row.is_a?(String) ? row : row.keys.first
|
42
42
|
match = pod.match(/(.+?)\s\((.+?)\)/i)
|
43
43
|
{
|
44
|
-
name: match[1].split(
|
44
|
+
name: match[1].split("/").first,
|
45
45
|
requirement: match[2],
|
46
|
-
type:
|
46
|
+
type: "runtime",
|
47
47
|
}
|
48
48
|
end.compact
|
49
49
|
end
|
50
50
|
|
51
|
-
def self.parse_podspec(file_contents, options: {})
|
51
|
+
def self.parse_podspec(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
52
52
|
manifest = Gemnasium::Parser.send(:podspec, file_contents)
|
53
53
|
parse_ruby_manifest(manifest)
|
54
54
|
end
|
55
55
|
|
56
|
-
def self.parse_podfile(file_contents, options: {})
|
56
|
+
def self.parse_podfile(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
57
57
|
manifest = Gemnasium::Parser.send(:podfile, file_contents)
|
58
58
|
parse_ruby_manifest(manifest)
|
59
59
|
end
|
60
60
|
|
61
|
-
def self.parse_json_manifest(file_contents, options: {})
|
61
|
+
def self.parse_json_manifest(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
62
62
|
manifest = JSON.parse(file_contents)
|
63
|
-
manifest[
|
63
|
+
manifest["dependencies"].inject([]) do |deps, dep|
|
64
64
|
deps.push({
|
65
65
|
name: dep[0],
|
66
66
|
requirement: dep[1],
|
67
|
-
type:
|
67
|
+
type: "runtime",
|
68
68
|
})
|
69
69
|
end.uniq
|
70
70
|
end
|
@@ -9,20 +9,20 @@ module Bibliothecary
|
|
9
9
|
{
|
10
10
|
match_filename("environment.yml") => {
|
11
11
|
parser: :parse_conda,
|
12
|
-
kind: "manifest"
|
12
|
+
kind: "manifest",
|
13
13
|
},
|
14
14
|
match_filename("environment.yaml") => {
|
15
15
|
parser: :parse_conda,
|
16
|
-
kind: "manifest"
|
16
|
+
kind: "manifest",
|
17
17
|
},
|
18
18
|
match_filename("environment.yml.lock") => {
|
19
19
|
parser: :parse_conda_lockfile,
|
20
|
-
kind: "lockfile"
|
20
|
+
kind: "lockfile",
|
21
21
|
},
|
22
22
|
match_filename("environment.yaml.lock") => {
|
23
23
|
parser: :parse_conda_lockfile,
|
24
|
-
kind: "lockfile"
|
25
|
-
}
|
24
|
+
kind: "lockfile",
|
25
|
+
},
|
26
26
|
}
|
27
27
|
end
|
28
28
|
|
@@ -30,11 +30,11 @@ module Bibliothecary
|
|
30
30
|
add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
|
31
31
|
add_multi_parser(Bibliothecary::MultiParsers::Spdx)
|
32
32
|
|
33
|
-
def self.parse_conda(file_contents, options: {})
|
33
|
+
def self.parse_conda(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
34
34
|
parse_conda_with_kind(file_contents, "manifest")
|
35
35
|
end
|
36
36
|
|
37
|
-
def self.parse_conda_lockfile(file_contents, options: {})
|
37
|
+
def self.parse_conda_lockfile(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
38
38
|
parse_conda_with_kind(file_contents, "lockfile")
|
39
39
|
end
|
40
40
|
|
@@ -48,12 +48,12 @@ module Bibliothecary
|
|
48
48
|
response = Typhoeus.post(
|
49
49
|
"#{host}/parse",
|
50
50
|
headers: {
|
51
|
-
ContentType: "multipart/form-data"
|
51
|
+
ContentType: "multipart/form-data",
|
52
52
|
},
|
53
53
|
body: {
|
54
54
|
file: file_contents,
|
55
55
|
# Unfortunately we do not get the filename in the mapping parsers, so hardcoding the file name depending on the kind
|
56
|
-
filename: kind == "manifest" ? "environment.yml" : "environment.yml.lock"
|
56
|
+
filename: kind == "manifest" ? "environment.yml" : "environment.yml.lock",
|
57
57
|
}
|
58
58
|
)
|
59
59
|
raise Bibliothecary::RemoteParsingError.new("Http Error #{response.response_code} when contacting: #{host}/parse", response.response_code) unless response.success?
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "yaml"
|
2
|
+
require "json"
|
3
3
|
|
4
4
|
module Bibliothecary
|
5
5
|
module Parsers
|
@@ -9,28 +9,28 @@ module Bibliothecary
|
|
9
9
|
def self.mapping
|
10
10
|
{
|
11
11
|
match_filename("META.json", case_insensitive: true) => {
|
12
|
-
kind:
|
13
|
-
parser: :parse_json_manifest
|
12
|
+
kind: "manifest",
|
13
|
+
parser: :parse_json_manifest,
|
14
14
|
},
|
15
15
|
match_filename("META.yml", case_insensitive: true) => {
|
16
|
-
kind:
|
17
|
-
parser: :parse_yaml_manifest
|
18
|
-
}
|
16
|
+
kind: "manifest",
|
17
|
+
parser: :parse_yaml_manifest,
|
18
|
+
},
|
19
19
|
}
|
20
20
|
end
|
21
21
|
|
22
22
|
add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
|
23
23
|
|
24
|
-
def self.parse_json_manifest(file_contents, options: {})
|
24
|
+
def self.parse_json_manifest(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
25
25
|
manifest = JSON.parse file_contents
|
26
|
-
manifest[
|
27
|
-
map_dependencies(deps,
|
26
|
+
manifest["prereqs"].map do |_group, deps|
|
27
|
+
map_dependencies(deps, "requires", "runtime")
|
28
28
|
end.flatten
|
29
29
|
end
|
30
30
|
|
31
|
-
def self.parse_yaml_manifest(file_contents, options: {})
|
31
|
+
def self.parse_yaml_manifest(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
32
32
|
manifest = YAML.load file_contents
|
33
|
-
map_dependencies(manifest,
|
33
|
+
map_dependencies(manifest, "requires", "runtime")
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "deb_control"
|
2
2
|
|
3
3
|
module Bibliothecary
|
4
4
|
module Parsers
|
@@ -10,9 +10,9 @@ module Bibliothecary
|
|
10
10
|
def self.mapping
|
11
11
|
{
|
12
12
|
match_filename("DESCRIPTION", case_insensitive: true) => {
|
13
|
-
kind:
|
14
|
-
parser: :parse_description
|
15
|
-
}
|
13
|
+
kind: "manifest",
|
14
|
+
parser: :parse_description,
|
15
|
+
},
|
16
16
|
}
|
17
17
|
end
|
18
18
|
|
@@ -20,23 +20,23 @@ module Bibliothecary
|
|
20
20
|
add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
|
21
21
|
add_multi_parser(Bibliothecary::MultiParsers::Spdx)
|
22
22
|
|
23
|
-
def self.parse_description(file_contents, options: {})
|
23
|
+
def self.parse_description(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
24
24
|
manifest = DebControl::ControlFileBase.parse(file_contents)
|
25
|
-
parse_section(manifest,
|
26
|
-
parse_section(manifest,
|
27
|
-
parse_section(manifest,
|
28
|
-
parse_section(manifest,
|
25
|
+
parse_section(manifest, "Depends") +
|
26
|
+
parse_section(manifest, "Imports") +
|
27
|
+
parse_section(manifest, "Suggests") +
|
28
|
+
parse_section(manifest, "Enhances")
|
29
29
|
end
|
30
30
|
|
31
31
|
def self.parse_section(manifest, name)
|
32
32
|
return [] unless manifest.first[name]
|
33
|
-
deps = manifest.first[name].delete("\n").split(
|
33
|
+
deps = manifest.first[name].delete("\n").split(",").map(&:strip)
|
34
34
|
deps.map do |dependency|
|
35
35
|
dep = dependency.match(REQUIRE_REGEXP)
|
36
36
|
{
|
37
37
|
name: dep[1],
|
38
|
-
requirement: dep[2] ||
|
39
|
-
type: name.downcase
|
38
|
+
requirement: dep[2] || "*",
|
39
|
+
type: name.downcase,
|
40
40
|
}
|
41
41
|
end
|
42
42
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "json"
|
2
|
+
require "sdl_parser"
|
3
3
|
|
4
4
|
module Bibliothecary
|
5
5
|
module Parsers
|
@@ -10,19 +10,19 @@ module Bibliothecary
|
|
10
10
|
def self.mapping
|
11
11
|
{
|
12
12
|
match_filename("dub.json") => {
|
13
|
-
kind:
|
14
|
-
parser: :parse_json_runtime_manifest
|
13
|
+
kind: "manifest",
|
14
|
+
parser: :parse_json_runtime_manifest,
|
15
15
|
},
|
16
16
|
match_filename("dub.sdl") => {
|
17
|
-
kind:
|
18
|
-
parser: :parse_sdl_manifest
|
19
|
-
}
|
17
|
+
kind: "manifest",
|
18
|
+
parser: :parse_sdl_manifest,
|
19
|
+
},
|
20
20
|
}
|
21
21
|
end
|
22
22
|
|
23
23
|
add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
|
24
24
|
|
25
|
-
def self.parse_sdl_manifest(file_contents, options: {})
|
25
|
+
def self.parse_sdl_manifest(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
26
26
|
SdlParser.new(:runtime, file_contents).dependencies
|
27
27
|
end
|
28
28
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "json"
|
2
2
|
|
3
3
|
module Bibliothecary
|
4
4
|
module Parsers
|
@@ -9,25 +9,25 @@ module Bibliothecary
|
|
9
9
|
def self.mapping
|
10
10
|
{
|
11
11
|
match_filenames("elm-package.json", "elm_dependencies.json") => {
|
12
|
-
kind:
|
13
|
-
parser: :parse_json_runtime_manifest
|
12
|
+
kind: "manifest",
|
13
|
+
parser: :parse_json_runtime_manifest,
|
14
14
|
},
|
15
15
|
match_filename("elm-stuff/exact-dependencies.json") => {
|
16
|
-
kind:
|
17
|
-
parser: :parse_json_lock
|
18
|
-
}
|
16
|
+
kind: "lockfile",
|
17
|
+
parser: :parse_json_lock,
|
18
|
+
},
|
19
19
|
}
|
20
20
|
end
|
21
21
|
|
22
22
|
add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
|
23
23
|
|
24
|
-
def self.parse_json_lock(file_contents, options: {})
|
24
|
+
def self.parse_json_lock(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
25
25
|
manifest = JSON.parse file_contents
|
26
26
|
manifest.map do |name, requirement|
|
27
27
|
{
|
28
28
|
name: name,
|
29
29
|
requirement: requirement,
|
30
|
-
type:
|
30
|
+
type: "runtime",
|
31
31
|
}
|
32
32
|
end
|
33
33
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "yaml"
|
2
|
+
require "json"
|
3
3
|
|
4
4
|
module Bibliothecary
|
5
5
|
module Parsers
|
@@ -7,61 +7,66 @@ module Bibliothecary
|
|
7
7
|
include Bibliothecary::Analyser
|
8
8
|
|
9
9
|
GPM_REGEXP = /^(.+)\s+(.+)$/
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
GOMOD_REPLACEMENT_SEPARATOR_REGEXP = /\s=>\s/
|
11
|
+
GOMOD_DEP_REGEXP = /(?<name>\S+)\s?(?<requirement>[^\s=>]+)?/ # the " =>" negative character class is to make sure we don't capture the delimiter for "replace" deps
|
12
|
+
GOMOD_SINGLELINE_DEP_REGEXP = /^(?<category>require|exclude|replace|retract)\s+#{GOMOD_DEP_REGEXP}.*$/
|
13
|
+
GOMOD_MULTILINE_DEP_REGEXP = /^#{GOMOD_DEP_REGEXP}.*$/
|
14
|
+
GOMOD_MULTILINE_START_REGEXP = /^(?<category>require|exclude|replace|retract)\s+\(/
|
15
|
+
GOMOD_MULTILINE_END_REGEXP = /^\)/
|
16
|
+
GOMOD_COMMENT_REGEXP = /(\/\/(.*))/
|
17
|
+
GOSUM_REGEXP = /^(.+)\s+(.+)\s+(.+)$/
|
13
18
|
|
14
19
|
def self.mapping
|
15
20
|
{
|
16
21
|
# Go Modules (recommended)
|
17
22
|
match_filename("go.mod") => {
|
18
|
-
kind:
|
19
|
-
parser: :parse_go_mod
|
23
|
+
kind: "manifest",
|
24
|
+
parser: :parse_go_mod,
|
20
25
|
},
|
21
26
|
match_filename("go.sum") => {
|
22
|
-
kind:
|
23
|
-
parser: :parse_go_sum
|
27
|
+
kind: "lockfile",
|
28
|
+
parser: :parse_go_sum,
|
24
29
|
},
|
25
30
|
# Glide (unmaintained: https://github.com/Masterminds/glide#go-modules)
|
26
31
|
match_filename("glide.yaml") => {
|
27
|
-
kind:
|
28
|
-
parser: :parse_glide_yaml
|
32
|
+
kind: "manifest",
|
33
|
+
parser: :parse_glide_yaml,
|
29
34
|
},
|
30
35
|
match_filename("glide.lock") => {
|
31
|
-
kind:
|
32
|
-
parser: :parse_glide_lockfile
|
36
|
+
kind: "lockfile",
|
37
|
+
parser: :parse_glide_lockfile,
|
33
38
|
},
|
34
39
|
# Godep (unmaintained: https://github.com/tools/godep)
|
35
40
|
match_filename("Godeps/Godeps.json") => {
|
36
|
-
kind:
|
37
|
-
parser: :parse_godep_json
|
41
|
+
kind: "manifest",
|
42
|
+
parser: :parse_godep_json,
|
38
43
|
},
|
39
44
|
match_filename("Godeps", case_insensitive: true) => {
|
40
|
-
kind:
|
41
|
-
parser: :parse_gpm
|
45
|
+
kind: "manifest",
|
46
|
+
parser: :parse_gpm,
|
42
47
|
},
|
43
48
|
# Govendor (unmaintained: https://github.com/kardianos/govendor)
|
44
49
|
match_filename("vendor/manifest") => {
|
45
|
-
kind:
|
46
|
-
parser: :parse_gb_manifest
|
50
|
+
kind: "manifest",
|
51
|
+
parser: :parse_gb_manifest,
|
47
52
|
},
|
48
53
|
match_filename("vendor/vendor.json") => {
|
49
|
-
kind:
|
50
|
-
parser: :parse_govendor
|
54
|
+
kind: "manifest",
|
55
|
+
parser: :parse_govendor,
|
51
56
|
},
|
52
57
|
# Go dep (deprecated: https://github.com/golang/dep#dep)
|
53
58
|
match_filename("Gopkg.toml") => {
|
54
|
-
kind:
|
55
|
-
parser: :parse_dep_toml
|
59
|
+
kind: "manifest",
|
60
|
+
parser: :parse_dep_toml,
|
56
61
|
},
|
57
62
|
match_filename("Gopkg.lock") => {
|
58
|
-
kind:
|
59
|
-
parser: :parse_dep_lockfile
|
63
|
+
kind: "lockfile",
|
64
|
+
parser: :parse_dep_lockfile,
|
60
65
|
},
|
61
66
|
match_filename("go-resolved-dependencies.json") => {
|
62
|
-
kind:
|
63
|
-
parser: :parse_go_resolved
|
64
|
-
}
|
67
|
+
kind: "lockfile",
|
68
|
+
parser: :parse_go_resolved,
|
69
|
+
},
|
65
70
|
}
|
66
71
|
end
|
67
72
|
|
@@ -69,97 +74,172 @@ module Bibliothecary
|
|
69
74
|
add_multi_parser(Bibliothecary::MultiParsers::Spdx)
|
70
75
|
add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
|
71
76
|
|
72
|
-
def self.parse_godep_json(file_contents, options: {})
|
77
|
+
def self.parse_godep_json(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
73
78
|
manifest = JSON.parse file_contents
|
74
|
-
map_dependencies(manifest,
|
79
|
+
map_dependencies(manifest, "Deps", "ImportPath", "Rev", "runtime")
|
75
80
|
end
|
76
81
|
|
77
|
-
def self.parse_gpm(file_contents, options: {})
|
82
|
+
def self.parse_gpm(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
78
83
|
deps = []
|
79
84
|
file_contents.split("\n").each do |line|
|
80
|
-
match = line.gsub(/(\#(.*))/,
|
85
|
+
match = line.gsub(/(\#(.*))/, "").match(GPM_REGEXP)
|
81
86
|
next unless match
|
82
87
|
deps << {
|
83
88
|
name: match[1].strip,
|
84
|
-
requirement: match[2].strip ||
|
85
|
-
type:
|
89
|
+
requirement: match[2].strip || "*",
|
90
|
+
type: "runtime",
|
86
91
|
}
|
87
92
|
end
|
88
93
|
deps
|
89
94
|
end
|
90
95
|
|
91
|
-
def self.parse_govendor(file_contents, options: {})
|
96
|
+
def self.parse_govendor(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
92
97
|
manifest = JSON.load file_contents
|
93
|
-
map_dependencies(manifest,
|
98
|
+
map_dependencies(manifest, "package", "path", "revision", "runtime")
|
94
99
|
end
|
95
100
|
|
96
|
-
def self.parse_glide_yaml(file_contents, options: {})
|
101
|
+
def self.parse_glide_yaml(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
97
102
|
manifest = YAML.load file_contents
|
98
|
-
map_dependencies(manifest,
|
99
|
-
map_dependencies(manifest,
|
103
|
+
map_dependencies(manifest, "import", "package", "version", "runtime") +
|
104
|
+
map_dependencies(manifest, "devImports", "package", "version", "development")
|
100
105
|
end
|
101
106
|
|
102
|
-
def self.parse_glide_lockfile(file_contents, options: {})
|
107
|
+
def self.parse_glide_lockfile(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
103
108
|
manifest = YAML.load file_contents
|
104
|
-
map_dependencies(manifest,
|
109
|
+
map_dependencies(manifest, "imports", "name", "version", "runtime")
|
105
110
|
end
|
106
111
|
|
107
|
-
def self.parse_gb_manifest(file_contents, options: {})
|
112
|
+
def self.parse_gb_manifest(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
108
113
|
manifest = JSON.parse file_contents
|
109
|
-
map_dependencies(manifest,
|
114
|
+
map_dependencies(manifest, "dependencies", "importpath", "revision", "runtime")
|
110
115
|
end
|
111
116
|
|
112
|
-
def self.parse_dep_toml(file_contents, options: {})
|
117
|
+
def self.parse_dep_toml(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
113
118
|
manifest = Tomlrb.parse file_contents
|
114
|
-
map_dependencies(manifest,
|
119
|
+
map_dependencies(manifest, "constraint", "name", "version", "runtime")
|
115
120
|
end
|
116
121
|
|
117
|
-
def self.parse_dep_lockfile(file_contents, options: {})
|
122
|
+
def self.parse_dep_lockfile(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
118
123
|
manifest = Tomlrb.parse file_contents
|
119
|
-
map_dependencies(manifest,
|
124
|
+
map_dependencies(manifest, "projects", "name", "revision", "runtime")
|
120
125
|
end
|
121
126
|
|
122
|
-
def self.parse_go_mod(file_contents, options: {})
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
127
|
+
def self.parse_go_mod(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
128
|
+
categorized_deps = parse_go_mod_categorized_deps(file_contents)
|
129
|
+
|
130
|
+
deps = categorized_deps["require"]
|
131
|
+
.map do |dep|
|
132
|
+
# NOTE: A "replace" directive doesn't add the dep to the module graph unless the original dep is also in a "require" directive,
|
133
|
+
# so we need to track down replacements here and use those instead of the originals, if present.
|
134
|
+
#
|
135
|
+
# NOTE: The "replace" directive doesn't actually change the version reported from Go (e.g. "go mod graph"), it only changes
|
136
|
+
# the *source code*. So by replacing the deps here, we're giving more honest results than you'd get when asking go
|
137
|
+
# about the versions used.
|
138
|
+
replaced_dep = categorized_deps["replace"]
|
139
|
+
.find do |replacement_dep|
|
140
|
+
replacement_dep[:original_name] == dep[:name] &&
|
141
|
+
(replacement_dep[:original_requirement] == "*" || replacement_dep[:original_requirement] == dep[:requirement])
|
142
|
+
end
|
143
|
+
|
144
|
+
replaced_dep || dep
|
132
145
|
end
|
133
|
-
|
134
|
-
deps
|
146
|
+
|
147
|
+
return deps
|
135
148
|
end
|
136
149
|
|
137
|
-
def self.
|
150
|
+
def self.parse_go_mod_categorized_deps(file_contents)
|
151
|
+
current_multiline_category = nil
|
152
|
+
# docs: https://go.dev/ref/mod#go-mod-file-require
|
153
|
+
categorized_deps = {
|
154
|
+
"require" => [],
|
155
|
+
"exclude" => [], # these deps are not necessarily used by the module
|
156
|
+
"replace" => [], # these deps are not necessarily used by the module
|
157
|
+
"retract" => [], # TODO: these are not parsed correctly right now, but they shouldn't be returned in list of deps anyway.
|
158
|
+
}
|
159
|
+
file_contents
|
160
|
+
.lines
|
161
|
+
.reject { |line| line =~ /^#{GOMOD_COMMENT_REGEXP}/ } # ignore comment lines
|
162
|
+
.map { |line| line.strip.gsub(GOMOD_COMMENT_REGEXP, "") } # strip out trailing comments
|
163
|
+
.each do |line|
|
164
|
+
if line.match(GOMOD_MULTILINE_END_REGEXP) # detect the end of a multiline
|
165
|
+
current_multiline_category = nil
|
166
|
+
elsif (match = line.match(GOMOD_MULTILINE_START_REGEXP)) # or, detect the start of a multiline
|
167
|
+
current_multiline_category = match[1]
|
168
|
+
elsif (match = line.match(GOMOD_SINGLELINE_DEP_REGEXP)) # or, detect a singleline dep
|
169
|
+
categorized_deps[match[:category]] << go_mod_category_relative_dep(category: match[:category], line: line, match: match)
|
170
|
+
elsif (current_multiline_category && match = line.match(GOMOD_MULTILINE_DEP_REGEXP)) # otherwise, parse the multiline dep
|
171
|
+
categorized_deps[current_multiline_category] << go_mod_category_relative_dep(category: current_multiline_category, line: line, match: match)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
categorized_deps
|
175
|
+
end
|
176
|
+
|
177
|
+
def self.parse_go_sum(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
138
178
|
deps = []
|
139
179
|
file_contents.lines.map(&:strip).each do |line|
|
140
|
-
if match = line.match(
|
180
|
+
if (match = line.match(GOSUM_REGEXP))
|
141
181
|
deps << {
|
142
182
|
name: match[1].strip,
|
143
|
-
requirement: match[2].strip.split(
|
144
|
-
type:
|
183
|
+
requirement: match[2].strip.split("/").first || "*",
|
184
|
+
type: "runtime",
|
145
185
|
}
|
146
186
|
end
|
147
187
|
end
|
148
188
|
deps.uniq
|
149
189
|
end
|
150
190
|
|
151
|
-
def self.parse_go_resolved(file_contents, options: {})
|
191
|
+
def self.parse_go_resolved(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
152
192
|
JSON.parse(file_contents)
|
153
193
|
.select { |dep| dep["Main"] != "true" }
|
154
|
-
.map
|
194
|
+
.map do |dep|
|
195
|
+
if dep["Replace"].is_a?(String) && dep["Replace"] != "<nil>" && dep["Replace"] != ""
|
196
|
+
# NOTE: The "replace" directive doesn't actually change the version reported from Go (e.g. "go mod graph"), it only changes
|
197
|
+
# the *source code*. So by replacing the deps here, we're giving more honest results than you'd get when asking go
|
198
|
+
# about the versions used.
|
199
|
+
name, requirement = dep["Replace"].split(" ", 2)
|
200
|
+
requirement = "*" if requirement.to_s.strip == ""
|
201
|
+
{ name: name, requirement: requirement, original_name: dep["Path"], original_requirement: dep["Version"], type: dep.fetch("Scope") { "runtime" } }
|
202
|
+
else
|
203
|
+
{ name: dep["Path"], requirement: dep["Version"], type: dep.fetch("Scope") { "runtime" } }
|
204
|
+
end
|
205
|
+
end
|
155
206
|
end
|
156
207
|
|
157
208
|
def self.map_dependencies(manifest, attr_name, dep_attr_name, version_attr_name, type)
|
158
209
|
manifest.fetch(attr_name,[]).map do |dependency|
|
159
210
|
{
|
160
211
|
name: dependency[dep_attr_name],
|
161
|
-
requirement: dependency[version_attr_name] ||
|
162
|
-
type: type
|
212
|
+
requirement: dependency[version_attr_name] || "*",
|
213
|
+
type: type,
|
214
|
+
}
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
# Returns our standard-ish dep Hash based on the category of dep matched ("require", "replace", etc.)
|
219
|
+
def self.go_mod_category_relative_dep(category:, line:, match:)
|
220
|
+
case category
|
221
|
+
when "replace"
|
222
|
+
replacement_dep = line.split(GOMOD_REPLACEMENT_SEPARATOR_REGEXP, 2).last
|
223
|
+
replacement_match = replacement_dep.match(GOMOD_DEP_REGEXP)
|
224
|
+
{
|
225
|
+
original_name: match[:name],
|
226
|
+
original_requirement: match[:requirement] || "*",
|
227
|
+
name: replacement_match[:name],
|
228
|
+
requirement: replacement_match[:requirement] || "*",
|
229
|
+
type: "runtime",
|
230
|
+
}
|
231
|
+
when "retract"
|
232
|
+
{
|
233
|
+
name: match[:name],
|
234
|
+
requirement: match[:requirement] || "*",
|
235
|
+
type: "runtime",
|
236
|
+
deprecated: true,
|
237
|
+
}
|
238
|
+
else
|
239
|
+
{
|
240
|
+
name: match[:name],
|
241
|
+
requirement: match[:requirement] || "*",
|
242
|
+
type: "runtime",
|
163
243
|
}
|
164
244
|
end
|
165
245
|
end
|