imw 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/imw.rb +6 -1
- data/lib/imw/archives.rb +17 -4
- data/lib/imw/dataset/workflow.rb +6 -12
- data/lib/imw/repository.rb +1 -0
- data/lib/imw/resource.rb +49 -30
- data/lib/imw/runner.rb +15 -12
- data/lib/imw/schemes/local.rb +41 -0
- data/lib/imw/tools/archiver.rb +10 -6
- data/lib/imw/tools/transferer.rb +17 -4
- data/lib/imw/utils/extensions.rb +1 -0
- data/lib/imw/utils/extensions/array.rb +1 -1
- data/lib/imw/utils/extensions/hash.rb +1 -1
- data/lib/imw/utils/extensions/string.rb +1 -1
- data/lib/imw/utils/log.rb +30 -6
- data/spec/imw/archives/rar_spec.rb +1 -1
- data/spec/imw/archives/tar_spec.rb +1 -1
- data/spec/imw/archives/tarbz2_spec.rb +1 -1
- data/spec/imw/archives/targz_spec.rb +1 -1
- data/spec/imw/archives/zip_spec.rb +1 -1
- data/spec/imw/{archive_spec.rb → archives_spec.rb} +9 -1
- data/spec/imw/compressed_files_spec.rb +0 -1
- data/spec/imw/resource_spec.rb +31 -4
- data/spec/imw/schemes/local_spec.rb +16 -2
- data/spec/imw/schemes/remote_spec.rb +1 -2
- data/spec/imw/tools/transferer_spec.rb +76 -6
- data/spec/spec_helper.rb +1 -1
- data/spec/support/custom_matchers.rb +22 -15
- data/spec/support/file_contents_matcher.rb +21 -41
- data/spec/support/paths_matcher.rb +53 -54
- data/spec/support/without_regard_to_order_matcher.rb +31 -48
- metadata +4 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.2
|
data/lib/imw.rb
CHANGED
@@ -46,9 +46,14 @@ module IMW
|
|
46
46
|
# Passing in an IMW::Resource will simply return it.
|
47
47
|
#
|
48
48
|
# @param [String, Addressable::URI, IMW::Resource] obj the URI to open
|
49
|
+
# @param [Hash] options
|
50
|
+
# @option options [Array<String,Module>] as same as <tt>:use_modules</tt> in IMW::Resource.extend_resource!
|
51
|
+
# @option options [Array<String,Module>] without same as <tt>:skip_modules</tt> in IMW::Resource.extend_resource!
|
49
52
|
# @return [IMW::Resource] the resulting resource, property extended for the given URI
|
50
53
|
def self.open obj, options={}
|
51
54
|
return obj if obj.is_a?(IMW::Resource)
|
55
|
+
options[:use_modules] ||= (options[:as] || [])
|
56
|
+
options[:skip_modules] ||= (options[:without] || [])
|
52
57
|
IMW::Resource.new(obj, options)
|
53
58
|
end
|
54
59
|
|
@@ -101,7 +106,7 @@ module IMW
|
|
101
106
|
# @param [Hash] options a hash of options (see IMW::Dataset)
|
102
107
|
# @return [IMW::Dataset] the new dataset
|
103
108
|
def self.dataset handle, options={}, &block
|
104
|
-
d = IMW::Dataset.new(handle, options)
|
109
|
+
d = IMW::Dataset.new(handle, options.merge(:repository => IMW.repository))
|
105
110
|
d.instance_eval(&block) if block_given?
|
106
111
|
d
|
107
112
|
end
|
data/lib/imw/archives.rb
CHANGED
@@ -39,7 +39,12 @@ module IMW
|
|
39
39
|
|
40
40
|
# Create an archive of the given +input_paths+.
|
41
41
|
#
|
42
|
-
#
|
42
|
+
# The input paths must be strings and will be shell-escaped
|
43
|
+
# before further processing. This means you cannot use a shell
|
44
|
+
# glob!
|
45
|
+
#
|
46
|
+
# @param [String] input_paths the paths to add to this archive
|
47
|
+
# @return [IMW::Resource] the resutling archive
|
43
48
|
def create *input_paths
|
44
49
|
should_have_archive_setting!("Cannot create archive #{path}", :program, :create)
|
45
50
|
IMW.system archive_settings[:program], archive_settings[:create], path, *input_paths.flatten
|
@@ -48,24 +53,32 @@ module IMW
|
|
48
53
|
|
49
54
|
# Append to this archive the given +input_paths+.
|
50
55
|
#
|
51
|
-
#
|
56
|
+
# The input paths must be strings and will be shell-escaped
|
57
|
+
# before further processing. This means you cannot use a shell
|
58
|
+
# glob!
|
59
|
+
#
|
60
|
+
# @param [String] input_paths the paths to add to this archive
|
61
|
+
# @return [IMW::Resource] the resutling archive
|
52
62
|
def append *input_paths
|
53
|
-
should_have_archive_setting!("Cannot append to archive #{path}", :append)
|
63
|
+
should_have_archive_setting!("Cannot append to archive #{path}", :program, :append)
|
54
64
|
IMW.system archive_settings[:program], archive_settings[:append], path, *input_paths.flatten
|
55
65
|
self
|
56
66
|
end
|
57
67
|
|
58
68
|
# Extract the files from this archive to the current directory.
|
69
|
+
#
|
70
|
+
# @return [IMW::Resource] this archive
|
59
71
|
def extract
|
60
72
|
should_exist!("Cannot extract archive.")
|
61
73
|
should_have_archive_setting!("Cannot extract archive #{path}", :extract, [:unarchving_program, :program])
|
62
74
|
program = archive_settings[:unarchiving_program] || archive_settings[:program]
|
63
75
|
IMW.system program, archive_settings[:extract], path
|
76
|
+
self
|
64
77
|
end
|
65
78
|
|
66
79
|
# Return a (sorted) list of contents in this archive.
|
67
80
|
#
|
68
|
-
# @return [Array] a list of paths in the archive.
|
81
|
+
# @return [Array<String>] a list of paths in the archive.
|
69
82
|
def contents
|
70
83
|
should_exist!("Cannot list archive contents.")
|
71
84
|
should_have_archive_setting!("Cannot list archive #{path}", :list, [:unarchiving_program, :program])
|
data/lib/imw/dataset/workflow.rb
CHANGED
@@ -148,7 +148,6 @@ module IMW
|
|
148
148
|
@options = OpenStruct.new(DEFAULT_OPTIONS)
|
149
149
|
define_initialize_task
|
150
150
|
define_workflow_tasks
|
151
|
-
define_workflow_task_methods
|
152
151
|
define_clean_task
|
153
152
|
define_tasks
|
154
153
|
end
|
@@ -186,16 +185,11 @@ module IMW
|
|
186
185
|
define_workflow_task({:package => [:fix]}, "Package dataset in final form." )
|
187
186
|
end
|
188
187
|
|
189
|
-
|
190
|
-
|
191
|
-
def
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
self[step].enhance(step => deps, &block)
|
196
|
-
end
|
197
|
-
RUBY
|
198
|
-
end
|
199
|
-
end
|
188
|
+
|
189
|
+
def rip(deps=nil, &block); self[:rip].enhance(deps, &block); end
|
190
|
+
def parse(deps=nil, &block); self[:parse].enhance(deps, &block); end
|
191
|
+
def fix(deps=nil, &block); self[:fix].enhance(deps, &block); end
|
192
|
+
def package(deps=nil, &block); self[:package].enhance(deps, &block); end
|
193
|
+
|
200
194
|
end
|
201
195
|
end
|
data/lib/imw/repository.rb
CHANGED
data/lib/imw/resource.rb
CHANGED
@@ -50,11 +50,36 @@ module IMW
|
|
50
50
|
class Resource
|
51
51
|
|
52
52
|
attr_reader :uri, :mode
|
53
|
-
|
53
|
+
|
54
|
+
# Create a new resource representing +uri+.
|
55
|
+
#
|
56
|
+
# IMW will automatically extend the resulting IMW::Resourcen
|
57
|
+
# instance with modules appropriate to the given URI.
|
58
|
+
#
|
59
|
+
# r = IMW::Resource.new("http://www.infochimps.com")
|
60
|
+
# r.resource_modules
|
61
|
+
# => [IMW::Schemes::Remote::Base, IMW::Schemes::Remote::RemoteFile, IMW::Schemes::HTTP, IMW::Formats::Html]
|
62
|
+
#
|
63
|
+
# You can prevent this altogether by passing in
|
64
|
+
# <tt>:no_modules</tt>:
|
65
|
+
#
|
66
|
+
# r = IMW::Resource.new("http://www.infochimps.com")
|
67
|
+
# r.resource_modules
|
68
|
+
# => [IMW::Schemes::Remote::Base, IMW::Schemes::Remote::RemoteFile, IMW::Schemes::HTTP, IMW::Formats::Html]
|
69
|
+
#
|
70
|
+
# And you can exert more fine-grained control with the
|
71
|
+
# <tt>:use_modules</tt> and <tt>:skip_modules</tt> options, see
|
72
|
+
# IMW::Resource.extend_resource! for details.
|
73
|
+
#
|
74
|
+
# @param [String, Addressable::URI] uri
|
75
|
+
# @param [Hash] options
|
76
|
+
# @option options [true, false] no_modules
|
77
|
+
# @option options [String] mode the mode to open the resource in (will be ignored when inapplicable)
|
78
|
+
# @return [IMW::Resource]
|
54
79
|
def initialize uri, options={}
|
55
80
|
self.uri = uri
|
56
81
|
@mode = options[:mode] || 'r'
|
57
|
-
extend_appropriately! unless options[:
|
82
|
+
extend_appropriately!(options) unless options[:no_modules]
|
58
83
|
end
|
59
84
|
|
60
85
|
# Return the modules this resource has been extended by.
|
@@ -73,8 +98,10 @@ module IMW
|
|
73
98
|
|
74
99
|
# Extend this resource with modules by passing it through a
|
75
100
|
# collection of handlers defined by IMW::Resource.handlers.
|
76
|
-
|
77
|
-
|
101
|
+
#
|
102
|
+
# Accepts the same options as Resource.extend_resource!.
|
103
|
+
def extend_appropriately! options={}
|
104
|
+
self.class.extend_resource!(self, options)
|
78
105
|
end
|
79
106
|
|
80
107
|
# Set the URI of this resource by parsing the given +uri+ (if
|
@@ -197,18 +224,26 @@ module IMW
|
|
197
224
|
# +resource+ with modules whose handler conditions match the
|
198
225
|
# resource.
|
199
226
|
#
|
227
|
+
# Passing in <tt>:use_modules</tt> or <tt>:skip_modules</tt>
|
228
|
+
# allows overriding the default behavior of handlers.
|
229
|
+
#
|
200
230
|
# @param [IMW::Resource] resource the resource to extend
|
231
|
+
# @param [Hash] options
|
232
|
+
# @option options [Array<String,Module>] use_modules a list of modules used regardless of handlers
|
233
|
+
# @option options [Array<String,Module>] skip_modules a list of modules not to be used regardless of handlers
|
201
234
|
# @return [IMW::Resource] the extended resource
|
202
|
-
def self.extend_resource! resource
|
235
|
+
def self.extend_resource! resource, options={}
|
236
|
+
options.reverse_merge!(:use_modules => [], :skip_modules => [])
|
203
237
|
handlers.each do |mod_name, handler|
|
204
238
|
case handler
|
205
|
-
when Regexp then extend_resource_with_mod_or_string!(resource, mod_name) if handler =~ resource.uri.to_s
|
206
|
-
when Proc then extend_resource_with_mod_or_string!(resource, mod_name) if handler.call(resource)
|
207
|
-
when TrueClass then extend_resource_with_mod_or_string!(resource, mod_name)
|
239
|
+
when Regexp then extend_resource_with_mod_or_string!(resource, mod_name, options[:skip_modules]) if handler =~ resource.uri.to_s
|
240
|
+
when Proc then extend_resource_with_mod_or_string!(resource, mod_name, options[:skip_modules]) if handler.call(resource)
|
241
|
+
when TrueClass then extend_resource_with_mod_or_string!(resource, mod_name, options[:skip_modules])
|
208
242
|
else
|
209
243
|
raise IMW::TypeError("A handler must be Regexp, Proc, or true")
|
210
244
|
end
|
211
245
|
end
|
246
|
+
options[:use_modules].each { |mod_name| extend_resource_with_mod_or_string!(resource, mod_name, options[:skip_modules]) }
|
212
247
|
resource
|
213
248
|
end
|
214
249
|
|
@@ -257,31 +292,15 @@ module IMW
|
|
257
292
|
#
|
258
293
|
# @param [Module, String] mod_or_string the module or string
|
259
294
|
# representing a module to extend the resource with
|
260
|
-
|
295
|
+
#
|
296
|
+
# @param [Array<Module,String>] skip_modules modules to exclude
|
297
|
+
def self.extend_resource_with_mod_or_string! resource, mod_or_string, skip_modules
|
298
|
+
return if skip_modules.include?(mod_or_string)
|
261
299
|
if mod_or_string.is_a?(Module)
|
262
300
|
resource.extend(mod_or_string)
|
263
301
|
else
|
264
|
-
|
265
|
-
|
266
|
-
# class_eval'ing them in order so that each is class_eval'd in
|
267
|
-
# the scope of the one before it.
|
268
|
-
#
|
269
|
-
# There is almost certainly a better way to do this.
|
270
|
-
# mod_names = mod_or_string.to_s.split('::')
|
271
|
-
# mods = []
|
272
|
-
# mod_names.each_with_index do |name, index|
|
273
|
-
# if index == 0
|
274
|
-
# mods << IMW.class_eval(name)
|
275
|
-
# else
|
276
|
-
# begin
|
277
|
-
# mods << class_eval(name)
|
278
|
-
# rescue NameError
|
279
|
-
# mods << mods[index - 1].class_eval(name)
|
280
|
-
# end
|
281
|
-
# end
|
282
|
-
# end
|
283
|
-
# resource.extend(mods.last)
|
284
|
-
resource.extend(IMW.class_eval(mod_or_string))
|
302
|
+
m = IMW.class_eval(mod_or_string)
|
303
|
+
resource.extend(m) unless skip_modules.include?(m)
|
285
304
|
end
|
286
305
|
end
|
287
306
|
end
|
data/lib/imw/runner.rb
CHANGED
@@ -33,6 +33,14 @@ module IMW
|
|
33
33
|
|
34
34
|
EOF
|
35
35
|
|
36
|
+
opts.on('-v', '--verbose', "Print verbose output") do
|
37
|
+
IMW.verbose = true # class level, see IMW::Runner.verbose?
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on('-d', '--skip-dependencies', "Execute given tasks without invoking dependencies first") do
|
41
|
+
options[:execute] = true
|
42
|
+
end
|
43
|
+
|
36
44
|
opts.on('-l', '--list', "List datasets in repository") do
|
37
45
|
options[:list] = true
|
38
46
|
end
|
@@ -49,7 +57,8 @@ EOF
|
|
49
57
|
end
|
50
58
|
|
51
59
|
def require_files
|
52
|
-
Dir['*.imw'].each { |path| load File.expand_path(path) }
|
60
|
+
Dir['*.imw'].each { |path| load File.expand_path(path) }
|
61
|
+
Dir['*.rb'].each { |path| require path.gsub(/\.rb$/,'') }
|
53
62
|
options[:requires].each do |path|
|
54
63
|
IMW.open(path) do |requireable|
|
55
64
|
if requireable.directory?
|
@@ -67,19 +76,13 @@ EOF
|
|
67
76
|
end
|
68
77
|
|
69
78
|
def handles
|
70
|
-
require 'set'
|
71
|
-
matched_handles = Set.new
|
72
79
|
if options[:selectors].blank?
|
73
|
-
|
80
|
+
IMW.repository.keys.sort
|
74
81
|
else
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
matched_handles += keys.find_all { |key| key =~ Regexp.new(selector) }
|
79
|
-
end
|
80
|
-
end
|
82
|
+
IMW.repository.handles.map do |handle|
|
83
|
+
handle if options[:selectors].all? { |selector| handle.to_s =~ Regexp.new(selector) }
|
84
|
+
end.compact.sort
|
81
85
|
end
|
82
|
-
matched_handles.to_a.sort
|
83
86
|
end
|
84
87
|
|
85
88
|
def datasets
|
@@ -93,7 +96,7 @@ EOF
|
|
93
96
|
|
94
97
|
def run_task!
|
95
98
|
datasets.each do |dataset|
|
96
|
-
dataset[task].invoke
|
99
|
+
dataset[task].send(options[:execute] ? :execute : :invoke)
|
97
100
|
end
|
98
101
|
exit
|
99
102
|
end
|
data/lib/imw/schemes/local.rb
CHANGED
@@ -58,6 +58,13 @@ module IMW
|
|
58
58
|
def mv new_uri
|
59
59
|
IMW::Tools::Transferer.new(:mv, self, new_uri).transfer!
|
60
60
|
end
|
61
|
+
|
62
|
+
# Return the directory of this resource.
|
63
|
+
#
|
64
|
+
# @return [IMW::Resource]
|
65
|
+
def dir
|
66
|
+
IMW.open(dirname)
|
67
|
+
end
|
61
68
|
|
62
69
|
end
|
63
70
|
|
@@ -155,6 +162,7 @@ module IMW
|
|
155
162
|
FileUtils.rmdir path
|
156
163
|
self
|
157
164
|
end
|
165
|
+
alias_method :rmdir!, :rmdir
|
158
166
|
|
159
167
|
# Delete this directory recursively.
|
160
168
|
#
|
@@ -163,6 +171,7 @@ module IMW
|
|
163
171
|
FileUtils.rm_rf path
|
164
172
|
self
|
165
173
|
end
|
174
|
+
alias_method :rm_rf!, :rm_rf
|
166
175
|
|
167
176
|
# Return a list of paths relative to this directory which match
|
168
177
|
# the +selector+. Works just like Dir[].
|
@@ -210,6 +219,38 @@ module IMW
|
|
210
219
|
end.compact
|
211
220
|
end
|
212
221
|
|
222
|
+
# Package the contents of this directory to an archive at
|
223
|
+
# +package_path+.
|
224
|
+
#
|
225
|
+
# @param [String, IMW::Resource] package_path
|
226
|
+
# @return [IMW::Resource] the new package
|
227
|
+
def package package_path
|
228
|
+
temp_package = IMW.open(File.join(dirname, File.basename(package_path)))
|
229
|
+
FileUtils.cd(dirname) { temp_package.create(basename) }
|
230
|
+
temp_package.path == File.expand_path(package_path) ? temp_package : temp_package.mv(package_path)
|
231
|
+
end
|
232
|
+
alias_method :package!, :package
|
233
|
+
|
234
|
+
# Change the working directory to this local directory.
|
235
|
+
#
|
236
|
+
# If passed a black, execute the block in this directory and
|
237
|
+
# then change back to the initial directory.
|
238
|
+
#
|
239
|
+
# This method works the same as FileUtils.cd.
|
240
|
+
def cd &block
|
241
|
+
FileUtils.cd(path, &block)
|
242
|
+
end
|
243
|
+
|
244
|
+
# Create this directory.
|
245
|
+
#
|
246
|
+
# No error if the directory already exists.
|
247
|
+
#
|
248
|
+
# @return [IMW::Resource] this directory
|
249
|
+
def create
|
250
|
+
FileUtils.mkdir_p(path) unless exist?
|
251
|
+
self
|
252
|
+
end
|
253
|
+
|
213
254
|
end
|
214
255
|
end
|
215
256
|
end
|
data/lib/imw/tools/archiver.rb
CHANGED
@@ -65,7 +65,7 @@ module IMW
|
|
65
65
|
|
66
66
|
attr_accessor :name, :local_inputs, :remote_inputs
|
67
67
|
|
68
|
-
def initialize name, raw_inputs
|
68
|
+
def initialize name, *raw_inputs
|
69
69
|
@name = name
|
70
70
|
self.inputs = raw_inputs
|
71
71
|
end
|
@@ -73,12 +73,12 @@ module IMW
|
|
73
73
|
# Set the inputs for this archiver.
|
74
74
|
#
|
75
75
|
# @param [String, IMW::Resource] new_inputs the inputs to archive, local or remote
|
76
|
-
def inputs=
|
76
|
+
def inputs= raw_inputs
|
77
77
|
@local_inputs, @remote_inputs = [], []
|
78
|
-
|
79
|
-
input =
|
78
|
+
raw_inputs.flatten.each do |raw_input|
|
79
|
+
input = IMW.open(raw_input)
|
80
80
|
if input.is_local?
|
81
|
-
@local_inputs <<
|
81
|
+
@local_inputs << input
|
82
82
|
else
|
83
83
|
@remote_inputs << input
|
84
84
|
end
|
@@ -133,17 +133,21 @@ module IMW
|
|
133
133
|
new_path = File.join(dir, existing_file.basename)
|
134
134
|
case
|
135
135
|
when existing_file.is_archive?
|
136
|
+
IMW.announce_if_verbose("Extracting #{existing_file}...")
|
136
137
|
FileUtils.cd(dir) do
|
137
138
|
existing_file.extract
|
138
139
|
end
|
139
140
|
when existing_file.is_compressed?
|
141
|
+
IMW.announce_if_verbose("Decompressing #{existing_file}...")
|
140
142
|
existing_file.cp(new_path).decompress!
|
141
143
|
else
|
144
|
+
IMW.announce_if_verbose("Copying #{existing_file}...")
|
142
145
|
existing_file.cp(new_path)
|
143
146
|
end
|
144
147
|
end
|
145
148
|
|
146
149
|
remote_inputs.each do |remote_input|
|
150
|
+
IMW.announce_if_verbose("Downloading #{remote_input}...")
|
147
151
|
remote_input.cp(File.join(dir, remote_input.effective_basename))
|
148
152
|
end
|
149
153
|
end
|
@@ -199,7 +203,7 @@ module IMW
|
|
199
203
|
output = IMW.open(output)
|
200
204
|
FileUtils.mkdir_p(output.dirname) unless File.exist?(output.dirname)
|
201
205
|
output.rm! if output.exist?
|
202
|
-
FileUtils.cd(tmp_dir) { IMW.open(output.basename).create(
|
206
|
+
FileUtils.cd(tmp_dir) { IMW.open(output.basename).create(name).mv(output.path) }
|
203
207
|
add_processing_error "Archiver: couldn't create archive #{output.path}" unless output.exists?
|
204
208
|
output
|
205
209
|
end
|
data/lib/imw/tools/transferer.rb
CHANGED
@@ -11,15 +11,27 @@ module IMW
|
|
11
11
|
raise IMW::PathError.new("Source and destination have the same URI: #{@source.uri}") if @source.uri.to_s == @destination.uri.to_s
|
12
12
|
end
|
13
13
|
|
14
|
+
# Transfer source to destination.
|
15
|
+
#
|
16
|
+
# For local transfer, will raise errors unless the necessary
|
17
|
+
# paths exist.
|
14
18
|
def transfer!
|
15
19
|
if source.is_local?
|
16
|
-
source.should_exist!("Cannot
|
17
|
-
source_scheme = 'file'
|
20
|
+
source.should_exist!("Cannot #{action}")
|
21
|
+
source_scheme = 'file'
|
18
22
|
else
|
19
23
|
source_scheme = source.scheme
|
20
24
|
end
|
21
|
-
|
25
|
+
|
26
|
+
if destination.is_local?
|
27
|
+
destination.dir.should_exist!("Cannot #{action}")
|
28
|
+
destination_scheme = 'file'
|
29
|
+
else
|
30
|
+
destination_scheme = destination.scheme
|
31
|
+
end
|
32
|
+
|
22
33
|
method = "#{source_scheme}_to_#{destination_scheme}"
|
34
|
+
|
23
35
|
if respond_to?(method)
|
24
36
|
send(method)
|
25
37
|
else
|
@@ -43,7 +55,8 @@ module IMW
|
|
43
55
|
#
|
44
56
|
|
45
57
|
def file_to_file
|
46
|
-
|
58
|
+
fu_action = (action == :cp && source.is_directory?) ? :cp_r : action
|
59
|
+
FileUtils.send(fu_action, source.path, destination.path)
|
47
60
|
end
|
48
61
|
|
49
62
|
#
|
data/lib/imw/utils/extensions.rb
CHANGED
@@ -57,6 +57,7 @@ module IMW
|
|
57
57
|
# which will work fine since +flags+ will automatically be flattend.
|
58
58
|
def self.system *commands
|
59
59
|
stripped_commands = commands.flatten.map { |command| command.to_s unless command.blank? }.compact
|
60
|
+
IMW.announce_if_verbose(stripped_commands.join(" "))
|
60
61
|
Kernel.system(*stripped_commands)
|
61
62
|
raise IMW::SystemCallError.new($?.dup, commands.join(' ')) unless $?.success?
|
62
63
|
end
|
data/lib/imw/utils/log.rb
CHANGED
@@ -4,10 +4,26 @@ module IMW
|
|
4
4
|
|
5
5
|
# Default log file.
|
6
6
|
LOG_FILE_DESTINATION = STDERR unless defined?(LOG_FILE_DESTINATION)
|
7
|
-
|
8
|
-
LOG_TIMEFORMAT = "%Y%m%d-%H:%M:%S " unless defined?(LOG_TIMEFORMAT)
|
9
7
|
|
10
|
-
|
8
|
+
# Default log file time format
|
9
|
+
LOG_TIMEFORMAT = "%Y-%m-%d %H:%M:%S " unless defined?(LOG_TIMEFORMAT)
|
10
|
+
|
11
|
+
# Default verbosity
|
12
|
+
VERBOSE = false
|
13
|
+
|
14
|
+
class << self; attr_accessor :log, :verbose end
|
15
|
+
|
16
|
+
# Is IMW operating in verbose mode?
|
17
|
+
#
|
18
|
+
# Calls to <tt>IMW.warn_if_verbose</tt> and friends utilize this
|
19
|
+
# method. Verbosity is controlled on the command line (see
|
20
|
+
# IMW::Runner) or by setting IMW::VERBOSE in your configuration
|
21
|
+
# file.
|
22
|
+
#
|
23
|
+
# @return [nil, false, true]
|
24
|
+
def self.verbose?
|
25
|
+
VERBOSE || verbose
|
26
|
+
end
|
11
27
|
|
12
28
|
# Create a Logger and point it at IMW::LOG_FILE_DESTINATION which is
|
13
29
|
# set in ~/.imwrc and defaults to STDERR.
|
@@ -17,21 +33,29 @@ module IMW
|
|
17
33
|
IMW.log.level = Logger::INFO
|
18
34
|
end
|
19
35
|
|
20
|
-
def announce *events
|
36
|
+
def self.announce *events
|
21
37
|
options = events.flatten.extract_options!
|
22
38
|
options.reverse_merge! :level => Logger::INFO
|
23
39
|
IMW.log.add options[:level], events.join("\n")
|
24
40
|
end
|
25
|
-
def
|
41
|
+
def self.announce_if_verbose *events
|
42
|
+
announce(*events) if IMW.verbose?
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.banner *events
|
26
46
|
options = events.flatten.extract_options!
|
27
47
|
options.reverse_merge! :level => Logger::INFO
|
28
48
|
announce(["*"*75, events, "*"*75], options)
|
29
49
|
end
|
30
|
-
|
50
|
+
|
51
|
+
def self.warn *events
|
31
52
|
options = events.flatten.extract_options!
|
32
53
|
options.reverse_merge! :level => Logger::WARN
|
33
54
|
announce events, options
|
34
55
|
end
|
56
|
+
def self.warn_if_verbose *events
|
57
|
+
warn(*events) if IMW.verbose?
|
58
|
+
end
|
35
59
|
|
36
60
|
PROGRESS_TRACKERS = {}
|
37
61
|
#
|
@@ -20,7 +20,6 @@ require File.join(File.dirname(__FILE__),'../spec_helper')
|
|
20
20
|
# variable should be defined OUTSIDE a before block.
|
21
21
|
|
22
22
|
share_examples_for "an archive of files" do
|
23
|
-
include Spec::Matchers::IMW
|
24
23
|
|
25
24
|
before do
|
26
25
|
@root = File.join(IMWTest::TMP_DIR, 'an_archive_of_files_shared_example_group')
|
@@ -40,6 +39,10 @@ share_examples_for "an archive of files" do
|
|
40
39
|
@archive.should contain_paths_like(@initial_directory, :relative_to => @root)
|
41
40
|
end
|
42
41
|
|
42
|
+
it "returns an IMW resource when creating" do
|
43
|
+
@archive.create(*Dir[@initial_directory + '/**/*']).class.should == IMW::Resource
|
44
|
+
end
|
45
|
+
|
43
46
|
if @cannot_append
|
44
47
|
it "cannot append to an archive which already exists" do
|
45
48
|
@archive.create(*Dir[@initial_directory + "/**/*"])
|
@@ -56,7 +59,12 @@ share_examples_for "an archive of files" do
|
|
56
59
|
@archive.append(*Dir[@appending_directory + "/**/*"])
|
57
60
|
@archive.should contain_paths_like(@appending_directory, :relative_to => @root)
|
58
61
|
end
|
62
|
+
|
63
|
+
it "returns an IMW resource when appending" do
|
64
|
+
@archive.append(*Dir[@appending_directory + "/**/*"]).class.should == IMW::Resource
|
65
|
+
end
|
59
66
|
end
|
67
|
+
|
60
68
|
|
61
69
|
it "can extract files which match the original ones it archived" do
|
62
70
|
@archive.create(*Dir[@initial_directory + "/**/*"])
|
data/spec/imw/resource_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe IMW::Resource do
|
|
4
4
|
|
5
5
|
describe "handling missing methods" do
|
6
6
|
before do
|
7
|
-
@resource = IMW::Resource.new('/home/foof.txt', :
|
7
|
+
@resource = IMW::Resource.new('/home/foof.txt', :no_modules => true)
|
8
8
|
end
|
9
9
|
|
10
10
|
it "should return false when querying with a method that isn't defined" do
|
@@ -28,7 +28,7 @@ describe IMW::Resource do
|
|
28
28
|
describe "parsing various and sundry URIs should correctly parse a" do
|
29
29
|
|
30
30
|
before do
|
31
|
-
IMW::Resource.should_receive(:extend_resource!).with(an_instance_of(IMW::Resource))
|
31
|
+
IMW::Resource.should_receive(:extend_resource!).with(an_instance_of(IMW::Resource), {})
|
32
32
|
end
|
33
33
|
|
34
34
|
it "local file path" do
|
@@ -69,9 +69,36 @@ describe IMW::Resource do
|
|
69
69
|
|
70
70
|
it "should open a URI without attempting to extend with modules if so asked" do
|
71
71
|
IMW::Resource.should_not_receive(:extend_resource!)
|
72
|
-
IMW::Resource.new("/path/to/some/file.txt", :
|
72
|
+
IMW::Resource.new("/path/to/some/file.txt", :no_modules => true)
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
|
+
describe "extending resources with specific modules" do
|
76
|
+
before do
|
77
|
+
@resource = IMW::Resource.new('http://www.infochimps.com/data', :no_modules => true)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should use a specific module when asked with a string" do
|
81
|
+
IMW::Resource.extend_resource!(@resource, :use_modules => ["Formats::Csv"])
|
82
|
+
@resource.resource_modules.should include(IMW::Formats::Csv)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should use a specific module when asked with a module" do
|
86
|
+
IMW::Resource.extend_resource!(@resource, :use_modules => [IMW::Formats::Csv])
|
87
|
+
@resource.resource_modules.should include(IMW::Formats::Csv)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should not use a specific module when asked with a string" do
|
91
|
+
IMW::Resource.extend_resource!(@resource, :skip_modules => ["Schemes::HTTP"])
|
92
|
+
@resource.resource_modules.should_not include(IMW::Schemes::HTTP)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should not use a specific module when asked with a module" do
|
96
|
+
IMW::Resource.extend_resource!(@resource, :skip_modules => [IMW::Schemes::HTTP])
|
97
|
+
@resource.resource_modules.should_not include(IMW::Schemes::HTTP)
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
75
102
|
end
|
76
103
|
|
77
104
|
|
@@ -3,13 +3,13 @@ require File.join(File.dirname(__FILE__),'../../spec_helper')
|
|
3
3
|
describe IMW::Schemes::Local::Base do
|
4
4
|
|
5
5
|
it "should not extend a local file with LocalDirectory" do
|
6
|
-
@file = IMW::Resource.new('foo.txt', :
|
6
|
+
@file = IMW::Resource.new('foo.txt', :no_modules => true)
|
7
7
|
@file.should_not_receive(:extend).with(IMW::Schemes::Local::LocalDirectory)
|
8
8
|
@file.extend_appropriately!
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should not extend a local directory with LocalFile" do
|
12
|
-
@dir = IMW::Resource.new(IMWTest::TMP_DIR, :
|
12
|
+
@dir = IMW::Resource.new(IMWTest::TMP_DIR, :no_modules => true)
|
13
13
|
@dir.should_not_receive(:extend).with(IMW::Schemes::Local::LocalFile)
|
14
14
|
@dir.extend_appropriately!
|
15
15
|
end
|
@@ -17,6 +17,13 @@ describe IMW::Schemes::Local::Base do
|
|
17
17
|
it "should correctly resolve relative paths" do
|
18
18
|
IMW.open('foobar').dirname.should == IMWTest::TMP_DIR
|
19
19
|
end
|
20
|
+
|
21
|
+
it "should be able to return its directory as an IMW object" do
|
22
|
+
IMW.open('/path/to/file').dir.path.should == '/path/to'
|
23
|
+
IMW.open('/').dir.path.should == '/'
|
24
|
+
end
|
25
|
+
|
26
|
+
|
20
27
|
end
|
21
28
|
|
22
29
|
describe IMW::Schemes::Local::LocalFile do
|
@@ -93,6 +100,13 @@ describe IMW::Schemes::Local::LocalDirectory do
|
|
93
100
|
@dir.resources.map(&:class).uniq.first.should == IMW::Resource
|
94
101
|
end
|
95
102
|
|
103
|
+
describe 'can package itself to' do
|
104
|
+
['tar', 'tar.bz2', 'tar.gz', 'zip', 'rar'].each do |extension|
|
105
|
+
it "a #{extension} archive" do
|
106
|
+
@dir.package("package.#{extension}").exist?.should be_true # FIXME should explicitly check paths are correct in archive
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
96
110
|
end
|
97
111
|
|
98
112
|
|
@@ -7,8 +7,7 @@ describe IMW::Schemes::Remote::RemoteFile do
|
|
7
7
|
|
8
8
|
before do
|
9
9
|
# skip modules or else it will automatically become HTML!
|
10
|
-
@file = IMW.open('http://www.google.com', :skip_modules =>
|
11
|
-
@file.extend(IMW::Schemes::Remote::Base)
|
10
|
+
@file = IMW.open('http://www.google.com', :skip_modules => ["Schemes::HTTP", "Formats::HTML"])
|
12
11
|
end
|
13
12
|
|
14
13
|
describe 'with the file' do
|
@@ -2,10 +2,14 @@ require File.dirname(__FILE__) + "/../../spec_helper"
|
|
2
2
|
|
3
3
|
describe IMW::Tools::Transferer do
|
4
4
|
before do
|
5
|
-
@
|
6
|
-
@
|
7
|
-
@
|
8
|
-
@
|
5
|
+
@dir = IMW.open("dir")
|
6
|
+
@new_dir = IMW.open("new_dir")
|
7
|
+
@nested = IMW.open('new_dir/nested.txt')
|
8
|
+
@nested_dir = IMW.open('new_dir/nested')
|
9
|
+
@local = IMW.open("foobar.txt")
|
10
|
+
@http = IMW.open("http://www.google.com")
|
11
|
+
@hdfs = IMW.open("hdfs:///path/to/foobar.txt")
|
12
|
+
@s3 = IMW.open("s3://mybucket/foo/bar")
|
9
13
|
end
|
10
14
|
|
11
15
|
it "should raise an error unless the action is one of :cp, :copy, :mv :move, or :mv!" do
|
@@ -22,25 +26,91 @@ describe IMW::Tools::Transferer do
|
|
22
26
|
end
|
23
27
|
|
24
28
|
describe "transfering local files" do
|
29
|
+
|
30
|
+
before do
|
31
|
+
IMWTest::Random.file @local.path
|
32
|
+
end
|
33
|
+
|
25
34
|
it "should raise an error if the source doesn't exist" do
|
35
|
+
@local.rm!
|
26
36
|
lambda { IMW::Tools::Transferer.new(:cp, @local, 'barbaz.txt').transfer! }.should raise_error(IMW::PathError)
|
27
37
|
end
|
28
38
|
|
39
|
+
it "should raise an error if the directory of the destination doesn't exist" do
|
40
|
+
lambda { IMW::Tools::Transferer.new(:cp, @local, @nested).transfer! }.should raise_error(IMW::PathError)
|
41
|
+
end
|
42
|
+
|
29
43
|
it "can copy a local file" do
|
30
|
-
IMWTest::Random.file @local.path
|
31
44
|
IMW::Tools::Transferer.new(:cp, @local, 'barbaz.txt').transfer!
|
32
45
|
@local.exist?.should be_true
|
33
46
|
IMW.open('barbaz.txt').exist?.should be_true
|
34
47
|
end
|
35
48
|
|
49
|
+
it "can copy a local file to a directory" do
|
50
|
+
FileUtils.mkdir(@dir.path)
|
51
|
+
IMW::Tools::Transferer.new(:cp, @local, @dir).transfer!
|
52
|
+
IMW.open(File.join(@dir.path, @local.basename)).exist?.should be_true
|
53
|
+
end
|
54
|
+
|
36
55
|
it "can move a local file" do
|
37
|
-
IMWTest::Random.file @local.path
|
38
56
|
IMW::Tools::Transferer.new(:mv, @local, 'barbaz.txt').transfer!
|
39
57
|
@local.exist?.should be_false
|
40
58
|
IMW.open('barbaz.txt').exist?.should be_true
|
41
59
|
end
|
42
60
|
|
61
|
+
it "can move a local file to a directory" do
|
62
|
+
FileUtils.mkdir(@dir.path)
|
63
|
+
IMW::Tools::Transferer.new(:mv, @local, @dir).transfer!
|
64
|
+
IMW.open(File.join(@dir.path, @local.basename)).exist?.should be_true
|
65
|
+
@local.exist?.should be_false
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "transfering local directories" do
|
72
|
+
|
73
|
+
before do
|
74
|
+
IMWTest::Random.directory_with_files @dir.path
|
75
|
+
@dir = @dir.reopen
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should raise an error if the source doesn't exist" do
|
79
|
+
@dir.rm_rf!
|
80
|
+
lambda { IMW::Tools::Transferer.new(:cp, @dir, @new_dir).transfer! }.should raise_error(IMW::PathError)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should raise an error if the directory of the destination doesn't exist" do
|
84
|
+
lambda { IMW::Tools::Transferer.new(:cp, @dir, @nested_dir).transfer! }.should raise_error(IMW::PathError)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "can copy a local directory" do
|
88
|
+
IMW::Tools::Transferer.new(:cp, @dir, @new_dir).transfer!
|
89
|
+
@dir.exist?.should be_true
|
90
|
+
@new_dir.exist?.should be_true
|
91
|
+
end
|
92
|
+
|
93
|
+
it "can move a local directory" do
|
94
|
+
IMW::Tools::Transferer.new(:mv, @dir, @new_dir).transfer!
|
95
|
+
@dir.exist?.should be_false
|
96
|
+
@new_dir.exist?.should be_true
|
97
|
+
end
|
98
|
+
|
99
|
+
it "can copy a local directory to an existing directory" do
|
100
|
+
FileUtils.mkdir(@new_dir.path)
|
101
|
+
IMW::Tools::Transferer.new(:cp, @dir, @nested_dir).transfer!
|
102
|
+
@dir.exist?.should be_true
|
103
|
+
@nested_dir.exist?.should be_true
|
104
|
+
end
|
105
|
+
|
106
|
+
it "can move a local directory to an existing directory" do
|
107
|
+
FileUtils.mkdir(@new_dir.path)
|
108
|
+
IMW::Tools::Transferer.new(:mv, @dir, @nested_dir).transfer!
|
109
|
+
@dir.exist?.should_not be_true
|
110
|
+
@nested_dir.exist?.should be_true
|
111
|
+
end
|
43
112
|
end
|
113
|
+
|
44
114
|
|
45
115
|
describe "transferring HTTP files" do
|
46
116
|
it "can copy a remote file to a local path" do
|
data/spec/spec_helper.rb
CHANGED
@@ -1,21 +1,28 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
module IMWTest
|
2
|
+
module CustomMatchers
|
3
|
+
|
4
|
+
# Check to see whether the given directory (a String) contains the
|
5
|
+
# given +paths+
|
6
|
+
#
|
7
|
+
# @param [Array<String>] paths
|
8
|
+
def contain *paths
|
9
|
+
paths = paths.flatten
|
10
|
+
simple_matcher("contain #{paths.inspect}") do |given, matcher|
|
11
|
+
given_contents = Dir[given + "/**/*"].map do |abs_path|
|
12
|
+
abs_path[(given.length + 1)..-1]
|
13
|
+
end
|
14
|
+
matcher.failure_message = "expected #{given} to contain #{paths.inspect}, instead it contained #{given_contents.inspect}"
|
15
|
+
matcher.negative_failure_message = "expected #{given} not to contain #{paths.inspect}"
|
16
|
+
paths.all? { |path| given_contents.include?(path.gsub(/\/+$/,'')) }
|
7
17
|
end
|
8
|
-
matcher.failure_message = "expected #{given} to contain #{paths.inspect}, instead it contained #{given_contents.inspect}"
|
9
|
-
matcher.negative_failure_message = "expected #{given} not to contain #{paths.inspect}"
|
10
|
-
paths.all? { |path| given_contents.include?(path) }
|
11
18
|
end
|
12
|
-
end
|
13
19
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
20
|
+
def exist
|
21
|
+
simple_matcher("exist") do |given, matcher|
|
22
|
+
matcher.failure_message = "expected #{given} to exist on disk"
|
23
|
+
matcher.failure_message = "expected #{given} not to exist on disk"
|
24
|
+
File.exist?(given)
|
25
|
+
end
|
19
26
|
end
|
20
27
|
end
|
21
28
|
end
|
@@ -1,50 +1,30 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
#
|
4
|
-
# == About
|
5
|
-
#
|
6
|
-
# An RSpec matcher which tests that two files have the same contents
|
7
|
-
# on disk.
|
8
|
-
#
|
9
|
-
# Author:: (Philip flip Kromer, Dhruv Bansal) for Infinite Monkeywrench Project (mailto:coders@infochimps.org)
|
10
|
-
# Copyright:: Copyright (c) 2008 infochimps.org
|
11
|
-
# License:: GPL 3.0
|
12
|
-
# Website:: http://infinitemonkeywrench.org/
|
13
|
-
#
|
1
|
+
module IMWTest
|
2
|
+
module CustomMatchers
|
14
3
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
module IMW
|
20
|
-
|
21
|
-
class FileContentsMatcher
|
22
|
-
def initialize orig
|
23
|
-
@orig = File.expand_path orig
|
24
|
-
end
|
25
|
-
|
26
|
-
def matches? copy
|
27
|
-
@copy = File.expand_path copy
|
28
|
-
File.compare(@orig,@copy)
|
29
|
-
end
|
4
|
+
class FileContentsMatcher
|
5
|
+
def initialize orig
|
6
|
+
@orig = File.expand_path orig
|
7
|
+
end
|
30
8
|
|
31
|
-
|
32
|
-
|
33
|
-
|
9
|
+
def matches? copy
|
10
|
+
@copy = File.expand_path copy
|
11
|
+
File.compare(@orig,@copy)
|
12
|
+
end
|
34
13
|
|
35
|
-
|
36
|
-
|
37
|
-
end
|
14
|
+
def failure_message
|
15
|
+
"files #{@orig} and #{@copy} are different"
|
38
16
|
end
|
39
17
|
|
40
|
-
|
41
|
-
|
42
|
-
def have_contents_matching_those_of path
|
43
|
-
FileContentsMatcher.new(path)
|
18
|
+
def negative_failure_message
|
19
|
+
"expected files #{@orig} and #{@copy} to differ"
|
44
20
|
end
|
45
|
-
|
46
21
|
end
|
22
|
+
|
23
|
+
# Matches the contents of one file against another using
|
24
|
+
# File.compare.
|
25
|
+
def have_contents_matching_those_of path
|
26
|
+
FileContentsMatcher.new(path)
|
27
|
+
end
|
28
|
+
|
47
29
|
end
|
48
30
|
end
|
49
|
-
|
50
|
-
# puts "#{File.basename(__FILE__)}: From far away, the folders appear the same; from up close, they are different." # at bottom
|
@@ -1,67 +1,66 @@
|
|
1
1
|
require 'set'
|
2
2
|
|
3
|
-
module
|
4
|
-
module Matchers
|
5
|
-
module IMW
|
3
|
+
module IMWTest
|
6
4
|
|
7
|
-
|
5
|
+
module CustomMatchers
|
8
6
|
|
9
|
-
|
7
|
+
class PathsMatcher
|
10
8
|
|
11
|
-
|
12
|
-
@given_base = options[:given_base] || options[:relative_to]
|
13
|
-
@to_match_base = options[:to_match_base]
|
14
|
-
@given = given
|
15
|
-
@given_contents = get_contents(given, given_base)
|
16
|
-
end
|
17
|
-
|
18
|
-
def matches? to_match
|
19
|
-
@to_match = to_match
|
20
|
-
@to_match_contents = get_contents(to_match, to_match_base)
|
21
|
-
to_match_contents == given_contents
|
22
|
-
end
|
9
|
+
attr_accessor :given, :given_contents, :given_base, :to_match, :to_match_contents, :to_match_base
|
23
10
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
11
|
+
def initialize given, options={}
|
12
|
+
@given_base = options[:given_base] || options[:relative_to]
|
13
|
+
@to_match_base = options[:to_match_base]
|
14
|
+
@given = given
|
15
|
+
@given_contents = get_contents(given, given_base)
|
16
|
+
end
|
17
|
+
|
18
|
+
def matches? to_match
|
19
|
+
@to_match = to_match
|
20
|
+
@to_match_contents = get_contents(to_match, to_match_base)
|
21
|
+
to_match_contents == given_contents
|
22
|
+
end
|
29
23
|
|
30
|
-
|
31
|
-
|
32
|
-
|
24
|
+
def failure_message
|
25
|
+
given_string = given_contents.to_a.join("\n\t")
|
26
|
+
to_match_string = to_match_contents.to_a.join("\n\t")
|
27
|
+
"expected contents to be identical.\n\ngiven #{given.inspect}:\n\t#{given_string}\n\nto match #{to_match}:\n\t#{to_match_string}"
|
28
|
+
end
|
33
29
|
|
34
|
-
|
35
|
-
|
36
|
-
if obj.is_a?(String) || obj.is_a?(Array)
|
37
|
-
contents = [obj].flatten.map do |raw_path|
|
38
|
-
path = File.expand_path(raw_path)
|
39
|
-
if File.directory?(path)
|
40
|
-
Dir[path + "/**/*"]
|
41
|
-
else
|
42
|
-
path
|
43
|
-
end
|
44
|
-
end.flatten
|
45
|
-
else
|
46
|
-
# obj is an IMW obj (archive or directory) so it has a
|
47
|
-
# contents method
|
48
|
-
contents = obj.contents
|
49
|
-
end
|
50
|
-
if base
|
51
|
-
contents.map do |path|
|
52
|
-
new_path = path[base.length + 1..-1]
|
53
|
-
new_path = nil if !new_path.nil? && new_path.size == 0
|
54
|
-
new_path
|
55
|
-
end.compact.to_set
|
56
|
-
else
|
57
|
-
contents.to_set
|
58
|
-
end
|
59
|
-
end
|
30
|
+
def negative_failure_message
|
31
|
+
"expected contents of #{given} and #{to_match} to be different"
|
60
32
|
end
|
61
|
-
|
62
|
-
|
63
|
-
|
33
|
+
|
34
|
+
protected
|
35
|
+
def get_contents obj, base=nil
|
36
|
+
if obj.is_a?(String) || obj.is_a?(Array)
|
37
|
+
contents = [obj].flatten.map do |raw_path|
|
38
|
+
path = File.expand_path(raw_path)
|
39
|
+
if File.directory?(path)
|
40
|
+
Dir[path + "/**/*"]
|
41
|
+
else
|
42
|
+
path
|
43
|
+
end
|
44
|
+
end.flatten
|
45
|
+
else
|
46
|
+
# obj is an IMW obj (archive or directory) so it has a
|
47
|
+
# contents method
|
48
|
+
contents = obj.send(obj.respond_to?(:all_contents) ? :all_contents : :contents)
|
49
|
+
end
|
50
|
+
if base
|
51
|
+
contents.map do |path|
|
52
|
+
new_path = path[base.length + 1..-1]
|
53
|
+
new_path = nil if !new_path.nil? && new_path.size == 0
|
54
|
+
new_path
|
55
|
+
end.compact.to_set
|
56
|
+
else
|
57
|
+
contents.to_set
|
58
|
+
end
|
64
59
|
end
|
65
60
|
end
|
61
|
+
|
62
|
+
def contain_paths_like given, options={}
|
63
|
+
PathsMatcher.new(given, options)
|
64
|
+
end
|
66
65
|
end
|
67
66
|
end
|
@@ -1,58 +1,41 @@
|
|
1
|
-
#
|
2
|
-
# h2. spec/imw/matchers/without_regard_to_order_matcher.rb -- set matcher for non-sets
|
3
|
-
#
|
4
|
-
# == About
|
5
|
-
#
|
6
|
-
# A simple matcher which compares two objects as though they were
|
7
|
-
# sets, i.e. - without regard to the order of their elements.
|
8
|
-
#
|
9
|
-
# Author:: (Philip flip Kromer, Dhruv Bansal) for Infinite Monkeywrench Project (mailto:coders@infochimps.org)
|
10
|
-
# Copyright:: Copyright (c) 2008 infochimps.org
|
11
|
-
# License:: GPL 3.0
|
12
|
-
# Website:: http://infinitemonkeywrench.org/
|
13
|
-
#
|
14
|
-
|
15
1
|
require 'set'
|
16
2
|
require 'imw/utils'
|
17
3
|
|
18
|
-
module
|
19
|
-
module
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
@array_to_test == @known_array
|
35
|
-
end
|
36
|
-
|
37
|
-
def failure_message
|
38
|
-
missing_from_array_to_test = "missing from array to test: #{(@known_array - @array_to_test).to_a.quote_items_with "and"}\n"
|
39
|
-
missing_from_known_array = "missing from known array: #{(@array_to_test - @known_array).to_a.quote_items_with "and"}\n"
|
40
|
-
common_to_both = "common to both: #{(@array_to_test & @known_array).to_a.quote_items_with "and"}\n"
|
41
|
-
"expected contents of the arrays to be identical:\n\n#{missing_from_array_to_test}\n#{missing_from_known_array}\n#{common_to_both}"
|
42
|
-
end
|
43
|
-
|
44
|
-
def negative_failure_message
|
45
|
-
"expected contents of the arrays to differ."
|
46
|
-
end
|
4
|
+
module IMWTest
|
5
|
+
module CustomMatchers
|
6
|
+
|
7
|
+
# Match the contents of two arrays without regard to the order
|
8
|
+
# of their elements by treating each as a set.
|
9
|
+
class WithoutRegardToOrder
|
10
|
+
|
11
|
+
private
|
12
|
+
def initialize known_array
|
13
|
+
@known_array = known_array.to_set
|
14
|
+
end
|
15
|
+
|
16
|
+
public
|
17
|
+
def matches? array_to_test
|
18
|
+
@array_to_test = array_to_test.to_set
|
19
|
+
@array_to_test == @known_array
|
47
20
|
end
|
48
21
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
22
|
+
def failure_message
|
23
|
+
missing_from_array_to_test = "missing from array to test: #{(@known_array - @array_to_test).to_a.quote_items_with "and"}\n"
|
24
|
+
missing_from_known_array = "missing from known array: #{(@array_to_test - @known_array).to_a.quote_items_with "and"}\n"
|
25
|
+
common_to_both = "common to both: #{(@array_to_test & @known_array).to_a.quote_items_with "and"}\n"
|
26
|
+
"expected contents of the arrays to be identical:\n\n#{missing_from_array_to_test}\n#{missing_from_known_array}\n#{common_to_both}"
|
53
27
|
end
|
28
|
+
|
29
|
+
def negative_failure_message
|
30
|
+
"expected contents of the arrays to differ."
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Check that the contents of one array match another without
|
35
|
+
# regard to ordering.
|
36
|
+
def match_without_regard_to_order known_array
|
37
|
+
WithoutRegardToOrder.new(known_array)
|
54
38
|
end
|
55
39
|
end
|
56
40
|
end
|
57
41
|
|
58
|
-
# puts "#{File.basename(__FILE__)}: The leg bone's connected to the...knee bone, the knee bone's connected...wait, isn't it the other way 'round?" # at bottom
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: imw
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dhruv Bansal
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2010-05-
|
13
|
+
date: 2010-05-17 00:00:00 -05:00
|
14
14
|
default_executable: imw
|
15
15
|
dependencies: []
|
16
16
|
|
@@ -95,12 +95,12 @@ files:
|
|
95
95
|
- spec/data/sample.txt
|
96
96
|
- spec/data/sample.xml
|
97
97
|
- spec/data/sample.yaml
|
98
|
-
- spec/imw/archive_spec.rb
|
99
98
|
- spec/imw/archives/rar_spec.rb
|
100
99
|
- spec/imw/archives/tar_spec.rb
|
101
100
|
- spec/imw/archives/tarbz2_spec.rb
|
102
101
|
- spec/imw/archives/targz_spec.rb
|
103
102
|
- spec/imw/archives/zip_spec.rb
|
103
|
+
- spec/imw/archives_spec.rb
|
104
104
|
- spec/imw/compressed_files/bz2_spec.rb
|
105
105
|
- spec/imw/compressed_files/compressible_spec.rb
|
106
106
|
- spec/imw/compressed_files/gz_spec.rb
|
@@ -168,7 +168,6 @@ test_files:
|
|
168
168
|
- spec/imw/archives/rar_spec.rb
|
169
169
|
- spec/imw/tools/archiver_spec.rb
|
170
170
|
- spec/imw/tools/transferer_spec.rb
|
171
|
-
- spec/imw/archive_spec.rb
|
172
171
|
- spec/imw/compressed_files/compressible_spec.rb
|
173
172
|
- spec/imw/compressed_files/bz2_spec.rb
|
174
173
|
- spec/imw/compressed_files/gz_spec.rb
|
@@ -182,6 +181,7 @@ test_files:
|
|
182
181
|
- spec/imw/formats/yaml_spec.rb
|
183
182
|
- spec/imw/formats/delimited_spec.rb
|
184
183
|
- spec/imw/formats/sgml_spec.rb
|
184
|
+
- spec/imw/archives_spec.rb
|
185
185
|
- spec/imw/schemes/http_spec.rb
|
186
186
|
- spec/imw/schemes/local_spec.rb
|
187
187
|
- spec/imw/schemes/remote_spec.rb
|