file_pipeline 0.0.7 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3b25bf4205819b6d0df2fcbb9a879c7855fc2b0a3cb973774049f44a7d6965b8
4
- data.tar.gz: 1191020063c4bb7669e9dfd88a03d539c7b081cd2f422decd87ac6bca288c86e
3
+ metadata.gz: ac388f4340b5d6327f4f83318e151654a1c1c15d9500a8fa1d2e9fcd1509c186
4
+ data.tar.gz: 2375865b7dc7d58334a81cbbb9df11f1b521480d5e803a2d550d04d7ef3f69d9
5
5
  SHA512:
6
- metadata.gz: 8ccb8dabb09322d7c3b6b258c8e4e06edb3a7774e36c1fc26421794b8c53915b219a85c8c9bf07da2bf203cd949a8fc484a1db1cb8ddf6d8443a5c2ba724d4ff
7
- data.tar.gz: 3e5a2ec367ab3a2d7280c9d6daaa41f6e3cadcba9b1b73bfdb891d4fef781bade2e4e5ffe970aee76e175ce43ea3ae82d967367f18b29f59dbffec180825262e
6
+ metadata.gz: 4f5a85862095d53802662177be37c0c147cf93a7861d6e3c2abb9eb080697f94fd63f3a605685da546b58bef781eb0e2322aa7efd61a9d9dbe70ccbeab47e659
7
+ data.tar.gz: f0380bd511501e8460526d54fd7cafe00d29d7404da642d721284eb3fde797e2e46077ec071a477848c8f992f1bbf9d9f49dcacee3dff52146fef6251d0a51a8
data/README.rdoc CHANGED
@@ -248,8 +248,7 @@ The <tt>#initialize</tt> method _must_ take an +options+ argument (a hash
248
248
  with a default value, or a <em>double splat</em>) and _must_ be exposed
249
249
  through an <tt>#options</tt> getter method.
250
250
 
251
- The options passed can be any for the file operation to properly configure
252
- a specific instance of a method.
251
+ The options passed can be any to properly configure an instance of the class.
253
252
 
254
253
  This requirement is imposed by the
