omnibus 5.2.0 → 5.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -197,13 +197,20 @@ module Omnibus
197
197
  #
198
198
  # Execute the given git command, inside the +project_dir+.
199
199
  #
200
+ # autcrlf is a hack to help support windows and posix clients using the
201
+ # same repository but canonicalizing files as they are committed to the
202
+ # repo but converting line endings when they are actually checked out
203
+ # into a working tree. We do not want to change the on-disk representation
204
+ # of our sources regardless of the platform we are building on unless
205
+ # explicitly asked for. Hence, we disable autocrlf.
206
+ #
200
207
  # @see Util#shellout!
201
208
  #
202
209
  # @return [Mixlib::ShellOut]
203
210
  # the shellout object
204
211
  #
205
212
  def git(command)
206
- shellout!("git #{command}", cwd: project_dir)
213
+ shellout!("git -c core.autocrlf=false #{command}", cwd: project_dir)
207
214
  end
208
215
 
209
216
  # Class methods
@@ -15,11 +15,12 @@
15
15
  #
16
16
 
17
17
  require 'fileutils'
18
- require 'open-uri'
19
- require 'ruby-progressbar'
18
+ require 'omnibus/download_helpers'
20
19
 
21
20
  module Omnibus
22
21
  class NetFetcher < Fetcher
22
+ include DownloadHelpers
23
+
23
24
  # Use 7-zip to extract 7z/zip for Windows
24
25
  WIN_7Z_EXTENSIONS = %w(.7z .zip)
25
26
 
@@ -159,53 +160,17 @@ module Omnibus
159
160
  def download
160
161
  log.warn(log_key) { source[:warning] } if source.key?(:warning)
161
162
 
162
- options = download_headers
163
+ options = {}
163
164
 
164
165
  if source[:unsafe]
165
166
  log.warn(log_key) { "Permitting unsafe redirects!" }
166
167
  options[:allow_unsafe_redirects] = true
167
168
  end
168
169
 
169
- options[:read_timeout] = Omnibus::Config.fetcher_read_timeout
170
- fetcher_retries ||= Omnibus::Config.fetcher_retries
171
-
172
- progress_bar = ProgressBar.create(
173
- output: $stdout,
174
- format: '%e %B %p%% (%r KB/sec)',
175
- rate_scale: ->(rate) { rate / 1024 },
176
- )
177
-
178
- reported_total = 0
179
-
180
- options[:content_length_proc] = ->(total) {
181
- reported_total = total
182
- progress_bar.total = total
183
- }
184
- options[:progress_proc] = ->(step) {
185
- downloaded_amount = [step, reported_total].min
186
- progress_bar.progress = downloaded_amount
187
- }
188
-
189
- file = open(download_url, options)
190
- # This is a temporary file. Close and flush it before attempting to copy
191
- # it over.
192
- file.close
193
- FileUtils.cp(file.path, downloaded_file)
194
- file.unlink
195
- rescue SocketError,
196
- Errno::ECONNREFUSED,
197
- Errno::ECONNRESET,
198
- Errno::ENETUNREACH,
199
- Timeout::Error,
200
- OpenURI::HTTPError => e
201
- if fetcher_retries != 0
202
- log.info(log_key) { "Retrying failed download due to #{e} (#{fetcher_retries} retries left)..." }
203
- fetcher_retries -= 1
204
- retry
205
- else
206
- log.error(log_key) { "Download failed - #{e.class}!" }
207
- raise
208
- end
170
+ # Set the cookie if one was given
171
+ options['Cookie'] = source[:cookie] if source[:cookie]
172
+
173
+ download_file!(download_url, downloaded_file, options)
209
174
  end
210
175
 
211
176
  #
@@ -358,43 +323,5 @@ module Omnibus
358
323
  def tar
359
324
  Omnibus.which('gtar') ? 'gtar' : 'tar'
360
325
  end
