cartage 2.0 → 2.2.1

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.
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"