dependabot-elm 0.82.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e4631c5a095b12bcb7680efa489f38c3706a65f02b6aff6bb5ac77efc5252301
4
+ data.tar.gz: f501e81ff96e0262008737a04ef0c952ae1ca6b4a799ed686761af7b29c25dc8
5
+ SHA512:
6
+ metadata.gz: 1289f30665a25cd7b5e98ced8d71c1b794311ccb9cbbfec89f6be6dab6d5f9210e135181ea979a5b3031149d316f3602e5480616c42cc4ae313552e63e78c1a6
7
+ data.tar.gz: a7ceb51fa33fbc0e94f44a305fe513e1483777dbfeb09f53a0e3b06d5d4163beaec1bec7c6ebaee6b7f05eb6a2a72026a101cac10d2d47ec122b286b86e5239e
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/file_fetchers"
4
+ require "dependabot/file_fetchers/base"
5
+
6
+ module Dependabot
7
+ module Elm
8
+ class FileFetcher < Dependabot::FileFetchers::Base
9
+ def self.required_files_in?(filenames)
10
+ return true if filenames.include?("elm-package.json")
11
+
12
+ filenames.include?("elm.json")
13
+ end
14
+
15
+ def self.required_files_message
16
+ "Repo must contain an elm-package.json or an elm.json"
17
+ end
18
+
19
+ private
20
+
21
+ def fetch_files
22
+ fetched_files = []
23
+
24
+ fetched_files << elm_package if elm_package
25
+ fetched_files << elm_json if elm_json
26
+
27
+ # Note: We *do not* fetch the exact-dependencies.json file, as it is
28
+ # recommended that this is not committed
29
+
30
+ check_required_files_present
31
+ fetched_files
32
+ end
33
+
34
+ def check_required_files_present
35
+ return if elm_package || elm_json
36
+
37
+ path = Pathname.new(File.join(directory, "elm.json")).
38
+ cleanpath.to_path
39
+ raise Dependabot::DependencyFileNotFound, path
40
+ end
41
+
42
+ def elm_package
43
+ @elm_package ||= fetch_file_if_present("elm-package.json")
44
+ end
45
+
46
+ def elm_json
47
+ @elm_json ||= fetch_file_if_present("elm.json")
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ Dependabot::FileFetchers.register("elm-package", Dependabot::Elm::FileFetcher)
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/dependency"
4
+ require "dependabot/errors"
5
+ require "dependabot/file_parsers"
6
+ require "dependabot/file_parsers/base"
7
+ require "dependabot/elm/requirement"
8
+
9
+ module Dependabot
10
+ module Elm
11
+ class FileParser < Dependabot::FileParsers::Base
12
+ require "dependabot/file_parsers/base/dependency_set"
13
+
14
+ DEPENDENCY_TYPES = %w(dependencies test-dependencies).freeze
15
+
16
+ def parse
17
+ dependency_set = DependencySet.new
18
+
19
+ dependency_set += elm_package_dependencies if elm_package
20
+ dependency_set += elm_json_dependencies if elm_json
21
+
22
+ dependency_set.dependencies.sort_by(&:name)
23
+ end
24
+
25
+ private
26
+
27
+ def elm_package_dependencies
28
+ dependency_set = DependencySet.new
29
+
30
+ parsed_package_file.fetch("dependencies").each do |name, req|
31
+ dependency_set <<
32
+ Dependency.new(
33
+ name: name,
34
+ version: version_for(req)&.to_s,
35
+ requirements: [{
36
+ requirement: req, # 4.0 <= v <= 4.0
37
+ groups: [], # we don't have this (its dev vs non-dev)
38
+ source: nil, # elm-package only has elm-package sources
39
+ file: "elm-package.json"
40
+ }],
41
+ package_manager: "elm-package"
42
+ )
43
+ end
44
+
45
+ dependency_set
46
+ end
47
+
48
+ # For docs on elm.json, see:
49
+ # https://github.com/elm/compiler/blob/master/docs/elm.json/application.md
50
+ # https://github.com/elm/compiler/blob/master/docs/elm.json/package.md
51
+ def elm_json_dependencies
52
+ dependency_set = DependencySet.new
53
+
54
+ DEPENDENCY_TYPES.each do |dep_type|
55
+ if repo_type == "application"
56
+ dependencies_hash = parsed_elm_json.fetch(dep_type, {})
57
+ dependencies_hash.fetch("direct", {}).each do |name, req|
58
+ dependency_set << build_elm_json_dependency(
59
+ name: name, group: dep_type, requirement: req, direct: true
60
+ )
61
+ end
62
+ dependencies_hash.fetch("indirect", {}).each do |name, req|
63
+ dependency_set << build_elm_json_dependency(
64
+ name: name, group: dep_type, requirement: req, direct: false
65
+ )
66
+ end
67
+ elsif repo_type == "package"
68
+ parsed_elm_json.fetch(dep_type, {}).each do |name, req|
69
+ dependency_set << build_elm_json_dependency(
70
+ name: name, group: dep_type, requirement: req, direct: true
71
+ )
72
+ end
73
+ else raise "Unexpected repo type for Elm repo: #{repo_type}"
74
+ end
75
+ end
76
+
77
+ dependency_set
78
+ end
79
+
80
+ def build_elm_json_dependency(name:, group:, requirement:, direct:)
81
+ requirements = [{
82
+ requirement: requirement,
83
+ groups: [group],
84
+ source: nil,
85
+ file: "elm.json"
86
+ }]
87
+
88
+ Dependency.new(
89
+ name: name,
90
+ version: version_for(requirement)&.to_s,
91
+ requirements: direct ? requirements : [],
92
+ package_manager: "elm-package"
93
+ )
94
+ end
95
+
96
+ def repo_type
97
+ parsed_elm_json.fetch("type")
98
+ end
99
+
100
+ def check_required_files
101
+ return if elm_json || elm_package
102
+
103
+ raise "No elm.json or elm-package.json!"
104
+ end
105
+
106
+ def version_for(version_requirement)
107
+ req = Dependabot::Elm::Requirement.new(version_requirement)
108
+
109
+ return unless req.exact?
110
+
111
+ req.requirements.first.last
112
+ end
113
+
114
+ def parsed_package_file
115
+ @parsed_package_file ||= JSON.parse(elm_package.content)
116
+ rescue JSON::ParserError
117
+ raise Dependabot::DependencyFileNotParseable, elm_package.path
118
+ end
119
+
120
+ def parsed_elm_json
121
+ @parsed_elm_json ||= JSON.parse(elm_json.content)
122
+ rescue JSON::ParserError
123
+ raise Dependabot::DependencyFileNotParseable, elm_json.path
124
+ end
125
+
126
+ def elm_package
127
+ @elm_package ||= get_original_file("elm-package.json")
128
+ end
129
+
130
+ def elm_json
131
+ @elm_json ||= get_original_file("elm.json")
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+ Dependabot::FileParsers.register("elm-package", Dependabot::Elm::FileParser)
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/file_updaters"
4
+ require "dependabot/file_updaters/base"
5
+
6
+ module Dependabot
7
+ module Elm
8
+ class FileUpdater < Dependabot::FileUpdaters::Base
9
+ require_relative "file_updater/elm_package_updater"
10
+ require_relative "file_updater/elm_json_updater"
11
+
12
+ def self.updated_files_regex
13
+ [
14
+ /^elm-package\.json$/,
15
+ /^elm\.json$/
16
+ ]
17
+ end
18
+
19
+ def updated_dependency_files
20
+ updated_files = []
21
+
22
+ elm_package_files.each do |file|
23
+ next unless file_changed?(file)
24
+
25
+ updated_files <<
26
+ updated_file(
27
+ file: file,
28
+ content: updated_elm_package_content(file)
29
+ )
30
+ end
31
+
32
+ elm_json_files.each do |file|
33
+ next unless file_changed?(file)
34
+
35
+ updated_files <<
36
+ updated_file(
37
+ file: file,
38
+ content: updated_elm_json_content(file)
39
+ )
40
+ end
41
+
42
+ raise "No files have changed!" if updated_files.none?
43
+
44
+ updated_files
45
+ end
46
+
47
+ private
48
+
49
+ def check_required_files
50
+ return if elm_json_files.any? || elm_package_files.any?
51
+
52
+ raise "No elm.json or elm-package.json!"
53
+ end
54
+
55
+ def updated_elm_package_content(file)
56
+ ElmPackageUpdater.new(
57
+ dependencies: dependencies,
58
+ elm_package_file: file
59
+ ).updated_elm_package_file_content
60
+ end
61
+
62
+ def updated_elm_json_content(file)
63
+ ElmJsonUpdater.new(
64
+ dependencies: dependencies,
65
+ elm_json_file: file
66
+ ).updated_content
67
+ end
68
+
69
+ def elm_package_files
70
+ dependency_files.select { |f| f.name.end_with?("elm-package.json") }
71
+ end
72
+
73
+ def elm_json_files
74
+ dependency_files.select { |f| f.name.end_with?("elm.json") }
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ Dependabot::FileUpdaters.register("elm-package", Dependabot::Elm::FileUpdater)
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/elm/file_updater"
4
+
5
+ module Dependabot
6
+ module Elm
7
+ class FileUpdater
8
+ class ElmJsonUpdater
9
+ def initialize(elm_json_file:, dependencies:)
10
+ @elm_json_file = elm_json_file
11
+ @dependencies = dependencies
12
+ end
13
+
14
+ def updated_content
15
+ dependencies.
16
+ select { |dep| requirement_changed?(elm_json_file, dep) }.
17
+ reduce(elm_json_file.content.dup) do |content, dep|
18
+ updated_content = content
19
+
20
+ updated_content = update_requirement(
21
+ content: updated_content,
22
+ filename: elm_json_file.name,
23
+ dependency: dep
24
+ )
25
+
26
+ next updated_content unless content == updated_content
27
+
28
+ raise "Expected content to change!"
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :elm_json_file, :dependencies
35
+
36
+ def requirement_changed?(file, dependency)
37
+ changed_requirements =
38
+ dependency.requirements - dependency.previous_requirements
39
+
40
+ changed_requirements.any? { |f| f[:file] == file.name }
41
+ end
42
+
43
+ def update_requirement(content:, filename:, dependency:)
44
+ updated_req =
45
+ dependency.requirements.
46
+ find { |r| r.fetch(:file) == filename }.
47
+ fetch(:requirement)
48
+
49
+ old_req =
50
+ dependency.previous_requirements.
51
+ find { |r| r.fetch(:file) == filename }.
52
+ fetch(:requirement)
53
+
54
+ return content unless old_req
55
+
56
+ dep = dependency
57
+ regex =
58
+ /"#{Regexp.quote(dep.name)}"\s*:\s+"#{Regexp.quote(old_req)}"/
59
+
60
+ content.gsub(regex) do |declaration|
61
+ declaration.gsub(%("#{old_req}"), %("#{updated_req}"))
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/elm/file_updater"
4
+
5
+ module Dependabot
6
+ module Elm
7
+ class FileUpdater
8
+ class ElmPackageUpdater
9
+ def initialize(elm_package_file:, dependencies:)
10
+ @elm_package_file = elm_package_file
11
+ @dependencies = dependencies
12
+ end
13
+
14
+ def updated_elm_package_file_content
15
+ dependencies.
16
+ select { |dep| requirement_changed?(elm_package_file, dep) }.
17
+ reduce(elm_package_file.content.dup) do |content, dep|
18
+ updated_content = content
19
+
20
+ updated_content = update_requirement(
21
+ content: updated_content,
22
+ filename: elm_package_file.name,
23
+ dependency: dep
24
+ )
25
+
26
+ next updated_content unless content == updated_content
27
+
28
+ raise "Expected content to change!"
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :elm_package_file, :dependencies
35
+
36
+ def requirement_changed?(file, dependency)
37
+ changed_requirements =
38
+ dependency.requirements - dependency.previous_requirements
39
+
40
+ changed_requirements.any? { |f| f[:file] == file.name }
41
+ end
42
+
43
+ def update_requirement(content:, filename:, dependency:)
44
+ updated_req =
45
+ dependency.requirements.
46
+ find { |r| r.fetch(:file) == filename }.
47
+ fetch(:requirement)
48
+
49
+ old_req =
50
+ dependency.previous_requirements.
51
+ find { |r| r.fetch(:file) == filename }.
52
+ fetch(:requirement)
53
+
54
+ return content unless old_req
55
+
56
+ dep = dependency
57
+ regex =
58
+ /"#{Regexp.quote(dep.name)}"\s*:\s+"#{Regexp.quote(old_req)}"/
59
+
60
+ content.gsub(regex) do |declaration|
61
+ declaration.gsub(%("#{old_req}"), %("#{updated_req}"))
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/metadata_finders"
4
+ require "dependabot/metadata_finders/base"
5
+ require "dependabot/source"
6
+
7
+ module Dependabot
8
+ module Elm
9
+ class MetadataFinder < Dependabot::MetadataFinders::Base
10
+ private
11
+
12
+ def look_up_source
13
+ # For Elm 0.18 an elm-package is guaranteed to be `owner/name`
14
+ # on github. For 0.19 a lot will change, including the name of
15
+ # the dependency file, so I won't try to build something more
16
+ # sophisticated here for now.
17
+ Source.from_url("https://github.com/" + dependency.name)
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ Dependabot::MetadataFinders.
24
+ register("elm-package", Dependabot::Elm::MetadataFinder)
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dependabot/utils"
4
+ require "dependabot/elm/version"
5
+
6
+ module Dependabot
7
+ module Elm
8
+ class Requirement < Gem::Requirement
9
+ # Override the version pattern to allow local versions
10
+ PATTERN_RAW =
11
+ "(#{Elm::Version::VERSION_PATTERN}) (<=?) v (<=?) " \
12
+ "(#{Elm::Version::VERSION_PATTERN})"
13
+ PATTERN = /\A#{PATTERN_RAW}\z/.freeze
14
+ EXACT_PATTERN = /\A#{Elm::Version::VERSION_PATTERN}\z/.freeze
15
+
16
+ # Returns an array of requirements. At least one requirement from the
17
+ # returned array must be satisfied for a version to be valid.
18
+ def self.requirements_array(requirement_string)
19
+ [new(requirement_string)]
20
+ end
21
+
22
+ # Override the parser to create Elm::Versions and return an
23
+ # array of parsed requirements
24
+ def self.parse(obj)
25
+ # If a version is given this is an equals requirement
26
+ if EXACT_PATTERN.match?(obj.to_s)
27
+ return [["=", Elm::Version.new(obj.to_s)]]
28
+ end
29
+
30
+ unless (matches = PATTERN.match(obj.to_s))
31
+ msg = "Illformed requirement #{obj.inspect}"
32
+ raise BadRequirementError, msg
33
+ end
34
+
35
+ # If the two versions specified are identical this is an equals
36
+ # requirement
37
+ if matches[1] == matches[4] && matches[3] == "<="
38
+ return [["=", Elm::Version.new(matches[4])]]
39
+ end
40
+
41
+ [
42
+ [matches[2].tr("<", ">"), Elm::Version.new(matches[1])],
43
+ [matches[3], Elm::Version.new(matches[4])]
44
+ ]
45
+ end
46
+
47
+ # Overwrite superclass method to use `flat_map`
48
+ def initialize(*requirements)
49
+ if requirements.any?(&:nil?)
50
+ raise BadRequirementError, "Nil requirement not supported in Elm"
51
+ end
52
+
53
+ requirements = requirements.flatten
54
+ requirements.compact!
55
+ requirements.uniq!
56
+
57
+ if requirements.empty?
58
+ @requirements = [DefaultRequirement]
59
+ else
60
+ @requirements = requirements.flat_map { |r| self.class.parse(r) }
61
+ sort_requirements!
62
+ end
63
+ end
64
+
65
+ # Overwrite superclass method to use `flat_map`
66
+ def concat(new)
67
+ new = new.flatten
68
+ new.compact!
69
+ new.uniq!
70
+ new = new.flat_map { |r| self.class.parse(r) }
71
+
72
+ @requirements.concat new
73
+ sort_requirements!
74
+ end
75
+
76
+ def sort_requirements!
77
+ @requirements.sort! do |l, r|
78
+ comp = l.last <=> r.last # first, sort by the requirement's version
79
+ next comp unless comp.zero?
80
+
81
+ l.first <=> r.first # then, sort by the operator (for stability)
82
+ end
83
+ end
84
+
85
+ def satisfied_by?(version)
86
+ version = Elm::Version.new(version.to_s)
87
+ super
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ Dependabot::Utils.
94
+ register_requirement_class("elm-package", Dependabot::Elm::Requirement)