elm_install 0.3.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.reek +4 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +4 -0
  5. data/Gemfile.lock +30 -25
  6. data/Rakefile +2 -2
  7. data/Readme.md +85 -23
  8. data/bin/elm-install +5 -2
  9. data/elm_install.gemspec +2 -0
  10. data/lib/elm_install.rb +18 -1
  11. data/lib/elm_install/base.rb +3 -46
  12. data/lib/elm_install/dependency.rb +37 -0
  13. data/lib/elm_install/directory_source.rb +66 -0
  14. data/lib/elm_install/ext.rb +23 -0
  15. data/lib/elm_install/git_source.rb +173 -0
  16. data/lib/elm_install/identifier.rb +133 -0
  17. data/lib/elm_install/installer.rb +38 -96
  18. data/lib/elm_install/populator.rb +54 -75
  19. data/lib/elm_install/repository.rb +82 -0
  20. data/lib/elm_install/resolver.rb +48 -118
  21. data/lib/elm_install/source.rb +18 -0
  22. data/lib/elm_install/types.rb +43 -0
  23. data/lib/elm_install/utils.rb +14 -20
  24. data/lib/elm_install/version.rb +1 -1
  25. data/package.json +1 -1
  26. data/packaging/Gemfile +1 -1
  27. data/packaging/Gemfile.lock +8 -4
  28. data/scripts/install.js +4 -4
  29. data/scripts/run.js +4 -4
  30. data/spec/directory_source_spec.rb +37 -0
  31. data/spec/{eml_install_spec.rb → elm_install_spec.rb} +6 -3
  32. data/spec/git_source_spec.rb +115 -0
  33. data/spec/identifer_spec.rb +53 -0
  34. data/spec/installer_spec.rb +57 -26
  35. data/spec/repository_spec.rb +44 -0
  36. data/spec/resolver_spec.rb +0 -73
  37. data/spec/spec_helper.rb +3 -1
  38. data/spec/utils_spec.rb +10 -15
  39. metadata +43 -17
  40. data/docs/How it works.md +0 -54
  41. data/lib/elm_install/cache.rb +0 -52
  42. data/lib/elm_install/elm_package.rb +0 -119
  43. data/lib/elm_install/git_resolver.rb +0 -129
  44. data/lib/elm_install/graph_builder.rb +0 -73
  45. data/spec/elm_package_spec.rb +0 -73
  46. data/spec/fixtures/cache.json +0 -8
  47. data/spec/fixtures/elm-package.json +0 -12
  48. data/spec/fixtures/invalid-elm-package.json +0 -6
  49. data/spec/fixtures/mismatched-elm-package.json +0 -9
  50. data/spec/fixtures/ref-cache.json +0 -4
  51. data/spec/git_resolver_spec.rb +0 -103
  52. data/spec/graph_builder_spec.rb +0 -36
  53. 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
@@ -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
@@ -1,8 +0,0 @@
1
- {
2
- "https://github.com/base/core": {
3
- "1.0.0": []
4
- },
5
- "https://github.com/test/test": {
6
- "1.0.0": [["https://github.com/base/core",">= 1.0.0"]]
7
- }
8
- }
@@ -1,12 +0,0 @@
1
- {
2
- "dependencies": {
3
- "test/repo": "2.0.0 <= v < 3.0.0",
4
- "base/core": "2.0.0 <= v < 3.0.0"
5
- },
6
- "dependency-sources": {
7
- "test/repo": {
8
- "url": "git@some-domain.com:test/repo",
9
- "ref": "development"
10
- }
11
- }
12
- }
@@ -1,6 +0,0 @@
1
- {
2
- "dependencies": {
3
- "test/repo": "2.0.0 <= v < 3.0.0"
4
- "base/core": "2.0.0 <= v < 3.0.0"
5
- }
6
- }
@@ -1,9 +0,0 @@
1
- {
2
- "dependencies": {
3
- "test/repo": "2.0.0 <= v < 3.0.0",
4
- "base/core": "2.0.0 <= v < 3.0.0"
5
- },
6
- "dependency-sources": {
7
- "test/repo": "git@some-domain.com:base/repo"
8
- }
9
- }
@@ -1,4 +0,0 @@
1
- {
2
- "https://github.com/base/core": {},
3
- "https://github.com/test/test": {}
4
- }
@@ -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
@@ -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