255
254
  {#define_operation}[rdoc-ref:FilePipeline::Pipeline#define_operation] instance
@@ -296,20 +295,26 @@ The three arguments required for implementations of <tt>#run</tt> are:
296
295
  succession of modified versions has been created.
297
296
 
298
297
  The <em>original file</em> will only be used by file operations that require
299
- it for reference, e.g. to restore file metadata that was compromised by
300
- other file operations.
298
+ it for reference, e.g. to restore or recover file metadata that was compromised
299
+ by other file operations.
301
300
 
302
301
  ===== Return value
303
302
 
304
- The method _must_ return the path to the file that was created by the
305
- operation (perferrably in the _directory_). It _may_ also return a
306
- {Results}[rdoc-ref:FilePipeline::FileOperations::Results] object, containing the
307
- operation itself, a _success_ flag (+true+ or +false+), and any logs or data
308
- returned by the operation.
303
+ If the operation modifies the file (i.e. creates a new version), the +run+
304
+ method _must_ return the path to the file that was created (perferrably in the
305
+ _directory_). If it does not modify and no results are returned, it _must_
306
+ return +nil+.
307
+
308
+ The method _may_ return a
309
+ {Results}[rdoc-ref:FilePipeline::FileOperations::Results] object along with the
310
+ path or +nil+. The results object should contain the operation itself, a
311
+ _success_ flag (+true+ or +false+), and any logs or data returned by the
312
+ operation.
309
313
 
310
314
  If results are returned with the path to the created file, both values must
311
315
  be wrapped in an array, with the path as the first element, the results as
312
- the second.
316
+ the second. If the operation does not modify and therefore not return a path,
317
+ the first element of the array must be +nil+.
313
318
 
314
319
  ===== Example
315
320
 
@@ -367,15 +372,21 @@ logic to perform the actual file operation, but will call an
367
372
  {#operation method}[rdoc-label:label-The+operation+method] that _must_ be
368
373
  defined in the subclass unless the subclass overrides the <tt>#run</tt> method.
369
374
 
370
- The <tt>#run</tt> method will generate the new path that is passed to the
371
- <tt>#operation</tt> method, and to which the latter will write the new
372
- version of the file. The new file path will need an appropriate file type
373
- extension. The default behavior is to assume that the extension will be the
374
- same as for the file that was passed in as the basis from which the new
375
- version will be created. If the operation will result in a different file
376
- type, the subclass _should_ define a <tt>#target_extension</tt> method that
377
- returns the appropriate file extension (see
378
- {Target file extensions}[rdoc-label:label-Target+file+extensions]).
375
+ If the operation is modifying (creates a new version), the <tt>#run</tt> method
376
+ will generate the new path that is passed to the <tt>#operation</tt> method,
377
+ and to which the latter will write the new version of the file. The new file
378
+ path will need an appropriate file type extension. The default behavior is to
379
+ assume that the extension will be the same as for the file that was passed in as
380
+ the basis from which the new version will be created. If the operation will
381
+ result in a different file type, the subclass _should_ define a
382
+ <tt>#target_extension</tt> method that returns the appropriate file extension
383
+ (see {Target file extensions}[rdoc-label:label-Target+file+extensions]).
384
+
385
+ Subclasses of FileOperation are by default modifying. If the operation is not
386
+ modifying (does not create a new version of the file), the subclass _must_
387
+ override the <tt>#modiies?</tt> method or override the <tt>#run</tt> method to
388
+ ensure it does not return a file path (see
389
+ {Non-modifying operations}[rdoc-label:label-Non-modifying+operations]).
379
390
 
380
391
  ==== Initializer
381
392
 
@@ -490,6 +501,16 @@ return the appropriate
490
501
  return
491
502
  end
492
503
 
504
+ ==== Non-modifying operations
505
+
506
+ If the operation will not create a new version, the class _must_ redefine the
507
+ <tt>#modifies?</tt> method to return +false+:
508
+
509
+ # non-modiyfing operation
510
+ def modifies?
511
+ false
512
+ end
513
+
493
514
  ==== Target file extensions
494
515
 
495
516
  If the file that the operation creates is of a different type than the file
data/lib/file_pipeline.rb CHANGED
@@ -23,7 +23,7 @@ module FilePipeline
23
23
  return source_directories if source_directories.include? directory_path
24
24
 
25
25
  no_dir = !File.directory?(directory_path)
26
- raise Errors::SourceDirectoryError, dir: directory if no_dir
26
+ raise Errors::SourceDirectoryError.new dir: directory if no_dir
27
27
 
28
28
  @src_directories.prepend directory_path
29
29
  end
@@ -33,7 +33,7 @@ module FilePipeline
33
33
  def self.load(file_operation)
34
34
  const = file_operation.split('_').map(&:capitalize).join
35
35
  FilePipeline.load_file(file_operation) unless const_defined? const
36
- const_get 'FileOperations::' + const
36
+ const_get "FileOperations::#{const}"
37
37
  rescue NameError
38
38
  # TODO: implement autogenerating module names from file_operation src path
39
39
  const_get const
@@ -45,9 +45,10 @@ module FilePipeline
45
45
  src_file += '.rb' unless src_file.end_with? '.rb'
46
46
  src_path = FilePipeline.source_path src_file
47
47
  if src_path.nil?
48
- raise Errors::SourceFileError,
49
- file: src_file,
50
- directories: FilePipeline.source_directories
48
+ raise Errors::SourceFileError.new(
49
+ file: src_file,
50
+ directories: FilePipeline.source_directories
51
+ )
51
52
  end
52
53
  require src_path
53
54
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'errors/failed_modification_error'
4
+ require_relative 'errors/misplaced_version_file_error'
4
5
  require_relative 'errors/missing_version_file_error'
5
6
  require_relative 'errors/source_directory_error'
6
7
  require_relative 'errors/source_file_error'
@@ -12,7 +12,7 @@ module FilePipeline
12
12
  #
13
13
  # ===== Arguments
14
14
  #
15
- # * +msg+ - error message for the exception. If none provided, the
15
+ # * +msg+ - error message for the exception. If none provided, the
16
16
  # instance will be initialized with the #default_message.
17
17
  #
18
18
  # ===== Options
@@ -38,15 +38,15 @@ module FilePipeline
38
38
 
39
39
  private
40
40
 
41
- # Appends the backtrace of the error that caused the exception to the
41
+ # Appends the backtrace of the error that caused the exception to the
42
42
  # #default_message.
43
43
  def append_backtrace(str)
44
- return str + "\n" unless original_backtrace
44
+ return "#{str}\n" unless original_backtrace
45
45
 
46
- str + " Backtrace:\n#{original_backtrace}"
46
+ "#{str} Backtrace:\n#{original_backtrace}"
47
47
  end
48
48
 
49
- # Appends the message of the error that caused the exception to the
49
+ # Appends the message of the error that caused the exception to the
50
50
  # #default_message.
51
51
  def append_error(str)
52
52
  return str unless original_error
@@ -58,7 +58,7 @@ module FilePipeline
58
58
 
59
59
  # Returns a String with the #message for +self+.
60
60
  def default_message
61
- if info&.respond_to?(:operation) && info&.respond_to?(:log)
61
+ if info.respond_to?(:operation) && info.respond_to?(:log)
62
62
  msg = "#{info.operation&.name} with options"\
63
63
  " #{info.operation&.options} failed on #{@file}."
64
64
  append_error msg
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FilePipeline
4
+ module Errors
5
+ # Error class for exceptions that are raised when a new version is added,
6
+ # but the file is not in the VersionedFile's working directory.
7
+ class MisplacedVersionFileError < StandardError
8
+ # Path for of the misplaced file for the version.
9
+ attr_reader :file
10
+
11
+ # Path for the directory where the file should have been (the
12
+ # VersionedFile's working directory).
13
+ attr_reader :directory
14
+
15
+ def initialize(msg = nil, file: nil, directory: nil)
16
+ @file = file
17
+ @directory = directory
18
+ msg ||= default_message
19
+ super msg
20
+ end
21
+
22
+ private
23
+
24
+ def default_message
25
+ "File #{File.basename @file} was expected in #{@directory},"\
26
+ " but was in #{File.dirname @file}."
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FilePipeline
4
+ module FileOperations
5
+ # A non-modifying FileOperation that compares a file's _Exif_ Metadata with
6
+ # that of a reference file and returns tags missing in the working file as
7
+ # captured data.
8
+ #
9
+ # Used to recover _Exif_ tags that were not preserved during e.g. a file
10
+ # conversion.
11
+ class ExifRecovery < FileOperation
12
+ include ExifManipulable
13
+
14
+ # :args: options
15
+ #
16
+ # Returns a new instance.
17
+ #
18
+ # ===== Options
19
+ #
20
+ # * <tt>skip_tags</tt> - _Exif_ tags to be ignored during comparison.
21
+ #
22
+ # The ExifManipulable mixin defines a set of _Exif_
23
+ # {tags}[rdoc-ref:FilePipeline::FileOperations::ExifManipulable.file_tags]
24
+ # that will always be ignored.
25
+ def initialize(**opts)
26
+ defaults = { skip_tags: [] }
27
+ super(opts, defaults)
28
+ @options[:skip_tags] += ExifManipulable.file_tags
29
+ end
30
+
31
+ # Returns the DROPPED_EXIF_DATA tag defined in CapturedDataTags.
32
+ #
33
+ # Instances of ExifRecovery will capture any _Exif_ tags and their values
34
+ # that are present in the reference file but missing in the working file.
35
+ def captured_data_tag
36
+ CapturedDataTags::DROPPED_EXIF_DATA
37
+ end
38
+
39
+ # Instances of ExifRecovery do not modify the working file.
40
+ def modifies?
41
+ false
42
+ end
43
+
44
+ # Compares the _Exif_ metadata of <tt>src_file</tt> with that of
45
+ # +original+ and returns all tags that are present in +original+ but
46
+ # missing in <tt>src_file</tt>.
47
+ def operation(src_file, _, original)
48
+ original_exif, src_file_exif = read_exif original, src_file
49
+ missing_exif_fields(src_file_exif, original_exif)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -2,9 +2,12 @@
2
2
 
3
3
  module FilePipeline
4
4
  module FileOperations
5
- # A FileOperation that compares Exif Metadata in two files and copies tags
6
- # missing in one from the other. Used to restore Exif tags that were not
7
- # preserved during e.g. a file conversion.
5
+ # A modifying FileOperation that compares a file's Exif Metadata with that
6
+ # of a reference file and attempts to copy tags missing in the working file
7
+ # from the reference file.
8
+ #
9
+ # Used to restore Exif tags that were not preserved during e.g. a file
10
+ # conversion.
8
11
  #
9
12
  # *Caveat:* if this operation is applied to a file together with
10
13
  # ExifRedaction, it should be applied _before_ the latter, to avoid
@@ -20,10 +23,9 @@ module FilePipeline
20
23
  #
21
24
  # * <tt>skip_tags</tt> - _Exif_ tags to be ignored during restoration.
22
25
  #
23
- # The ExifManipulable mixin defines a set of _Exif_ tags that will always
24
- # be ignored. These are tags relating to the file properties (e.g.
25
- # filesize, MIME-type) that will have been altered by any prior operation,
26
- # such as file format conversions.
26
+ # The ExifManipulable mixin defines a set of _Exif_
27
+ # {tags}[rdoc-ref:FilePipeline::FileOperations::ExifManipulable.file_tags]
28
+ # that will always be ignored.
27
29
  def initialize(**opts)
28
30
  defaults = { skip_tags: [] }
29
31
  super(opts, defaults)
@@ -38,8 +40,6 @@ module FilePipeline
38
40
  CapturedDataTags::DROPPED_EXIF_DATA
39
41
  end
40
42
 
41
- # :args: src_file, out_file
42
- #
43
43
  # Writes a new version of <tt>src_file</tt> to <tt>out_file</tt> with all
44
44
  # writable _Exif_ tags from +original+ restored.
45
45
  #
@@ -34,7 +34,7 @@ module FilePipeline
34
34
  def operation(*args)
35
35
  src_file, out_file = args
36
36
  image = Vips::Image.new_from_file src_file
37
- image.tiffsave(out_file, options)
37
+ image.tiffsave(out_file, **options)
38
38
  # Return lof if any
39
39
  end
40
40
 
@@ -9,6 +9,10 @@ module FilePipeline
9
9
  # Returns an Array of tags to be ignored during comparison. These can
10
10
  # be merged with an ExifManipulable including FileOperation's options
11
11
  # to skip tags (e.g. the <tt>skip_tags</tt> option in ExifRestoration).
12
+ #
13
+ # The included tags relate to the file properties (e.g. filesize,
14
+ # MIME-type) that will have been altered by any prior operation, such as
15
+ # file format conversions.
12
16
  def self.file_tags
13
17
  %w[FileSize FileModifyDate FileAccessDate FileInodeChangeDate
14
18
  FilePermissions FileType FileTypeExtension MIMEType]
@@ -20,7 +24,7 @@ module FilePipeline
20
24
  end
21
25
 
22
26
  def self.strip_path(str) # :nodoc:
23
- str.sub(%r{ - \/?(\/|[-:.]+|\w+)+\.\w+$}, '')
27
+ str.sub(%r{ - /?(/|[-:.]+|\w+)+\.\w+$}, '')
24
28
  end
25
29
 
26
30
  # Redacts (deletes) all <tt>tags_to_delete</tt> in <tt>out_file</tt>.
@@ -18,6 +18,9 @@ module FilePipeline
18
18
  # that is passed to #run or #operation as <tt>src_file</tt>, the subclass
19
19
  # must have a #target_extension method that returns the appropriate
20
20
  # extension.
21
+ #
22
+ # If the operation is non-modifying, the subclass must redefine the
23
+ # #modifies? methods to return +false+.
21
24
  class FileOperation
22
25
  # A Hash; any options used when performing #operation.
23
26
  attr_reader :options
@@ -62,6 +65,12 @@ module FilePipeline
62
65
  results false, log_data
63
66
  end
64
67
 
68
+ # Returns +true+ if the FIleOperation will create a new version.
69
+ # _Default:_ +true+.
70
+ def modifies?
71
+ true
72
+ end
73
+
65
74
  # Returns the class name (string) of +self+ _without_ the names of the
66
75
  # modules that the class is nested in.
67
76
  def name
@@ -133,11 +142,11 @@ module FilePipeline
133
142
  # e.g. when exif metadata tags missing in the <tt>src_file</tt> are to
134
143
  # be copied over from another file.
135
144
  def run(src_file, directory, original = nil)
136
- out_file = target directory, extension(src_file)
145
+ out_file = target directory, extension(src_file) if modifies?
137
146
  log_data = operation src_file, out_file, original
138
147
  [out_file, success(log_data)]
139
148
  rescue StandardError => e
140
- FileUtils.rm out_file if File.exist? out_file
149
+ FileUtils.rm out_file if out_file && File.exist?(out_file)
141
150
  [out_file, failure(e)]
142
151
  end
143
152
 
@@ -41,10 +41,7 @@ module FilePipeline
41
41
  # Adds a file operation object #file_operations. The object must implement
42
42
  # a _run_ method (see FileOperations::FileOperation#run for details).
43
43
  def <<(file_operation_instance)
44
- unless file_operation_instance.respond_to? :run
45
- raise TypeError, 'File operations must implement a #run method'
46
- end
47
-
44
+ validate file_operation_instance
48
45
  @file_operations << file_operation_instance
49
46
  end
50
47
 
@@ -88,7 +85,7 @@ module FilePipeline
88
85
  #
89
86
  def define_operation(file_operation, options = {})
90
87
  operation = FilePipeline.load file_operation
91
- self << operation.new(options)
88
+ self << operation.new(**options)
92
89
  self
93
90
  end
94
91
 
@@ -106,5 +103,15 @@ module FilePipeline
106
103
  operation.run version, directory, original
107
104
  end
108
105
  end
106
+
107
+ private
108
+
109
+ # Raises TypeError if <tt>file_operation_instance</tt> does not implement a
110
+ # #run method.
111
+ def validate(file_operation_instance)
112
+ return file_operation_instance if file_operation_instance.respond_to? :run
113
+
114
+ raise TypeError, 'File operations must implement a #run method'
115
+ end
109
116
  end
110
117
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'versions/validator'
3
4
  module FilePipeline
4
5
  # VersionedFile creates a directory where it stores any versions of _file_.
5
6
  class VersionedFile
@@ -81,14 +82,10 @@ module FilePipeline
81
82
  # <tt>version_info</tt> must be a path to an existing file or an array with
82
83
  # the path and optionally a FileOperations::Results instance:
83
84
  # <tt>['path/to/file', results_object]</tt>.
84
- # Will move the file to #directory if it is in another directory.
85
+ # Will raise MisplacedVersionFileError if it is in another directory.
85
86
  def <<(version_info)
86
- file, info = version_info
87
- if info&.failure
88
- raise Errors::FailedModificationError, info: info, file: original
89
- end
90
-
91
- version = validate(file)
87
+ version, info = Versions::Validator[version_info, self]
88
+ version ||= @current
92
89
  @history[version] = info
93
90
  self
94
91
  rescue StandardError => e
@@ -144,7 +141,9 @@ module FilePipeline
144
141
  # * +true+ - The finalized version will replace the #original.
145
142
  def finalize(overwrite: false)
146
143
  yield(self) if block_given?
147
- filename = overwrite ? replacing_trarget : preserving_taget
144
+ return original unless changed?
145
+
146
+ filename = overwrite ? replacing_target : preserving_target
148
147
  FileUtils.rm original if overwrite
149
148
  @original = Versions.copy(current, original_dir, filename)
150
149
  ensure
@@ -165,10 +164,12 @@ module FilePipeline
165
164
  # than exif.
166
165
  #++
167
166
  def metadata(for_version: :current)
168
- if %i[current original].include? for_version
169
- file = public_send(for_version)
170
- end
171
- file ||= for_version
167
+ file = case for_version
168
+ when :current, :original
169
+ public_send for_version
170
+ else
171
+ for_version
172
+ end
172
173
  read_exif(file).first
173
174
  end
174
175
 
@@ -198,6 +199,7 @@ module FilePipeline
198
199
  # FileOperations::CapturedDataTags::DROPPED_EXIF_DATA has been merged.
199
200
  def recovered_metadata
200
201
  return unless changed?
202
+
201
203
  captured_data_with(FileOperations::CapturedDataTags::DROPPED_EXIF_DATA)
202
204
  &.reduce({}) { |recovered, data| recovered.merge data }
203
205
  end
@@ -208,13 +210,13 @@ module FilePipeline
208
210
 
209
211
  # Returns the filename for a target file that will not overwrite the
210
212
  # original.
211
- def preserving_taget
212
- basename + '_' + target_suffix + current_extension
213
+ def preserving_target
214
+ "#{basename}_#{target_suffix}#{current_extension}"
213
215
  end
214
216
 
215
217
  # Returns the filename for a target file that will overwrite the
216
218
  # original.
217
- def replacing_trarget
219
+ def replacing_target
218
220
  basename + current_extension
219
221
  end
220
222
 
@@ -224,25 +226,13 @@ module FilePipeline
224
226
  history.clear!
225
227
  end
226
228
 
227
- # Validates if file exists and has been stored in #directory.
228
- def validate(file)
229
- return current unless file
230
-
231
- raise Errors::MissingVersionFileError, file: file unless File.exist? file
232
-
233
- return file if File.dirname(file) == directory
234
-
235
- Versions.move file, directory, File.basename(file)
236
- end
237
-
238
229
  # Creates the directory containing all version files. Directory name is
239
230
  # composed of the basename plus '_version'.
240
231
  #
241
232
  # Raises SystemCallError if the directory already exists.
242
233
  def workdir
243
- subdir = basename + '_versions'
244
234
  filedir = File.dirname(original)
245
- dirname = File.join filedir, subdir
235
+ dirname = File.join filedir, "#{basename}_versions"
246
236
  FileUtils.mkdir(dirname)
247
237
  File.path dirname
248
238
  end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FilePipeline
4
+ module Versions
5
+ # Validator objects verify the version file and results returned by a
6
+ # FileOperation.
7
+ #
8
+ # They will validate:
9
+ # - that the version file existst
10
+ # - that it is in the correct directory
11
+ # - that the file operation has not returned any failures
12
+ class Validator
13
+ extend Forwardable
14
+
15
+ # File for the version that resulted from a FileOperation.
16
+ attr_reader :file
17
+
18
+ # FileOperation::Results object.
19
+ attr_reader :info
20
+
21
+ # Returns a new instance.
22
+ #
23
+ # ===== Arguments
24
+ #
25
+ # * <tt>version_info</tt> - path to an existing file or an array with the
26
+ # path and optionally a FileOperations::Results instance.
27
+ # * +directory+ - directory where the file is expected (the working
28
+ # directory of a VersionedFile).
29
+ # * +filename+ - name of the file to be returned if the file operation was
30
+ # was non-modifying (usually the VersionedFile#original).
31
+ def initialize(version_info, directory, filename)
32
+ @file, @info = [version_info].flatten
33
+ @directory = directory
34
+ @filename = filename
35
+ end
36
+
37
+ # Validates file, directory, and info for <tt>version_info</tt> in the
38
+ # context of <tt>versioned_file</tt>.
39
+ #
40
+ # ===== Arguments
41
+ #
42
+ # * <tt>version_info</tt> - path to an existing file or an array with the
43
+ # path and optionally a FileOperations::Results instance.
44
+ # * <tt>versioned_file</tt> - an object that responds to #original and
45
+ # returns a file path, and #directory and returns a directory path.
46
+ def self.[](version_info, versioned_file)
47
+ new(version_info, versioned_file.directory, versioned_file.original)
48
+ .validate_info
49
+ .validate_file
50
+ .validate_directory
51
+ .then { |validator| [validator.file, validator.info] }
52
+ end
53
+
54
+ # Returns +true+ when there is no file for the version (result of a
55
+ # non-modifying file operation), +false+ otherwise.
56
+ def unmodified?
57
+ @file.nil?
58
+ end
59
+
60
+ # Raises MisplacedVersionFileError if #file is not in #directory.
61
+ def validate_directory
62
+ return self if unmodified? || File.dirname(@file) == @directory
63
+
64
+ raise Errors::MisplacedVersionFileError.new file: @file,
65
+ directory: @directory
66
+ end
67
+
68
+ # Raises MissingVersionFileError if #file does not exist on the file
69
+ # system.
70
+ def validate_file
71
+ return self if unmodified? || File.exist?(@file)
72
+
73
+ raise Errors::MissingVersionFileError.new file: @file
74
+ end
75
+
76
+ # Raises FailedModificationError if the file operation generatint the
77
+ # #info failed.
78
+ def validate_info
79
+ return self unless @info&.failure
80
+
81
+ raise Errors::FailedModificationError.new info: @info, file: @filename
82
+ end
83
+ end
84
+ end
85
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: file_pipeline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Stein
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-09 00:00:00.000000000 Z
11
+ date: 2021-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_exiftool
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.11.0
19
+ version: 0.16.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.11.0
26
+ version: 0.16.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: ruby-vips
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 2.0.16
33
+ version: '2.1'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 2.0.16
40
+ version: '2.1'
41
41
  description: The file_pipeline gem provides a framework for nondestructive application
42
42
  of file operation batches to files.
43
43
  email: loveablelobster@fastmail.fm
@@ -50,11 +50,13 @@ files:
50
50
  - lib/file_pipeline.rb
51
51
  - lib/file_pipeline/errors.rb
52
52
  - lib/file_pipeline/errors/failed_modification_error.rb
53
+ - lib/file_pipeline/errors/misplaced_version_file_error.rb
53
54
  - lib/file_pipeline/errors/missing_version_file_error.rb
54
55
  - lib/file_pipeline/errors/source_directory_error.rb
55
56
  - lib/file_pipeline/errors/source_file_error.rb
56
57
  - lib/file_pipeline/file_operations.rb
57
58
  - lib/file_pipeline/file_operations/captured_data_tags.rb
59
+ - lib/file_pipeline/file_operations/default_operations/exif_recovery.rb
58
60
  - lib/file_pipeline/file_operations/default_operations/exif_redaction.rb
59
61
  - lib/file_pipeline/file_operations/default_operations/exif_restoration.rb
60
62
  - lib/file_pipeline/file_operations/default_operations/ptiff_conversion.rb
@@ -67,11 +69,12 @@ files:
67
69
  - lib/file_pipeline/versioned_file.rb
68
70
  - lib/file_pipeline/versions.rb
69
71
  - lib/file_pipeline/versions/history.rb
72
+ - lib/file_pipeline/versions/validator.rb
70
73
  homepage: https://github.com/loveablelobster/file_pipeline
71
74
  licenses:
72
75
  - MIT
73
76
  metadata: {}
74
- post_install_message:
77
+ post_install_message:
75
78
  rdoc_options: []
76
79
  require_paths:
77
80
  - lib
@@ -79,15 +82,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
82
  requirements:
80
83
  - - ">="
81
84
  - !ruby/object:Gem::Version
82
- version: '2.6'
85
+ version: '3.0'
83
86
  required_rubygems_version: !ruby/object:Gem::Requirement
84
87
  requirements:
85
88
  - - ">="
86
89
  - !ruby/object:Gem::Version
87
90
  version: '0'
88
91
  requirements: []
89
- rubygems_version: 3.0.6
90
- signing_key:
92
+ rubygems_version: 3.2.15
93
+ signing_key:
91
94
  specification_version: 4
92
95
  summary: Nondestructive file processing with a defined batch
93
96
  test_files: []