mini_exiftool 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog +3 -0
- data/lib/mini_exiftool.new.rb +445 -0
- data/lib/mini_exiftool.rb +4 -4
- data/x.rb +3 -0
- metadata +38 -22
data/Changelog
CHANGED
@@ -0,0 +1,445 @@
|
|
1
|
+
#
|
2
|
+
# MiniExiftool
|
3
|
+
#
|
4
|
+
# This library is wrapper for the Exiftool command-line
|
5
|
+
# application (http://www.sno.phy.queensu.ca/~phil/exiftool/)
|
6
|
+
# written by Phil Harvey.
|
7
|
+
# Read and write access is done in a clean OO manner.
|
8
|
+
#
|
9
|
+
# Author: Jan Friedrich
|
10
|
+
# Copyright (c) 2007, 2008 by Jan Friedrich
|
11
|
+
# Licensed under the GNU LESSER GENERAL PUBLIC LICENSE,
|
12
|
+
# Version 2.1, February 1999
|
13
|
+
#
|
14
|
+
|
15
|
+
require 'fileutils'
|
16
|
+
require 'tempfile'
|
17
|
+
require 'pstore'
|
18
|
+
require 'set'
|
19
|
+
|
20
|
+
# Simple OO access to the Exiftool command-line application.
|
21
|
+
class MiniExiftool
|
22
|
+
|
23
|
+
# Name of the Exiftool command-line application
|
24
|
+
@@cmd = 'exiftool'
|
25
|
+
|
26
|
+
# Hash of the standard options used when call MiniExiftool.new
|
27
|
+
@@opts = { :numerical => false, :composite => true, :convert_encoding => false, :timestamps => Time }
|
28
|
+
|
29
|
+
attr_reader :filename
|
30
|
+
attr_accessor :numerical, :composite, :convert_encoding, :errors, :timestamps
|
31
|
+
|
32
|
+
VERSION = '1.0.1'
|
33
|
+
|
34
|
+
# +opts+ support at the moment
|
35
|
+
# * <code>:numerical</code> for numerical values, default is +false+
|
36
|
+
# * <code>:composite</code> for including composite tags while loading,
|
37
|
+
# default is +true+
|
38
|
+
# * <code>:convert_encoding</code> convert encoding (See -L-option of
|
39
|
+
# the exiftool command-line application, default is +false+
|
40
|
+
# * <code>:timestamps</code> generating DateTime objects instead of
|
41
|
+
# Time objects if set to <code>DateTime</code>, default is +Time+
|
42
|
+
#
|
43
|
+
# <b>ATTENTION:</b> Time objects are created using <code>Time.local</code>
|
44
|
+
# therefore they use <em>your local timezone</em>, DateTime objects instead
|
45
|
+
# are created <em>without timezone</em>!
|
46
|
+
def initialize filename=nil, opts={}
|
47
|
+
opts = @@opts.merge opts
|
48
|
+
@numerical = opts[:numerical]
|
49
|
+
@composite = opts[:composite]
|
50
|
+
@convert_encoding = opts[:convert_encoding]
|
51
|
+
@timestamps = opts[:timestamps]
|
52
|
+
@values = TagHash.new
|
53
|
+
@tag_names = TagHash.new
|
54
|
+
@changed_values = TagHash.new
|
55
|
+
@errors = TagHash.new
|
56
|
+
load filename unless filename.nil?
|
57
|
+
end
|
58
|
+
|
59
|
+
def initialize_from_hash hash # :nodoc:
|
60
|
+
hash.each_pair do |tag,value|
|
61
|
+
set_value tag, value
|
62
|
+
end
|
63
|
+
set_attributes_by_heuristic
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
# Load the tags of filename.
|
68
|
+
def load filename
|
69
|
+
unless filename && File.exist?(filename)
|
70
|
+
raise MiniExiftool::Error.new("File '#{filename}' does not exist.")
|
71
|
+
end
|
72
|
+
if File.directory?(filename)
|
73
|
+
raise MiniExiftool::Error.new("'#{filename}' is a directory.")
|
74
|
+
end
|
75
|
+
@filename = filename
|
76
|
+
@values.clear
|
77
|
+
@tag_names.clear
|
78
|
+
@changed_values.clear
|
79
|
+
opt_params = ''
|
80
|
+
opt_params << (@numerical ? '-n ' : '')
|
81
|
+
opt_params << (@composite ? '' : '-e ')
|
82
|
+
opt_params << (@convert_encoding ? '-L ' : '')
|
83
|
+
cmd = %Q(#@@cmd -q -q -s -t #{opt_params} #{@@sep_op} "#{filename}")
|
84
|
+
if run(cmd)
|
85
|
+
parse_output
|
86
|
+
else
|
87
|
+
raise MiniExiftool::Error.new(@error_text)
|
88
|
+
end
|
89
|
+
self
|
90
|
+
end
|
91
|
+
|
92
|
+
# Reload the tags of an already readed file.
|
93
|
+
def reload
|
94
|
+
load @filename
|
95
|
+
end
|
96
|
+
|
97
|
+
# Returns the value of a tag.
|
98
|
+
def [] tag
|
99
|
+
@changed_values[tag] || @values[tag]
|
100
|
+
end
|
101
|
+
|
102
|
+
# Set the value of a tag.
|
103
|
+
def []=(tag, val)
|
104
|
+
@changed_values[tag] = val
|
105
|
+
end
|
106
|
+
|
107
|
+
# Returns true if any tag value is changed or if the value of a
|
108
|
+
# given tag is changed.
|
109
|
+
def changed? tag=false
|
110
|
+
if tag
|
111
|
+
@changed_values.include? tag
|
112
|
+
else
|
113
|
+
!@changed_values.empty?
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Revert all changes or the change of a given tag.
|
118
|
+
def revert tag=nil
|
119
|
+
if tag
|
120
|
+
val = @changed_values.delete(tag)
|
121
|
+
res = val != nil
|
122
|
+
else
|
123
|
+
res = @changed_values.size > 0
|
124
|
+
@changed_values.clear
|
125
|
+
end
|
126
|
+
res
|
127
|
+
end
|
128
|
+
|
129
|
+
# Returns an array of the tags (original tag names) of the readed file.
|
130
|
+
def tags
|
131
|
+
@values.keys.map { |key| @tag_names[key] }
|
132
|
+
end
|
133
|
+
|
134
|
+
# Returns an array of all changed tags.
|
135
|
+
def changed_tags
|
136
|
+
@changed_values.keys.map { |key| MiniExiftool.original_tag(key) }
|
137
|
+
end
|
138
|
+
|
139
|
+
# Save the changes to the file.
|
140
|
+
def save
|
141
|
+
return false if @changed_values.empty?
|
142
|
+
@errors.clear
|
143
|
+
temp_file = Tempfile.new('mini_exiftool')
|
144
|
+
temp_file.close
|
145
|
+
temp_filename = temp_file.path
|
146
|
+
FileUtils.cp filename, temp_filename
|
147
|
+
all_ok = true
|
148
|
+
@changed_values.each do |tag, val|
|
149
|
+
original_tag = MiniExiftool.original_tag(tag)
|
150
|
+
arr_val = val.kind_of?(Array) ? val : [val]
|
151
|
+
arr_val.map! {|e| convert e}
|
152
|
+
tag_params = ''
|
153
|
+
arr_val.each do |v|
|
154
|
+
tag_params << %Q(-#{original_tag}="#{v}" )
|
155
|
+
end
|
156
|
+
opt_params = ''
|
157
|
+
opt_params << (arr_val.detect {|x| x.kind_of?(Numeric)} ? '-n ' : '')
|
158
|
+
opt_params << (@convert_encoding ? '-L ' : '')
|
159
|
+
cmd = %Q(#@@cmd -q -P -overwrite_original #{opt_params} #{tag_params} "#{temp_filename}")
|
160
|
+
result = run(cmd)
|
161
|
+
unless result
|
162
|
+
all_ok = false
|
163
|
+
@errors[tag] = @error_text.gsub(/Nothing to do.\n\z/, '').chomp
|
164
|
+
end
|
165
|
+
end
|
166
|
+
if all_ok
|
167
|
+
FileUtils.cp temp_filename, filename
|
168
|
+
reload
|
169
|
+
end
|
170
|
+
temp_file.delete
|
171
|
+
all_ok
|
172
|
+
end
|
173
|
+
|
174
|
+
# Returns a hash of the original loaded values of the MiniExiftool
|
175
|
+
# instance.
|
176
|
+
def to_hash
|
177
|
+
result = {}
|
178
|
+
@values.each do |k,v|
|
179
|
+
result[@tag_names[k]] = v
|
180
|
+
end
|
181
|
+
result
|
182
|
+
end
|
183
|
+
|
184
|
+
# Returns a YAML representation of the original loaded values of the
|
185
|
+
# MiniExiftool instance.
|
186
|
+
def to_yaml
|
187
|
+
to_hash.to_yaml
|
188
|
+
end
|
189
|
+
|
190
|
+
# Create a MiniExiftool instance from a hash
|
191
|
+
def self.from_hash hash
|
192
|
+
instance = MiniExiftool.new
|
193
|
+
instance.initialize_from_hash hash
|
194
|
+
instance
|
195
|
+
end
|
196
|
+
|
197
|
+
# Create a MiniExiftool instance from YAML data created with
|
198
|
+
# MiniExiftool#to_yaml
|
199
|
+
def self.from_yaml yaml
|
200
|
+
MiniExiftool.from_hash YAML.load(yaml)
|
201
|
+
end
|
202
|
+
|
203
|
+
# Returns the command name of the called Exiftool application.
|
204
|
+
def self.command
|
205
|
+
@@cmd
|
206
|
+
end
|
207
|
+
|
208
|
+
# Setting the command name of the called Exiftool application.
|
209
|
+
def self.command= cmd
|
210
|
+
@@cmd = cmd
|
211
|
+
end
|
212
|
+
|
213
|
+
# Returns the options hash.
|
214
|
+
def self.opts
|
215
|
+
@@opts
|
216
|
+
end
|
217
|
+
|
218
|
+
# Returns a set of all known tags of Exiftool.
|
219
|
+
def self.all_tags
|
220
|
+
unless defined? @@all_tags
|
221
|
+
@@all_tags = pstore_get :all_tags
|
222
|
+
end
|
223
|
+
@@all_tags
|
224
|
+
end
|
225
|
+
|
226
|
+
# Returns a set of all possible writable tags of Exiftool.
|
227
|
+
def self.writable_tags
|
228
|
+
unless defined? @@writable_tags
|
229
|
+
@@writable_tags = pstore_get :writable_tags
|
230
|
+
end
|
231
|
+
@@writable_tags
|
232
|
+
end
|
233
|
+
|
234
|
+
# Returns the original Exiftool name of the given tag
|
235
|
+
def self.original_tag tag
|
236
|
+
unless defined? @@all_tags_map
|
237
|
+
@@all_tags_map = pstore_get :all_tags_map
|
238
|
+
end
|
239
|
+
@@all_tags_map[tag]
|
240
|
+
end
|
241
|
+
|
242
|
+
# Returns the version of the Exiftool command-line application.
|
243
|
+
def self.exiftool_version
|
244
|
+
output = `#{MiniExiftool.command} -ver 2>&1`
|
245
|
+
unless $?.exitstatus == 0
|
246
|
+
raise MiniExiftool::Error.new("Command '#{MiniExiftool.command}' not found")
|
247
|
+
end
|
248
|
+
output.chomp!
|
249
|
+
end
|
250
|
+
|
251
|
+
def self.unify tag
|
252
|
+
tag.gsub(/[-_]/,'').downcase
|
253
|
+
end
|
254
|
+
|
255
|
+
# Exception class
|
256
|
+
class MiniExiftool::Error < StandardError; end
|
257
|
+
|
258
|
+
############################################################################
|
259
|
+
private
|
260
|
+
############################################################################
|
261
|
+
|
262
|
+
@@error_file = Tempfile.new 'errors'
|
263
|
+
@@error_file.close
|
264
|
+
|
265
|
+
if Float(exiftool_version) < 7.41
|
266
|
+
@@separator = ', '
|
267
|
+
@@sep_op = ''
|
268
|
+
else
|
269
|
+
@@separator = '@@'
|
270
|
+
@@sep_op = '-sep @@'
|
271
|
+
end
|
272
|
+
|
273
|
+
def run cmd
|
274
|
+
if $DEBUG
|
275
|
+
$stderr.puts cmd
|
276
|
+
end
|
277
|
+
@output = `#{cmd} 2>#{@@error_file.path}`
|
278
|
+
@status = $?
|
279
|
+
unless @status.exitstatus == 0
|
280
|
+
@error_text = File.readlines(@@error_file.path).join
|
281
|
+
return false
|
282
|
+
else
|
283
|
+
@error_text = ''
|
284
|
+
return true
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def convert val
|
289
|
+
case val
|
290
|
+
when Time
|
291
|
+
val = val.strftime('%Y:%m:%d %H:%M:%S')
|
292
|
+
end
|
293
|
+
val
|
294
|
+
end
|
295
|
+
|
296
|
+
def method_missing symbol, *args
|
297
|
+
tag_name = symbol.id2name
|
298
|
+
if tag_name.sub!(/=$/, '')
|
299
|
+
self[tag_name] = args.first
|
300
|
+
else
|
301
|
+
self[tag_name]
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def parse_output
|
306
|
+
@output.each_line do |line|
|
307
|
+
tag, value = parse_line line
|
308
|
+
set_value tag, value
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
def parse_line line
|
313
|
+
if line =~ /^([^\t]+)\t(.*)$/
|
314
|
+
tag, value = $1, $2
|
315
|
+
case value
|
316
|
+
when /^\d{4}:\d\d:\d\d \d\d:\d\d:\d\d$/
|
317
|
+
arr = value.split(/[: ]/) #Fixed by kro44 - add parentheses
|
318
|
+
arr.map! {|elem| elem.to_i}
|
319
|
+
begin
|
320
|
+
if @timestamps == Time
|
321
|
+
value = Time.local(*arr) #Fixed by kro44 - add parentheses
|
322
|
+
elsif @timestamps == DateTime
|
323
|
+
value = DateTime.strptime(value,'%Y:%m:%d %H:%M:%S')
|
324
|
+
else
|
325
|
+
raise MiniExiftool::Error.new("Value #@timestamps not allowed for option timestamps.")
|
326
|
+
end
|
327
|
+
rescue ArgumentError
|
328
|
+
value = false
|
329
|
+
end
|
330
|
+
when /^\d+\.\d+$/
|
331
|
+
value = value.to_f
|
332
|
+
when /^0+[1-9]+$/
|
333
|
+
# nothing => String
|
334
|
+
when /^-?\d+$/
|
335
|
+
value = value.to_i
|
336
|
+
when /^[\d ]+$/
|
337
|
+
# nothing => String
|
338
|
+
when /#{@@separator}/
|
339
|
+
value = value.split @@separator
|
340
|
+
end
|
341
|
+
else
|
342
|
+
raise MiniExiftool::Error.new("Malformed line #{line.inspect} of exiftool output.")
|
343
|
+
end
|
344
|
+
unless value.respond_to?('to_a')
|
345
|
+
class << value
|
346
|
+
def to_a
|
347
|
+
[self]
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
return [tag, value]
|
352
|
+
end
|
353
|
+
|
354
|
+
def set_value tag, value
|
355
|
+
@tag_names[tag] = tag
|
356
|
+
@values[tag] = value
|
357
|
+
end
|
358
|
+
|
359
|
+
def set_attributes_by_heuristic
|
360
|
+
self.composite = tags.include?('ImageSize') ? true : false
|
361
|
+
self.numerical = self.file_size.kind_of?(Integer) ? true : false
|
362
|
+
# TODO: Is there a heuristic to determine @convert_encoding?
|
363
|
+
self.timestamps = self.FileModifyDate.kind_of?(DateTime) ? DateTime : Time
|
364
|
+
end
|
365
|
+
|
366
|
+
def temp_filename
|
367
|
+
unless @temp_filename
|
368
|
+
temp_file = Tempfile.new('mini-exiftool')
|
369
|
+
temp_file.close
|
370
|
+
FileUtils.cp(@filename, temp_file.path)
|
371
|
+
@temp_filename = temp_file.path
|
372
|
+
end
|
373
|
+
@temp_filename
|
374
|
+
end
|
375
|
+
|
376
|
+
def self.pstore_get attribute
|
377
|
+
load_or_create_pstore unless defined? @@pstore
|
378
|
+
result = nil
|
379
|
+
@@pstore.transaction(true) do |ps|
|
380
|
+
result = ps[attribute]
|
381
|
+
end
|
382
|
+
result
|
383
|
+
end
|
384
|
+
|
385
|
+
def self.load_or_create_pstore
|
386
|
+
# This will hopefully work on *NIX and Windows systems
|
387
|
+
home = ENV['HOME'] || ENV['HOMEDRIVE'] + ENV['HOMEPATH'] || ENV['USERPROFILE']
|
388
|
+
subdir = RUBY_PLATFORM =~ /win/i ? '_mini_exiftool' : '.mini_exiftool'
|
389
|
+
FileUtils.mkdir_p(File.join(home, subdir))
|
390
|
+
filename = File.join(home, subdir, 'exiftool_tags_' << exiftool_version.gsub('.', '_') << '.pstore')
|
391
|
+
@@pstore = PStore.new filename
|
392
|
+
if !File.exist?(filename) || File.size(filename) == 0
|
393
|
+
@@pstore.transaction do |ps|
|
394
|
+
ps[:all_tags] = all_tags = determine_tags('list')
|
395
|
+
ps[:writable_tags] = determine_tags('listw')
|
396
|
+
map = {}
|
397
|
+
all_tags.each { |k| map[unify(k)] = k }
|
398
|
+
ps[:all_tags_map] = map
|
399
|
+
end
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
def self.determine_tags arg
|
404
|
+
output = `#{@@cmd} -#{arg}`
|
405
|
+
lines = output.split(/\n/) #Fixed by kro44 - add parentheses
|
406
|
+
tags = Set.new
|
407
|
+
lines.each do |line|
|
408
|
+
next unless line =~ /^\s/
|
409
|
+
tags |= line.chomp.split
|
410
|
+
end
|
411
|
+
tags
|
412
|
+
end
|
413
|
+
|
414
|
+
|
415
|
+
# Hash with indifferent access:
|
416
|
+
# DateTimeOriginal == datetimeoriginal == date_time_original
|
417
|
+
class TagHash < Hash # :nodoc:
|
418
|
+
def[] k
|
419
|
+
super(unify(k))
|
420
|
+
end
|
421
|
+
def []= k, v
|
422
|
+
super(unify(k), v)
|
423
|
+
end
|
424
|
+
def delete k
|
425
|
+
super(unify(k))
|
426
|
+
end
|
427
|
+
|
428
|
+
def unify tag
|
429
|
+
MiniExiftool.unify tag
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
end
|
434
|
+
|
435
|
+
# Add to_a to Numerical if it's not yet defined
|
436
|
+
unless Numeric.instance_methods.include? 'to_a'
|
437
|
+
class Numeric
|
438
|
+
def to_a
|
439
|
+
[self]
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
# Test if we can run the Exiftool command
|
445
|
+
MiniExiftool.exiftool_version
|
data/lib/mini_exiftool.rb
CHANGED
@@ -29,7 +29,7 @@ class MiniExiftool
|
|
29
29
|
attr_reader :filename
|
30
30
|
attr_accessor :numerical, :composite, :convert_encoding, :errors, :timestamps
|
31
31
|
|
32
|
-
VERSION = '1.0.
|
32
|
+
VERSION = '1.0.2'
|
33
33
|
|
34
34
|
# +opts+ support at the moment
|
35
35
|
# * <code>:numerical</code> for numerical values, default is +false+
|
@@ -314,11 +314,11 @@ class MiniExiftool
|
|
314
314
|
tag, value = $1, $2
|
315
315
|
case value
|
316
316
|
when /^\d{4}:\d\d:\d\d \d\d:\d\d:\d\d$/
|
317
|
-
arr = value.split
|
317
|
+
arr = value.split(/[: ]/)
|
318
318
|
arr.map! {|elem| elem.to_i}
|
319
319
|
begin
|
320
320
|
if @timestamps == Time
|
321
|
-
value = Time.local
|
321
|
+
value = Time.local(*arr)
|
322
322
|
elsif @timestamps == DateTime
|
323
323
|
value = DateTime.strptime(value,'%Y:%m:%d %H:%M:%S')
|
324
324
|
else
|
@@ -402,7 +402,7 @@ class MiniExiftool
|
|
402
402
|
|
403
403
|
def self.determine_tags arg
|
404
404
|
output = `#{@@cmd} -#{arg}`
|
405
|
-
lines = output.split
|
405
|
+
lines = output.split(/\n/)
|
406
406
|
tags = Set.new
|
407
407
|
lines.each do |line|
|
408
408
|
next unless line =~ /^\s/
|
data/x.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mini_exiftool
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 19
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 2
|
10
|
+
version: 1.0.2
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Jan Friedrich
|
@@ -9,7 +15,7 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date:
|
18
|
+
date: 2010-12-30 00:00:00 +01:00
|
13
19
|
default_executable:
|
14
20
|
dependencies: []
|
15
21
|
|
@@ -23,32 +29,36 @@ extra_rdoc_files:
|
|
23
29
|
- README
|
24
30
|
- Tutorial
|
25
31
|
files:
|
32
|
+
- examples/external_photo.rb
|
33
|
+
- examples/print_portraits.rb
|
34
|
+
- examples/shift_time.rb
|
35
|
+
- lib/mini_exiftool.new.rb
|
26
36
|
- lib/mini_exiftool.rb
|
27
|
-
-
|
28
|
-
- test/
|
29
|
-
- test/test_special.rb
|
37
|
+
- setup.rb
|
38
|
+
- test/helpers_for_test.rb
|
30
39
|
- test/test_class_methods.rb
|
31
|
-
- test/test_save.rb
|
32
40
|
- test/test_composite.rb
|
41
|
+
- test/test_dumping.rb
|
42
|
+
- test/test_read.rb
|
33
43
|
- test/test_read_numerical.rb
|
34
|
-
- test/
|
44
|
+
- test/test_save.rb
|
45
|
+
- test/test_special.rb
|
35
46
|
- test/test_special_dates.rb
|
36
|
-
- test/
|
37
|
-
-
|
38
|
-
- examples/print_portraits.rb
|
39
|
-
- examples/shift_time.rb
|
40
|
-
- setup.rb
|
47
|
+
- test/test_write.rb
|
48
|
+
- x.rb
|
41
49
|
- Rakefile
|
42
50
|
- COPYING
|
43
51
|
- Changelog
|
44
|
-
- test/data/test.jpg
|
45
52
|
- test/data/Canon.jpg
|
46
53
|
- test/data/INFORMATION
|
54
|
+
- test/data/test.jpg
|
47
55
|
- test/data/test_special_dates.jpg
|
48
56
|
- README
|
49
57
|
- Tutorial
|
50
58
|
has_rdoc: true
|
51
59
|
homepage: http://miniexiftool.rubyforge.org/
|
60
|
+
licenses: []
|
61
|
+
|
52
62
|
post_install_message:
|
53
63
|
rdoc_options:
|
54
64
|
- --title
|
@@ -58,31 +68,37 @@ rdoc_options:
|
|
58
68
|
require_paths:
|
59
69
|
- lib
|
60
70
|
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
61
72
|
requirements:
|
62
73
|
- - ">="
|
63
74
|
- !ruby/object:Gem::Version
|
75
|
+
hash: 3
|
76
|
+
segments:
|
77
|
+
- 0
|
64
78
|
version: "0"
|
65
|
-
version:
|
66
79
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
67
81
|
requirements:
|
68
82
|
- - ">="
|
69
83
|
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
86
|
+
- 0
|
70
87
|
version: "0"
|
71
|
-
version:
|
72
88
|
requirements: []
|
73
89
|
|
74
90
|
rubyforge_project: miniexiftool
|
75
|
-
rubygems_version: 1.
|
91
|
+
rubygems_version: 1.3.7
|
76
92
|
signing_key:
|
77
|
-
specification_version:
|
93
|
+
specification_version: 3
|
78
94
|
summary: A library for nice OO access to the Exiftool command-line application written by Phil Harvey.
|
79
95
|
test_files:
|
80
|
-
- test/test_write.rb
|
81
|
-
- test/test_read.rb
|
82
|
-
- test/test_special.rb
|
83
96
|
- test/test_class_methods.rb
|
84
|
-
- test/test_save.rb
|
85
97
|
- test/test_composite.rb
|
98
|
+
- test/test_dumping.rb
|
99
|
+
- test/test_read.rb
|
86
100
|
- test/test_read_numerical.rb
|
101
|
+
- test/test_save.rb
|
102
|
+
- test/test_special.rb
|
87
103
|
- test/test_special_dates.rb
|
88
|
-
- test/
|
104
|
+
- test/test_write.rb
|