evm 0.6.1 → 0.9.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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +278 -0
  3. data/bin/evm +12 -0
  4. data/lib/evm.rb +7 -28
  5. data/lib/evm/builder.rb +18 -17
  6. data/lib/evm/cli.rb +43 -18
  7. data/lib/evm/command.rb +2 -1
  8. data/lib/evm/command/bin.rb +2 -2
  9. data/lib/evm/command/config.rb +19 -0
  10. data/lib/evm/command/disuse.rb +15 -0
  11. data/lib/evm/command/install.rb +3 -1
  12. data/lib/evm/command/list.rb +1 -1
  13. data/lib/evm/command/uninstall.rb +3 -1
  14. data/lib/evm/command/use.rb +3 -1
  15. data/lib/evm/config.rb +43 -0
  16. data/lib/evm/git.rb +1 -1
  17. data/lib/evm/package.rb +26 -11
  18. data/lib/evm/remote_file.rb +9 -55
  19. data/lib/evm/tar_file.rb +1 -1
  20. data/spec/evm/builder_spec.rb +209 -0
  21. data/spec/evm/cli_spec.rb +53 -0
  22. data/spec/evm/command/bin_spec.rb +32 -0
  23. data/spec/evm/command/config_spec.rb +34 -0
  24. data/spec/evm/command/disuse_spec.rb +19 -0
  25. data/spec/evm/command/install_spec.rb +103 -0
  26. data/spec/evm/command/list_spec.rb +36 -0
  27. data/spec/evm/command/uninstall_spec.rb +35 -0
  28. data/spec/evm/command/use_spec.rb +32 -0
  29. data/spec/evm/config_spec.rb +36 -0
  30. data/spec/evm/evm_spec.rb +11 -0
  31. data/spec/evm/git_spec.rb +39 -0
  32. data/spec/evm/os_spec.rb +47 -0
  33. data/spec/evm/package_spec.rb +274 -0
  34. data/spec/evm/recipe_spec.rb +47 -0
  35. data/spec/evm/remote_file_spec.rb +47 -0
  36. data/spec/evm/system_spec.rb +36 -0
  37. data/spec/evm/tar_file_spec.rb +21 -0
  38. data/spec/spec_helper.rb +13 -0
  39. metadata +29 -17
  40. data/lib/evm/exception.rb +0 -4
  41. data/lib/evm/progress_bar.rb +0 -37
  42. data/recipes/emacs-23.4-bin.rb +0 -7
  43. data/recipes/emacs-23.4.rb +0 -27
  44. data/recipes/emacs-24.1-bin.rb +0 -7
  45. data/recipes/emacs-24.1.rb +0 -24
  46. data/recipes/emacs-24.2-bin.rb +0 -7
  47. data/recipes/emacs-24.2.rb +0 -24
  48. data/recipes/emacs-24.3-bin.rb +0 -7
  49. data/recipes/emacs-24.3.rb +0 -24
  50. data/recipes/emacs-24.4-bin.rb +0 -7
  51. data/recipes/emacs-24.4.rb +0 -24
  52. data/recipes/emacs-git-snapshot.rb +0 -25
@@ -6,6 +6,7 @@ end
6
6
  require 'evm/command/install'
7
7
  require 'evm/command/uninstall'
8
8
  require 'evm/command/use'
9
+ require 'evm/command/disuse'
9
10
  require 'evm/command/list'
10
11
  require 'evm/command/bin'
11
- require 'evm/command/help'
12
+ require 'evm/command/config'
@@ -1,8 +1,8 @@
1
1
  module Evm
2
2
  module Command
3
3
  class Bin
4
- def initialize(package_name = nil, options = {})
5
- if package_name
4
+ def initialize(argv, options = {})
5
+ if (package_name = argv[0])
6
6
  package = Evm::Package.find(package_name)
7
7
  else
8
8
  package = Evm::Package.current
