evm 0.6.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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