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