omnibus 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -0
  3. data/.travis.yml +3 -11
  4. data/CHANGELOG.md +50 -0
  5. data/MAINTAINERS.md +26 -0
  6. data/README.md +61 -4
  7. data/appveyor.yml +35 -0
  8. data/docs/Build Cache.md +28 -3
  9. data/docs/Building on RHEL.md +1 -1
  10. data/features/commands/publish.feature +4 -9
  11. data/features/step_definitions/generator_steps.rb +14 -1
  12. data/features/support/env.rb +5 -3
  13. data/lib/omnibus.rb +10 -0
  14. data/lib/omnibus/build_version.rb +34 -25
  15. data/lib/omnibus/build_version_dsl.rb +43 -4
  16. data/lib/omnibus/builder.rb +30 -11
  17. data/lib/omnibus/changelog.rb +52 -0
  18. data/lib/omnibus/changelog_printer.rb +77 -0
  19. data/lib/omnibus/cli.rb +37 -2
  20. data/lib/omnibus/cli/changelog.rb +149 -0
  21. data/lib/omnibus/cli/publish.rb +30 -10
  22. data/lib/omnibus/config.rb +41 -2
  23. data/lib/omnibus/digestable.rb +6 -1
  24. data/lib/omnibus/exceptions.rb +15 -1
  25. data/lib/omnibus/fetcher.rb +78 -34
  26. data/lib/omnibus/fetchers/git_fetcher.rb +84 -42
  27. data/lib/omnibus/fetchers/net_fetcher.rb +64 -13
  28. data/lib/omnibus/fetchers/null_fetcher.rb +8 -1
  29. data/lib/omnibus/fetchers/path_fetcher.rb +24 -1
  30. data/lib/omnibus/file_syncer.rb +52 -1
  31. data/lib/omnibus/generator.rb +22 -21
  32. data/lib/omnibus/generator_files/.kitchen.yml.erb +8 -12
  33. data/lib/omnibus/generator_files/Berksfile.erb +4 -4
  34. data/lib/omnibus/generator_files/Gemfile.erb +3 -3
  35. data/lib/omnibus/generator_files/README.md.erb +17 -0
  36. data/lib/omnibus/generator_files/omnibus.rb.erb +6 -0
  37. data/lib/omnibus/git_repository.rb +43 -0
  38. data/lib/omnibus/health_check.rb +5 -1
  39. data/lib/omnibus/manifest.rb +134 -0
  40. data/lib/omnibus/manifest_diff.rb +88 -0
  41. data/lib/omnibus/manifest_entry.rb +43 -0
  42. data/lib/omnibus/metadata.rb +19 -1
  43. data/lib/omnibus/package.rb +9 -0
  44. data/lib/omnibus/packagers/base.rb +1 -1
  45. data/lib/omnibus/packagers/bff.rb +5 -5
  46. data/lib/omnibus/packagers/deb.rb +11 -4
  47. data/lib/omnibus/packagers/msi.rb +243 -2
  48. data/lib/omnibus/packagers/rpm.rb +68 -14
  49. data/lib/omnibus/packagers/solaris.rb +17 -23
  50. data/lib/omnibus/project.rb +129 -16
  51. data/lib/omnibus/publisher.rb +62 -49
  52. data/lib/omnibus/publishers/artifactory_publisher.rb +96 -5
  53. data/lib/omnibus/publishers/s3_publisher.rb +20 -25
  54. data/lib/omnibus/s3_cache.rb +13 -34
  55. data/lib/omnibus/s3_helpers.rb +119 -0
  56. data/lib/omnibus/semantic_version.rb +57 -0
  57. data/lib/omnibus/software.rb +87 -28
  58. data/lib/omnibus/sugarable.rb +18 -0
  59. data/lib/omnibus/templating.rb +8 -1
  60. data/lib/omnibus/version.rb +1 -1
  61. data/omnibus.gemspec +10 -7
  62. data/resources/bff/gen.template.erb +1 -1
  63. data/resources/msi/bundle.wxs.erb +17 -0
  64. data/resources/msi/localization-en-us.wxl.erb +1 -1
  65. data/resources/rpm/spec.erb +1 -1
  66. data/spec/functional/builder_spec.rb +15 -7
  67. data/spec/functional/fetchers/git_fetcher_spec.rb +44 -12
  68. data/spec/functional/fetchers/net_fetcher_spec.rb +171 -20
  69. data/spec/functional/fetchers/path_fetcher_spec.rb +16 -1
  70. data/spec/functional/file_syncer_spec.rb +58 -5
  71. data/spec/functional/templating_spec.rb +17 -6
  72. data/spec/spec_helper.rb +17 -0
  73. data/spec/support/file_helpers.rb +12 -2
  74. data/spec/support/git_helpers.rb +23 -18
  75. data/spec/support/matchers.rb +22 -0
  76. data/spec/support/output_helpers.rb +29 -0
  77. data/spec/unit/build_version_dsl_spec.rb +31 -4
  78. data/spec/unit/build_version_spec.rb +11 -4
  79. data/spec/unit/builder_spec.rb +33 -0
  80. data/spec/unit/changelog_spec.rb +55 -0
  81. data/spec/unit/cleanroom_spec.rb +1 -1
  82. data/spec/unit/compressors/dmg_spec.rb +3 -3
  83. data/spec/unit/compressors/tgz_spec.rb +3 -3
  84. data/spec/unit/config_spec.rb +3 -1
  85. data/spec/unit/fetcher_spec.rb +35 -0
  86. data/spec/unit/fetchers/git_fetcher_spec.rb +28 -14
  87. data/spec/unit/fetchers/net_fetcher_spec.rb +178 -24
  88. data/spec/unit/fetchers/path_fetcher_spec.rb +8 -7
  89. data/spec/unit/generator_spec.rb +22 -21
  90. data/spec/unit/git_repository_spec.rb +60 -0
  91. data/spec/unit/manifest_diff_spec.rb +75 -0
  92. data/spec/unit/manifest_spec.rb +116 -0
  93. data/spec/unit/metadata_spec.rb +11 -0
  94. data/spec/unit/omnibus_spec.rb +9 -6
  95. data/spec/unit/package_spec.rb +1 -1
  96. data/spec/unit/packagers/base_spec.rb +8 -18
  97. data/spec/unit/packagers/bff_spec.rb +9 -5
  98. data/spec/unit/packagers/deb_spec.rb +44 -12
  99. data/spec/unit/packagers/makeself_spec.rb +4 -4
  100. data/spec/unit/packagers/msi_spec.rb +122 -6
  101. data/spec/unit/packagers/pkg_spec.rb +3 -3
  102. data/spec/unit/packagers/rpm_spec.rb +37 -12
  103. data/spec/unit/project_spec.rb +18 -1
  104. data/spec/unit/publisher_spec.rb +65 -0
  105. data/spec/unit/publishers/artifactory_publisher_spec.rb +26 -20
  106. data/spec/unit/publishers/s3_publisher_spec.rb +14 -30
  107. data/spec/unit/s3_cacher_spec.rb +1 -1
  108. data/spec/unit/s3_helpers_spec.rb +32 -0
  109. data/spec/unit/semantic_version_spec.rb +55 -0
  110. data/spec/unit/software_spec.rb +112 -4
  111. metadata +86 -16
