elm_install 0.3.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.reek +4 -0
- data/.rspec +1 -0
- data/.rubocop.yml +4 -0
- data/Gemfile.lock +30 -25
- data/Rakefile +2 -2
- data/Readme.md +85 -23
- data/bin/elm-install +5 -2
- data/elm_install.gemspec +2 -0
- data/lib/elm_install.rb +18 -1
- data/lib/elm_install/base.rb +3 -46
- data/lib/elm_install/dependency.rb +37 -0
- data/lib/elm_install/directory_source.rb +66 -0
- data/lib/elm_install/ext.rb +23 -0
- data/lib/elm_install/git_source.rb +173 -0
- data/lib/elm_install/identifier.rb +133 -0
- data/lib/elm_install/installer.rb +38 -96
- data/lib/elm_install/populator.rb +54 -75
- data/lib/elm_install/repository.rb +82 -0
- data/lib/elm_install/resolver.rb +48 -118
- data/lib/elm_install/source.rb +18 -0
- data/lib/elm_install/types.rb +43 -0
- data/lib/elm_install/utils.rb +14 -20
- data/lib/elm_install/version.rb +1 -1
- data/package.json +1 -1
- data/packaging/Gemfile +1 -1
- data/packaging/Gemfile.lock +8 -4
- data/scripts/install.js +4 -4
- data/scripts/run.js +4 -4
- data/spec/directory_source_spec.rb +37 -0
- data/spec/{eml_install_spec.rb → elm_install_spec.rb} +6 -3
- data/spec/git_source_spec.rb +115 -0
- data/spec/identifer_spec.rb +53 -0
- data/spec/installer_spec.rb +57 -26
- data/spec/repository_spec.rb +44 -0
- data/spec/resolver_spec.rb +0 -73
- data/spec/spec_helper.rb +3 -1
- data/spec/utils_spec.rb +10 -15
- metadata +43 -17
- data/docs/How it works.md +0 -54
- data/lib/elm_install/cache.rb +0 -52
- data/lib/elm_install/elm_package.rb +0 -119
- data/lib/elm_install/git_resolver.rb +0 -129
- data/lib/elm_install/graph_builder.rb +0 -73
- data/spec/elm_package_spec.rb +0 -73
- data/spec/fixtures/cache.json +0 -8
- data/spec/fixtures/elm-package.json +0 -12
- data/spec/fixtures/invalid-elm-package.json +0 -6
- data/spec/fixtures/mismatched-elm-package.json +0 -9
- data/spec/fixtures/ref-cache.json +0 -4
- data/spec/git_resolver_spec.rb +0 -103
- data/spec/graph_builder_spec.rb +0 -36
- data/spec/populator_spec.rb +0 -44
@@ -1,100 +1,79 @@
|
|
1
1
|
module ElmInstall
|
2
|
-
#
|
3
|
-
class Populator
|
4
|
-
|
2
|
+
# Populator for 'elm-stuff' directory
|
3
|
+
class Populator < Base
|
4
|
+
Contract ArrayOf[Dependency] => Populator
|
5
|
+
# Initializes a new populator
|
5
6
|
#
|
6
|
-
# @param
|
7
|
-
def initialize(git_resolver)
|
8
|
-
@git_resolver = git_resolver
|
9
|
-
end
|
10
|
-
|
11
|
-
# Populates `elm-stuff` from the given solution.
|
12
|
-
#
|
13
|
-
# @param solution [Hash] The solution.
|
14
|
-
#
|
15
|
-
# @return [void]
|
16
|
-
def populate(solution)
|
17
|
-
solution.each do |package, version|
|
18
|
-
resolve_package package, version
|
19
|
-
end
|
20
|
-
|
21
|
-
write_exact_dependencies(solution)
|
22
|
-
end
|
23
|
-
|
24
|
-
# Resolves and copies a package and it's version to `elm-stuff/packages`
|
25
|
-
# directory.
|
26
|
-
#
|
27
|
-
# :reek:TooManyStatements { max_statements: 9 }
|
7
|
+
# @param dependencies [Array] The dependencies to populate
|
28
8
|
#
|
29
|
-
# @
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
def resolve_package(package, version_str)
|
34
|
-
version, ref = self.class.version_and_ref(version_str)
|
35
|
-
|
36
|
-
package_name, package_path = Utils.package_version_path package, version
|
37
|
-
|
38
|
-
@git_resolver.repository(package).checkout(ref)
|
39
|
-
|
40
|
-
Logger.dot "#{package_name.bold} - #{version.bold} (#{ref})"
|
41
|
-
|
42
|
-
FileUtils.rm_rf(package_path) if Dir.exist?(package_path)
|
43
|
-
|
44
|
-
copy_package package, package_path
|
9
|
+
# @return Populator The populator instance
|
10
|
+
def initialize(dependencies)
|
11
|
+
@dependencies = dependencies
|
12
|
+
self
|
45
13
|
end
|
46
14
|
|
47
|
-
|
15
|
+
Contract None => NilClass
|
16
|
+
# Populates 'elm-stuff' directory and writes
|
17
|
+
# 'elm-stuff/exact-dependencies.json'.
|
48
18
|
#
|
49
|
-
# @
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
def copy_package(package, package_path)
|
54
|
-
repository_path = File.join(@git_resolver.repository_path(package), '.')
|
55
|
-
|
56
|
-
FileUtils.mkdir_p(package_path)
|
57
|
-
FileUtils.cp_r(repository_path, package_path)
|
58
|
-
FileUtils.rm_rf(File.join(package_path, '.git'))
|
19
|
+
# @return nil
|
20
|
+
def populate
|
21
|
+
copy_dependencies
|
22
|
+
write_exact_dependencies
|
59
23
|
end
|
60
24
|
|
61
|
-
|
62
|
-
#
|
63
|
-
# @param solution [Hash] The solution
|
25
|
+
Contract None => NilClass
|
26
|
+
# Writes the 'elm-stuff/exact-dependencies.json'
|
64
27
|
#
|
65
|
-
# @return
|
66
|
-
def write_exact_dependencies
|
28
|
+
# @return nil
|
29
|
+
def write_exact_dependencies
|
67
30
|
File.binwrite(
|
68
31
|
File.join('elm-stuff', 'exact-dependencies.json'),
|
69
|
-
JSON.pretty_generate(
|
32
|
+
JSON.pretty_generate(exact_dependencies)
|
70
33
|
)
|
34
|
+
nil
|
71
35
|
end
|
72
36
|
|
73
|
-
|
37
|
+
Contract None => HashOf[String => String]
|
38
|
+
# Returns the contents for 'elm-stuff/exact-dependencies.json'
|
74
39
|
#
|
75
|
-
# @
|
40
|
+
# @return [Hash] The dependencies
|
41
|
+
def exact_dependencies
|
42
|
+
@dependencies.each_with_object({}) do |dependency, memo|
|
43
|
+
memo[dependency.name] = dependency.version.to_simple
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Contract None => NilClass
|
48
|
+
# Copies dependencies to 'elm-stuff/packages/package/version' directory
|
76
49
|
#
|
77
|
-
# @return
|
78
|
-
def
|
79
|
-
|
80
|
-
|
50
|
+
# @return nil
|
51
|
+
def copy_dependencies
|
52
|
+
@dependencies.each do |dependency|
|
53
|
+
path =
|
54
|
+
File.join('elm-stuff', 'packages', dependency.name,
|
55
|
+
dependency.version.to_simple)
|
81
56
|
|
82
|
-
|
57
|
+
log_dependency dependency
|
58
|
+
|
59
|
+
dependency.source.copy_to(dependency.version, Pathname.new(path))
|
83
60
|
end
|
61
|
+
nil
|
84
62
|
end
|
85
63
|
|
86
|
-
|
64
|
+
Contract Dependency => NilClass
|
65
|
+
# Logs the dependency with a dot
|
87
66
|
#
|
88
|
-
# @param
|
67
|
+
# @param dependency [Dependency] The dependency
|
89
68
|
#
|
90
|
-
# @return
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
69
|
+
# @return nil
|
70
|
+
def log_dependency(dependency)
|
71
|
+
log = "#{dependency.name} - "
|
72
|
+
log += dependency.source.to_log.to_s
|
73
|
+
log += " (#{dependency.version.to_simple})"
|
74
|
+
|
75
|
+
Logger.dot log
|
76
|
+
nil
|
98
77
|
end
|
99
78
|
end
|
100
79
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module ElmInstall
|
2
|
+
# Handles git repositories.
|
3
|
+
class Repository < Base
|
4
|
+
extend Forwardable
|
5
|
+
|
6
|
+
# The url of the git repository
|
7
|
+
# @return [String]
|
8
|
+
attr_reader :url
|
9
|
+
|
10
|
+
# The path to the directory where the repository lives
|
11
|
+
# @return [String]
|
12
|
+
attr_reader :path
|
13
|
+
|
14
|
+
def_delegators :repo, :fetch
|
15
|
+
|
16
|
+
Contract String, String => Repository
|
17
|
+
# Initializes a repository.
|
18
|
+
#
|
19
|
+
# @param url [String] The url
|
20
|
+
# @param path [String] The path
|
21
|
+
#
|
22
|
+
# @return [Repository] The repository instance
|
23
|
+
def initialize(url, path)
|
24
|
+
@path = path
|
25
|
+
@url = url
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
Contract String => Dir
|
30
|
+
# Checks out the version and returns it's directory
|
31
|
+
#
|
32
|
+
# @param ref [String] The reference to checkout
|
33
|
+
#
|
34
|
+
# @return [Dir] The directory
|
35
|
+
def checkout(ref)
|
36
|
+
repo.checkout ref
|
37
|
+
directory
|
38
|
+
end
|
39
|
+
|
40
|
+
Contract None => Dir
|
41
|
+
# Returns the directory of the repository
|
42
|
+
#
|
43
|
+
# @return [Dir] The directory
|
44
|
+
def directory
|
45
|
+
# This removes the .git from filename
|
46
|
+
Dir.new(File.dirname(repo.repo.path))
|
47
|
+
end
|
48
|
+
|
49
|
+
Contract None => ArrayOf[Semverse::Version]
|
50
|
+
# Returns the versions of the repository
|
51
|
+
#
|
52
|
+
# @return [Array<Semverse::Version>] The versions
|
53
|
+
def versions
|
54
|
+
repo
|
55
|
+
.tags
|
56
|
+
.map(&:name)
|
57
|
+
.map { |tag| Semverse::Version.try_new tag }
|
58
|
+
.compact
|
59
|
+
end
|
60
|
+
|
61
|
+
Contract None => Git::Base
|
62
|
+
# Returns the existing repository or clones it if it does not exists.
|
63
|
+
#
|
64
|
+
# @return [Git::Base]
|
65
|
+
def repo
|
66
|
+
clone unless Dir.exist?(path)
|
67
|
+
@repo ||= Git.open path
|
68
|
+
@repo.reset_hard
|
69
|
+
@repo
|
70
|
+
end
|
71
|
+
|
72
|
+
Contract None => Git::Base
|
73
|
+
# Clones the repository
|
74
|
+
#
|
75
|
+
# @return [Git::Base]
|
76
|
+
def clone
|
77
|
+
Logger.arrow "Package: #{url.bold} not found in cache, cloning..."
|
78
|
+
FileUtils.mkdir_p path
|
79
|
+
@repo = Git.clone(url, path)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/elm_install/resolver.rb
CHANGED
@@ -1,145 +1,75 @@
|
|
1
|
-
require_relative './cache'
|
2
|
-
require_relative './utils'
|
3
|
-
|
4
1
|
module ElmInstall
|
5
|
-
# Resolves
|
6
|
-
class Resolver
|
7
|
-
# @return [Array] The
|
8
|
-
attr_reader :
|
9
|
-
|
10
|
-
# Initializes a resolver with a chace and git resolver.
|
11
|
-
#
|
12
|
-
# @param cache [Cache] The cache
|
13
|
-
# @param git_resolver [GitResolver] The git resolver
|
14
|
-
def initialize(cache, git_resolver)
|
15
|
-
@git_resolver = git_resolver
|
16
|
-
@constraints = []
|
17
|
-
@cache = cache
|
18
|
-
end
|
2
|
+
# Resolves dependencies
|
3
|
+
class Resolver < Base
|
4
|
+
# @return [Array<Dependency>] The dependencies
|
5
|
+
attr_reader :dependencies
|
19
6
|
|
20
|
-
|
7
|
+
Contract Identifier => Resolver
|
8
|
+
# Initializes a resolver
|
21
9
|
#
|
22
|
-
# @param
|
10
|
+
# @param identifier [Identifier] The identifier
|
23
11
|
#
|
24
|
-
# @return [
|
25
|
-
def
|
26
|
-
@
|
27
|
-
|
28
|
-
|
12
|
+
# @return [Resolver]
|
13
|
+
def initialize(identifier)
|
14
|
+
@graph = Solve::Graph.new
|
15
|
+
@identifier = identifier
|
16
|
+
@dependencies = {}
|
17
|
+
self
|
29
18
|
end
|
30
19
|
|
31
|
-
|
32
|
-
#
|
33
|
-
# :reek:NestedIterators { max_allowed_nesting: 2 }
|
20
|
+
Contract None => Solve::Graph
|
21
|
+
# Resolves the constraints for a version
|
34
22
|
#
|
35
|
-
# @
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
def add_dependencies(dependencies)
|
40
|
-
dependencies.flat_map do |package, constraint|
|
41
|
-
add_package(package)
|
42
|
-
|
43
|
-
constraints = Utils.transform_constraint(constraint)
|
44
|
-
next add_ref_dependency(package, constraint) if constraints.empty?
|
45
|
-
|
46
|
-
constraints.map do |dependency|
|
47
|
-
yield package, dependency
|
48
|
-
end
|
23
|
+
# @return [Solve::Graph] Returns the graph
|
24
|
+
def resolve
|
25
|
+
@identifier.initial_dependencies.each do |dependency|
|
26
|
+
resolve_dependency dependency
|
49
27
|
end
|
50
|
-
end
|
51
28
|
|
52
|
-
|
53
|
-
#
|
54
|
-
# @param package [String] The package
|
55
|
-
# @param ref [String] The reference
|
56
|
-
#
|
57
|
-
# @return [void]
|
58
|
-
def add_ref_dependency(package, ref)
|
59
|
-
@git_resolver.repository(package).checkout(ref)
|
60
|
-
pkg_version = elm_package(package)['version']
|
61
|
-
version = "#{pkg_version}+#{ref}"
|
62
|
-
@cache.ensure_version(package, version)
|
63
|
-
add_package_dependencies(package, version)
|
64
|
-
[[package, "= #{version}"]]
|
29
|
+
@graph
|
65
30
|
end
|
66
31
|
|
67
|
-
|
68
|
-
#
|
69
|
-
# * Getting all the tags and adding the valid ones to the cache
|
70
|
-
# * Checking out and getting the `elm-package.json` for each version
|
71
|
-
# and adding them recursivly
|
32
|
+
Contract Dependency => NilClass
|
33
|
+
# Resolves the dependencies of a dependency
|
72
34
|
#
|
73
|
-
# @param
|
35
|
+
# @param dependency [Dependency] The dependency
|
74
36
|
#
|
75
|
-
# @return
|
76
|
-
def
|
77
|
-
return if @
|
37
|
+
# @return nil
|
38
|
+
def resolve_dependency(dependency)
|
39
|
+
return if @dependencies[dependency.name]
|
40
|
+
|
41
|
+
@dependencies[dependency.name] ||= dependency
|
78
42
|
|
79
|
-
|
80
|
-
.
|
81
|
-
.
|
82
|
-
.map(&:name)
|
43
|
+
dependency
|
44
|
+
.source
|
45
|
+
.versions(dependency.constraints)
|
83
46
|
.each do |version|
|
84
|
-
|
85
|
-
add_version(package, version)
|
47
|
+
resolve_dependencies(dependency, version)
|
86
48
|
end
|
87
|
-
end
|
88
49
|
|
89
|
-
|
90
|
-
#
|
91
|
-
# @param package [String] The package
|
92
|
-
# @param version [String] The version
|
93
|
-
#
|
94
|
-
# @return [void]
|
95
|
-
def add_package_dependencies(package, version)
|
96
|
-
add_dependencies(elm_dependencies(package)) do |dep_package, constraint|
|
97
|
-
add_package(dep_package)
|
98
|
-
@cache.dependency(package, version, [dep_package, constraint])
|
99
|
-
end
|
50
|
+
nil
|
100
51
|
end
|
101
52
|
|
102
|
-
|
53
|
+
Contract Dependency, Semverse::Version => NilClass
|
54
|
+
# Resolves the dependencies of a dependency and version
|
103
55
|
#
|
104
|
-
# @param
|
105
|
-
# @param version [
|
56
|
+
# @param main [Dependency] The dependency
|
57
|
+
# @param version [Semverse::Version] The version
|
106
58
|
#
|
107
|
-
# @return
|
108
|
-
def
|
109
|
-
@
|
110
|
-
|
111
|
-
.checkout(version)
|
112
|
-
|
113
|
-
add_package_dependencies(package, version)
|
114
|
-
end
|
59
|
+
# @return nil
|
60
|
+
def resolve_dependencies(main, version)
|
61
|
+
dependencies = @identifier.identify(main.source.fetch(version))
|
62
|
+
artifact = @graph.artifact main.name, version
|
115
63
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
# @return [Hash] The dependencies
|
121
|
-
def elm_dependencies(package)
|
122
|
-
ElmPackage.dependencies elm_package_path(package)
|
123
|
-
rescue
|
124
|
-
{}
|
125
|
-
end
|
64
|
+
dependencies.each do |dependency|
|
65
|
+
dependency.constraints.each do |constraint|
|
66
|
+
artifact.depends dependency.name, constraint
|
67
|
+
end
|
126
68
|
|
127
|
-
|
128
|
-
|
129
|
-
# @param package [String] The package
|
130
|
-
#
|
131
|
-
# @return [Hash] The contents
|
132
|
-
def elm_package(package)
|
133
|
-
ElmPackage.read elm_package_path(package)
|
134
|
-
end
|
69
|
+
resolve_dependency dependency
|
70
|
+
end
|
135
71
|
|
136
|
-
|
137
|
-
#
|
138
|
-
# @param package [String] The package
|
139
|
-
#
|
140
|
-
# @return [String] The path
|
141
|
-
def elm_package_path(package)
|
142
|
-
File.join(@git_resolver.repository_path(package), 'elm-package.json')
|
72
|
+
nil
|
143
73
|
end
|
144
74
|
end
|
145
75
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ElmInstall
|
2
|
+
# Abstract class for a source
|
3
|
+
class Source < Base
|
4
|
+
# @overload identifier
|
5
|
+
# @return [Identifier] The identifier
|
6
|
+
# @overload identifier=(value)
|
7
|
+
# Sets the identifier
|
8
|
+
# @param [Identifier] The identifier
|
9
|
+
attr_accessor :identifier
|
10
|
+
|
11
|
+
# @overload options
|
12
|
+
# @return [Hash] The options
|
13
|
+
# @overload options=(value)
|
14
|
+
# Sets the options
|
15
|
+
# @param [Hash] The options
|
16
|
+
attr_accessor :options
|
17
|
+
end
|
18
|
+
end
|