361
-
362
- #
363
- # The list of headers to pass to the download.
364
- #
365
- # @return [Hash]
366
- #
367
- def download_headers
368
- {}.tap do |h|
369
- # Alright kids, sit down while grandpa tells you a story. Back when the
370
- # Internet was just a series of tubes, and you had to "dial in" using
371
- # this thing called a "modem", ancient astronaunt theorists (computer
372
- # scientists) invented gzip to compress requests sent over said tubes
373
- # and make the Internet faster.
374
- #
375
- # Fast forward to the year of broadband - ungzipping these files was
376
- # tedious and hard, so Ruby and other client libraries decided to do it
377
- # for you:
378
- #
379
- # https://github.com/ruby/ruby/blob/c49ae7/lib/net/http.rb#L1031-L1033
380
- #
381
- # Meanwhile, software manufacturers began automatically compressing
382
- # their software for distribution as a +.tar.gz+, publishing the
383
- # appropriate checksums accordingly.
384
- #
385
- # But consider... If a software manufacturer is publishing the checksum
386
- # for a gzipped tarball, and the client is automatically ungzipping its
387
- # responses, then checksums can (read: should) never match! Herein lies
388
- # the bug that took many hours away from the lives of a once-happy
389
- # developer.
390
- #
391
- # TL;DR - Do not let Ruby ungzip our file
392
- #
393
- h['Accept-Encoding'] = 'identity'
394
-
395
- # Set the cookie if one was given
396
- h['Cookie'] = source[:cookie] if source[:cookie]
397
- end
398
- end
399
326
  end
400
327
  end
@@ -97,6 +97,12 @@ module Omnibus
97
97
  /librt\.so\.1/,
98
98
  /libcrypt\.so\.1/,
99
99
  /libgdbm\.so\.3/,
100
+ /libgcc_s\.so\.1/,
101
+ /libcryptoutil\.so\.1/,
102
+ /libucrypto\.so\.1/,
103
+ /libz\.so\.1/, # while we package our own libz, this get dragged along from Solaris 11's libelf library for some reason...
104
+ /libelf\.so\.1/,
105
+ /libssp\.so\.0/,
100
106
  # solaris 9 libraries:
101
107
  /libm\.so\.1/,
102
108
  /libc_psr\.so\.1/,
@@ -151,6 +157,49 @@ module Omnibus
151
157
  /libmd\.so/,
152
158
  ].freeze
153
159
 
160
+ IGNORED_ENDINGS = %w(
161
+ .[ch]
162
+ .e*rb
163
+ .gemspec
164
+ .gitignore
165
+ .h*h
166
+ .java
167
+ .js
168
+ .json
169
+ .lock
170
+ .log
171
+ .lua
172
+ .md
173
+ .mkd
174
+ .out
175
+ .pl
176
+ .pm
177
+ .png
178
+ .py[oc]*
179
+ .r*html
180
+ .rdoc
181
+ .ri
182
+ .sh
183
+ .sql
184
+ .toml
185
+ .ttf
186
+ .txt
187
+ .xml
188
+ .yml
189
+ Gemfile
190
+ LICENSE
191
+ README
192
+ Rakefile
193
+ VERSION
194
+ ).freeze
195
+
196
+ IGNORED_PATTERNS = %w(
197
+ /share/doc/
198
+ /share/postgresql/
199
+ /share/terminfo/
200
+ /terminfo/
201
+ ).freeze
202
+
154
203
  class << self
155
204
  # @see (HealthCheck#new)
156
205
  def run!(project)
@@ -450,10 +499,14 @@ module Omnibus
450
499
  # the bad libraries (library_name -> dependency_name -> satisfied_lib_path -> count)
451
500
  #
452
501
  def health_check_ldd