@@ -32,12 +32,18 @@ module Omnibus
32
32
  module Sugarable
33
33
  def self.included(base)
34
34
  base.send(:include, Chef::Sugar::DSL)
35
+ base.send(:include, Omnibus::Sugar)
35
36
 
36
37
  if base < Cleanroom
37
38
  # Make all the "sugars" available in the cleanroom (DSL)
38
39
  Chef::Sugar::DSL.instance_methods.each do |instance_method|
39
40
  base.send(:expose, instance_method)
40
41
  end
42
+
43
+ # Make all the common "sugars" available in the cleanroom (DSL)
44
+ Omnibus::Sugar.instance_methods.each do |instance_method|
45
+ base.send(:expose, instance_method)
46
+ end
41
47
  end
42
48
  end
43
49
 
@@ -49,4 +55,16 @@ module Omnibus
49
55
  Ohai
50
56
  end
51
57
  end
58
+
59
+ # This module is a wrapper for common Chef::Sugar-like functions that
60
+ # are common to multiple DSLs (like project and software). The extensions
61
+ # below will be injected into CleanRoom, and hence visible to the DSLs.
62
+ module Sugar
63
+
64
+ # Returns whether the Windows build target is 32-bit (x86).
65
+ # If this returns false, the target is x64. Itanium is not supported.
66
+ def windows_arch_i386?
67
+ Config.windows_arch.to_sym == :x86
68
+ end
69
+ end
52
70
  end
