cartage 1.2 → 2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest_config'
4
+
5
+ describe 'Cartage::BuildTarball' do
6
+ let(:config) {
7
+ Cartage::Config.new(
8
+ root_path: '/a/b/c',
9
+ name: 'test',
10
+ timestamp: 'value'
11
+ )
12
+ }
13
+ let(:cartage) {
14
+ Cartage.new(config)
15
+ }
16
+ let(:subject) { cartage.build_tarball }
17
+
18
+ it '#build_package requests :pre_build_tarball and :post_build_tarball' do
19
+ requests = %i(pre_build_tarball post_build_tarball)
20
+
21
+ verify_request = ->(f) { assert_equal requests.shift, f }
22
+ verify_run = ->(c) {
23
+ assert_equal [
24
+ 'tar',
25
+ 'cfj',
26
+ '/a/b/c/tmp/test-value.tar.bz2',
27
+ '-C',
28
+ '/a/b/c/tmp',
29
+ 'test'
30
+ ], c
31
+ }
32
+
33
+ instance_stub Cartage::Plugins, :request, verify_request do
34
+ instance_stub Cartage, :run, verify_run do
35
+ subject.build_package
36
+ end
37
+ end
38
+
39
+ assert_empty requests
40
+ end
41
+
42
+ describe '#package_name is dependent on Cartage configuration' do
43
+ it 'is .tar.bz2 when compression is :bzip2' do
44
+ assert_equal Pathname('/a/b/c/tmp/test-value.tar.bz2'), subject.package_name
45
+ end
46
+
47
+ it 'is .tar when compression is :none' do
48
+ cartage.compression = 'none'
49
+ assert_equal Pathname('/a/b/c/tmp/test-value.tar'), subject.package_name
50
+ end
51
+
52
+ it 'is .tar.gz when compression is :gzip' do
53
+ cartage.compression = 'gzip'
54
+ assert_equal Pathname('/a/b/c/tmp/test-value.tar.gz'), subject.package_name
55
+ end
56
+ end
57
+ end
@@ -1,47 +1,119 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'minitest_config'
2
4
  require 'cartage/config'
3
5
 
4
6
  describe Cartage::Config do
