cartage 2.0 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/cartage.rb CHANGED
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pathname'
4
- require 'json'
3
+ require "pathname"
4
+ require "json"
5
5
 
6
- require 'cartage/core'
7
- require 'cartage/plugin'
8
- require 'cartage/config'
6
+ require "cartage/core"
7
+ require "cartage/plugin"
8
+ require "cartage/config"
9
9
 
10
10
  ##
11
11
  # Cartage, a reliable package builder.
12
12
  class Cartage
13
- VERSION = '2.0' #:nodoc:
13
+ VERSION = "2.2.1" # :nodoc:
14
14
 
15
15
  # Creates a new Cartage instance. If provided a Cartage::Config object in
16
16
  # +config+, sets the configuration and resolves it. If +config+ is not
@@ -30,7 +30,7 @@ class Cartage
30
30
  # The default name of the package to be created, derived from the
31
31
  # repository's Git URL.
32
32
 
33
- attr_accessor_with_default :name, default: -> { File.basename(repo_url, '.git') }
33
+ attr_accessor_with_default :name, default: -> { File.basename(repo_url, ".git") }
34
34
 
35
35
  ##
36
36
  # :attr_accessor: root_path
@@ -44,11 +44,11 @@ class Cartage
44
44
  # repository.
45
45
 
46
46
  attr_reader_with_default :root_path do
47
- Pathname(%x(git rev-parse --show-cdup).chomp).expand_path
47
+ Pathname(`git rev-parse --show-cdup`.chomp).expand_path
48
48
  end
49
49
 
50
50
  ##
51
- def root_path=(v) #:nodoc:
51
+ def root_path=(v) # :nodoc:
52
52
  reset_computed_values
53
53
  @root_path = Pathname(v).expand_path
54
54
  end
@@ -65,7 +65,7 @@ class Cartage
65
65
 
66
66
  attr_accessor_with_default :target,
67
67
  transform: ->(v) { Pathname(v) },
68
- default: -> { Pathname('tmp') }
68
+ default: -> { Pathname("tmp") }
69
69
 
70
70
  ##
71
71
  # :attr_accessor: timestamp
@@ -78,7 +78,7 @@ class Cartage
78
78
  # The default timestamp.
79
79
 
80
80
  attr_accessor_with_default :timestamp, default: -> {
81
- Time.now.utc.strftime('%Y%m%d%H%M%S')
81
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
82
82
  }
83
83
 
84
84
  ##
@@ -97,9 +97,9 @@ class Cartage
97
97
  end
98
98
 
99
99
  ##
100
- def compression=(value) #:nodoc:
100
+ def compression=(value) # :nodoc:
101
101
  case value
102
- when :bzip2, :none, :gzip, 'bzip2', 'none', 'gzip'
102
+ when :bzip2, :none, :gzip, "bzip2", "none", "gzip"
103
103
  @compression = value
104
104
  reset_computed_values
105
105
  else
@@ -142,10 +142,10 @@ class Cartage
142
142
  end
143
143
 
144
144
  ##
145
- def dependency_cache_path=(path) #:nodoc:
145
+ def dependency_cache_path=(path) # :nodoc:
146
146
  @dependency_cache_path = Pathname(path || tmp_path).expand_path
147
- @dependency_cache = @dependency_cache_path.
148
- join("dependency-cache.tar#{tar_compression_extension}")
147
+ @dependency_cache = @dependency_cache_path
148
+ .join("dependency-cache.tar#{tar_compression_extension}")
149
149
  end
150
150
 
151
151
  # Commands that normally output data will have that output suppressed.
@@ -159,7 +159,7 @@ class Cartage
159
159
  # by providing the +for_plugin+ or +for_command+ parameters.
160
160
  def config(for_plugin: nil, for_command: nil)
161
161
  if for_plugin && for_command
162
- fail ArgumentError, 'Cannot get config for plug-in and command together'
162
+ fail ArgumentError, "Cannot get config for plug-in and command together"
163
163
  elsif for_plugin
164
164
  @config.dig(:plugins, for_plugin.to_sym) || OpenStruct.new
165
165
  elsif for_command
@@ -171,7 +171,7 @@ class Cartage
171
171
 
172
172
  # The config file. This should not be used by clients.
173
173
  def config=(cfg) # :nodoc:
