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.
- checksums.yaml +5 -5
- data/Contributing.md +3 -3
- data/History.md +105 -66
- data/Manifest.txt +1 -0
- data/README.rdoc +15 -5
- data/Rakefile +52 -37
- data/lib/cartage/backport.rb +3 -3
- data/lib/cartage/cli.rb +76 -76
- data/lib/cartage/commands/echo.rb +6 -6
- data/lib/cartage/commands/info.rb +17 -17
- data/lib/cartage/commands/manifest.rb +46 -46
- data/lib/cartage/commands/metadata.rb +10 -0
- data/lib/cartage/commands/pack.rb +6 -6
- data/lib/cartage/config.rb +27 -25
- data/lib/cartage/core.rb +18 -18
- data/lib/cartage/gli_ext.rb +10 -10
- data/lib/cartage/minitest.rb +7 -7
- data/lib/cartage/plugin.rb +14 -10
- data/lib/cartage/plugins/build_tarball.rb +2 -2
- data/lib/cartage/plugins/manifest.rb +85 -85
- data/lib/cartage.rb +138 -67
- data/test/minitest_config.rb +8 -8
- data/test/test_cartage.rb +130 -130
- data/test/test_cartage_build_tarball.rb +22 -22
- data/test/test_cartage_config.rb +27 -27
- data/test/test_cartage_core.rb +36 -36
- data/test/test_cartage_manifest.rb +51 -53
- data/test/test_cartage_plugin.rb +21 -21
- metadata +52 -26
data/lib/cartage.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "pathname"
|
4
|
+
require "json"
|
5
5
|
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
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 =
|
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,
|
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(
|
47
|
+
Pathname(`git rev-parse --show-cdup`.chomp).expand_path
|
48
48
|
end
|
49
49
|
|
50
50
|
##
|
51
|
-
def root_path=(v)
|
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(
|
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(
|
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)
|
100
|
+
def compression=(value) # :nodoc:
|
101
101
|
case value
|
102
|
-
when :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)
|
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,
|
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,
|
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:
|
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 ||=
|
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 =
|
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(
|
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 + [
|
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(
|
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,
|
281
|
-
|
282
|
-
when :gzip,
|
283
|
-
|
284
|
-
when :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,
|
293
|
-
|
294
|
-
when :gzip,
|
295
|
-
|
296
|
-
when :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
|
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
|
-
|
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
|
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
|
-
|
441
|
+
"tar", "cf", "-", "-C", parent, "-h", "-T", file_list
|
366
442
|
].map(&:to_s)
|
367
443
|
|
368
444
|
tar_xf_cmd = [
|
369
|
-
|
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,
|
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(
|
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(
|
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
|
-
|
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
|
-
|
475
|
+
"git", "show", "#{release_hashref}:#{filename}"
|
405
476
|
]
|
406
477
|
|
407
478
|
IO.popen(command) do |show|
|
408
|
-
work_path.join(filename).open(
|
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
|
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
|
-
|
503
|
+
"tar",
|
433
504
|
"cf#{tar_compression_flag}",
|
434
505
|
dependency_cache,
|
435
|
-
|
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
|
530
|
+
require_relative "cartage/config"
|
data/test/minitest_config.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
gem
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
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
|
11
|
+
require "cartage/minitest"
|