5
- before do
6
- @data = {
7
- "x" => 1,
8
- "arr" => %w(a b c),
9
- "plugins" => {
10
- "test" => {
11
- "x" => 2
12
- }
13
- },
14
- "development" => {
15
- "x" => 3,
16
- "plugins" => {
17
- "test" => OpenStruct.new("x" => 4)
7
+ let(:data) {
8
+ {
9
+ 'x' => 1,
10
+ 'arr' => %w(a b c),
11
+ 'commands' => {},
12
+ 'plugins' => {
13
+ 'test' => {
14
+ 'x' => 2
18
15
  }
19
16
  }
20
17
  }
18
+ }
19
+ let(:odata) { Cartage::Config.send(:ostructify, data) }
20
+ let(:config) { Cartage::Config.new(odata) }
21
+ let(:hdata) { Marshal.load(Marshal.dump(data)) }
22
+
23
+ describe 'load' do
24
+ def watch_pathname_exist
25
+ mpname = Pathname.singleton_class
26
+ mpname.send(:define_method, :exist_tries, -> { @exist_tries ||= [] })
27
+
28
+ Pathname.send(:alias_method, :__stub_exist__?, :exist?)
29
+ Pathname.send(:define_method, :exist?, -> { !(self.class.exist_tries << to_s) })
30
+
31
+ yield
32
+ ensure
33
+ mpname.send(:undef_method, :exist_tries)
34
+ Pathname.send(:undef_method, :exist?)
35
+ Pathname.send(:alias_method, :exist?, :__stub_exist__?)
36
+ Pathname.send(:undef_method, :__stub_exist__?)
37
+ end
38
+
39
+ def ignore_pathname_expand_path
40
+ Pathname.send(:alias_method, :__stub_expand_path__, :expand_path)
41
+ Pathname.send(:define_method, :expand_path, -> { self })
42
+
43
+ yield
44
+ ensure
45
+ Pathname.send(:undef_method, :expand_path)
46
+ Pathname.send(:alias_method, :expand_path, :__stub_expand_path__)
47
+ Pathname.send(:undef_method, :__stub_expand_path__)
48
+ end
49
+
50
+ it 'looks for default files when given :default' do
51
+ watch_pathname_exist do
52
+ ignore_pathname_expand_path do
53
+ Cartage::Config.load(:default)
54
+ assert_equal Cartage::Config::DEFAULT_CONFIG_FILES, Pathname.exist_tries
55
+ end
56
+ end
57
+ end
21
58
 
22
- @odata = Cartage::Config.send(:ostructify, @data)
23
- @config = Cartage::Config.new(@odata)
24
- @hdata = Marshal.load(Marshal.dump(@data))
25
- @hdata['development']['plugins']['test'] = { "x" => 4 }
59
+ it 'fails if the file does not exist' do
60
+ instance_stub Pathname, :exist?, -> { false } do
61
+ assert_raises_with_message ArgumentError,
62
+ 'Configuration file foo does not exist.' do
63
+ Cartage::Config.load('foo')
64
+ end
65
+ end
66
+ end
67
+
68
+ it 'loads the file if it exists' do
69
+ instance_stub Pathname, :read, -> { '{ faked: true }' } do
70
+ instance_stub Pathname, :exist?, -> { true } do
71
+ expected = {
72
+ faked: true,
73
+ commands: OpenStruct.new,
74
+ plugins: OpenStruct.new
75
+ }
76
+ assert_equal expected,
77
+ Cartage::Config.load('foo').instance_variable_get(:@table)
78
+ end
79
+ end
80
+ end
81
+
82
+ it 'uses a default configuration if there is no default config file' do
83
+ expected = {
84
+ commands: OpenStruct.new,
85
+ plugins: OpenStruct.new
86
+ }
87
+ assert_equal expected,
88
+ Cartage::Config.load(:default).instance_variable_get(:@table)
89
+ end
26
90
  end
27
91
 
28
- describe '#ostructify (private)' do
29
- it 'converts hash structures correctly' do
30
- expected = OpenStruct.new(x: 1)
31
- expected.arr = %w(a b c)
32
- expected.plugins = OpenStruct.new
33
- expected.plugins.test = OpenStruct.new(x: 2)
34
- expected.development = OpenStruct.new(x: 3)
35
- expected.development.plugins = OpenStruct.new
36
- expected.development.plugins.test = OpenStruct.new(x: 4)
92
+ describe 'import' do
93
+ it 'reads a file if it exists' do
94
+ stub File, :exist?, ->(_) { true } do
95
+ stub File, :read, ->(_) { 'faked' } do
96
+ assert_equal 'faked', Cartage::Config.import('foo')
97
+ end
98
+ end
99
+ end
37
100
 
38
- assert_equal expected, @odata
101
+ it 'returns nil if the file does not exist' do
102
+ stub File, :exist?, ->(_) { false } do
103
+ assert_nil Cartage::Config.import('foo')
104
+ end
39
105
  end
40
106
  end
41
107
 
42
108
  describe '#to_h' do
43
109
  it 'completely converts a Config object to hash' do
44
- assert_equal @hdata, @config.to_h
110
+ assert_equal hdata, config.to_h
111
+ end
112
+ end
113
+
114
+ describe '#to_yaml' do
115
+ it 'overrides the OpenStruct implementation' do
116
+ assert_equal hdata.to_yaml, config.to_yaml
45
117
  end
46
118
  end
47
119
  end
@@ -0,0 +1,172 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest_config'
4
+
5
+ describe Cartage::Core do
6
+ let(:subject) {
7
+ Class.new.tap do |klass|
8
+ klass.class_eval do
9
+ extend Cartage::Core
10
+
11
+ class << self
12
+ public :attr_reader_with_default
13
+ public :attr_writer_with_transform
14
+ public :attr_accessor_with_default
15
+ end
16
+ end
17
+ end
18
+ }
19
+ let(:object) { subject.new }
20
+
21
+ describe 'attr_reader_with_default' do
22
+ it 'fails without a default' do
23
+ assert_raises_with_message ArgumentError, 'No default provided.' do
24
+ subject.attr_reader_with_default :answer
25
+ end
26
+ end
27
+
28
+ it 'fails with too many defaults' do
29
+ assert_raises_with_message ArgumentError, 'Too many defaults provided.' do
30
+ subject.attr_reader_with_default :answer, 42, &-> { 42 }
31
+ end
32
+ end
33
+
34
+ it 'defines default and reader methods when given a value' do
35
+ subject.attr_reader_with_default :answer, 42
36
+ assert_respond_to object, :answer
37
+ assert_equal 42, object.answer
38
+
39
+ assert_respond_to object, :default_answer
40
+ assert_equal 42, object.default_answer
41
+ end
42
+
43
+ it 'defines default and reader methods when given a block' do
44
+ subject.attr_reader_with_default :answer do
45
+ 42
46
+ end
47
+
48
+ assert_respond_to object, :answer
49
+ assert_equal 42, object.answer
50
+
51
+ assert_respond_to object, :default_answer
52
+ assert_equal 42, object.default_answer
53
+ end
54
+
55
+ it 'memoizes the default value' do
56
+ subject.attr_reader_with_default :favourite_colour, 'blue'
57
+ assert_same object.default_favourite_colour, object.default_favourite_colour
58
+ end
59
+ end
60
+
61
+ describe 'attr_writer_with_transform' do
62
+ it 'fails without a transform' do
63
+ assert_raises_with_message ArgumentError, 'No transform provided.' do
64
+ subject.attr_writer_with_transform :answer
65
+ end
66
+ end
67
+
68
+ it 'fails with too many transforms' do
69
+ assert_raises_with_message ArgumentError, 'Too many transforms provided.' do
70
+ subject.attr_writer_with_transform :answer, 42, &-> { 42 }
71
+ end
72
+ end
73
+
74
+ it 'fails if the transform is not callable' do
75
+ assert_raises_with_message ArgumentError, 'Transform is not callable.' do
76
+ subject.attr_writer_with_transform :answer, 42
77
+ end
78
+ end
79
+
80
+ it 'defines a writer method when given a symbol' do
81
+ subject.attr_writer_with_transform :answer, :to_s
82
+ assert_respond_to object, :answer=
83
+ object.answer = 42
84
+ assert_equal '42', object.instance_variable_get(:"@answer")
85
+ end
86
+
87
+ it 'defines a writer method when given a callable' do
88
+ subject.attr_writer_with_transform :answer, ->(v) { v.to_s }
89
+ assert_respond_to object, :answer=
90
+ object.answer = 42
91
+ assert_equal '42', object.instance_variable_get(:"@answer")
92
+ end
93
+
94
+ it 'defines a writer method when given a block' do
95
+ subject.attr_writer_with_transform :answer do |v|
96
+ String(v)
97
+ end
98
+ assert_respond_to object, :answer=
99
+ object.answer = 42
100
+ assert_equal '42', object.instance_variable_get(:"@answer")
101
+ end
102
+ end
103
+
104
+ describe 'attr_accessor_with_default' do
105
+ it 'fails without a default' do
106
+ assert_raises_with_message ArgumentError, 'No default provided.' do
107
+ subject.attr_accessor_with_default :answer
108
+ end
109
+ end
110
+
111
+ it 'defines a default, reader, and writer methods when given a value' do
112
+ subject.attr_accessor_with_default :answer, default: 42
113
+
114
+ assert_respond_to object, :answer
115
+ assert_respond_to object, :default_answer
116
+ assert_respond_to object, :answer=
117
+
118
+ object.answer = 21
119
+ assert_equal 21, object.answer
120
+ assert_equal 42, object.default_answer
121
+ end
122
+
123
+ it 'defines a default, reader, and writer methods when given a block' do
124
+ subject.attr_accessor_with_default :answer do
125
+ 42
126
+ end
127
+
128
+ assert_respond_to object, :answer
129
+ assert_respond_to object, :default_answer
130
+ assert_respond_to object, :answer=
131
+
132
+ object.answer = 21
133
+ assert_equal 21, object.answer
134
+ assert_equal 42, object.default_answer
135
+ end
136
+
137
+ it 'memoizes the default value' do
138
+ subject.attr_accessor_with_default :favourite_colour, default: 'blue'
139
+ assert_same object.favourite_colour, object.favourite_colour
140
+ end
141
+
142
+ it 'fails if transform is not callable' do
143
+ assert_raises_with_message ArgumentError, 'Transform is not callable.' do
144
+ subject.attr_accessor_with_default :answer, default: 42, transform: 42
145
+ end
146
+ end
147
+
148
+ it 'accepts a symbol for transform' do
149
+ subject.attr_accessor_with_default :answer, default: 42, transform: :to_s
150
+
151
+ assert_respond_to object, :answer
152
+ assert_respond_to object, :default_answer
153
+ assert_respond_to object, :answer=
154
+
155
+ assert_equal 42, object.answer
156
+ object.answer = 21
157
+ assert_equal '21', object.answer
158
+ end
159
+
160
+ it 'accepts a callable for transform' do
161
+ subject.attr_accessor_with_default :answer,
162
+ default: 42, transform: ->(v) { v.to_s }
163
+ assert_respond_to object, :answer
164
+ assert_respond_to object, :default_answer
165
+ assert_respond_to object, :answer=
166
+
167
+ assert_equal 42, object.answer
168
+ object.answer = 21
169
+ assert_equal '21', object.answer
170
+ end
171
+ end
172
+ end
@@ -1,22 +1,243 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'minitest_config'
2
- require 'cartage/plugin'
3
- require 'cartage/command'
4
- require 'cartage/manifest'
5
4
 
6
- describe Cartage::Manifest do
5
+ describe 'Cartage::Manifest' do
6
+ let(:cartage) { Cartage.new }
7
+ let(:manifest) { cartage.manifest }
8
+ let(:manifest_contents) { %w(bin/build bin/cartage lib/cartage.rb spec/cartage.rb) }
9
+ let(:expected_tmpfile) { %W(foo/bin/build\n foo/bin/cartage\n foo/lib/cartage.rb\n) }
10
+
7
11
  before do
8
- @cartage = Cartage.new
9
- @manifest = Cartage::Manifest.new(@cartage)
12
+ cartage
13
+ end
14
+
15
+ def stub_slugignore_file(exists: true, contents: nil)
16
+ ignore_file = manifest.send(:slugignore_file)
17
+ stub ignore_file, :exist?, -> { exists } do
18
+ if contents
19
+ stub ignore_file, :readlines, -> { contents } do
20
+ yield
21
+ end
22
+ else
23
+ yield
24
+ end
25
+ end
26
+ end
27
+
28
+ def stub_ignore_file(exists: true, contents: nil)
29
+ ignore_file = manifest.send(:ignore_file)
30
+ stub ignore_file, :exist?, -> { exists } do
31
+ if contents
32
+ stub ignore_file, :readlines, -> { contents } do
33
+ yield ignore_file
34
+ end
35
+ else
36
+ yield ignore_file
37
+ end
38
+ end
39
+ end
40
+
41
+ def stub_manifest_file(exists: true, contents: nil)
42
+ manifest_file = manifest.send(:manifest_file)
43
+ stub manifest_file, :exist?, -> { exists } do
44
+ if contents
45
+ stub manifest_file, :readlines, -> { contents } do
46
+ yield
47
+ end
48
+ else
49
+ yield
50
+ end
51
+ end
52
+ end
53
+
54
+ describe '#resolve' do
55
+ it 'fails if there is no manifest_file' do
56
+ stub_manifest_file exists: false do
57
+ ex = assert_raises Cartage::Manifest::MissingError do
58
+ manifest.resolve
59
+ end
60
+ assert_match(/cannot create/, ex.message)
61
+ end
62
+ end
63
+
64
+ it 'fails if there is no block given' do
65
+ stub_manifest_file do
66
+ assert_raises_with_message ArgumentError, 'A block is required.' do
67
+ manifest.resolve
68
+ end
69
+ end
70
+ end
71
+
72
+ it 'fails if the manifest is empty' do
73
+ stub_manifest_file contents: [] do
74
+ assert_raises_with_message RuntimeError, 'Manifest.txt is empty.' do
75
+ manifest.resolve {}
76
+ end
77
+ end
78
+ end
79
+
80
+ it 'yields the name of a tempfile with the manifest contents' do
81
+ stub_ignore_file contents: [] do
82
+ stub_manifest_file contents: manifest_contents do
83
+ manifest.resolve(Pathname('foo')) { |name|
84
+ assert_match(/Manifest\./, name)
85
+ assert_equal (expected_tmpfile << "foo/spec/cartage.rb\n"),
86
+ Pathname(name).readlines
87
+ }
88
+ end
89
+ end
90
+ end
91
+
92
+ it 'prunes out ignored files from a specified cartignore' do
93
+ stub_ignore_file contents: %w(spec/) do
94
+ stub_manifest_file contents: manifest_contents do
95
+ manifest.resolve(Pathname('foo')) { |name|
96
+ assert_equal expected_tmpfile, Pathname(name).readlines
97
+ }
98
+ end
99
+ end
100
+ end
101
+
102
+ it 'prunes out ignored files from a specified slugignore' do
103
+ stub_ignore_file exists: false do
104
+ stub_slugignore_file contents: %w(spec/) do
105
+ stub_manifest_file contents: manifest_contents do
106
+ manifest.resolve(Pathname('foo')) { |name|
107
+ assert_equal expected_tmpfile, Pathname(name).readlines
108
+ }
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ it 'prunes out ignored files from the default cartignore' do
115
+ stub_ignore_file exists: false do
116
+ stub_slugignore_file exists: false do
117
+ stub_manifest_file contents: manifest_contents do
118
+ manifest.resolve(Pathname('foo')) { |name|
119
+ assert_equal expected_tmpfile.reject { |v| v =~ /build/ },
120
+ Pathname(name).readlines
121
+ }
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ it 'prunes out ignored files with a leading slash' do
128
+ stub_ignore_file contents: %w(/spec) do
129
+ stub_manifest_file contents: manifest_contents do
130
+ manifest.resolve(Pathname('foo')) { |name|
131
+ assert_equal expected_tmpfile, Pathname(name).readlines
132
+ }
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ describe '#generate' do
139
+ it 'is created with sorted and unique filenames' do
140
+ assert_pathname_write "a\nb\nc\n" do
141
+ stub_backticks %w(b a a a b c).join("\n") do
142
+ manifest.generate
143
+ end
144
+ end
145
+ end
10
146
  end
11
147
 
12
- describe '#create_file_list' do
13
- it 'only sets unique files' do
14
- files = %w(a a a b c).join("\n")
15
- expected = %w(a b c).join("\n") + "\n"
148
+ describe '#check' do
149
+ it 'fails if there is no manifest_file' do
150
+ stub_manifest_file exists: false do
151
+ ex = assert_raises Cartage::Manifest::MissingError do
152
+ manifest.check
153
+ end
154
+ assert_match(/cannot create/, ex.message)
155
+ end
156
+ end
157
+
158
+ it 'compares the current files against the manifest' do
159
+ begin
160
+ sysc = ->(*args) { IO.popen(args) { |diff| puts diff.read } }
161
+
162
+ assert_output(/^\+d/) do
163
+ instance_stub Kernel, :system, sysc do
164
+ stub_backticks %w(a b c).join("\n") do
165
+ manifest.instance_variable_set(:@manifest_file, Pathname('Manifest.test'))
166
+ manifest.generate
167
+ end
168
+
169
+ stub_backticks %w(a b c d).join("\n") do
170
+ manifest.check
171
+ end
172
+ end
173
+ end
174
+ ensure
175
+ file = manifest.send(:manifest_file)
176
+ file.unlink if file.to_s.end_with?('Manifest.test')
177
+ end
178
+ end
179
+ end
180
+
181
+ describe '#install_default_ignore' do
182
+ before do
183
+ cartage.verbose = true
184
+ end
185
+
186
+ it 'does nothing if the ignore file exists without overwrite or merge' do
187
+ assert_output ".cartignore already exists, skipping...\n" do
188
+ stub_ignore_file do |ignore_file|
189
+ stub ignore_file, :write, ->(_) {} do
190
+ manifest.install_default_ignore
191
+ end
192
+
193
+ refute_instance_called ignore_file.class, :write
194
+ end
195
+ end
196
+ end
197
+
198
+ def ignore_file_writer(expected = nil)
199
+ case expected
200
+ when Regexp
201
+ ->(actual) { assert_match expected, actual }
202
+ when String
203
+ ->(actual) { assert_equal expected, actual }
204
+ when nil
205
+ ->(_) {}
206
+ end
207
+ end
208
+
209
+ it 'merges if mode is merge' do
210
+ stub_ignore_file contents: %w(xyz/) do |ignore_file|
211
+ stub ignore_file, :write, ignore_file_writer(%r{^xyz/.*vendor/bundle/$}m) do
212
+ assert_output "Merging .cartignore...\n" do
213
+ manifest.install_default_ignore(mode: 'merge')
214
+ end
215
+
216
+ assert_instance_called ignore_file.class, :write
217
+ end
218
+ end
219
+ end
220
+
221
+ it 'merges if mode is merge and ignore file is empty' do
222
+ stub_ignore_file contents: [] do |ignore_file|
223
+ stub ignore_file, :write, ignore_file_writer(%r{^# Some .*vendor/bundle/$}m) do
224
+ assert_output "Merging .cartignore...\n" do
225
+ manifest.install_default_ignore(mode: 'merge')
226
+ end
227
+
228
+ assert_instance_called ignore_file.class, :write
229
+ end
230
+ end
231
+ end
232
+
233
+ it 'forces when mode is force' do
234
+ stub_ignore_file contents: %w(xyz/) do |ignore_file|
235
+ stub ignore_file, :write, ignore_file_writer(%r{^# Some .*vendor/bundle/$}m) do
236
+ assert_output "Creating .cartignore...\n" do
237
+ manifest.install_default_ignore(mode: 'force')
238
+ end
16
239
 
17
- stub_file_open_for_write expected do
18
- stub_backticks files do
19
- @manifest.send :create_file_list, 'x'
240
+ assert_instance_called ignore_file.class, :write
20
241
  end
21
242
  end
22
243
  end