@@ -0,0 +1,19 @@
1
+ module Evm
2
+ module Command
3
+ class Config
4
+ def initialize(argv, options = {})
5
+ type, value = argv
6
+
7
+ unless Evm::CONFIG_TYPES.include?(type.to_sym)
8
+ raise Evm::Exception, "Invalid config type: #{type}"
9
+ end
10
+
11
+ if value
12
+ Evm.config[type] = value
13
+ end
14
+
15
+ STDOUT.puts(Evm.config[type])
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ module Evm
2
+ module Command
3
+ class Disuse
4
+ def initialize(argv, options = {})
5
+ package = Evm::Package.current
6
+
7
+ if package
8
+ package.disuse!
9
+ else
10
+ raise Evm::Exception.new('No package currently selected')
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,7 +1,9 @@
1
1
  module Evm
2
2
  module Command
3
3
  class Install
4
- def initialize(package_name, options = {})
4
+ def initialize(argv, options = {})
5
+ package_name = argv[0]
6
+
5
7
  unless package_name
6
8
  raise Evm::Exception.new('The install command requires an argument')
7
9
  end
@@ -1,7 +1,7 @@
1
1
  module Evm
2
2
  module Command
3
3
  class List
4
- def initialize(*args)
4
+ def initialize(*)
5
5
  packages = Evm::Package.all
6
6
  packages.each do |package|
7
7
  if package.current?
@@ -1,7 +1,9 @@
1
1
  module Evm
2
2
  module Command
3
3
  class Uninstall
4
- def initialize(package_name, options = {})
4
+ def initialize(argv, options = {})
5
+ package_name = argv[0]
6
+
5
7
  unless package_name
6
8
  raise Evm::Exception.new('The uninstall command requires an argument')
7
9
  end
@@ -1,7 +1,9 @@
1
1
  module Evm
2
2
  module Command
3
3
  class Use
4
- def initialize(package_name, options = {})
4
+ def initialize(argv, options = {})
5
+ package_name = argv[0]
6
+
5
7
  unless package_name
6
8
  raise Evm::Exception.new('The use command requires an argument')
7
9
  end
@@ -0,0 +1,43 @@
1
+ require 'json'
2
+
3
+ module Evm
4
+ class Config
5
+ def initialize(config_file, defaults = {})
6
+ @config_file = config_file
7
+ @defaults = defaults
8
+ end
9
+
10
+ def [](type)
11
+ config[type.to_s] || begin
12
+ default = @defaults.find { |key, value| key.to_s == type.to_s }
13
+ default[1] if default
14
+ end
15
+ end
16
+
17
+ def []=(type, value)
18
+ write(config.merge(type.to_s => value))
19
+ end
20
+
21
+
22
+ private
23
+
24
+ def config
25
+ if File.exist?(@config_file)
26
+ contents = File.read(@config_file)
27
+ if contents.empty?
28
+ {}
29
+ else
30
+ JSON.parse(contents)
31
+ end
32
+ else
33
+ {}
34
+ end
35
+ end
36
+
37
+ def write(config = {})
38
+ File.open(@config_file, 'w') do |file|
39
+ file.write(config.to_json)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -23,7 +23,7 @@ module Evm
23
23
 
24
24
  def git(*args)
25
25
  @git ||= Evm::System.new('git')
26
- @git.run(*args)
26
+ @git.run(*args, '--depth=1')
27
27
  end
28
28
  end
29
29
  end
@@ -2,8 +2,9 @@ module Evm
2
2
  class Package
3
3
  attr_reader :name
4
4
 
5
- def initialize(name)
5
+ def initialize(name, options = {})
6
6
  @name = name
7
+ @file = options[:file] || File
7
8
  end
8
9
 
9
10
  def current?
@@ -23,9 +24,24 @@ module Evm
23
24
  end
24
25
 
25
26
  def use!