174
- fail ArgumentError, 'No config provided' unless cfg
174
+ fail ArgumentError, "No config provided" unless cfg
175
175
  @plugins = Plugins.new
176
176
  @config = cfg
177
177
  resolve_config!
@@ -183,7 +183,7 @@ class Cartage
183
183
  package: {
184
184
  name: name,
185
185
  repo: {
186
- type: 'git', # Hardcoded until we have other support
186
+ type: "git", # Hardcoded until we have other support
187
187
  url: repo_url
188
188
  },
189
189
  hashref: release_hashref,
@@ -194,21 +194,21 @@ class Cartage
194
194
 
195
195
  # Return the release hashref.
196
196
  def release_hashref
197
- @release_hashref ||= %x(git rev-parse HEAD).chomp
197
+ @release_hashref ||= `git rev-parse HEAD`.chomp
198
198
  end
199
199
 
200
200
  # The repository URL.
201
201
  def repo_url
202
202
  unless defined? @repo_url
203
- @repo_url = %x(git remote show -n origin).
204
- match(/\n\s+Fetch URL: (?<fetch>[^\n]+)/)[:fetch]
203
+ @repo_url = `git remote show -n origin`
204
+ .match(/\n\s+Fetch URL: (?<fetch>[^\n]+)/)[:fetch]
205
205
  end
206
206
  @repo_url
207
207
  end
208
208
 
209
209
  # The temporary path.
210
210
  def tmp_path
211
- @tmp_path ||= root_path.join('tmp')
211
+ @tmp_path ||= root_path.join("tmp")
212
212
  end
213
213
 
214
214
  # The working path for the job, in #tmp_path.
@@ -236,13 +236,13 @@ class Cartage
236
236
  # A utility method for Cartage plug-ins to run a +command+ in the shell. Uses
237
237
  # IO.popen.
238
238
  def run(command)
239
- display command.join(' ')
239
+ display command.join(" ")
240
240
 
241
- IO.popen(command + [ err: %i(child out) ]) do |io|
241
+ IO.popen(command + [err: %i[child out]]) do |io|
242
242
  __display(io.read(128), partial: true, verbose: true) until io.eof?
243
243
  end
244
244
 
245
- fail StandardError, "Error running '#{command.join(' ')}'" unless $?.success?
245
+ fail StandardError, "Error running '#{command.join(" ")}'" unless $?.success?
246
246
  end
247
247
 
248
248
  # Returns the registered plug-ins, once configuration has been resolved.
@@ -274,38 +274,108 @@ class Cartage
274
274
  request_build_package
275
275
  end
276
276
 
277
+ # Just save the release metadata.
278
+ def save_release_metadata(local: false)
279
+ display "Saving release metadata..."
280
+ json = JSON.generate(release_metadata)
281
+
282
+ if local
283
+ Pathname(".").join("release-metadata.json").write(json)
284
+ else
285
+ work_path.join("release-metadata.json").write(json)
286
+ final_release_metadata_json.write(json)
287
+ end
288
+ end
289
+
277
290
  # Returns the flag to use with +tar+ given the value of +compression+.
278
291
  def tar_compression_flag
279
292
  case compression
280
- when :bzip2, 'bzip2', nil
281
- 'j'
282
- when :gzip, 'gzip'
283
- 'z'
284
- when :none, 'none'
285
- ''
293
+ when :bzip2, "bzip2", nil
294
+ "j"
295
+ when :gzip, "gzip"
296
+ "z"
297
+ when :none, "none"
298
+ ""
286
299
  end
287
300
  end
288
301
 
289
302
  # Returns the extension to use with +tar+ given the value of +compression+.
290
303
  def tar_compression_extension
291
304
  case compression
292
- when :bzip2, 'bzip2', nil
293
- '.bz2'
294
- when :gzip, 'gzip'
295
- '.gz'
296
- when :none, 'none'
297
- ''
305
+ when :bzip2, "bzip2", nil
306
+ ".bz2"
307
+ when :gzip, "gzip"
308
+ ".gz"
309
+ when :none, "none"
310
+ ""
298
311
  end
299
312
  end
300
313
 
314
+ # Recursively copy a provided +path+ to the #work_path, using a tar pipeline.
315
+ # The target location can be amended by the use of the +to+ parameter as a
316
+ # relative path to #work_path.
317
+ #
318
+ # If a relative +path+ is provided, it will be treated as relative to
319
+ # #root_path, and it will be used unmodified for writing to the target
320
+ # location. If an absolute path is provided, only the last part of the path
321
+ # will be used as the target name.
322
+ #
323
+ # An error will be raised if either +path+ or +to+ contains a parent-relative
324
+ # reference (<tt>../</tt>), or if the tar pipeline fails.
325
+ #
326
+ # === Examples
327
+ #
328
+ # cartage.recursive_copy('public/assets')
329
+ #
330
+ # This will cause <tt><em>root_path</em>/public/assets</tt> to be copied into
331
+ # <tt><em>work_path</em>/public/assets</tt>.
332
+ #
333
+ # cartage.recursive_copy('/tmp/public/assets')
334
+ #
335
+ # This will cause <tt>/tmp/public/assets</tt> to be copied into
336
+ # <tt><em>work_path</em>/assets</tt>.
337
+ #
338
+ # cartage.recursive_copy('/tmp/public/assets', to: 'public')
339
+ #
340
+ # This will cause <tt>/tmp/public/assets</tt> to be copied into
341
+ # <tt><em>work_path</em>/public/assets</tt>.
342
+ def recursive_copy(path, to: nil)
343
+ path = Pathname(path)
344
+ to = Pathname(to) if to
345
+
346
+ if path.to_s =~ %r{\.\./} || (to && to.to_s =~ %r{\.\./})
347
+ fail StandardError, "Recursive copy parameters cannot contain '/../'"
348
+ end
349
+
350
+ if path.relative?
351
+ parent = root_path
352
+ else
353
+ parent, path = path.split
354
+ end
355
+
356
+ target = work_path
357
+ target /= to if to
358
+
359
+ tar_cf_cmd = ["tar", "cf", "-", "-h", "-C", parent, path].map(&:to_s)
360
+ tar_xf_cmd = ["tar", "xf", "-", "-C", target].map(&:to_s)
361
+
362
+ IO.popen(tar_cf_cmd) do |cf|
363
+ IO.popen(tar_xf_cmd, "w") do |xf|
364
+ xf.write cf.read
365
+ end
366
+
367
+ fail StandardError, "Error running #{tar_xf_cmd.join(" ")}" unless $?.success?
368
+ end
369
+
370
+ fail StandardError, "Error running #{tar_cf_cmd.join(" ")}" unless $?.success?
371
+ end
372
+
301
373
  private
302
374
 
303
375
  attr_writer :release_hashref
304
376
 
305
377
  def resolve_config!
306
- fail 'No configuration' unless config
307
-
308
- Cartage::Plugin.load_for(singleton_class)
378
+ fail "No configuration" unless config
309
379
 
310
380
  self.disable_dependency_cache = config.disable_dependency_cache
311
381
  self.quiet = config.quiet
@@ -318,6 +388,12 @@ class Cartage
318
388
  maybe_assign :dependency_cache_path, config.dependency_cache_path
319
389
  maybe_assign :release_hashref, config.release_hashref
320
390
 
391
+ lib = root_path.join("lib").to_s
392
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.any? { |l| l == lib }
393
+ Cartage::Plugin.load(rescan: true)
394
+
395
+ Cartage::Plugin.load_for(singleton_class)
396
+
321
397
  Cartage::Plugin.each do |name|
322
398
  next unless respond_to?(name)
323
399
  plugin = send(name) or next
@@ -331,7 +407,7 @@ class Cartage
331
407
 
332
408
  def maybe_assign(name, value)
333
409
  return if value.nil? || (value.respond_to?(:empty?) && value.empty?) ||
334
- instance_variable_defined?(:"@#{name}")
410
+ instance_variable_defined?(:"@#{name}")
335
411
  send(:"#{name}=", value)
336
412
  end
337
413
 
@@ -355,57 +431,52 @@ class Cartage
355
431
  end
356
432
 
357
433
  def prepare_work_area
358
- display 'Preparing cartage work area...'
434
+ display "Preparing cartage work area..."
359
435
 
360
436
  work_path.rmtree if work_path.exist?
361
437
  work_path.mkpath
362
438
 
363
439
  manifest.resolve(root_path) do |file_list|
364
440
  tar_cf_cmd = [
365
- 'tar', 'cf', '-', '-C', parent, '-h', '-T', file_list
441
+ "tar", "cf", "-", "-C", parent, "-h", "-T", file_list
366
442
  ].map(&:to_s)
367
443
 
368
444
  tar_xf_cmd = [
369
- 'tar', 'xf', '-', '-C', work_path, '--strip-components=1'
445
+ "tar", "xf", "-", "-C", work_path, "--strip-components=1"
370
446
  ].map(&:to_s)
371
447
 
372
448
  IO.popen(tar_cf_cmd) do |cf|
373
- IO.popen(tar_xf_cmd, 'w') do |xf|
449
+ IO.popen(tar_xf_cmd, "w") do |xf|
374
450
  xf.write cf.read
375
451
  end
376
452
 
377
- fail StandardError, "Error running #{tar_xf_cmd.join(' ')}" unless $?.success?
453
+ fail StandardError, "Error running #{tar_xf_cmd.join(" ")}" unless $?.success?
378
454
  end
379
455
 
380
- fail StandardError, "Error running #{tar_cf_cmd.join(' ')}" unless $?.success?
456
+ fail StandardError, "Error running #{tar_cf_cmd.join(" ")}" unless $?.success?
381
457
  end
382
458
  end
383
459
 
384
- def save_release_metadata
385
- display 'Saving release metadata...'
386
- json = JSON.generate(release_metadata)
387
- work_path.join('release-metadata.json').write(json)
388
- final_release_metadata_json.write(json)
389
- end
390
-
391
460
  def restore_modified_files
392
- %x(git status -s).
393
- split($/).
394
- map(&:split).
395
- select { |s, _f| s !~ /\?/ }.
396
- map(&:last).
397
- each { |file|
461
+ `git status -s`
462
+ .split($/)
463
+ .map(&:split)
464
+ .select { |s, _f| s !~ /\?/ }
465
+ .map(&:last)
466
+ .each { |file|
398
467
  restore_modified_file file
399
468
  }
400
469
  end
401
470
 
402
471
  def restore_modified_file(filename)
472
+ return unless work_path.join(filename).exist?
473
+
403
474
  command = [
404
- 'git', 'show', "#{release_hashref}:#{filename}"
475
+ "git", "show", "#{release_hashref}:#{filename}"
405
476
  ]
406
477
 
407
478
  IO.popen(command) do |show|
408
- work_path.join(filename).open('w') { |f|
479
+ work_path.join(filename).open("w") { |f|
409
480
  f.puts show.read
410
481
  }
411
482
  end
@@ -423,16 +494,16 @@ class Cartage
423
494
 
424
495
  def extract_dependency_cache
425
496
  return if disable_dependency_cache || !dependency_cache.exist?
426
- run %W(tar xf#{tar_compression_flag} #{dependency_cache} -C #{work_path})
497
+ run %W[tar xf#{tar_compression_flag} #{dependency_cache} -C #{work_path}]
427
498
  end
428
499
 
429
500
  def create_dependency_cache(paths = [])
430
501
  return if disable_dependency_cache || paths.empty?
431
502
  run [
432
- 'tar',
503
+ "tar",
433
504
  "cf#{tar_compression_flag}",
434
505
  dependency_cache,
435
- '-C',
506
+ "-C",
436
507
  work_path,
437
508
  *paths
438
509
  ].map(&:to_s)
@@ -456,4 +527,4 @@ class Cartage
456
527
  end
457
528
  end
458
529
 
459
- require_relative 'cartage/config'
530
+ require_relative "cartage/config"
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- gem 'minitest'
4
- require 'minitest/autorun'
5
- require 'minitest/pretty_diff'
6
- require 'minitest/focus'
7
- require 'minitest/moar'
8
- require 'minitest/bisect'
9
- require 'minitest-bonus-assertions'
3
+ gem "minitest"
4
+ require "minitest/autorun"
5
+ require "minitest/pretty_diff"
6
+ require "minitest/focus"
7
+ require "minitest/moar"
8
+ require "minitest/bisect"
9
+ require "minitest-bonus-assertions"
10
10
 
11
- require 'cartage/minitest'
11
+ require "cartage/minitest"