imw 0.2.1 → 0.2.2

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
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
- # @param [String, IMW::Resource] input_paths the paths to add to this archive
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
- # @param [String, IMW::Resource] input_paths the paths to add to this archive
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])
@@ -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
- # Dynamically define methods for each of the workflow steps which
190
- # act as shorcuts for accessing the corresponding tasks.
191
- def define_workflow_task_methods
192
- workflow_steps.each do |step|
193
- self.class.class_eval <<RUBY
194
- def #{step} deps, &block
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
@@ -4,6 +4,7 @@ module IMW
4
4
  # command-line +imw+ tool.
5
5
  class Repository < Hash
6
6
  alias_method :datasets, :values
7
+ alias_method :handles, :keys
7
8
  end
8
9
 
9
10
  end
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[:skip_modules]
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
- def extend_appropriately!
77
- self.class.extend_resource!(self)
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
- def self.extend_resource_with_mod_or_string! resource, mod_or_string
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
- # Given a string "Mod::SubMod::SubSubMod" first split it into
265
- # its parts ["Mod", "SubMod", "SubSubMod"] and then begin
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
- matched_handles += IMW.repository.keys
80
+ IMW.repository.keys.sort
74
81
  else
75
- keys = IMW.repository.keys
76
- unless keys.empty?
77
- options[:selectors].each do |selector|
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
@@ -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
@@ -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= new_inputs
76
+ def inputs= raw_inputs
77
77
  @local_inputs, @remote_inputs = [], []
78
- new_inputs.each do |obj|
79
- input = obj.is_a?(IMW::Resource) ? obj : IMW.open(obj) # take either paths/URIs or IMW::Resource objects
78
+ raw_inputs.flatten.each do |raw_input|
79
+ input = IMW.open(raw_input)
80
80
  if input.is_local?
81
- @local_inputs << (input.directory? ? input.resources : input) # recurse through directories
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(*Dir["#{name}/**/*"]).mv(output.path) }
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
@@ -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 copy") # don't bother checking for remote resources
17
- source_scheme = 'file' # make sure it isn't blank
20
+ source.should_exist!("Cannot #{action}")
21
+ source_scheme = 'file'
18
22
  else
19
23
  source_scheme = source.scheme
20
24
  end
21
- destination_scheme = destination.is_local? ? 'file' : destination.scheme
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
- FileUtils.send(action, source.path, destination.path)
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
  #
@@ -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
@@ -109,7 +109,7 @@ class Array
109
109
 
110
110
  # Dump the data in this array to the resource at the given +uri+.
111
111
  def dump uri
112
- IMW.open(uri, :mode => 'w').dump(self)
112
+ IMW.open!(uri).dump(self)
113
113
  end
114
114
 
115
115
  end
@@ -203,6 +203,6 @@ class Hash
203
203
 
204
204
  # Dump the data from this Hash into the given +uri+.
205
205
  def dump uri
206
- IMW.open(uri).dump(self)
206
+ IMW.open!(uri).dump(self)
207
207
  end
208
208
  end
@@ -33,7 +33,7 @@ class String
33
33
 
34
34
  # Dump this string into the given +uri+.
35
35
  def dump uri
36
- IMW.open(uri).dump(self)
36
+ IMW.open!(uri).dump(self)
37
37
  end
38
38
 
39
39
  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
- class << self; attr_accessor :log end
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 banner *events
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
- def warn *events
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
  #
@@ -1,5 +1,5 @@
1
1
  require File.dirname(__FILE__) + "/../../spec_helper"
2
- require File.dirname(__FILE__) + "/../archive_spec"
2
+ require File.dirname(__FILE__) + "/../archives_spec"
3
3
 
4
4
  describe IMW::Archives::Rar do
5
5
 
@@ -1,5 +1,5 @@
1
1
  require File.dirname(__FILE__) + "/../../spec_helper"
2
- require File.dirname(__FILE__) + "/../archive_spec"
2
+ require File.dirname(__FILE__) + "/../archives_spec"
3
3
 
4
4
  describe IMW::Archives::Tar do
5
5
 
@@ -1,5 +1,5 @@
1
1
  require File.dirname(__FILE__) + "/../../spec_helper"
2
- require File.dirname(__FILE__) + "/../archive_spec"
2
+ require File.dirname(__FILE__) + "/../archives_spec"
3
3
  require File.dirname(__FILE__) + "/../compressed_files_spec"
4
4
 
5
5
  describe IMW::Archives::Tarbz2 do