26
- FileUtils.ln_sf(bin, Evm::EVM_EMACS_PATH)
27
- unless File.symlink?(Evm::EMACS_PATH)
28
- FileUtils.ln_sf(Evm::EVM_EMACS_PATH, Evm::EMACS_PATH)
27
+ delete_shims!
28
+ [Evm::EMACS_PATH, Evm::EVM_EMACS_PATH].each do |bin_path|
29
+ @file.open(bin_path, 'w') do |file|
30
+ file.puts("#!/bin/bash\nexec \"#{bin}\" \"$@\"")
31
+ end
32
+ @file.chmod(0755, bin_path)
33
+ end
34
+ Evm.config[:current] = name
35
+ end
36
+
37
+ def disuse!
38
+ delete_shims!
39
+ Evm.config[:current] = nil
40
+ end
41
+
42
+ def delete_shims!
43
+ [Evm::EMACS_PATH, Evm::EVM_EMACS_PATH].each do |bin_path|
44
+ @file.delete(bin_path) if @file.exists?(bin_path)
29
45
  end
30
46
  end
31
47
 
@@ -60,20 +76,17 @@ module Evm
60
76
  end
61
77
 
62
78
  def path
63
- File.join(Evm::LOCAL_PATH, @name)
79
+ File.join(Evm.config[:path], @name)
64
80
  end
65
81
 
66
82
  def tmp_path
67
- File.join(Evm::LOCAL_PATH, 'tmp')
83
+ File.join(Evm.config[:path], 'tmp')
68
84
  end
69
85
 
70
86
  class << self
71
87
  def current
72
- if File.symlink?(Evm::EVM_EMACS_PATH)
73
- current_bin_path = File.readlink(Evm::EVM_EMACS_PATH)
74
- if (match = Regexp.new("#{Evm::LOCAL_PATH}/?(?<current>[^/]+)/.+").match(current_bin_path))
75
- find match[:current]
76
- end
88
+ if (name = Evm.config[:current])
89
+ find(name)
77
90
  end
78
91
  end
79
92
 
@@ -93,5 +106,7 @@ module Evm
93
106
  end
94
107
  end
95
108
  end
109
+
110
+ private :delete_shims!
96
111
  end
97
112
  end
@@ -1,64 +1,18 @@
1
- require 'uri'
2
- require 'thread'
3
- require 'net/http'
4
- require 'openssl'
1
+ require 'open-uri'
5
2
 
6
3
  module Evm
7
4
  class RemoteFile
8
- def initialize(url)
5
+ def initialize(url, options = {})
9
6
  @url = url
7
+ @options = options
8
+ @file = options[:file] ||= File
9
+ @uri = options[:uri] ||= URI
10
10
  end
11
11
 
12
- def download(path, &block)
13
- return if File.exist?(path)
14
-
15
- file = File.open(path, 'w')
16
-
17
- thread = Thread.new do
18
- this = Thread.current
19
- body = this[:body] = []
20
-
21
- request @url do |response|
22
- length = this[:length] = response['Content-Length'].to_i
23
-
24
- response.read_body do |fragment|
25
- body << fragment
26
-
27
- this[:done] = (this[:done] || 0) + fragment.length
28
- this[:progress] = this[:done].quo(length) * 100
29
- end
30
- end
31
-
32
- file.write(body.join)
33
- end
34
-
35
- until thread.join(1)
36
- yield thread[:progress]
37
- end
38
-
39
- file.close
40
- end
41
-
42
- private
43
-
44
- def request(url, &block)
45
- uri = URI.parse(url)
46
-
47
- http = Net::HTTP.new(uri.host, uri.port)
48
- if uri.scheme == 'https'
49
- http.use_ssl = true
50
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
51
- end
52
- http.request_get(uri.path) do |response|
53
- case response
54
- when Net::HTTPSuccess
55
- block.call(response)
56
- when Net::HTTPRedirection
57
- request response['location'] do |response|
58
- block.call(response)
59
- end
60
- else
61
- response.error!
12
+ def download(path)
13
+ unless @file.exist?(path)
14
+ @file.open(path, 'w') do |file|
15
+ file.write(@uri.parse(@url).read)
62
16
  end
