class FilePipeline::VersionedFile
VersionedFile
creates a directory where it stores any versions of file.
Attributes
The basename of the versioned file.
A hash with file paths as keys, information on the modifications applied to create the version as values (instances of FileOperations::Results
).
The path to the original file of self.
A String that is appended to the file basename when the file written by finalize
is not replacing the original.
Public Class Methods
Returns a new instance with file
as the original
.
Arguments¶ ↑
-
file
- Path to the file the instance will be based on. That file should not be touched unlessfinalize
is called with the:overwrite
option set totrue
.
Caveat it can not be ruled out that buggy or malignant file operations modify the original.
Options¶ ↑
<tt>target_suffix</ttm> is a string to be appended to the file that will be written by finalize
(the last version) if finalize
is to preserve the original. It is recommended to use a randomized string (default) to avoid clashes with other files in the directory.
# File lib/file_pipeline/versioned_file.rb, line 69 def initialize(file, target_suffix: SecureRandom.hex(4)) raise Errors::MissingVersionFileError, file: file unless File.exist? file @original = file @basename = File.basename(file, '.*') @history = Versions::History.new @directory = nil @target_suffix = target_suffix history[original] = nil end
Public Instance Methods
Adds a new version to history
and returns self.
version_info
must be a path to an existing file or an array with the path and optionally a FileOperations::Results
instance: ['path/to/file', results_object]
. Will raise MisplacedVersionFileError if it is in another directory.
# File lib/file_pipeline/versioned_file.rb, line 86 def <<(version_info) version, info = Versions::Validator[version_info, self] version ||= @current @history[version] = info self rescue StandardError => e reset raise e end
Returns true
if there are versions (file has been modified).
Warning: It will also return true
if the file has been cloned.
# File lib/file_pipeline/versioned_file.rb, line 99 def changed? current != original end
Creates a new identical version of current
. Will only add the path of the file to history, but no FileOperations::Results
.
# File lib/file_pipeline/versioned_file.rb, line 105 def clone filename = FilePipeline.new_basename + current_extension clone_file = Versions.copy(current, directory, filename) self << clone_file end
Returns the path to the current file or the original
if no versions have been created.
# File lib/file_pipeline/versioned_file.rb, line 113 def current versions.last || original end
Returns the file extension for the current
file.
# File lib/file_pipeline/versioned_file.rb, line 118 def current_extension File.extname current end
Returns the path to the directory where the versioned of self
are stored. Creates the directory if it does not exist.
# File lib/file_pipeline/versioned_file.rb, line 124 def directory @directory ||= workdir end
Writes the current
version to basename
, optionally the target_suffix
, and the current_extension
in original_dir
. Deletes all versions and resets the history
to an empty Hash. Returns the path to the written file.
If the optional block is passed, it will be evaluated before the file is finalized.
Options¶ ↑
-
overwrite
-true
orfalse
-
false
(default) - Thetarget_suffix
will be appended to thebasename
and theoriginal
will be preserved. -
true
- The finalized version will replace theoriginal
.
-
# File lib/file_pipeline/versioned_file.rb, line 142 def finalize(overwrite: false) yield(self) if block_given? return original unless changed? filename = overwrite ? replacing_target : preserving_target FileUtils.rm original if overwrite @original = Versions.copy(current, original_dir, filename) ensure reset end
Creates a new version. Requires a block that must return a path to an existing file or an array with the path and optionally a FileOperations::Results
instance: ['path/to/file', results_object]
.
The actual file modification logic will be in the block.
The block must take three arguments: for the current
file (from which the modified version will be created), the work directory
(to where the modified file will be written), and the original
file (which will only be used in modifications that need the original file for reference, such as modifications that restore file metadata that was lost in other modifications).
# File lib/file_pipeline/versioned_file.rb, line 189 def modify self << yield(current, directory, original) end
Returns the directory where original
is stored.
# File lib/file_pipeline/versioned_file.rb, line 194 def original_dir File.dirname original end
Returns a hash into which all captured data from file operations with the FileOperations::CapturedDataTags::DROPPED_EXIF_DATA has been merged.
# File lib/file_pipeline/versioned_file.rb, line 200 def recovered_metadata return unless changed? captured_data_with(FileOperations::CapturedDataTags::DROPPED_EXIF_DATA) &.reduce({}) { |recovered, data| recovered.merge data } end
Private Instance Methods
Returns the filename for a target file that will not overwrite the original.
# File lib/file_pipeline/versioned_file.rb, line 213 def preserving_target "#{basename}_#{target_suffix}#{current_extension}" end
Returns the filename for a target file that will overwrite the original.
# File lib/file_pipeline/versioned_file.rb, line 219 def replacing_target basename + current_extension end
Deletes the work directory and resets versions
# File lib/file_pipeline/versioned_file.rb, line 224 def reset FileUtils.rm_r directory, force: true history.clear! end
Creates the directory containing all version files. Directory name is composed of the basename plus '_version'.
Raises SystemCallError if the directory already exists.
# File lib/file_pipeline/versioned_file.rb, line 233 def workdir filedir = File.dirname(original) dirname = File.join filedir, "#{basename}_versions" FileUtils.mkdir(dirname) File.path dirname end