@@ -1,5 +1,5 @@
1
1
  require File.dirname(__FILE__) + "/../../spec_helper"
2
- require File.dirname(__FILE__) + "/../archive_spec"
2
+ require File.dirname(__FILE__) + "/../archives_spec"
3
3
  require File.dirname(__FILE__) + "/../compressed_files_spec"
4
4
 
5
5
  describe IMW::Archives::Targz do
@@ -1,5 +1,5 @@
1
1
  require File.dirname(__FILE__) + "/../../spec_helper"
2
- require File.dirname(__FILE__) + "/../archive_spec"
2
+ require File.dirname(__FILE__) + "/../archives_spec"
3
3
 
4
4
  describe IMW::Archives::Zip do
5
5
 
@@ -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 + "/**/*"])
@@ -14,7 +14,6 @@ require File.join(File.dirname(__FILE__),'../spec_helper')
14
14
  # registered handler.
15
15
 
16
16
  share_examples_for "a compressed file" do
17
- include Spec::Matchers::IMW
18
17
 
19
18
  before do
20
19
  @root = File.join(IMWTest::TMP_DIR, 'a_compressed_file_shared_example_group')
@@ -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', :skip_modules => true)
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", :skip_modules => true)
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', :skip_modules => true)
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, :skip_modules => true)
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 => true)
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
- @local = IMW.open("foobar.txt")
6
- @http = IMW.open("http://www.google.com")
7
- @hdfs = IMW.open("hdfs:///path/to/foobar.txt")
8
- @s3 = IMW.open("s3://mybucket/foo/bar")
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
@@ -16,7 +16,7 @@ end
16
16
 
17
17
  Spec::Runner.configure do |config|
18
18
 
19
- config.include CustomMatchers
19
+ config.include IMWTest::CustomMatchers
20
20
 
21
21
  config.before do
22
22
  FileUtils.mkdir_p IMWTest::TMP_DIR
@@ -1,21 +1,28 @@
1
- module CustomMatchers
2
- def contain *paths
3
- paths = paths.flatten
4
- simple_matcher("contain #{paths.inspect}") do |given, matcher|
5
- given_contents = Dir[given + "/**/*"].map do |abs_path|
6
- abs_path[(given.length + 1)..-1]
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
- def exist
15
- simple_matcher("exist") do |given, matcher|
16
- matcher.failure_message = "expected #{given} to exist on disk"
17
- matcher.failure_message = "expected #{given} not to exist on disk"
18
- File.exist?(given)
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
- # h2. spec/imw/matchers/file_contents_matcher.rb -- matches contents of two files
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
- require 'ftools'
16
-
17
- module Spec
18
- module Matchers
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
- def failure_message
32
- "files #{@orig} and #{@copy} are different"
33
- end
9
+ def matches? copy
10
+ @copy = File.expand_path copy
11
+ File.compare(@orig,@copy)
12
+ end
34
13
 
35
- def negative_failure_message
36
- "expected files #{@orig} and #{@copy} to differ"
37
- end
14
+ def failure_message
15
+ "files #{@orig} and #{@copy} are different"
38
16
  end
39
17
 
40
- # Matches the contents of one file against another using
41
- # File.compare.
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 Spec
4
- module Matchers
5
- module IMW
3
+ module IMWTest
6
4
 
7
- class PathsMatcher
5
+ module CustomMatchers
8
6
 
9
- attr_accessor :given, :given_contents, :given_base, :to_match, :to_match_contents, :to_match_base
7
+ class PathsMatcher
10
8
 
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
9
+ attr_accessor :given, :given_contents, :given_base, :to_match, :to_match_contents, :to_match_base
23
10
 
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
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
- def negative_failure_message
31
- "expected contents of #{given} and #{to_match} to be different"
32
- end
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
- 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.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
- def contain_paths_like given, options={}
63
- PathsMatcher.new(given, options)
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 Spec
19
- module Matchers
20
- module IMW
21
-
22
- # Match the contents of two arrays without regard to the order
23
- # of their elements by treating each as a set.
24
- class WithoutRegardToOrder
25
-
26
- private
27
- def initialize known_array
28
- @known_array = known_array.to_set
29
- end
30
-
31
- public
32
- def matches? array_to_test
33
- @array_to_test = array_to_test.to_set
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
- # Check that the contents of one array match another without
50
- # regard to ordering.
51
- def match_without_regard_to_order known_array
52
- WithoutRegardToOrder.new(known_array)
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.1
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-14 00:00:00 -05:00
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