63
17
  end
64
18
  end
@@ -6,7 +6,7 @@ module Evm
6
6
 
7
7
  def extract(extract_to, name = nil)
8
8
  args = []
9
- args << '-xzf'
9
+ args << '-xf'
10
10
  args << @tar_file
11
11
  args << '-C'
12
12
 
@@ -0,0 +1,209 @@
1
+ require 'spec_helper'
2
+
3
+ describe Evm::Builder do
4
+ describe Evm::Builder::Dsl do
5
+ before do
6
+ @tar_gz_url = 'http://domain.com/foo.tar.gz'
7
+ @git_url = 'git://domain.com/emacs.git'
8
+
9
+ @dsl = Evm::Builder::Dsl.new
10
+ allow(@dsl).to receive(:path).and_return('/path/to')
11
+ end
12
+
13
+ describe '#tar_gz' do
14
+ it 'should download and extract tar' do
15
+ tar_file_path = '/tmp/evm/tmp/name.tar.gz'
16
+
17
+ remote_file = double('remote_file')
18
+ expect(remote_file).to receive(:download).with(tar_file_path)
19
+
20
+ expect(Evm::RemoteFile).to receive(:new).with(@tar_gz_url).and_return(remote_file)
21
+
22
+ tar_file = double('tar_file')
23
+ expect(tar_file).to receive(:extract).with('/tmp/evm/tmp', 'name')
24
+
25
+ expect(Evm::TarFile).to receive(:new).with(tar_file_path).and_return(tar_file)
26
+
27
+ expect(FileUtils).to receive(:mkdir).with('/tmp/evm/tmp/name')
28
+
29
+ @dsl.recipe 'name' do
30
+ @dsl.tar_gz(@tar_gz_url)
31
+ end
32
+ end
33
+ end
34
+
35
+ describe '#git' do
36
+ before do
37
+ @git_repo = double('git_repo')
38
+ allow(@git_repo).to receive(:exist?).and_return(true)
39
+ allow(@git_repo).to receive(:clone)
40
+ allow(@git_repo).to receive(:pull)
41
+
42
+ allow(Evm::Git).to receive(:new).and_return(@git_repo)
43
+ end
44
+
45
+ it 'should pull if exist' do
46
+ allow(@git_repo).to receive(:exist?).and_return(true)
47
+ expect(@git_repo).to receive(:pull)
48
+
49
+ @dsl.recipe 'name' do
50
+ @dsl.git(@git_url)
51
+ end
52
+ end
53
+
54
+ it 'should clone if not exist' do
55
+ allow(@git_repo).to receive(:exist?).and_return(false)
56
+ expect(@git_repo).to receive(:clone).with(@git_url)
57
+
58
+ @dsl.recipe 'name' do
59
+ @dsl.git(@git_url)
60
+ end
61
+ end
62
+ end
63
+
64
+ describe '#osx' do
65
+ it 'should yield if osx' do
66
+ allow(Evm::Os).to receive(:osx?).and_return(true)
67
+
68
+ expect { |block|
69
+ @dsl.osx(&block)
70
+ }.to yield_control
71
+ end
72
+
73
+ it 'should not yield if not osx' do
74
+ allow(Evm::Os).to receive(:osx?).and_return(false)
75
+
76
+ expect { |block|
77
+ @dsl.osx(&block)
78
+ }.not_to yield_control
79
+ end
80
+ end
81
+
82
+ describe '#linux' do
83
+ it 'should yield if linux' do
84
+ allow(Evm::Os).to receive(:linux?).and_return(true)
85
+
86
+ expect { |block|
87
+ @dsl.linux(&block)
88
+ }.to yield_control
89
+ end
90
+
91
+ it 'should not yield if not linux' do
92
+ allow(Evm::Os).to receive(:linux?).and_return(false)
93
+
94
+ expect { |block|
95
+ @dsl.linux(&block)
96
+ }.not_to yield_control
97
+ end
98
+ end
99
+
100
+ describe '#option' do
101
+ it 'should add option without value' do
102
+ @dsl.option '--foo'
103
+ expect(@dsl.instance_variable_get('@options')).to eq(['--foo'])
104
+ end
105
+
106
+ it 'should add option with value' do
107
+ @dsl.option '--foo', 'bar'
108
+ expect(@dsl.instance_variable_get('@options')).to eq(['--foo', 'bar'])
109
+ end
110
+
111
+ it 'should add multiple options' do
112
+ @dsl.option '--foo'
113
+ @dsl.option '--foo', 'bar'
114
+ @dsl.option '--bar', 'baz'
115
+ @dsl.option '--qux'
116
+ expect(@dsl.instance_variable_get('@options')).to eq(['--foo', '--foo', 'bar', '--bar', 'baz', '--qux'])
117
+ end
118
+ end
119
+
120
+ describe '#install' do
121
+ it 'should yield' do
122
+ expect { |block|
123
+ @dsl.install(&block)
124
+ }.to yield_control
125
+ end
126
+ end
127
+
128
+ describe '#autogen' do
129
+ it 'should run make command with target' do
130
+ expect(@dsl).to receive(:run_command).with('./autogen.sh')
131
+ @dsl.autogen
132
+ end
133
+ end
134
+
135
+ describe '#configure' do
136
+ it 'should configure when no options' do
137
+ expect(@dsl).to receive(:run_command).with('./configure')
138
+ @dsl.configure
139
+ end
140
+
141
+ it 'should configure when single option' do
142
+ expect(@dsl).to receive(:run_command).with('./configure', '--foo', 'bar')
143
+ @dsl.option '--foo', 'bar'
144
+ @dsl.configure
145
+ end
146
+
147
+ it 'should configure when multiple options' do
148
+ expect(@dsl).to receive(:run_command).with('./configure', '--foo', 'bar', '--baz')
149
+ @dsl.option '--foo', 'bar'
150
+ @dsl.option '--baz'
151
+ @dsl.configure
152
+ end
153
+ end
154
+
155
+ describe '#make' do
156
+ it 'should run make command with target' do
157
+ expect(@dsl).to receive(:run_command).with('make', 'foo')
158
+ @dsl.make('foo')
159
+ end
160
+ end
161
+
162
+ describe '#build_path' do
163
+ it 'should return package build path' do
164
+ @dsl.recipe 'name' do
165
+ expect(@dsl.build_path).to eq('/tmp/evm/tmp/name')
166
+ end
167
+ end
168
+ end
169
+
170
+ describe '#builds_path' do
171
+ it 'should return package builds path' do
172
+ @dsl.recipe 'name' do
173
+ expect(@dsl.builds_path).to eq('/tmp/evm/tmp')
174
+ end
175
+ end
176
+ end
177
+
178
+ describe '#installation_path' do
179
+ it 'should return package installation path' do
180
+ @dsl.recipe 'name' do
181
+ expect(@dsl.installation_path).to eq('/tmp/evm/name')
182
+ end
183
+ end
184
+ end
185
+
186
+ describe '#installations_path' do
187
+ it 'should return package installations path' do
188
+ @dsl.recipe 'name' do
189
+ expect(@dsl.installations_path).to eq('/tmp/evm')
190
+ end
191
+ end
192
+ end
193
+
194
+ describe '#platform_name' do
195
+ it 'should platform name' do
196
+ allow(Evm::Os).to receive(:platform_name).and_return(:foo)
197
+
198
+ expect(@dsl.platform_name).to eq(:foo)
199
+ end
200
+ end
201
+
202
+ describe '#copy' do
203
+ it 'copies all files recursively and preserves file attributes' do
204
+ expect(@dsl).to receive(:run_command).with('cp -a from to')
205
+ @dsl.copy 'from', 'to'
206
+ end
207
+ end
208
+ end
209
+ end