@@ -53,7 +53,14 @@ module Omnibus
53
53
  end
54
54
 
55
55
  template = ERB.new(File.read(source), nil, '-')
56
- struct = Struct.new(*variables.keys).new(*variables.values)
56
+
57
+ struct =
58
+ if variables.empty?
59
+ Struct.new("Empty")
60
+ else
61
+ Struct.new(*variables.keys).new(*variables.values)
62
+ end
63
+
57
64
  result = template.result(struct.instance_eval { binding })
58
65
 
59
66
  File.open(destination, 'w', mode) do |file|
@@ -15,5 +15,5 @@
15
15
  #
16
16
 
17
17
  module Omnibus
18
- VERSION = '4.0.0'
18
+ VERSION = '4.1.0'
19
19
  end
@@ -21,19 +21,22 @@ Gem::Specification.new do |gem|
21
21
  gem.test_files = gem.files.grep(/^(test|spec|features)\//)
22
22
  gem.require_paths = ['lib']
23
23
 
24
- gem.add_dependency 'chef-sugar', '~> 2.2'
25
- gem.add_dependency 'cleanroom', '~> 1.0'
26
- gem.add_dependency 'mixlib-shellout', '~> 1.4'
27
- gem.add_dependency 'ohai', '~> 7.2'
28
- gem.add_dependency 'uber-s3'
29
- gem.add_dependency 'thor', '~> 0.18'
24
+ gem.add_dependency 'chef-sugar', '~> 3.0'
25
+ gem.add_dependency 'cleanroom', '~> 1.0'
26
+ gem.add_dependency 'mixlib-shellout', '~> 2.0'
27
+ gem.add_dependency 'mixlib-versioning'
28
+ gem.add_dependency 'ohai', '~> 8.0'
29
+ gem.add_dependency 'ruby-progressbar', '~> 1.7'
30
+ gem.add_dependency 'aws-sdk', '~> 2'
31
+ gem.add_dependency 'thor', '~> 0.18'
30
32
 
31
33
  gem.add_development_dependency 'bundler'
32
34
  gem.add_development_dependency 'artifactory', '~> 2.0'
33
35
  gem.add_development_dependency 'aruba', '~> 0.5'
34
- gem.add_development_dependency 'fauxhai', '~> 2.1'
36
+ gem.add_development_dependency 'fauxhai', '~> 2.3'
35
37
  gem.add_development_dependency 'rspec', '~> 3.0'
36
38
  gem.add_development_dependency 'rspec-its'
39
+ gem.add_development_dependency 'webmock'
37
40
  gem.add_development_dependency 'rake'
38
41
  gem.add_development_dependency 'appbundler'
39
42
  end
@@ -15,7 +15,7 @@ Fileset
15
15
  Include license files in this package: N
16
16
  Requisites:
17
17
  ROOT Part: Y
18
- USRFiles
18
+ USRFiles
19
19
  <% files.each do |file| -%>
20
20
  <%= file %>
21
21
  <% end -%>
@@ -0,0 +1,17 @@
1
+ <?xml version='1.0' encoding="utf-8"?>
2
+ <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
3
+ <!-- This is how we include wxi files -->
4
+ <?include "parameters.wxi" ?>
5
+
6
+ <Bundle Version="$(var.VersionNumber)" Manufacturer="!(loc.ManufacturerName)" UpgradeCode="$(var.UpgradeCode)">
7
+ <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" >
8
+ <bal:WixStandardBootstrapperApplication LicenseFile="Resources\assets\LICENSE.rtf"/>
9
+ </BootstrapperApplicationRef>
10
+
11
+ <Chain>
12
+ <ExePackage SourceFile="$(var.OmnibusCacheDir)\vcredist_x64.exe" InstallCommand="/Q"
13
+ DownloadUrl="http://download.microsoft.com/download/d/2/4/d242c3fb-da5a-4542-ad66-f9661d0a8d19/vcredist_x64.exe" />
14
+ <MsiPackage SourceFile="<%= msi %>" EnableFeatureSelection="no" />
15
+ </Chain>
16
+ </Bundle>
17
+ </Wix>
@@ -2,7 +2,7 @@
2
2
  <WixLocalization Culture="en-us" xmlns="http://schemas.microsoft.com/wix/2006/localization">
3
3
  <String Id="LANG">1033</String>
4
4
  <String Id="ProductName"><%= friendly_name %></String>
5
- <String Id="ManufacturerName"><%= maintainer %></String>
5
+ <String Id="ManufacturerName"><%= maintainer.encode(:xml => :attr) %></String>
6
6
  <String Id="WelcomeDlgTitle">{\WixUI_Font_Bigger}Welcome to the [ProductName] Setup Wizard</String>
7
7
 
8
8
  <String Id="LicenseAgreementDlgTitle">{\WixUI_Font_Title_White}End-User License Agreement</String>
@@ -17,7 +17,7 @@
17
17
  # Metadata
18
18
  Name: <%= name %>
19
19
  Version: <%= version %>
20
- Release: <%= iteration %>
20
+ Release: <%= iteration %><%= dist_tag %>
21
21
  Summary: <%= description.split("\n").first.empty? ? "_" : description.split("\n").first %>
22
22
  BuildArch: <%= architecture %>
23
23
  AutoReqProv: no
@@ -7,10 +7,18 @@ module Omnibus
7
7
  #
8
8
  # Fakes the embedded bin path to whatever exists in bundler. This is useful
9
9
  # for testing methods like +ruby+ and +rake+ without the need to compile
10
- # a real Ruby just for functional tests.
10
+ # a real Ruby just for functional tests. This strategy does not work on
11
+ # Windows because a) windows doesn't have symlinks and b) the windows
12
+ # omnibus installation has a post installation step that fixes up
13
+ # shebang paths to point to embedded ruby and drops bat files with
14
+ # the correct path. If we need to invoke bundler/appbundler etc. in a
15
+ # manner similar to one that omnibus provides, we would need to emulate
16
+ # the fixup steps here as well, which is a pain the ass.
11
17
  #
18
+ # So just don't run those tests on windows.
12
19
  def fake_embedded_bin(name)
13
20
  create_directory(embedded_bin_dir)
21
+ name = 'ruby.exe' if windows? && name == 'ruby'
14
22
  create_link(Bundler.which(name), File.join(embedded_bin_dir, name))
15
23
  end
16
24
 
@@ -32,7 +40,7 @@ module Omnibus
32
40
  end
33
41
  end
34
42
 
35
- describe '#patch' do
43
+ describe '#patch', :not_supported_on_windows do
36
44
  it 'applies the patch' do
37
45
  configure = File.join(project_dir, 'configure')
38
46
  File.open(configure, 'w') do |f|
@@ -79,7 +87,7 @@ module Omnibus
79
87
  end
80
88
  end
81
89
 
82
- describe '#gem' do
90
+ describe '#gem', :not_supported_on_windows do
83
91
  it 'executes the command as the embedded gem' do
84
92
  gemspec = File.join(tmp_path, 'example.gemspec')
85
93
  File.open(gemspec, 'w') do |f|
@@ -106,7 +114,7 @@ module Omnibus
106
114
  end
107
115
  end
108
116
 
109
- describe '#bundler' do
117
+ describe '#bundler', :not_supported_on_windows do
110
118
  it 'executes the command as the embedded bundler' do
111
119
  gemspec = File.join(tmp_path, 'example.gemspec')
112
120
  File.open(gemspec, 'w') do |f|
@@ -145,7 +153,7 @@ module Omnibus
145
153
  end
146
154
  end
147
155
 
148
- describe '#appbundle' do
156
+ describe '#appbundle', :not_supported_on_windows do
149
157
  it 'executes the command as the embedded appbundler' do
150
158
 
151
159
  source_dir = "#{Omnibus::Config.source_dir}/example"
@@ -210,7 +218,7 @@ module Omnibus
210
218
  end
211
219
  end
212
220
 
213
- describe '#rake' do
221
+ describe '#rake', :not_supported_on_windows do
214
222
  it 'executes the command as the embedded rake' do
215
223
  rakefile = File.join(tmp_path, 'Rakefile')
216
224
  File.open(rakefile, 'w') do |f|
@@ -445,7 +453,7 @@ module Omnibus
445
453
  end
446
454
  end
447
455
 
448
- describe '#link' do
456
+ describe '#link', :not_supported_on_windows do
449
457
  it 'links the file' do
450
458
  path_a = File.join(tmp_path, 'file1')
451
459
  path_b = File.join(tmp_path, 'file2')
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'omnibus/manifest_entry'
2
3
 
3
4
  module Omnibus
4
5
  describe GitFetcher do
@@ -11,7 +12,15 @@ module Omnibus
11
12
  { git: remote }
12
13
  end
13
14
 
14
- subject { described_class.new(software) }
15
+ let(:manifest_entry) do
16
+ double(ManifestEntry,
17
+ name: 'software',
18
+ locked_version: '45ded6d3b1a35d66ed866b2c3eb418426e6382b0',
19
+ described_version: version,
20
+ locked_source: source)
21
+ end
22
+
23
+ subject { described_class.new(manifest_entry, project_dir, build_dir) }
15
24
 
16
25
  describe '#fetch_required?' do
17
26
  context 'when the repo is not cloned' do
@@ -82,19 +91,38 @@ module Omnibus
82
91
 
83
92
  describe '#fetch' do
84
93
  let(:revision) { shellout!('git rev-parse HEAD', cwd: project_dir).stdout.strip }
94
+ let(:version) { 'v1.2.4' }
95
+ let(:remote) { remote_git_repo('zlib', annotated_tags: [version]) }
96
+ let(:manifest_entry) do
97
+ double(ManifestEntry,
98
+ name: 'software',
99
+ locked_version: 'efde208366abd0f91419d8a54b45e3f6e0540105',
100
+ described_version: version,
101
+ locked_source: source)
102
+ end
103
+
104
+ subject { described_class.new(manifest_entry, project_dir, build_dir) }
105
+
85
106
 
86
107
  it 'clones the repository' do
87
108
  subject.fetch
88
109
  expect("#{project_dir}/.git").to be_a_directory
89
110
  end
90
111
 
112
+ it 'fetches the locked_version from the manifest' do
113
+ subject.fetch
114
+ expect(revision).to eq(manifest_entry.locked_version)
115
+ end
116
+ end
117
+
118
+
119
+ describe '#resolve_version' do
91
120
  context 'when the version is a tag' do
92
121
  let(:version) { 'v1.2.3' }
93
122
  let(:remote) { remote_git_repo('zlib', tags: [version]) }
94
123
 
95
124
  it 'parses the tag' do
96
- subject.fetch
97
- expect(revision).to eq('53c72c4abcc961b153996f5b5f402ce715e47146')
125
+ expect(GitFetcher.resolve_version(version, source)).to eq('53c72c4abcc961b153996f5b5f402ce715e47146')
98
126
  end
99
127
  end
100
128
 
@@ -103,8 +131,7 @@ module Omnibus
103
131
  let(:remote) { remote_git_repo('zlib', annotated_tags: [version]) }
104
132
 
105
133
  it 'it defererences and parses the annotated tag' do
106
- subject.fetch
107
- expect(revision).to eq('efde208366abd0f91419d8a54b45e3f6e0540105')
134
+ expect(GitFetcher.resolve_version(version, source)).to eq('efde208366abd0f91419d8a54b45e3f6e0540105')
108
135
  end
109
136
  end
110
137
 
@@ -113,8 +140,7 @@ module Omnibus
113
140
  let(:remote) { remote_git_repo('zlib', branches: [version]) }
114
141
 
115
142
  it 'parses the branch' do
116
- subject.fetch
117
- expect(revision).to eq('171a1aec35ac0a050f8dccd9c9ef4609b1d8d8ea')
143
+ expect(GitFetcher.resolve_version(version, source)).to eq('171a1aec35ac0a050f8dccd9c9ef4609b1d8d8ea')
118
144
  end
119
145
  end
120
146
 
@@ -123,8 +149,7 @@ module Omnibus
123
149
  let(:remote) { remote_git_repo('zlib') }
124
150
 
125
151
  it 'parses the full SHA-1' do
126
- subject.fetch
127
- expect(revision).to eq('45ded6d3b1a35d66ed866b2c3eb418426e6382b0')
152
+ expect(GitFetcher.resolve_version(version, source)).to eq('45ded6d3b1a35d66ed866b2c3eb418426e6382b0')
128
153
  end
129
154
  end
130
155
 
@@ -133,8 +158,7 @@ module Omnibus
133
158
  let(:remote) { remote_git_repo('zlib') }
134
159
 
135
160
  it 'parses the abbreviated SHA-1' do
136
- subject.fetch
137
- expect(revision).to eq('45ded6d3b1a35d66ed866b2c3eb418426e6382b0')
161
+ expect(GitFetcher.resolve_version(version, source)).to eq('45ded6d')
138
162
  end
139
163
  end
140
164
 
@@ -143,7 +167,7 @@ module Omnibus
143
167
  let(:remote) { remote_git_repo('zlib') }
144
168
 
145
169
  it 'raise an exception' do
146
- expect { subject.fetch }.to raise_error(UnresolvableGitReference)
170
+ expect { GitFetcher.resolve_version(version, source) }.to raise_error(UnresolvableGitReference)
147
171
  end
148
172
  end
149
173
  end
@@ -154,6 +178,14 @@ module Omnibus
154
178
  it 'includes the revision' do
155
179
  expect(subject.version_for_cache).to eq("revision:#{revision}")
156
180
  end
181
+
182
+ it 'does not returned cached revision after fetching' do
183
+ before_fetch = subject.version_for_cache
184
+ subject.fetch
185
+ after_fetch = revision
186
+ expect(subject.version_for_cache).to eq("revision:#{after_fetch}")
187
+ expect(subject.version_for_cache).not_to eq("revision:#{before_fetch}")
188
+ end
157
189
  end
158
190
  end
159
191
  end
@@ -2,18 +2,32 @@ require 'spec_helper'
2
2
 
3
3
  module Omnibus
4
4
  describe NetFetcher do
5
- include_examples 'a software'
5
+ include_examples 'a software', 'zlib'
6
+
7
+ let(:source_url) { 'http://downloads.sourceforge.net/project/libpng/zlib/1.2.8/zlib-1.2.8.tar.gz' }
8
+ let(:source_md5) { '44d667c142d7cda120332623eab69f40' }
9
+ let(:source_sha1) { 'a4d316c404ff54ca545ea71a27af7dbc29817088' }
10
+ let(:source_sha256) { '36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d' }
11
+ let(:source_sha512) { 'ece209d4c7ec0cb58ede791444dc754e0d10811cbbdebe3df61c0fd9f9f9867c1c3ccd5f1827f847c005e24eef34fb5bf87b5d3f894d75da04f1797538290e4a' }
6
12
 
7
- let(:source_url) { 'http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz' }
8
- let(:source_md5) { '00b516f4704d4a7cb50a1d97e6e8e15b' }
9
13
  let(:source) do
10
14
  { url: source_url, md5: source_md5 }
11
15
  end
12
16
 
13
17
  let(:downloaded_file) { subject.send(:downloaded_file) }
14
- let(:extracted) { File.join(source_dir, 'bzip2-1.0.6') }
18
+ let(:extracted) { File.join(source_dir, 'zlib-1.2.8') }
19
+
20
+ let(:fetch!) { capture_stdout { subject.fetch } }
15
21
 
16
- subject { described_class.new(software) }
22
+ let(:manifest_entry) do
23
+ double(ManifestEntry,
24
+ name: 'software',
25
+ locked_version: '1.2.8',
26
+ described_version: '1.2.8',
27
+ locked_source: source)
28
+ end
29
+
30
+ subject { described_class.new(manifest_entry, project_dir, build_dir) }
17
31
 
18
32
  describe '#fetch_required?' do
19
33
  context 'when the file is not downloaded' do
@@ -23,7 +37,7 @@ module Omnibus
23
37
  end
24
38
 
25
39
  context 'when the file is downloaded' do
26
- before { subject.fetch }
40
+ before { fetch! }
27
41
 
28
42
  context 'when the checksum is different' do
29
43
  it 'return true' do
@@ -41,13 +55,45 @@ module Omnibus
41
55
  end
42
56
 
43
57
  describe '#version_guid' do
44
- it 'includes the source md5' do
45
- expect(subject.version_guid).to eq("md5:#{source_md5}")
58
+ context 'source with md5' do
59
+ it 'includes the md5 digest' do
60
+ expect(subject.version_guid).to eq("md5:#{source_md5}")
61
+ end
62
+ end
63
+
64
+ context 'source with sha1' do
65
+ let(:source) do
66
+ { url: source_url, sha1: source_sha1 }
67
+ end
68
+
69
+ it 'includes the sha1 digest' do
70
+ expect(subject.version_guid).to eq("sha1:#{source_sha1}")
71
+ end
72
+ end
73
+
74
+ context 'source with sha256' do
75
+ let(:source) do
76
+ { url: source_url, sha256: source_sha256 }
77
+ end
78
+
79
+ it 'includes the sha256 digest' do
80
+ expect(subject.version_guid).to eq("sha256:#{source_sha256}")
81
+ end
82
+ end
83
+
84
+ context 'source with sha512' do
85
+ let(:source) do
86
+ { url: source_url, sha512: source_sha512 }
87
+ end
88
+
89
+ it 'includes the sha512 digest' do
90
+ expect(subject.version_guid).to eq("sha512:#{source_sha512}")
91
+ end
46
92
  end
47
93
  end
48
94
 
49
95
  describe '#clean' do
50
- before { subject.fetch }
96
+ before { fetch! }
51
97
 
52
98
  context 'when the project directory exists' do
53
99
  before do
@@ -76,21 +122,94 @@ module Omnibus
76
122
  end
77
123
 
78
124
  describe '#fetch' do
79
- it 'downloads the file' do
80
- subject.fetch
81
- expect(downloaded_file).to be_a_file
125
+ context 'source with md5' do
126
+ it 'downloads the file' do
127
+ fetch!
128
+ expect(downloaded_file).to be_a_file
129
+ end
130
+
131
+ context 'when the checksum is invalid' do
132
+ let(:source_md5) { 'bad01234checksum' }
133
+
134
+ it 'raises an exception' do
135
+ expect { fetch! }.to raise_error(ChecksumMismatch)
136
+ end
137
+ end
138
+ end
139
+
140
+ context 'source with sha1' do
141
+ let(:source) do
142
+ { url: source_url, sha1: source_sha1 }
143
+ end
144
+
145
+ it 'downloads the file' do
146
+ fetch!
147
+ expect(downloaded_file).to be_a_file
148
+ end
149
+
150
+ context 'when the checksum is invalid' do
151
+ let(:source_sha1) { 'bad01234checksum' }
152
+
153
+ it 'raises an exception' do
154
+ expect { fetch! }.to raise_error(ChecksumMismatch)
155
+ end
156
+ end
82
157
  end
83
158
 
84
- context 'when the checksum is invalid' do
85
- let(:source_md5) { 'bad01234checksum' }
159
+ context 'source with sha256' do
160
+ let(:source) do
161
+ { url: source_url, sha256: source_sha256 }
162
+ end
163
+
164
+ it 'downloads the file' do
165
+ fetch!
166
+ expect(downloaded_file).to be_a_file
167
+ end
168
+
169
+ context 'when the checksum is invalid' do
170
+ let(:source_sha256) { 'bad01234checksum' }
171
+
172
+ it 'raises an exception' do
173
+ expect { fetch! }.to raise_error(ChecksumMismatch)
174
+ end
175
+ end
176
+ end
177
+
178
+ context 'source with sha512' do
179
+ let(:source) do
180
+ { url: source_url, sha512: source_sha512 }
181
+ end
182
+
183
+ it 'downloads the file' do
184
+ fetch!
185
+ expect(downloaded_file).to be_a_file
186
+ end
187
+
188
+ context 'when the checksum is invalid' do
189
+ let(:source_sha512) { 'bad01234checksum' }
190
+
191
+ it 'raises an exception' do
192
+ expect { fetch! }.to raise_error(ChecksumMismatch)
193
+ end
194
+ end
195
+ end
86
196
 
87
- it 'raises an exception' do
88
- expect { subject.fetch }.to raise_error(ChecksumMismatch)
197
+ it 'when the download times out' do
198
+ # Mock the Timeout::Error for this particular test only
199
+ WebMock.disable_net_connect!
200
+ stub_request(:get, "http://downloads.sourceforge.net/project/libpng/zlib/1.2.8/zlib-1.2.8.tar.gz").to_timeout
201
+ output = capture_logging do
202
+ expect { subject.send(:download) }.to raise_error(Timeout::Error)
89
203
  end
204
+
205
+ expect(output).to include('Retrying failed download')
206
+ expect(output).to include('Download failed')
207
+ retry_count = output.scan('Retrying failed download').count
208
+ expect(retry_count).to eq(Omnibus::Config.fetcher_retries)
90
209
  end
91
210
 
92
211
  it 'extracts the file' do
93
- subject.fetch
212
+ fetch!
94
213
  expect(extracted).to be_a_directory
95
214
  end
96
215
 
@@ -99,7 +218,7 @@ module Omnibus
99
218
  let(:source_md5) { '369efc3a19b9118cdf51c7e87a34f266' }
100
219
 
101
220
  it 'downloads the file' do
102
- subject.fetch
221
+ fetch!
103
222
  expect(downloaded_file).to be_a_file
104
223
  end
105
224
  end
@@ -112,8 +231,40 @@ module Omnibus
112
231
  create_file("#{project_dir}/.file_c")
113
232
  end
114
233
 
115
- it 'includes the download_url and checksum' do
116
- expect(subject.version_for_cache).to eq("download_url:#{source_url}|md5:#{source_md5}")
234
+ context 'source with md5' do
235
+ it 'includes the download_url and checksum' do
236
+ expect(subject.version_for_cache).to eq("download_url:#{source_url}|md5:#{source_md5}")
237
+ end
238
+ end
239
+
240
+ context 'source with sha1' do
241
+ let(:source) do
242
+ { url: source_url, sha1: source_sha1 }
243
+ end
244
+
245
+ it 'includes the download_url and checksum' do
246
+ expect(subject.version_for_cache).to eq("download_url:#{source_url}|sha1:#{source_sha1}")
247
+ end
248
+ end
249
+
250
+ context 'source with sha256' do
251
+ let(:source) do
252
+ { url: source_url, sha256: source_sha256 }
253
+ end
254
+
255
+ it 'includes the download_url and checksum' do
256
+ expect(subject.version_for_cache).to eq("download_url:#{source_url}|sha256:#{source_sha256}")
257
+ end
258
+ end
259
+
260
+ context 'source with sha512' do
261
+ let(:source) do
262
+ { url: source_url, sha512: source_sha512 }
263
+ end
264
+
265
+ it 'includes the download_url and checksum' do
266
+ expect(subject.version_for_cache).to eq("download_url:#{source_url}|sha512:#{source_sha512}")
267
+ end
117
268
  end
118
269
  end
119
270
  end