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,129 +0,0 @@
|
|
1
|
-
require_relative './logger'
|
2
|
-
|
3
|
-
module ElmInstall
|
4
|
-
# This class if for cloning and fetching repositories based
|
5
|
-
# on a cache.
|
6
|
-
class GitResolver < Base
|
7
|
-
# Initializes a git resolver with the given options.
|
8
|
-
#
|
9
|
-
# @param options [Hash] The options
|
10
|
-
def initialize(options)
|
11
|
-
@file = 'ref-cache.json'
|
12
|
-
super options
|
13
|
-
@check_cache =
|
14
|
-
@cache.keys.each_with_object({}) { |key, memo| memo[key] = true }
|
15
|
-
end
|
16
|
-
|
17
|
-
# Returns the refs for a given url.
|
18
|
-
#
|
19
|
-
# @param url [String] the url
|
20
|
-
#
|
21
|
-
# @return [Hash] The refs
|
22
|
-
def refs(url)
|
23
|
-
self.class.refs(url)
|
24
|
-
end
|
25
|
-
|
26
|
-
# Clears the cache
|
27
|
-
#
|
28
|
-
# @return [void]
|
29
|
-
def clear
|
30
|
-
@check_cache = {}
|
31
|
-
end
|
32
|
-
|
33
|
-
# Returns the refs for a given url.
|
34
|
-
#
|
35
|
-
# @param url [String] the url
|
36
|
-
#
|
37
|
-
# @return [Hash] The refs
|
38
|
-
def self.refs(url)
|
39
|
-
refs = Git.ls_remote url
|
40
|
-
refs.delete 'head'
|
41
|
-
JSON.parse(refs.to_json)
|
42
|
-
end
|
43
|
-
|
44
|
-
# Returns if the given package (url) is in the cache.
|
45
|
-
#
|
46
|
-
# @param url [String] The url
|
47
|
-
#
|
48
|
-
# @return [Boolean] True if exists false if not
|
49
|
-
def package?(url)
|
50
|
-
@check_cache.key?(repository_path(url))
|
51
|
-
end
|
52
|
-
|
53
|
-
# Returns the path of the repository for a given url.
|
54
|
-
#
|
55
|
-
# :reek:FeatureEnvy
|
56
|
-
#
|
57
|
-
# @param url [String] The url
|
58
|
-
#
|
59
|
-
# @return [String] The path
|
60
|
-
def repository_path(url)
|
61
|
-
uri = GitCloneUrl.parse(url)
|
62
|
-
File.join(directory, uri.host, uri.path)
|
63
|
-
end
|
64
|
-
|
65
|
-
# Returns a git repository object for the given url, cloning it
|
66
|
-
# if it does not exists.
|
67
|
-
#
|
68
|
-
# @param url [String] The url
|
69
|
-
#
|
70
|
-
# @return [Git::Base] The repository
|
71
|
-
def repository(url)
|
72
|
-
open(url) do |repo|
|
73
|
-
update_cache repo
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
# Updates a repository checking it's refs and fetching changes if needed.
|
78
|
-
#
|
79
|
-
# @param repo [Git::Base] The repository
|
80
|
-
#
|
81
|
-
# @return [void]
|
82
|
-
def update_cache(repo)
|
83
|
-
directory = File.dirname(repo.repo.path)
|
84
|
-
url = repo.remote.url
|
85
|
-
refs = refs(url)
|
86
|
-
|
87
|
-
unless HashDiff.diff(cache[directory], refs).empty?
|
88
|
-
Logger.arrow "Package: #{url.bold} is outdated, fetching changes..."
|
89
|
-
repo.fetch
|
90
|
-
end
|
91
|
-
|
92
|
-
@check_cache[directory] = true
|
93
|
-
cache[directory] = refs
|
94
|
-
end
|
95
|
-
|
96
|
-
# Opens a git repository cloning if it's not exists.
|
97
|
-
#
|
98
|
-
# @param url [String] The url
|
99
|
-
#
|
100
|
-
# @return [Git::Base] The repository
|
101
|
-
def open(url)
|
102
|
-
path = repository_path(url)
|
103
|
-
|
104
|
-
return clone url, path unless Dir.exist?(path)
|
105
|
-
|
106
|
-
repo = Git.open path
|
107
|
-
repo.reset_hard
|
108
|
-
|
109
|
-
yield repo unless @check_cache[path]
|
110
|
-
|
111
|
-
repo
|
112
|
-
end
|
113
|
-
|
114
|
-
# Clones the repostiry from the given url to the given path.
|
115
|
-
#
|
116
|
-
# @param url [String] The url
|
117
|
-
# @param path [String] The path
|
118
|
-
#
|
119
|
-
# @return [Git::Base] The repository
|
120
|
-
def clone(url, path)
|
121
|
-
Logger.arrow "Package: #{url.bold} not found in cache, cloning..."
|
122
|
-
FileUtils.mkdir_p path
|
123
|
-
repo = Git.clone(url, path)
|
124
|
-
@check_cache[path] = true
|
125
|
-
cache[path] = refs url
|
126
|
-
repo
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
module ElmInstall
|
2
|
-
# This class is for building dependency graphs from a cache.
|
3
|
-
class GraphBuilder
|
4
|
-
# @return [Solve::Graph] The graph
|
5
|
-
attr_reader :graph
|
6
|
-
|
7
|
-
# Returns a graph from a cache and options.
|
8
|
-
#
|
9
|
-
# @param cache [Cache] The cache to generate the graph from.
|
10
|
-
# @param options [Hash] The options to use.
|
11
|
-
#
|
12
|
-
# @return [Solve::Graph] The graph
|
13
|
-
def self.graph_from_cache(cache, options = { verbose: false })
|
14
|
-
graph = new cache, options
|
15
|
-
graph.build
|
16
|
-
graph.graph
|
17
|
-
end
|
18
|
-
|
19
|
-
# Initialies a graph build with a cache and options.
|
20
|
-
#
|
21
|
-
# @param cache [Cache] The cache to generate the graph from.
|
22
|
-
# @param options [Hash] The options to use.
|
23
|
-
def initialize(cache, options = { verbose: false })
|
24
|
-
@graph = Solve::Graph.new
|
25
|
-
@options = options
|
26
|
-
@cache = cache
|
27
|
-
end
|
28
|
-
|
29
|
-
# Builds the graph.
|
30
|
-
#
|
31
|
-
# @return [void]
|
32
|
-
def build
|
33
|
-
@cache.each do |package, versions|
|
34
|
-
add_versions package, versions
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
# Adds the given package & version combinations to the graph.
|
41
|
-
def add_versions(package, versions)
|
42
|
-
versions.each do |version, dependencies|
|
43
|
-
add_version package, version, dependencies
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# Adds the given package, version and dependency
|
48
|
-
# combinations to the graph.
|
49
|
-
def add_version(package, version, dependencies)
|
50
|
-
artifact = @graph.artifact(package, version)
|
51
|
-
|
52
|
-
dependencies.each do |dependency|
|
53
|
-
add_dependency artifact, *dependency
|
54
|
-
end
|
55
|
-
rescue
|
56
|
-
if @options[:verbose]
|
57
|
-
puts "WARNING: Could not add version #{version} to #{package}."
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
# Adds the given package version and single dependency to the
|
62
|
-
# graph.
|
63
|
-
def add_dependency(artifact, package, version)
|
64
|
-
artifact.depends package, version
|
65
|
-
rescue
|
66
|
-
if @options[:verbose]
|
67
|
-
puts "
|
68
|
-
WARNING: Could not add dependency #{package}-#{version} to #{artifact}
|
69
|
-
".strip
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
data/spec/elm_package_spec.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ElmInstall::ElmPackage do
|
4
|
-
subject { described_class }
|
5
|
-
|
6
|
-
let(:path) { 'spec/fixtures/elm-package.json' }
|
7
|
-
let(:invalid_path) { 'spec/fixtures/invalid-elm-package.json' }
|
8
|
-
let(:mismatch_path) { 'spec/fixtures/mismatched-elm-package.json' }
|
9
|
-
|
10
|
-
context 'package mismatch' do
|
11
|
-
subject { described_class.dependencies(mismatch_path, silent: false) }
|
12
|
-
|
13
|
-
it 'should exit' do
|
14
|
-
expect(ElmInstall::ElmPackage)
|
15
|
-
.to receive(:puts)
|
16
|
-
|
17
|
-
expect(Process).to receive(:exit)
|
18
|
-
subject
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
context 'missing file' do
|
23
|
-
subject { described_class.dependencies('test', silent: false) }
|
24
|
-
|
25
|
-
it 'should exit' do
|
26
|
-
expect(ElmInstall::Logger)
|
27
|
-
.to receive(:arrow)
|
28
|
-
.with "Could not find file: #{'test'.bold}."
|
29
|
-
|
30
|
-
expect(Process).to receive(:exit)
|
31
|
-
|
32
|
-
expect { subject }.to raise_error(NoMethodError)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
context 'invalid file' do
|
37
|
-
subject { described_class.dependencies(invalid_path, silent: false) }
|
38
|
-
|
39
|
-
it 'should exit' do
|
40
|
-
expect(ElmInstall::Logger)
|
41
|
-
.to receive(:arrow)
|
42
|
-
.with "Invalid JSON in file: #{invalid_path.bold}."
|
43
|
-
|
44
|
-
expect(Process).to receive(:exit)
|
45
|
-
|
46
|
-
expect { subject }.to raise_error(NoMethodError)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
describe '.transform_dependencies' do
|
51
|
-
subject { described_class.dependencies(path) }
|
52
|
-
|
53
|
-
it 'should return transformed dependencies' do
|
54
|
-
expect(subject)
|
55
|
-
.to eq(
|
56
|
-
'git@some-domain.com:test/repo' => 'development',
|
57
|
-
'https://github.com/base/core' => '2.0.0 <= v < 3.0.0'
|
58
|
-
)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
describe '.transform_package' do
|
63
|
-
it 'should transform normal packages names to github ones' do
|
64
|
-
expect(subject.transform_package('test/repo'))
|
65
|
-
.to eq 'https://github.com/test/repo'
|
66
|
-
end
|
67
|
-
|
68
|
-
it 'should return valid git urls' do
|
69
|
-
expect(subject.transform_package('git@github.com:test/repo'))
|
70
|
-
.to eq 'git@github.com:test/repo'
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
data/spec/fixtures/cache.json
DELETED
data/spec/git_resolver_spec.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ElmInstall::GitResolver do
|
4
|
-
subject { described_class.new directory: CACHE_DIRECTORY }
|
5
|
-
|
6
|
-
let(:uri) { 'git@github.com:test/repo' }
|
7
|
-
|
8
|
-
context 'With cache' do
|
9
|
-
subject { described_class.new directory: 'spec/fixtures' }
|
10
|
-
|
11
|
-
describe '#save' do
|
12
|
-
it 'should save cache' do
|
13
|
-
expect(File).to receive(:binwrite)
|
14
|
-
subject.save
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
describe '#clear' do
|
19
|
-
it 'should clear the cache' do
|
20
|
-
expect do
|
21
|
-
subject.clear
|
22
|
-
end.to change {
|
23
|
-
subject.instance_variable_get('@check_cache').keys.count
|
24
|
-
}.from(2).to(0)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe '.repository' do
|
30
|
-
let(:refs) { {} }
|
31
|
-
let(:repo) { Git.init CACHE_DIRECTORY }
|
32
|
-
|
33
|
-
context 'with repository' do
|
34
|
-
let(:directory) { File.join CACHE_DIRECTORY, 'github.com/test/repo' }
|
35
|
-
|
36
|
-
before do
|
37
|
-
FileUtils.mkdir_p directory
|
38
|
-
Git.init directory
|
39
|
-
end
|
40
|
-
|
41
|
-
context 'with cache' do
|
42
|
-
before do
|
43
|
-
subject.instance_variable_get('@check_cache')[directory] = {}
|
44
|
-
subject.cache[directory] = {}
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'should return repository' do
|
48
|
-
repo = subject.repository uri
|
49
|
-
expect(File.dirname(repo.repo.path))
|
50
|
-
.to eq File.join(Dir.pwd, directory)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
context 'without cache' do
|
55
|
-
before do
|
56
|
-
expect_any_instance_of(Git::Base)
|
57
|
-
.to receive(:fetch)
|
58
|
-
|
59
|
-
expect_any_instance_of(Git::Remote)
|
60
|
-
.to receive(:url)
|
61
|
-
.and_return uri.to_s
|
62
|
-
|
63
|
-
expect(Git)
|
64
|
-
.to receive(:ls_remote)
|
65
|
-
.and_return(refs)
|
66
|
-
|
67
|
-
expect(ElmInstall::Logger)
|
68
|
-
.to receive(:arrow)
|
69
|
-
.with "Package: #{'git@github.com:test/repo'.bold} is outdated, \
|
70
|
-
fetching changes...".gsub(/\s+/, ' ')
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'should fetch refs and update cache' do
|
74
|
-
subject.repository uri
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
context 'without repository' do
|
80
|
-
before do
|
81
|
-
expect(Git)
|
82
|
-
.to receive(:clone)
|
83
|
-
.and_return(repo)
|
84
|
-
|
85
|
-
expect(Git)
|
86
|
-
.to receive(:ls_remote)
|
87
|
-
.and_return(refs)
|
88
|
-
|
89
|
-
expect(ElmInstall::Logger)
|
90
|
-
.to receive(:arrow)
|
91
|
-
.with "Package: #{'git@github.com:test/repo'.bold} not found in \
|
92
|
-
cache, cloning...".gsub(/\s+/, ' ')
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'should clone a new repository' do
|
96
|
-
expect { subject.repository uri }
|
97
|
-
.to change { subject.cache.keys.count }
|
98
|
-
.from(0)
|
99
|
-
.to(1)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
data/spec/graph_builder_spec.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ElmInstall::GraphBuilder do
|
4
|
-
let(:cache) { ElmInstall::Cache.new(directory: 'spec/fixtures') }
|
5
|
-
|
6
|
-
subject { described_class.new cache, verbose: true }
|
7
|
-
|
8
|
-
describe '.graph_from_cache' do
|
9
|
-
it 'should generate a graph from cache' do
|
10
|
-
graph = described_class.graph_from_cache(cache)
|
11
|
-
names = graph.artifacts.map(&:name)
|
12
|
-
expect(names)
|
13
|
-
.to eq(['https://github.com/base/core',
|
14
|
-
'https://github.com/test/test'])
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
describe '.add_version' do
|
19
|
-
it 'should rescue from errors' do
|
20
|
-
expect(subject).to receive(:puts)
|
21
|
-
|
22
|
-
subject.send(:add_version, 'test', 'asd', {})
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
describe '.add_dependency' do
|
27
|
-
let(:artifact) { double :artifact }
|
28
|
-
|
29
|
-
it 'should rescue from errors' do
|
30
|
-
expect(subject).to receive(:puts)
|
31
|
-
expect(artifact).to receive(:depends).and_raise 'test'
|
32
|
-
|
33
|
-
subject.send(:add_dependency, artifact, 'asd', {})
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|