thingfish 0.5.0.pre20160707192835 → 0.5.0.pre20161103181816
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Manifest.txt +5 -0
- data/lib/thingfish/handler.rb +72 -3
- data/spec/thingfish/handler_spec.rb +46 -1
- metadata +34 -28
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74a092349d627e3de7578603e6cbba04c29f8045
|
4
|
+
data.tar.gz: eb4868b63ef6b8ad8b95c4ff5954f4482924bb3d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e3a206fa9f2ad2dd07543f407f85972a42b4f073ae8cc3eab66ead4ec5947b74c6f4228741a96efdb15a22101c4251cc49cee7a6e4b5720a1bf5acefda41967
|
7
|
+
data.tar.gz: a923141975987b85e96e84bd20c017d06609110abf10e319bd76a61ef51be1f0b6e59e2c66d8bc5d3d4d0275c862d8a3826b2e6c17f844daf456d6b7cfb21d91
|
checksums.yaml.gz.sig
ADDED
Binary file
|
data.tar.gz.sig
ADDED
Binary file
|
data/Manifest.txt
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
.simplecov
|
2
|
+
ChangeLog
|
3
|
+
Gemfile
|
2
4
|
History.rdoc
|
3
5
|
LICENSE
|
4
6
|
Manifest.txt
|
@@ -7,6 +9,7 @@ README.rdoc
|
|
7
9
|
Rakefile
|
8
10
|
bin/tfprocessord
|
9
11
|
bin/thingfish
|
12
|
+
etc/mongrel2-config.rb
|
10
13
|
etc/thingfish.conf.example
|
11
14
|
lib/strelka/app/metadata.rb
|
12
15
|
lib/strelka/httprequest/metadata.rb
|
@@ -20,6 +23,7 @@ lib/thingfish/metastore/memory.rb
|
|
20
23
|
lib/thingfish/mixins.rb
|
21
24
|
lib/thingfish/processor.rb
|
22
25
|
lib/thingfish/processor/mp3.rb
|
26
|
+
lib/thingfish/processor/sha256.rb
|
23
27
|
lib/thingfish/processordaemon.rb
|
24
28
|
lib/thingfish/spechelpers.rb
|
25
29
|
spec/data/APIC-1-image.mp3
|
@@ -35,5 +39,6 @@ spec/thingfish/metastore/memory_spec.rb
|
|
35
39
|
spec/thingfish/metastore_spec.rb
|
36
40
|
spec/thingfish/mixins_spec.rb
|
37
41
|
spec/thingfish/processor/mp3_spec.rb
|
42
|
+
spec/thingfish/processor/sha256_spec.rb
|
38
43
|
spec/thingfish/processor_spec.rb
|
39
44
|
spec/thingfish_spec.rb
|
data/lib/thingfish/handler.rb
CHANGED
@@ -230,6 +230,7 @@ class Thingfish::Handler < Strelka::App
|
|
230
230
|
:datastore => self.datastore.class.name
|
231
231
|
}
|
232
232
|
|
233
|
+
self.check_resource_permissions( req )
|
233
234
|
res.for( :text, :json, :yaml ) { info }
|
234
235
|
return res
|
235
236
|
end
|
@@ -244,6 +245,8 @@ class Thingfish::Handler < Strelka::App
|
|
244
245
|
get do |req|
|
245
246
|
finish_with HTTP::BAD_REQUEST, req.params.error_messages.join(', ') unless req.params.okay?
|
246
247
|
|
248
|
+
self.check_resource_permissions( req )
|
249
|
+
|
247
250
|
uuids = self.metastore.search( req.params.valid )
|
248
251
|
self.log.debug "UUIDs are: %p" % [ uuids ]
|
249
252
|
|
@@ -340,13 +343,15 @@ class Thingfish::Handler < Strelka::App
|
|
340
343
|
metadata = self.metastore.fetch( uuid )
|
341
344
|
|
342
345
|
finish_with HTTP::NOT_FOUND, "No such object." unless object && metadata
|
346
|
+
self.check_resource_permissions( req, nil, metadata )
|
343
347
|
|
344
348
|
res = req.response
|
345
349
|
res.content_type = metadata['format']
|
346
350
|
|
351
|
+
self.add_etag_headers( req, metadata )
|
352
|
+
|
347
353
|
if object.respond_to?( :path )
|
348
354
|
path = Pathname( object.path )
|
349
|
-
self.log.debug "Server is chrooted to: %p" % [ req.server_chroot ]
|
350
355
|
chroot_path = path.relative_path_from( req.server_chroot )
|
351
356
|
res.extend_reply_with( :sendfile )
|
352
357
|
res.headers.content_length = object.size
|
@@ -387,6 +392,7 @@ class Thingfish::Handler < Strelka::App
|
|
387
392
|
self.datastore.include?( uuid ) or
|
388
393
|
finish_with HTTP::NOT_FOUND, "No such object."
|
389
394
|
|
395
|
+
self.check_resource_permissions( req, uuid )
|
390
396
|
self.remove_related_resources( uuid )
|
391
397
|
self.save_resource( req, uuid )
|
392
398
|
self.send_event( :replaced, :uuid => uuid )
|
@@ -403,6 +409,8 @@ class Thingfish::Handler < Strelka::App
|
|
403
409
|
delete ':uuid' do |req|
|
404
410
|
uuid = req.params[:uuid]
|
405
411
|
|
412
|
+
self.check_resource_permissions( req, uuid )
|
413
|
+
|
406
414
|
self.datastore.remove( uuid ) or finish_with( HTTP::NOT_FOUND, "No such object." )
|
407
415
|
metadata = self.metastore.remove( uuid )
|
408
416
|
self.remove_related_resources( uuid )
|
@@ -433,9 +441,13 @@ class Thingfish::Handler < Strelka::App
|
|
433
441
|
|
434
442
|
finish_with( HTTP::NOT_FOUND, "No such object." ) unless self.metastore.include?( uuid )
|
435
443
|
|
444
|
+
metadata = self.metastore.fetch( uuid )
|
445
|
+
metadata[ 'oid' ] = uuid
|
446
|
+
self.check_resource_permissions( req, uuid, metadata )
|
447
|
+
|
436
448
|
res = req.response
|
437
449
|
res.status = HTTP::OK
|
438
|
-
res.for( :json, :yaml ) {
|
450
|
+
res.for( :json, :yaml ) { metadata }
|
439
451
|
|
440
452
|
return res
|
441
453
|
end
|
@@ -449,9 +461,12 @@ class Thingfish::Handler < Strelka::App
|
|
449
461
|
|
450
462
|
finish_with( HTTP::NOT_FOUND, "No such object." ) unless self.metastore.include?( uuid )
|
451
463
|
|
464
|
+
metadata = self.metastore.fetch( uuid )
|
465
|
+
self.check_resource_permissions( req, uuid, metadata )
|
466
|
+
|
452
467
|
res = req.response
|
453
468
|
res.status = HTTP::OK
|
454
|
-
res.for( :json, :yaml ) {
|
469
|
+
res.for( :json, :yaml ) { metadata[key] }
|
455
470
|
|
456
471
|
return res
|
457
472
|
end
|
@@ -467,6 +482,9 @@ class Thingfish::Handler < Strelka::App
|
|
467
482
|
finish_with( HTTP::CONFLICT, "Key already exists." ) unless
|
468
483
|
self.metastore.fetch_value( uuid, key ).nil?
|
469
484
|
|
485
|
+
metadata = self.metastore.fetch( uuid )
|
486
|
+
self.check_resource_permissions( req, uuid, metadata )
|
487
|
+
|
470
488
|
self.metastore.merge( uuid, key => req.body.read )
|
471
489
|
self.send_event( :metadata_updated, :uuid => uuid, :key => key )
|
472
490
|
|
@@ -490,6 +508,9 @@ class Thingfish::Handler < Strelka::App
|
|
490
508
|
finish_with( HTTP::NOT_FOUND, "No such object." ) unless self.metastore.include?( uuid )
|
491
509
|
previous_value = self.metastore.fetch( uuid, key )
|
492
510
|
|
511
|
+
metadata = self.metastore.fetch( uuid )
|
512
|
+
self.check_resource_permissions( req, uuid, metadata )
|
513
|
+
|
493
514
|
self.metastore.merge( uuid, key => req.body.read )
|
494
515
|
self.send_event( :metadata_replaced, :uuid => uuid, :key => key )
|
495
516
|
|
@@ -514,6 +535,9 @@ class Thingfish::Handler < Strelka::App
|
|
514
535
|
|
515
536
|
finish_with( HTTP::NOT_FOUND, "No such object." ) unless self.metastore.include?( uuid )
|
516
537
|
|
538
|
+
metadata = self.metastore.fetch( uuid )
|
539
|
+
self.check_resource_permissions( req, uuid, metadata )
|
540
|
+
|
517
541
|
op_metadata = self.metastore.fetch( uuid, *OPERATIONAL_METADATA_KEYS )
|
518
542
|
new_metadata = self.extract_metadata( req )
|
519
543
|
self.metastore.save( uuid, new_metadata.merge(op_metadata) )
|
@@ -533,6 +557,9 @@ class Thingfish::Handler < Strelka::App
|
|
533
557
|
|
534
558
|
finish_with( HTTP::NOT_FOUND, "No such object." ) unless self.metastore.include?( uuid )
|
535
559
|
|
560
|
+
metadata = self.metastore.fetch( uuid )
|
561
|
+
self.check_resource_permissions( req, uuid, metadata )
|
562
|
+
|
536
563
|
new_metadata = self.extract_metadata( req )
|
537
564
|
self.metastore.merge( uuid, new_metadata )
|
538
565
|
self.send_event( :metadata_updated, :uuid => uuid )
|
@@ -551,6 +578,9 @@ class Thingfish::Handler < Strelka::App
|
|
551
578
|
|
552
579
|
finish_with( HTTP::NOT_FOUND, "No such object." ) unless self.metastore.include?( uuid )
|
553
580
|
|
581
|
+
metadata = self.metastore.fetch( uuid )
|
582
|
+
self.check_resource_permissions( req, uuid, metadata )
|
583
|
+
|
554
584
|
self.metastore.remove_except( uuid, *OPERATIONAL_METADATA_KEYS )
|
555
585
|
self.send_event( :metadata_deleted, :uuid => uuid )
|
556
586
|
|
@@ -571,6 +601,9 @@ class Thingfish::Handler < Strelka::App
|
|
571
601
|
finish_with( HTTP::FORBIDDEN, "Protected metadata." ) if
|
572
602
|
OPERATIONAL_METADATA_KEYS.include?( key )
|
573
603
|
|
604
|
+
metadata = self.metastore.fetch( uuid )
|
605
|
+
self.check_resource_permissions( req, uuid, metadata )
|
606
|
+
|
574
607
|
self.metastore.remove( uuid, key )
|
575
608
|
self.send_event( :metadata_deleted, :uuid => uuid, :key => key )
|
576
609
|
|
@@ -593,6 +626,9 @@ class Thingfish::Handler < Strelka::App
|
|
593
626
|
metadata.merge!( self.extract_header_metadata(request) )
|
594
627
|
metadata.merge!( self.extract_default_metadata(request) )
|
595
628
|
|
629
|
+
self.verify_operational_metadata( metadata )
|
630
|
+
self.check_resource_permissions( request, uuid, metadata )
|
631
|
+
|
596
632
|
if uuid
|
597
633
|
self.log.info "Replacing resource %s (encoding: %p)" %
|
598
634
|
[ uuid, request.headers.content_encoding ]
|
@@ -714,6 +750,15 @@ class Thingfish::Handler < Strelka::App
|
|
714
750
|
end
|
715
751
|
|
716
752
|
|
753
|
+
### Check that the metadata provided contains valid values for
|
754
|
+
### the operational keys, before saving a resource to disk.
|
755
|
+
def verify_operational_metadata( metadata )
|
756
|
+
if metadata.values_at( *OPERATIONAL_METADATA_KEYS ).any?( &:nil? )
|
757
|
+
finish_with( HTTP::BAD_REQUEST, "Missing operational attribute." )
|
758
|
+
end
|
759
|
+
end
|
760
|
+
|
761
|
+
|
717
762
|
### Send an event of +type+ with the given +msg+ over the zmq event socket.
|
718
763
|
def send_event( type, msg )
|
719
764
|
esock = self.event_socket or return
|
@@ -723,6 +768,30 @@ class Thingfish::Handler < Strelka::App
|
|
723
768
|
end
|
724
769
|
|
725
770
|
|
771
|
+
### Add browser cache headers for resources. This requires the sha256
|
772
|
+
### processor plugin to be enabled for stored resources.
|
773
|
+
def add_etag_headers( request, metadata )
|
774
|
+
response = request.response
|
775
|
+
checksum = metadata[ 'checksum' ]
|
776
|
+
return unless checksum
|
777
|
+
|
778
|
+
if (( match = request.headers[ :if_none_match ] ))
|
779
|
+
match = match.gsub( '"', '' ).split( /,\s*/ )
|
780
|
+
finish_with( HTTP::NOT_MODIFIED ) if match.include?( checksum )
|
781
|
+
end
|
782
|
+
|
783
|
+
response.headers[ :etag ] = checksum
|
784
|
+
return
|
785
|
+
end
|
786
|
+
|
787
|
+
|
788
|
+
### Supply a method that child handlers can override. The regular auth
|
789
|
+
### plugin runs too early (but can also be used), this hook allows
|
790
|
+
### child handlers to make access decisions based on the +request+
|
791
|
+
### object, +uuid+ of the resource, or +metadata+ of the fetched resource.
|
792
|
+
def check_resource_permissions( request, uuid=nil, metadata=nil ); end
|
793
|
+
|
794
|
+
|
726
795
|
end # class Thingfish::Handler
|
727
796
|
|
728
797
|
# vim: set nosta noet ts=4 sw=4:
|
@@ -70,7 +70,9 @@ describe Thingfish::Handler do
|
|
70
70
|
|
71
71
|
|
72
72
|
it 'accepts a POSTed upload' do
|
73
|
-
req = factory.post( '/', TEST_TEXT_DATA
|
73
|
+
req = factory.post( '/', TEST_TEXT_DATA )
|
74
|
+
req.content_type = 'text/plain'
|
75
|
+
req.headers.content_length = TEST_TEXT_DATA.bytesize
|
74
76
|
res = @handler.handle( req )
|
75
77
|
|
76
78
|
expect( res.status_line ).to match( /201 created/i )
|
@@ -145,6 +147,17 @@ describe Thingfish::Handler do
|
|
145
147
|
end
|
146
148
|
|
147
149
|
|
150
|
+
it 'returns a BAD_REQUEST if unable to extract operational metadata' do
|
151
|
+
req = factory.post( '/', TEST_TEXT_DATA )
|
152
|
+
req.content_type = 'text/plain'
|
153
|
+
|
154
|
+
res = @handler.handle( req )
|
155
|
+
res.body.rewind
|
156
|
+
expect( res.status ).to be( HTTP::BAD_REQUEST )
|
157
|
+
expect( res.body.read ).to match( /missing operational attribute/i )
|
158
|
+
end
|
159
|
+
|
160
|
+
|
148
161
|
it "allows additional metadata to be attached to uploads via X-Thingfish-* headers" do
|
149
162
|
headers = {
|
150
163
|
content_type: 'text/plain',
|
@@ -152,6 +165,7 @@ describe Thingfish::Handler do
|
|
152
165
|
x_thingfish_tags: 'rapper,ukraine,potap',
|
153
166
|
}
|
154
167
|
req = factory.post( '/', TEST_TEXT_DATA, headers )
|
168
|
+
req.headers.content_length = TEST_TEXT_DATA.bytesize
|
155
169
|
res = @handler.handle( req )
|
156
170
|
|
157
171
|
expect( res.status_line ).to match( /201 created/i )
|
@@ -169,6 +183,7 @@ describe Thingfish::Handler do
|
|
169
183
|
@handler.metastore.save( uuid, {'format' => 'text/plain'} )
|
170
184
|
|
171
185
|
req = factory.put( "/#{uuid}", @png_io, content_type: 'image/png' )
|
186
|
+
req.headers.content_length = @png_io.read.bytesize
|
172
187
|
res = @handler.handle( req )
|
173
188
|
|
174
189
|
expect( res.status ).to eq( HTTP::NO_CONTENT )
|
@@ -182,6 +197,7 @@ describe Thingfish::Handler do
|
|
182
197
|
@handler.metastore.save( uuid, {'format' => 'text/plain'} )
|
183
198
|
|
184
199
|
req = factory.put( "/#{uuid.upcase}", @png_io, content_type: 'image/png' )
|
200
|
+
req.headers.content_length = @png_io.read.bytesize
|
185
201
|
res = @handler.handle( req )
|
186
202
|
|
187
203
|
expect( res.status ).to eq( HTTP::NO_CONTENT )
|
@@ -339,6 +355,32 @@ describe Thingfish::Handler do
|
|
339
355
|
end
|
340
356
|
|
341
357
|
|
358
|
+
it "adds browser cache headers to resources with a checksum attribute" do
|
359
|
+
uuid = @handler.datastore.save( @png_io )
|
360
|
+
@handler.metastore.save( uuid, 'format' => 'image/png', 'checksum' => '123456' )
|
361
|
+
|
362
|
+
req = factory.get( "/#{uuid}" )
|
363
|
+
result = @handler.handle( req )
|
364
|
+
|
365
|
+
expect( result.status_line ).to match( /200 ok/i )
|
366
|
+
expect( result.headers.etag ).to eq( '123456' )
|
367
|
+
end
|
368
|
+
|
369
|
+
|
370
|
+
it "returns a 304 not modified for unchanged client cache requests" do
|
371
|
+
uuid = @handler.datastore.save( @png_io )
|
372
|
+
@handler.metastore.save( uuid, 'format' => 'image/png', 'checksum' => '123456' )
|
373
|
+
|
374
|
+
req = factory.get( "/#{uuid}" )
|
375
|
+
req.headers[ :if_none_match ] = '123456'
|
376
|
+
result = @handler.handle( req )
|
377
|
+
|
378
|
+
expect( result.status_line ).to match( /304 not modified/i )
|
379
|
+
expect( result.body.read ).to be_empty
|
380
|
+
end
|
381
|
+
|
382
|
+
|
383
|
+
|
342
384
|
it "can remove everything associated with an object id" do
|
343
385
|
uuid = @handler.datastore.save( @png_io )
|
344
386
|
@handler.metastore.save( uuid, {
|
@@ -391,6 +433,7 @@ describe Thingfish::Handler do
|
|
391
433
|
expect( result.status ).to eq( 200 )
|
392
434
|
expect( result.headers.content_type ).to eq( 'application/json' )
|
393
435
|
expect( content_hash ).to be_a( Hash )
|
436
|
+
expect( content_hash['oid'] ).to eq( uuid )
|
394
437
|
expect( content_hash['extent'] ).to eq( 288 )
|
395
438
|
expect( content_hash['created'] ).to eq( Time.at(1378313840).to_s )
|
396
439
|
end
|
@@ -733,6 +776,7 @@ describe Thingfish::Handler do
|
|
733
776
|
described_class.configure( :processors => %w[test] )
|
734
777
|
|
735
778
|
req = factory.post( '/', TEST_TEXT_DATA, content_type: 'text/plain' )
|
779
|
+
req.headers.content_length = TEST_TEXT_DATA.bytesize
|
736
780
|
res = @handler.handle( req )
|
737
781
|
uuid = res.headers.x_thingfish_uuid
|
738
782
|
|
@@ -816,6 +860,7 @@ describe Thingfish::Handler do
|
|
816
860
|
|
817
861
|
it "publishes notifications about uploaded assets to a PUBSUB socket" do
|
818
862
|
req = factory.post( '/', TEST_TEXT_DATA, content_type: 'text/plain' )
|
863
|
+
req.headers.content_length = TEST_TEXT_DATA.bytesize
|
819
864
|
res = @handler.handle( req )
|
820
865
|
|
821
866
|
handles = ZMQ.select( [@subsock], nil, nil, 0 )
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thingfish
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.0.
|
4
|
+
version: 0.5.0.pre20161103181816
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Granger
|
@@ -11,26 +11,32 @@ bindir: bin
|
|
11
11
|
cert_chain:
|
12
12
|
- |
|
13
13
|
-----BEGIN CERTIFICATE-----
|
14
|
-
|
14
|
+
MIIEbDCCAtSgAwIBAgIBATANBgkqhkiG9w0BAQsFADA+MQwwCgYDVQQDDANnZWQx
|
15
15
|
GTAXBgoJkiaJk/IsZAEZFglGYWVyaWVNVUQxEzARBgoJkiaJk/IsZAEZFgNvcmcw
|
16
|
-
|
16
|
+
HhcNMTYwODIwMTgxNzQyWhcNMTcwODIwMTgxNzQyWjA+MQwwCgYDVQQDDANnZWQx
|
17
17
|
GTAXBgoJkiaJk/IsZAEZFglGYWVyaWVNVUQxEzARBgoJkiaJk/IsZAEZFgNvcmcw
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
18
|
+
ggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC/JWGRHO+USzR97vXjkFgt
|
19
|
+
83qeNf2KHkcvrRTSnR64i6um/ziin0I0oX23H7VYrDJC9A/uoUa5nGRJS5Zw/+wW
|
20
|
+
ENcvWVZS4iUzi4dsYJGY6yEOsXh2CcF46+QevV8iE+UmbkU75V7Dy1JCaUOyizEt
|
21
|
+
TH5UHsOtUU7k9TYARt/TgYZKuaoAMZZd5qyVqhF1vV+7/Qzmp89NGflXf2xYP26a
|
22
|
+
4MAX2qqKX/FKXqmFO+AGsbwYTEds1mksBF3fGsFgsQWxftG8GfZQ9+Cyu2+l1eOw
|
23
|
+
cZ+lPcg834G9DrqW2zhqUoLr1MTly4pqxYGb7XoDhoR7dd1kFE2a067+DzWC/ADt
|
24
|
+
+QkcqWUm5oh1fN0eqr7NsZlVJDulFgdiiYPQiIN7UNsii4Wc9aZqBoGcYfBeQNPZ
|
25
|
+
soo/6za/bWajOKUmDhpqvaiRv9EDpVLzuj53uDoukMMwxCMfgb04+ckQ0t2G7wqc
|
26
|
+
/D+K9JW9DDs3Yjgv9k4h7YMhW5gftosd+NkNC/+Y2CkCAwEAAaN1MHMwCQYDVR0T
|
27
|
+
BAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFHKN/nkRusdqCJEuq3lgB3fJvyTg
|
28
|
+
MBwGA1UdEQQVMBOBEWdlZEBGYWVyaWVNVUQub3JnMBwGA1UdEgQVMBOBEWdlZEBG
|
29
|
+
YWVyaWVNVUQub3JnMA0GCSqGSIb3DQEBCwUAA4IBgQAPJzKiT0zBU7kpqe0aS2qb
|
30
|
+
FI0PJ4y5I8buU4IZGUD5NEt/N7pZNfOyBxkrZkXhS44Fp+xwBH5ebLbq/WY78Bqd
|
31
|
+
db0z6ZgW4LMYMpWFfbXsRbd9TU2f52L8oMAhxOvF7Of5qJMVWuFQ8FPagk2iHrdH
|
32
|
+
inYLQagqAF6goWTXgAJCdPd6SNeeSNqA6vlY7CV1Jh5kfNJJ6xu/CVij1GzCLu/5
|
33
|
+
DMOr26DBv+qLJRRC/2h34uX71q5QgeOyxvMg+7V3u/Q06DXyQ2VgeeqiwDFFpEH0
|
34
|
+
PFkdPO6ZqbTRcLfNH7mFgCBJjsfSjJrn0sPBlYyOXgCoByfZnZyrIMH/UY+lgQqS
|
35
|
+
6Von1VDsfQm0eJh5zYZD64ZF86phSR7mUX3mXItwH04HrZwkWpvgd871DZVR3i1n
|
36
|
+
w8aNA5re5+Rt/Vvjxj5AcEnZnZiz5x959NaddQocX32Z1unHw44pzRNUur1GInfW
|
37
|
+
p4vpx2kUSFSAGjtCbDGTNV2AH8w9OU4xEmNz8c5lyoA=
|
32
38
|
-----END CERTIFICATE-----
|
33
|
-
date: 2016-
|
39
|
+
date: 2016-11-04 00:00:00.000000000 Z
|
34
40
|
dependencies:
|
35
41
|
- !ruby/object:Gem::Dependency
|
36
42
|
name: strelka
|
@@ -103,47 +109,47 @@ dependencies:
|
|
103
109
|
- !ruby/object:Gem::Version
|
104
110
|
version: '0.2'
|
105
111
|
- !ruby/object:Gem::Dependency
|
106
|
-
name:
|
112
|
+
name: simplecov
|
107
113
|
requirement: !ruby/object:Gem::Requirement
|
108
114
|
requirements:
|
109
115
|
- - "~>"
|
110
116
|
- !ruby/object:Gem::Version
|
111
|
-
version: '
|
117
|
+
version: '0.7'
|
112
118
|
type: :development
|
113
119
|
prerelease: false
|
114
120
|
version_requirements: !ruby/object:Gem::Requirement
|
115
121
|
requirements:
|
116
122
|
- - "~>"
|
117
123
|
- !ruby/object:Gem::Version
|
118
|
-
version: '
|
124
|
+
version: '0.7'
|
119
125
|
- !ruby/object:Gem::Dependency
|
120
|
-
name:
|
126
|
+
name: ruby-mp3info
|
121
127
|
requirement: !ruby/object:Gem::Requirement
|
122
128
|
requirements:
|
123
129
|
- - "~>"
|
124
130
|
- !ruby/object:Gem::Version
|
125
|
-
version: '0.
|
131
|
+
version: '0.8'
|
126
132
|
type: :development
|
127
133
|
prerelease: false
|
128
134
|
version_requirements: !ruby/object:Gem::Requirement
|
129
135
|
requirements:
|
130
136
|
- - "~>"
|
131
137
|
- !ruby/object:Gem::Version
|
132
|
-
version: '0.
|
138
|
+
version: '0.8'
|
133
139
|
- !ruby/object:Gem::Dependency
|
134
|
-
name:
|
140
|
+
name: rdoc
|
135
141
|
requirement: !ruby/object:Gem::Requirement
|
136
142
|
requirements:
|
137
143
|
- - "~>"
|
138
144
|
- !ruby/object:Gem::Version
|
139
|
-
version: '0
|
145
|
+
version: '4.0'
|
140
146
|
type: :development
|
141
147
|
prerelease: false
|
142
148
|
version_requirements: !ruby/object:Gem::Requirement
|
143
149
|
requirements:
|
144
150
|
- - "~>"
|
145
151
|
- !ruby/object:Gem::Version
|
146
|
-
version: '0
|
152
|
+
version: '4.0'
|
147
153
|
- !ruby/object:Gem::Dependency
|
148
154
|
name: hoe
|
149
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -237,7 +243,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
237
243
|
version: 1.3.1
|
238
244
|
requirements: []
|
239
245
|
rubyforge_project:
|
240
|
-
rubygems_version: 2.
|
246
|
+
rubygems_version: 2.5.1
|
241
247
|
signing_key:
|
242
248
|
specification_version: 4
|
243
249
|
summary: Thingfish is a extensible, web-based digital asset manager
|
metadata.gz.sig
ADDED
Binary file
|