digest_extensions 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/Gemfile +1 -1
- data/README.rdoc +40 -3
- data/VERSION +1 -1
- data/digest_extensions.gemspec +11 -13
- data/spec/digest_extensions_spec.rb +59 -15
- metadata +33 -14
- data/Gemfile.lock +0 -29
data/.rspec
CHANGED
data/Gemfile
CHANGED
@@ -7,7 +7,7 @@ source "http://rubygems.org"
|
|
7
7
|
# Include everything needed to run rake, tests, features, etc.
|
8
8
|
group :development do
|
9
9
|
gem "rspec", "~> 2.6.0"
|
10
|
-
gem "bundler", "~> 1.0
|
10
|
+
gem "bundler", "~> 1.0"
|
11
11
|
gem "jeweler", "~> 1.6.4"
|
12
12
|
gem "rake-compiler", "~> 0.7.9"
|
13
13
|
# gem "rcov", ">= 0"
|
data/README.rdoc
CHANGED
@@ -1,9 +1,46 @@
|
|
1
1
|
= digest_extensions
|
2
2
|
|
3
|
-
|
3
|
+
Extension to the Digest module of the ruby standard library to support marshalling
|
4
|
+
|
5
|
+
With this gem you can accumulatively compute the digest of a byte
|
6
|
+
sequence over several executions by storing the marshalled digest
|
7
|
+
object in a database:
|
8
|
+
|
9
|
+
class FakeDatabase
|
10
|
+
attr_accessor :value
|
11
|
+
end
|
12
|
+
@db = FakeDatabase.new
|
13
|
+
|
14
|
+
def update_digest(part)
|
15
|
+
marshalled_digest = Marshal::load(@db.value) # Fetch the last digest from database
|
16
|
+
marshalled_digest << part # Compute digest incrementally
|
17
|
+
@db.value = Marshal::dump(marshalled_digest) # Store updated digest in database
|
18
|
+
end
|
19
|
+
|
20
|
+
## parts_array is provided; for example as a series of files
|
21
|
+
## generated with the command split on a larger file.
|
22
|
+
@db.value = Marshal::dump(Digest::MD5.new) #An initial value
|
23
|
+
parts_array.each do |part|
|
24
|
+
# Assume this method is invoked in a new process each time, and
|
25
|
+
# the only thing they share is the database (faked in the example with @db)
|
26
|
+
update_digest(part)
|
27
|
+
end
|
28
|
+
Marshal::load(@db.value).hexdigest.should == Digest::MD5.hexdigest(parts_array.inject("", :+))
|
29
|
+
|
30
|
+
The plan is to have this feature to be included in the ruby standard library.
|
31
|
+
|
32
|
+
== Known issues
|
33
|
+
|
34
|
+
Currently the marshalled values are specific to the underlying native
|
35
|
+
library used to compute the digest values. That means that if you are
|
36
|
+
using a ruby that is compiled with linkage to OpenSSL as the
|
37
|
+
underlying md5 library, then the marshalled values (in the database)
|
38
|
+
cannot be used with a ruby version compiled with linkage to rubys
|
39
|
+
native md5 implementation. So take care of that when you consider
|
40
|
+
upgrading your ruby version.
|
4
41
|
|
5
42
|
== Contributing to digest_extensions
|
6
|
-
|
43
|
+
|
7
44
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
8
45
|
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
9
46
|
* Fork the project
|
@@ -14,6 +51,6 @@ Description goes here.
|
|
14
51
|
|
15
52
|
== Copyright
|
16
53
|
|
17
|
-
Copyright (c) 2011 Jarl Friis. See LICENSE.txt for
|
54
|
+
Copyright (c) 2011-2012 Jarl Friis. See LICENSE.txt for
|
18
55
|
further details.
|
19
56
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/digest_extensions.gemspec
CHANGED
@@ -4,14 +4,14 @@
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
|
-
s.name =
|
8
|
-
s.version = "0.0
|
7
|
+
s.name = "digest_extensions"
|
8
|
+
s.version = "0.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jarl Friis"]
|
12
|
-
s.date =
|
13
|
-
s.description =
|
14
|
-
s.email =
|
12
|
+
s.date = "2012-08-05"
|
13
|
+
s.description = "With marshalling of digest objects, it is possible to compute the digests over several executions by storing the marshalled object on file or database, this is handy for computing digests for large files that comes in parts."
|
14
|
+
s.email = "jarl@softace.dk"
|
15
15
|
s.extensions = ["ext/digest_extensions/extconf.rb"]
|
16
16
|
s.extra_rdoc_files = [
|
17
17
|
"LICENSE.txt",
|
@@ -21,7 +21,6 @@ Gem::Specification.new do |s|
|
|
21
21
|
".document",
|
22
22
|
".rspec",
|
23
23
|
"Gemfile",
|
24
|
-
"Gemfile.lock",
|
25
24
|
"LICENSE.txt",
|
26
25
|
"README.rdoc",
|
27
26
|
"Rakefile",
|
@@ -34,30 +33,29 @@ Gem::Specification.new do |s|
|
|
34
33
|
"spec/digest_extensions_spec.rb",
|
35
34
|
"spec/spec_helper.rb"
|
36
35
|
]
|
37
|
-
s.homepage =
|
36
|
+
s.homepage = "http://github.com/jarl-dk/digest_extensions"
|
38
37
|
s.licenses = ["GPL"]
|
39
38
|
s.require_paths = ["lib"]
|
40
|
-
s.rubygems_version =
|
41
|
-
s.summary =
|
39
|
+
s.rubygems_version = "1.8.24"
|
40
|
+
s.summary = "Extensions to the Digest module of the ruby standard library to support marshalling"
|
42
41
|
|
43
42
|
if s.respond_to? :specification_version then
|
44
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
45
43
|
s.specification_version = 3
|
46
44
|
|
47
45
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
48
46
|
s.add_development_dependency(%q<rspec>, ["~> 2.6.0"])
|
49
|
-
s.add_development_dependency(%q<bundler>, ["~> 1.0
|
47
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0"])
|
50
48
|
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
51
49
|
s.add_development_dependency(%q<rake-compiler>, ["~> 0.7.9"])
|
52
50
|
else
|
53
51
|
s.add_dependency(%q<rspec>, ["~> 2.6.0"])
|
54
|
-
s.add_dependency(%q<bundler>, ["~> 1.0
|
52
|
+
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
55
53
|
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
56
54
|
s.add_dependency(%q<rake-compiler>, ["~> 0.7.9"])
|
57
55
|
end
|
58
56
|
else
|
59
57
|
s.add_dependency(%q<rspec>, ["~> 2.6.0"])
|
60
|
-
s.add_dependency(%q<bundler>, ["~> 1.0
|
58
|
+
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
61
59
|
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
62
60
|
s.add_dependency(%q<rake-compiler>, ["~> 0.7.9"])
|
63
61
|
end
|
@@ -4,29 +4,42 @@ require 'digest/md5'
|
|
4
4
|
|
5
5
|
describe Digest::MD5 do
|
6
6
|
describe "#marshal_dump" do
|
7
|
+
it "can marshal md5 sum for empty object " do
|
8
|
+
digest = Digest::MD5.new
|
9
|
+
digest.marshal_dump
|
10
|
+
end
|
11
|
+
|
7
12
|
it "returns a byte sequence that is larger than 176" do
|
8
13
|
## 88 bytes is minum state information for MD5
|
9
14
|
digest = Digest::MD5.new
|
10
15
|
digest.marshal_dump.should have_at_least(176).bytes.to_a
|
11
16
|
end
|
12
17
|
|
13
|
-
it "returns a byte sequence that is accepted by marshal_load" do
|
14
|
-
Digest::MD5.new.marshal_load(Digest::MD5.new.marshal_dump)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
it "can marshal md5 sum for empty object " do
|
18
|
-
digest = Digest::MD5.new
|
19
|
-
digest.marshal_load(Digest::MD5.new.marshal_dump)
|
20
|
-
digest.hexdigest.should == Digest::MD5.new.hexdigest
|
21
18
|
end
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
19
|
+
|
20
|
+
describe "#marshal_load" do
|
21
|
+
context "with a marshalled digest of empty byte sequence" do
|
22
|
+
digest = Digest::MD5.new
|
23
|
+
marshalled_digest = digest.marshal_dump
|
24
|
+
|
25
|
+
it "can load to the correct digest" do
|
26
|
+
Digest::MD5.new.tap{|h|h.marshal_load(marshalled_digest)}.hexdigest.should == digest.hexdigest
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "with marshalled digest of a random byte sequence" do
|
31
|
+
size = 10000
|
32
|
+
byte_sequence = (0...size).map{|i| rand(256)}.pack('c*')
|
33
|
+
digest = Digest::MD5.new
|
34
|
+
digest << byte_sequence
|
35
|
+
marshalled_digest = digest.marshal_dump
|
36
|
+
|
37
|
+
it "can load to the correct digest " do
|
38
|
+
Digest::MD5.new.tap{|h|h.marshal_load(marshalled_digest)}.hexdigest.should == digest.hexdigest
|
39
|
+
end
|
40
|
+
end
|
29
41
|
end
|
42
|
+
|
30
43
|
it "can continue on partial digestions " do
|
31
44
|
size = 10000
|
32
45
|
byte_sequence = (0...size).map{|i| rand(256)}.pack('c*')
|
@@ -39,4 +52,35 @@ describe Digest::MD5 do
|
|
39
52
|
continue << byte_sequence[split+1..-1]
|
40
53
|
continue.hexdigest.should == hex_digest
|
41
54
|
end
|
55
|
+
|
56
|
+
context "with an array of parts" do
|
57
|
+
size = 1000000
|
58
|
+
byte_sequence = (0...size).map{|i| rand(256)}.pack('c*')
|
59
|
+
parts = 100 + rand(900)
|
60
|
+
max_size = size/parts #Integer
|
61
|
+
parts_array = (0..parts).map{|p| byte_sequence[(p*max_size)...((p+1)*max_size)]}
|
62
|
+
|
63
|
+
it "can be used to take a series of parts and compute the digest of the concatenation" do
|
64
|
+
class FakeDatabase
|
65
|
+
attr_accessor :value
|
66
|
+
end
|
67
|
+
@db = FakeDatabase.new
|
68
|
+
|
69
|
+
def update_digest(part)
|
70
|
+
marshalled_digest = Marshal::load(@db.value) # Fetch the last digest from database
|
71
|
+
marshalled_digest << part # Compute digest incrementally
|
72
|
+
@db.value = Marshal::dump(marshalled_digest) # Store updated digest in database
|
73
|
+
end
|
74
|
+
|
75
|
+
## parts_array is provided; for example as a series of files
|
76
|
+
## generated with the command split on a larger file.
|
77
|
+
@db.value = Marshal::dump(Digest::MD5.new) #An initial value
|
78
|
+
parts_array.each do |part|
|
79
|
+
# Assume this method is invoked in a new process each time, and
|
80
|
+
# the only thing they share is the database (faked in the example with @db)
|
81
|
+
update_digest(part)
|
82
|
+
end
|
83
|
+
Marshal::load(@db.value).hexdigest.should == Digest::MD5.hexdigest(parts_array.inject("", :+))
|
84
|
+
end
|
85
|
+
end
|
42
86
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: digest_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-08-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,21 +21,31 @@ dependencies:
|
|
21
21
|
version: 2.6.0
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 2.6.0
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: bundler
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ~>
|
31
36
|
- !ruby/object:Gem::Version
|
32
|
-
version: 1.0
|
37
|
+
version: '1.0'
|
33
38
|
type: :development
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.0'
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: jeweler
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ~>
|
@@ -43,10 +53,15 @@ dependencies:
|
|
43
53
|
version: 1.6.4
|
44
54
|
type: :development
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.6.4
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
63
|
name: rake-compiler
|
49
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
67
|
- - ~>
|
@@ -54,7 +69,12 @@ dependencies:
|
|
54
69
|
version: 0.7.9
|
55
70
|
type: :development
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.7.9
|
58
78
|
description: With marshalling of digest objects, it is possible to compute the digests
|
59
79
|
over several executions by storing the marshalled object on file or database, this
|
60
80
|
is handy for computing digests for large files that comes in parts.
|
@@ -69,7 +89,6 @@ files:
|
|
69
89
|
- .document
|
70
90
|
- .rspec
|
71
91
|
- Gemfile
|
72
|
-
- Gemfile.lock
|
73
92
|
- LICENSE.txt
|
74
93
|
- README.rdoc
|
75
94
|
- Rakefile
|
@@ -96,7 +115,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
96
115
|
version: '0'
|
97
116
|
segments:
|
98
117
|
- 0
|
99
|
-
hash:
|
118
|
+
hash: 42947112275077556
|
100
119
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
120
|
none: false
|
102
121
|
requirements:
|
@@ -105,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
124
|
version: '0'
|
106
125
|
requirements: []
|
107
126
|
rubyforge_project:
|
108
|
-
rubygems_version: 1.8.
|
127
|
+
rubygems_version: 1.8.24
|
109
128
|
signing_key:
|
110
129
|
specification_version: 3
|
111
130
|
summary: Extensions to the Digest module of the ruby standard library to support marshalling
|
data/Gemfile.lock
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
GEM
|
2
|
-
remote: http://rubygems.org/
|
3
|
-
specs:
|
4
|
-
diff-lcs (1.1.2)
|
5
|
-
git (1.2.5)
|
6
|
-
jeweler (1.6.4)
|
7
|
-
bundler (~> 1.0)
|
8
|
-
git (>= 1.2.5)
|
9
|
-
rake
|
10
|
-
rake (0.9.2)
|
11
|
-
rake-compiler (0.7.9)
|
12
|
-
rake
|
13
|
-
rspec (2.6.0)
|
14
|
-
rspec-core (~> 2.6.0)
|
15
|
-
rspec-expectations (~> 2.6.0)
|
16
|
-
rspec-mocks (~> 2.6.0)
|
17
|
-
rspec-core (2.6.4)
|
18
|
-
rspec-expectations (2.6.0)
|
19
|
-
diff-lcs (~> 1.1.2)
|
20
|
-
rspec-mocks (2.6.0)
|
21
|
-
|
22
|
-
PLATFORMS
|
23
|
-
ruby
|
24
|
-
|
25
|
-
DEPENDENCIES
|
26
|
-
bundler (~> 1.0.0)
|
27
|
-
jeweler (~> 1.6.4)
|
28
|
-
rake-compiler (~> 0.7.9)
|
29
|
-
rspec (~> 2.6.0)
|