502
+ regexp_ends = '.*(' + IGNORED_ENDINGS.map { |e| e.gsub(/\./, '\.') }.join('|') + ')$'
503
+ regexp_patterns = IGNORED_PATTERNS.map { |e| '.*' + e.gsub(/\//, '\/') + '.*' }.join('|')
504
+ regexp = regexp_ends + '|' + regexp_patterns
505
+
453
506
  current_library = nil
454
507
  bad_libs = {}
455
508
 
456
- read_shared_libs("find #{project.install_dir}/ -type f | xargs ldd") do |line|
509
+ read_shared_libs("find #{project.install_dir}/ -type f -regextype posix-extended ! -regex '#{regexp}' | xargs ldd") do |line|
457
510
  case line
458
511
  when /^(.+):$/
459
512
  current_library = Regexp.last_match[1]
@@ -16,10 +16,12 @@
16
16
 
17
17
  require 'uri'
18
18
  require 'fileutils'
19
+ require 'omnibus/download_helpers'
19
20
 
20
21
  module Omnibus
21
22
  class Licensing
22
23
  include Logging
24
+ include DownloadHelpers
23
25
 
24
26
  OUTPUT_DIRECTORY = "LICENSES".freeze
25
27
 
@@ -53,6 +55,7 @@ module Omnibus
53
55
  #
54
56
  def create!
55
57
  prepare
58
+ validate_license_info
56
59
  create_software_license_files
57
60
  create_project_license_file
58
61
  end
@@ -67,6 +70,49 @@ module Omnibus
67
70
  FileUtils.mkdir_p(output_dir)
68
71
  end
69
72
 
73
+ #
74
+ # Inspects the licensing information for the project and the included
75
+ # software components. Logs the found issues to the log as warning.
76
+ #
77
+ # @return [void]
78
+ #
79
+ def validate_license_info
80
+ # First check the project licensing information
81
+
82
+ # Check existence of licensing information
83
+ if project.license == "Unspecified"
84
+ licensing_warning("Project '#{project.name}' does not contain licensing information.")
85
+ end
86
+
87
+ # Check license file exists
88
+ if project.license != "Unspecified" && project.license_file.nil?
89
+ licensing_warning("Project '#{project.name}' does not point to a license file.")
90
+ end
91
+
92
+ # Check used license is a standard license
93
+ if project.license != "Unspecified" && !STANDARD_LICENSES.include?(project.license)
94
+ licensing_warning("Project '#{project.name}' is using '#{project.license}' which is not one of the standard licenses identified in https://opensource.org/licenses/alphabetical. Consider using one of the standard licenses.")
95
+ end
96
+
97
+ # Now let's check the licensing info for software components
98
+ license_map.each do |software_name, license_info|
99
+ # First check if the software specified a license
100
+ if license_info[:license] == "Unspecified"
101
+ licensing_warning("Software '#{software_name}' does not contain licensing information.")
102
+ end
103
+
104
+ # Check if the software specifies any license files
105
+ if license_info[:license] != "Unspecified" && license_info[:license_files].empty?
106
+ licensing_warning("Software '#{software_name}' does not point to any license files.")
107
+ end
108
+
109
+ # Check if the software license is one of the standard licenses
110
+ if license_info[:license] != "Unspecified" && !STANDARD_LICENSES.include?(license_info[:license])
111
+ licensing_warning("Software '#{software_name}' uses license '#{license_info[:license]}' which is not one of the standard licenses identified in https://opensource.org/licenses/alphabetical. Consider using one of the standard licenses.")
112
+ end
113
+ end
114
+ end
115
+
70
116
  #
71
117
  # Creates the top level license file for the project.
72
118
  # Top level file is created at #{project.license_file_path}
@@ -97,10 +143,28 @@ module Omnibus
97
143
  license_files = values[:license_files]
98
144
 
99
145
  license_files.each do |license_file|
100
- if license_file && local?(license_file)
101
- input_file = File.expand_path(license_file, values[:project_dir])
146
+ if license_file
102
147
  output_file = license_package_location(name, license_file)
103
- FileUtils.cp(input_file, output_file) if File.exist?(input_file)
148
+
149
+ if local?(license_file)
150
+ input_file = File.expand_path(license_file, values[:project_dir])
151
+ if File.exist?(input_file)
152
+ FileUtils.cp(input_file, output_file)
153
+ else
154
+ licensing_warning("License file '#{input_file}' does not exist for software '#{name}'.")
155
+ end
156
+ else
157
+ begin
158
+ download_file!(license_file, output_file, enable_progress_bar: false)
159
+ rescue SocketError,
160
+ Errno::ECONNREFUSED,
161
+ Errno::ECONNRESET,
162
+ Errno::ENETUNREACH,
163
+ Timeout::Error,
164
+ OpenURI::HTTPError
165
+ licensing_warning("Can not download license file '#{license_file}' for software '#{name}'.")
166
+ end
167
+ end
104
168
  end
105
169
  end
106
170
  end
@@ -201,7 +265,8 @@ module Omnibus
201
265
  if local?(where)
202
266
  File.join(output_dir, "#{component_name}-#{File.split(where).last}")
203
267
  else
204
- where
268
+ u = URI(where)
269
+ File.join(output_dir, "#{component_name}-#{File.basename(u.path)}")
205
270
  end
206
271
  end
207
272
 
@@ -223,5 +288,108 @@ module Omnibus
223
288
  u = URI(license)
224
289
  return u.scheme.nil?
225
290
  end
291
+
292
+ #
293
+ # Logs the given message as warning.
294
+ #
295
+ # @param [String] message
296
+ # message to log as warning
297
+ def licensing_warning(message)
298
+ log.warn(log_key) { message }
299
+ end
300
+
301
+ STANDARD_LICENSES = [
302
+ #
303
+ # Below licenses are compiled based on https://opensource.org/licenses/alphabetical
304
+ #
305
+ "AFL-3.0", # Academic Free License 3.0
306
+ "AGPL-3.0", # Affero General Public License
307
+ "APL-1.0", # Adaptive Public License
308
+ "Apache-2.0", # Apache License 2.0
309
+ "APSL-2.0", # Apple Public Source License
310
+ "Artistic-2.0", # Artistic license 2.0
311
+ "AAL", # Attribution Assurance Licenses
312
+ "BSD-3-Clause", # BSD 3-Clause "New" or "Revised" License
313
+ "BSD-2-Clause", # BSD 2-Clause "Simplified" or "FreeBSD" License
314
+ "BSL-1.0", # Boost Software License
315
+ "CECILL-2.1", # CeCILL License 2.1
316
+ "CATOSL-1.1", # Computer Associates Trusted Open Source License 1.1
317
+ "CDDL-1.0", # Common Development and Distribution License 1.0
318
+ "CPAL-1.0", # Common Public Attribution License 1.0
319
+ "CUA-OPL-1.0", # CUA Office Public License Version 1.0
320
+ "EUDatagrid", # EU DataGrid Software License
321
+ "EPL-1.0", # Eclipse Public License 1.0
322
+ "eCos-2.0", # eCos License version 2.0
323
+ "ECL-2.0", # Educational Community License, Version 2.0
324
+ "EFL-2.0", # Eiffel Forum License V2.0
325
+ "Entessa", # Entessa Public License
326
+ "EUPL-1.1", # European Union Public License, Version 1.1
327
+ "Fair", # Fair License
328
+ "Frameworx-1.0", # Frameworx License
329
+ "FPL-1.0.0", # Free Public License 1.0.0
330
+ "AGPL-3.0", # GNU Affero General Public License v3
331
+ "GPL-2.0", # GNU General Public License version 2.0
332
+ "GPL-3.0", # GNU General Public License version 3.0
333
+ "LGPL-2.1", # GNU Library or "Lesser" General Public License version 2.1
334
+ "LGPL-3.0", # GNU Library or "Lesser" General Public License version 3.0
335
+ "HPND", # Historical Permission Notice and Disclaimer
336
+ "IPL-1.0", # IBM Public License 1.0
337
+ "IPA", # IPA Font License
338
+ "ISC", # ISC License
339
+ "LPPL-1.3c", # LaTeX Project Public License 1.3c
340
+ "LiLiQ-P", # Licence Libre du Quebec Permissive
341
+ "LiLiQ-R", # Licence Libre du Quebec Reciprocite
342
+ "LiLiQ-R+", # Licence Libre du Quebec Reciprocite forte
343
+ "LPL-1.02", # Lucent Public License Version 1.02
344
+ "MirOS", # MirOS Licence
345
+ "MS-PL", # Microsoft Public License
346
+ "MS-RL", # Microsoft Reciprocal License
347
+ "MIT", # MIT license
348
+ "Motosoto", # Motosoto License
349
+ "MPL-2.0", # Mozilla Public License 2.0
350
+ "Multics", # Multics License
351
+ "NASA-1.3", # NASA Open Source Agreement 1.3
352
+ "NTP", # NTP License
353
+ "Naumen", # Naumen Public License
354
+ "NGPL", # Nethack General Public License
355
+ "Nokia", # Nokia Open Source License
356
+ "NPOSL-3.0", # Non-Profit Open Software License 3.0
357
+ "OCLC-2.0", # OCLC Research Public License 2.0
358
+ "OGTSL", # Open Group Test Suite License
359
+ "OSL-3.0", # Open Software License 3.0
360
+ "OPL-2.1", # OSET Public License version 2.1
361
+ "PHP-3.0", # PHP License 3.0
362
+ "PostgreSQL", # The PostgreSQL License
363
+ "Python-2.0", # Python License
364
+ "CNRI-Python", # CNRI Python license
365
+ "QPL-1.0", # Q Public License
366
+ "RPSL-1.0", # RealNetworks Public Source License V1.0
367
+ "RPL-1.5", # Reciprocal Public License 1.5
368
+ "RSCPL", # Ricoh Source Code Public License
369
+ "OFL-1.1", # SIL Open Font License 1.1
370
+ "SimPL-2.0", # Simple Public License 2.0
371
+ "Sleepycat", # Sleepycat License
372
+ "SPL-1.0", # Sun Public License 1.0
373
+ "Watcom-1.0", # Sybase Open Watcom Public License 1.0
374
+ "NCSA", # University of Illinois/NCSA Open Source License
375
+ "UPL", # Universal Permissive License
376
+ "VSL-1.0", # Vovida Software License v. 1.0
377
+ "W3C", # W3C License
378
+ "WXwindows", # wxWindows Library License
379
+ "Xnet", # X.Net License
380
+ "0BSD", # Zero Clause BSD License
381
+ "ZPL-2.0", # Zope Public License 2.0
382
+ "Zlib", # zlib/libpng license
383
+ #
384
+ # In addition to these we would like to add some of the licenses that
385
+ # are frequently used in our depedencies.
386
+ #
387
+ "Public-Domain", # https://opensource.org/faq#public-domain
388
+ "Ruby", # http://www.ruby-lang.org/en/LICENSE.txt
389
+ "Erlang-Public", # http://www.erlang.org/EPLICENSE
390
+ "Oracle-Binary", # http://www.oracle.com/technetwork/java/javase/terms/license/index.html
391
+ "OpenSSL", # https://www.openssl.org/source/license.html
392
+ "Chef-MLSA", # https://www.chef.io/online-master-agreement/
393
+ ].freeze
226
394
  end
227
395
  end
@@ -36,6 +36,7 @@ module Omnibus
36
36
  PLATFORM_PACKAGER_MAP = {
37
37
  'debian' => DEB,
38
38
  'fedora' => RPM,
39
+ 'suse' => RPM,
39
40
  'rhel' => RPM,
40
41
  'wrlinux' => RPM,
41
42
  'aix' => BFF,
@@ -131,8 +131,14 @@ module Omnibus
131
131
  def write_gen_template
132
132
 
133
133
  # Get a list of all files
134
- files = FileSyncer.glob("#{staging_dir}/**/*").map do |path|
135
-
134
+ files = FileSyncer.glob("#{staging_dir}/**/*").reject do |path|
135
+ # remove any files with spaces.
136
+ if path =~ /[[:space:]]/
137
+ log.warn(log_key) { "Skipping packaging '#{path}' file due to whitespace in filename" }
138
+ true
139
+ end
140
+ end
141
+ files.map! do |path|
136
142
  # If paths have colons or commas, rename them and add them to a post-install,
137
143
  # post-sysck renaming script ('config') which is created if needed
138
144
  if path.match(/:|,/)