gibbler 0.8.10 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,16 @@
1
1
  GIBBLER, CHANGES
2
2
 
3
+
4
+ #### 0.9.0 (2012-04-20) ###############################
5
+
6
+ * FIXED: Gibbler::Complex now checks has_method? and will use that before instance variables.
7
+ * CHANGE: Gibbler is now a class which supplies the default standalone usage
8
+ * CHANGE: Ruby object mixins must now be explicitly loaded via "require 'gibbler/mixins'"
9
+ * CHANGE: Removed Gibbler.enable_debug/disable_debug
10
+ * CHANGE: Gibbler.digest now returns nil for an empty Array
11
+ * ADDED: Gibbler.delimiter
12
+
13
+
3
14
  #### 0.8.10 (2011-10-23) ###############################
4
15
 
5
16
  * CHANGE: Gibbler::Hash and Gibbler::Array now skip values that have no __gibbler method
@@ -199,7 +210,7 @@ NOTE: Calculated digests have changed since 0.3. Most digests created with
199
210
  * CHANGE: Gibbler methods are no longer available to all Ruby classes
200
211
  by default. The default list is now: String, Hash, Array, Symbol,
201
212
  Class, Fixnum, Bignum.
202
- * CHANGE: Renamed Gibbler.gibbler_digest_type to Gibbler.digest_type
213
+ * CHANGE: Renamed Gibbler.digest_type to Gibbler.digest_type
203
214
  * ADDED: Custom objects can now "include Gibbler::Complex"
204
215
 
205
216
 
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Solutious Inc, Delano Mandelbaum
1
+ Copyright (c) 2009-2012 Solutious Inc, Delano Mandelbaum
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
@@ -1,4 +1,4 @@
1
- = Gibbler - v0.8
1
+ = Gibbler - v0.9
2
2
 
3
3
  Git-like hashes and history for Ruby objects for Ruby 1.8, 1.9 and JRuby.
4
4
 
@@ -8,13 +8,23 @@ Check out the screencast[http://www.rubypulse.com/episode-0.3-gibbler.html] crea
8
8
 
9
9
  * Digest calculation may change between minor releases (as it did between 0.6 and 0.7)
10
10
  * Gibbler history is not suitable for very large objects since it keeps complete copies of the object in memory. This is a very early implementation of this feature so don't rely on it for production code.
11
- * Don't forget to enjoy what you do!
11
+ * Don't forget to enjoy your life!
12
12
 
13
13
 
14
- == Example 1 -- Basic Usage
14
+ == Example 1 -- Standalone Usage
15
15
 
16
16
  require 'gibbler'
17
17
 
18
+ g = Gibbler.new 'id', 1001 # => f4fb3796ababa3788d1bded8fdc589ab1ccb1c3d
19
+ g.base(36) # => sm71s7eam4hm5jlsuzlqkbuktwpe5h9
20
+
21
+ g == 'f4fb3796ababa3788d1bded8fdc589ab1ccb1c3d' # => true
22
+ g === 'f4fb379' # => true
23
+
24
+ == Example 2 -- Mixins Usage
25
+
26
+ require 'gibbler/mixins'
27
+
18
28
  "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
19
29
  :kimmy.gibbler # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df
20
30
 
@@ -40,11 +50,11 @@ Check out the screencast[http://www.rubypulse.com/episode-0.3-gibbler.html] crea
40
50
  config.gibbler.base36.short # => 8x00l83j
41
51
 
42
52
 
43
- == Example 2 -- Object History
53
+ == Example 3 -- Object History
44
54
 
45
55
  Gibbler can also keep track of the history of changes to an object. By default Gibbler supports history for Hash, Array, and String objects. The <tt>gibbler_commit</tt> method creates a clone of the current object and stores in an instance variable using the current hash digest as the key.
46
56
 
47
- require 'gibbler'
57
+ require 'gibbler/mixins'
48
58
  require 'gibbler/history'
49
59
 
50
60
  a = { :magic => :original }
@@ -75,7 +85,7 @@ Gibbler can also keep track of the history of changes to an object. By default G
75
85
  http://delano.github.com/gibbler/img/whoababy.gif
76
86
 
77
87
 
78
- == Example 3 -- Method Aliases
88
+ == Example 4 -- Method Aliases
79
89
 
80
90
  If you have control over the namespaces of your objects, you can use the method aliases to tighten up your code a bit. The "gibbler" and "gibbled?" methods can be accessed via "digest" and "changed?", respectively. (The reason they're not enabled by default is to avoid conflicts.)
81
91
 
@@ -101,11 +111,11 @@ The history methods also have aliases which remove the "gibbler_" prefix.
101
111
  a.revert!
102
112
  # etc...
103
113
 
104
- == Example 4 -- Different Digest types
114
+ == Example 5 -- Different Digest types
105
115
 
106
116
  By default Gibbler creates SHA1 hashes. You can change this globally or per instance.
107
117
 
108
- require 'gibbler'
118
+ require 'gibbler/mixins'
109
119
 
110
120
  Gibbler.digest_type = Digest::MD5
111
121
 
@@ -123,9 +133,9 @@ In Jruby, you can grab the digest types from the openssl library.
123
133
  :kimmy.gibbler # => 1069428e6273cf329436c3dce9b680d4d4e229d7b7...
124
134
 
125
135
 
126
- == Example 5 -- All your base
136
+ == Example 6 -- All your base
127
137
 
128
- require 'gibbler'
138
+ require 'gibbler/mixins'
129
139
 
130
140
  :kimmy.gibbler # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df
131
141
  :kimmy.gibbler.base(16) # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df
@@ -135,11 +145,11 @@ In Jruby, you can grab the digest types from the openssl library.
135
145
  :kimmy.gibbler.to_i # => 472384540402900668368761869477227308873774630879
136
146
 
137
147
 
138
- == Example 6 -- Global secret
148
+ == Example 7 -- Global secret
139
149
 
140
150
  Gibbler can prepend all digest inputs with a global secret. You can set this once per project to ensure your project's digests are unique.
141
151
 
142
- require 'gibbler'
152
+ require 'gibbler/mixins'
143
153
 
144
154
  :kimmy.gibbler # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df
145
155
 
@@ -180,17 +190,15 @@ As of 0.7 all Proc objects have the same digest: <tt>12075835e94be34438376cd7a54
180
190
  == Known Issues
181
191
 
182
192
  * gibbler or gibbled? must be called at least once before gibbled? will be able to return a useful value (otherwise there is no previous digest value to compare to)
183
- * Digests for Bignum objects are different between Ruby and JRuby. Does anyone know why?
193
+ * Digests for Bignum objects are different between Ruby and JRuby. Why?
184
194
  * Digests for Proc objects are different between Ruby 1.8 and 1.9 because Proc.arity returns different values and 1.8 has no lambda? method.
185
195
 
186
196
 
187
197
  == Installation
188
198
 
189
- Via Rubygems, one of:
199
+ Via Rubygems:
190
200
 
191
201
  $ gem install gibbler
192
- $ gem install delano-gibbler
193
-
194
202
 
195
203
  or via download:
196
204
  * gibbler-latest.tar.gz[http://github.com/delano/gibbler/tarball/latest]
@@ -220,7 +228,7 @@ or via download:
220
228
 
221
229
  == Credits
222
230
 
223
- * Delano (@solutious.com)
231
+ * [Delano Mandelbaum](http://delanotes.com/) (@solutious.com)
224
232
 
225
233
 
226
234
  == License
data/Rakefile CHANGED
@@ -3,15 +3,11 @@ require "rake"
3
3
  require "rake/clean"
4
4
  require 'yaml'
5
5
 
6
- begin
7
- require 'hanna/rdoctask'
8
- rescue LoadError
9
- require 'rake/rdoctask'
10
- end
11
-
6
+ require 'rdoc/task'
7
+
12
8
  config = YAML.load_file("VERSION.yml")
13
9
  task :default => ["build"]
14
- CLEAN.include [ 'pkg', 'doc' ]
10
+ CLEAN.include [ 'pkg', 'rdoc' ]
15
11
  name = "gibbler"
16
12
 
17
13
  begin
@@ -20,22 +16,20 @@ begin
20
16
  gem.version = "#{config[:MAJOR]}.#{config[:MINOR]}.#{config[:PATCH]}"
21
17
  gem.name = name
22
18
  gem.rubyforge_project = gem.name
23
- gem.summary = "Gibbler: Git-like hashes for Ruby objects"
24
- gem.description = gem.summary
19
+ gem.summary = "Git-like hashes for Ruby objects"
20
+ gem.description = "Git-like hashes for Ruby objects"
25
21
  gem.email = "delano@solutious.com"
26
22
  gem.homepage = "http://github.com/delano/gibbler"
27
23
  gem.authors = ["Delano Mandelbaum"]
28
- gem.add_dependency("attic", ">= 0.4.0")
29
24
  end
30
25
  Jeweler::GemcutterTasks.new
31
26
  rescue LoadError
32
27
  puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
33
28
  end
34
29
 
35
-
36
- Rake::RDocTask.new do |rdoc|
30
+ RDoc::Task.new do |rdoc|
37
31
  version = "#{config[:MAJOR]}.#{config[:MINOR]}.#{config[:PATCH]}"
38
- rdoc.rdoc_dir = "doc"
32
+ rdoc.rdoc_dir = "rdoc"
39
33
  rdoc.title = "#{name} #{version}"
40
34
  rdoc.rdoc_files.include("README*")
41
35
  rdoc.rdoc_files.include("LICENSE.txt")
@@ -43,22 +37,3 @@ Rake::RDocTask.new do |rdoc|
43
37
  rdoc.rdoc_files.include("lib/**/*.rb")
44
38
  end
45
39
 
46
-
47
- # Rubyforge Release / Publish Tasks ==================================
48
-
49
- #about 'Publish website to rubyforge'
50
- task 'publish:rdoc' => 'doc/index.html' do
51
- #sh "scp -rp doc/* rubyforge.org:/var/www/gforge-projects/#{name}/"
52
- end
53
-
54
- #about 'Public release to rubyforge'
55
- task 'publish:gem' => [:package] do |t|
56
- sh <<-end
57
- rubyforge add_release -o Any -a CHANGES.txt -f -n README.md #{name} #{name} #{@spec.version} pkg/#{name}-#{@spec.version}.gem &&
58
- rubyforge add_file -o Any -a CHANGES.txt -f -n README.md #{name} #{name} #{@spec.version} pkg/#{name}-#{@spec.version}.tgz
59
- end
60
- end
61
-
62
-
63
-
64
-
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :MAJOR: 0
3
- :MINOR: 8
4
- :PATCH: 10
3
+ :MINOR: 9
4
+ :PATCH: 0
@@ -1,57 +1,59 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "gibbler"
8
- s.version = "0.8.10"
8
+ s.version = "0.9.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Delano Mandelbaum"]
12
- s.date = "2011-10-23"
12
+ s.date = "2012-04-20"
13
13
  s.description = "Gibbler: Git-like hashes for Ruby objects"
14
14
  s.email = "delano@solutious.com"
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE.txt",
17
- "README.rdoc"
17
+ "README.rdoc"
18
18
  ]
19
19
  s.files = [
20
20
  "CHANGES.txt",
21
- "LICENSE.txt",
22
- "README.rdoc",
23
- "Rakefile",
24
- "VERSION.yml",
25
- "gibbler.gemspec",
26
- "lib/gibbler.rb",
27
- "lib/gibbler/aliases.rb",
28
- "lib/gibbler/history.rb",
29
- "lib/gibbler/mixins.rb",
30
- "try/01_mixins_try.rb",
31
- "try/02_compat_try.rb",
32
- "try/05_gibbler_digest_try.rb",
33
- "try/10_basic_try.rb",
34
- "try/11_basic_sha256_try.rb",
35
- "try/14_extended_try.rb",
36
- "try/15_file_try.rb",
37
- "try/16_uri_try.rb",
38
- "try/17_complex_object_try.rb",
39
- "try/18_proc_try.rb",
40
- "try/20_time_try.rb",
41
- "try/30_secret_try.rb",
42
- "try/50_history_try.rb",
43
- "try/51_hash_history_try.rb",
44
- "try/52_array_history_try.rb",
45
- "try/53_string_history_try.rb",
46
- "try/57_arbitrary_history_try.rb",
47
- "try/59_history_exceptions_try.rb",
48
- "try/80_performance_try.rb",
49
- "try/90_alias_try.rb"
21
+ "LICENSE.txt",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION.yml",
25
+ "gibbler.gemspec",
26
+ "lib/gibbler.rb",
27
+ "lib/gibbler/aliases.rb",
28
+ "lib/gibbler/history.rb",
29
+ "lib/gibbler/mixins.rb",
30
+ "try/01_core_ext_try.rb",
31
+ "try/02_compat_try.rb",
32
+ "try/05_gibbler_digest_try.rb",
33
+ "try/10_standalone_try.rb",
34
+ "try/11_basic_try.rb",
35
+ "try/12_basic_sha256_try.rb",
36
+ "try/14_extended_try.rb",
37
+ "try/15_file_try.rb",
38
+ "try/16_uri_try.rb",
39
+ "try/17_complex_object_try.rb",
40
+ "try/18_proc_try.rb",
41
+ "try/20_time_try.rb",
42
+ "try/30_secret_try.rb",
43
+ "try/50_history_try.rb",
44
+ "try/51_hash_history_try.rb",
45
+ "try/52_array_history_try.rb",
46
+ "try/53_string_history_try.rb",
47
+ "try/57_arbitrary_history_try.rb",
48
+ "try/59_history_exceptions_try.rb",
49
+ "try/80_performance_try.rb",
50
+ "try/90_alias_try.rb"
50
51
  ]
51
52
  s.homepage = "http://github.com/delano/gibbler"
53
+ s.rdoc_options = ["--charset=UTF-8"]
52
54
  s.require_paths = ["lib"]
53
55
  s.rubyforge_project = "gibbler"
54
- s.rubygems_version = "1.8.10"
56
+ s.rubygems_version = "1.8.22"
55
57
  s.summary = "Gibbler: Git-like hashes for Ruby objects"
56
58
 
57
59
  if s.respond_to? :specification_version then
@@ -14,7 +14,7 @@ require 'digest/sha1'
14
14
  #
15
15
  # "Hola, Tanneritos"
16
16
  #
17
- module Gibbler
17
+ class Gibbler < String
18
18
  module VERSION
19
19
  def self.to_s
20
20
  load_config
@@ -33,8 +33,6 @@ module Gibbler
33
33
  attr_accessor :secret, :default_base
34
34
  end
35
35
 
36
- require 'gibbler/mixins'
37
-
38
36
  class Error < RuntimeError
39
37
  def initialize(obj); @obj = obj; end
40
38
  end
@@ -47,87 +45,92 @@ end
47
45
  #
48
46
  class Gibbler::Digest < String
49
47
 
50
- # Return an integer assuming base is Gibbler.default_base.
51
- def to_i(base=nil)
52
- base ||= Gibbler.default_base
53
- super(base)
54
- end
48
+ module InstanceMethods
49
+ # Return an integer assuming base is Gibbler.default_base.
50
+ def to_i(base=nil)
51
+ base ||= Gibbler.default_base
52
+ super(base)
53
+ end
55
54
 
56
- # Returns a string. Takes an optional base.
57
- def to_s(base=nil)
58
- base.nil? ? super() : super().to_i(Gibbler.default_base).to_s(base)
59
- end
55
+ # Returns a string. Takes an optional base.
56
+ def to_s(base=nil)
57
+ base.nil? ? super() : super().to_i(Gibbler.default_base).to_s(base)
58
+ end
60
59
 
61
- def base(base=Gibbler.default_base)
62
- self.class.new(self.to_i(Gibbler.default_base).to_s(base))
63
- end
60
+ def base(base=Gibbler.default_base)
61
+ v = self.to_i(Gibbler.default_base).to_s(base)
62
+ v.extend Gibbler::Digest::InstanceMethods
63
+ self.class.new v
64
+ end
64
65
 
65
- def base36
66
- base(36)
67
- end
66
+ def base36
67
+ base(36)
68
+ end
68
69
 
69
- # Shorten the digest to the given (optional) length.
70
- def shorten(len=20)
71
- self[0..len-1]
72
- end
70
+ # Shorten the digest to the given (optional) length.
71
+ def shorten(len=20)
72
+ self[0..len-1]
73
+ end
73
74
 
74
- # Returns the first 8 characters of itself (the digest).
75
- #
76
- # e.g.
77
- #
78
- # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
79
- # "kimmy".gibbler.short # => c8027100
80
- #
81
- def short
82
- shorten(8)
83
- end
75
+ # Returns the first 8 characters of itself (the digest).
76
+ #
77
+ # e.g.
78
+ #
79
+ # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
80
+ # "kimmy".gibbler.short # => c8027100
81
+ #
82
+ def short
83
+ shorten(8)
84
+ end
84
85
 
85
- # Returns the first 6 characters of itself (the digest).
86
- #
87
- # e.g.
88
- #
89
- # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
90
- # "kimmy".gibbler.shorter # => c80271
91
- #
92
- def shorter
93
- shorten(6)
94
- end
86
+ # Returns the first 6 characters of itself (the digest).
87
+ #
88
+ # e.g.
89
+ #
90
+ # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
91
+ # "kimmy".gibbler.shorter # => c80271
92
+ #
93
+ def shorter
94
+ shorten(6)
95
+ end
95
96
 
96
- # Returns the first 4 characters of itself (the digest).
97
- #
98
- # e.g.
99
- #
100
- # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
101
- # "kimmy".gibbler.tiny # => c802
102
- #
103
- def tiny
104
- shorten(4)
105
- end
97
+ # Returns the first 4 characters of itself (the digest).
98
+ #
99
+ # e.g.
100
+ #
101
+ # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
102
+ # "kimmy".gibbler.tiny # => c802
103
+ #
104
+ def tiny
105
+ shorten(4)
106
+ end
106
107
 
107
- # Returns true when +ali+ matches +self+
108
- #
109
- # "kimmy".gibbler == "c8027100ecc54945ab15ddac529230e38b1ba6a1" # => true
110
- # "kimmy".gibbler == "c8027100" # => false
111
- #
112
- def ==(ali)
113
- return true if self.to_s == ali.to_s
114
- false
115
- end
108
+ # Returns true when +ali+ matches +self+
109
+ #
110
+ # "kimmy".gibbler == "c8027100ecc54945ab15ddac529230e38b1ba6a1" # => true
111
+ # "kimmy".gibbler == "c8027100" # => false
112
+ #
113
+ def ==(ali)
114
+ return true if self.to_s == ali.to_s
115
+ false
116
+ end
116
117
 
117
- # Returns true when +g+ matches one of: +self+, +short+, +shorter+, +tiny+
118
- #
119
- # "kimmy".gibbler === "c8027100ecc54945ab15ddac529230e38b1ba6a1" # => true
120
- # "kimmy".gibbler === "c8027100" # => true
121
- # "kimmy".gibbler === "c80271" # => true
122
- # "kimmy".gibbler === "c802" # => true
123
- #
124
- def ===(g)
125
- return true if [to_s, short, shorter, tiny].member?(g.to_s)
126
- false
118
+ # Returns true when +g+ matches one of: +self+, +short+, +shorter+, +tiny+
119
+ #
120
+ # "kimmy".gibbler === "c8027100ecc54945ab15ddac529230e38b1ba6a1" # => true
121
+ # "kimmy".gibbler === "c8027100" # => true
122
+ # "kimmy".gibbler === "c80271" # => true
123
+ # "kimmy".gibbler === "c802" # => true
124
+ #
125
+ def ===(g)
126
+ return true if [to_s, short, shorter, tiny].member?(g.to_s)
127
+ false
128
+ end
127
129
  end
130
+ include InstanceMethods
128
131
  end
129
132
 
130
- module Gibbler
133
+ class Gibbler < String
131
134
  module Object
132
135
 
133
136
  def self.included(obj)
@@ -215,38 +218,70 @@ module Gibbler
215
218
 
216
219
  end
217
220
 
221
+ class Gibbler < String
222
+ include Gibbler::Digest::InstanceMethods
223
+ # Modify the digest type for this instance. See Gibbler.digest_type
224
+ attr_writer :digest_type
225
+ attr_reader :input
226
+ # Creates a digest from the given +input+. See Gibbler.digest.
227
+ #
228
+ # If only one argument is given and it's a digest, this will
229
+ # simply create an instance of that digest. In other words,
230
+ # it won't calculate a new digest based on that input.
231
+ def initialize *input
232
+ if input.size == 1 && Gibbler::Digest::InstanceMethods === input.first
233
+ super input.first
234
+ else
235
+ input.collect!(&:to_s)
236
+ super Gibbler.digest(input) || ''
237
+ end
238
+ end
239
+ def digest_type
240
+ @digest_type || self.class.digest_type
241
+ end
242
+
243
+ def digest *input
244
+ replace Gibbler.digest(input, digest_type)
245
+ end
246
+
247
+ end
218
248
 
219
- module Gibbler
249
+ class Gibbler < String
220
250
 
221
- @@gibbler_debug = false
222
- @@gibbler_digest_type = ::Digest::SHA1
251
+ @debug = false
252
+ @digest_type = ::Digest::SHA1
253
+ @delimiter = ':'
223
254
 
224
- # Specify a different digest class. The default is +Digest::SHA1+. You
225
- # could try +Digest::SHA256+ by doing this:
226
- #
227
- # Object.gibbler_digest_type = Digest::SHA256
228
- #
229
- def self.digest_type=(v)
230
- @@gibbler_digest_type = v
255
+ class << self
256
+ # Specify a different digest class. The default is +Digest::SHA1+. You
257
+ # could try +Digest::SHA256+ by doing this:
258
+ #
259
+ # Object.digest_type = Digest::SHA256
260
+ #
261
+ attr_accessor :digest_type
262
+ # The delimiter to use when joining Array values before creating a
263
+ # new digest hash. The default is ":".
264
+ attr_accessor :delimiter
265
+ # Set to true for debug output (including all digest inputs)
266
+ attr_accessor :debug
267
+ # Returns the current debug status (true or false)
268
+ def debug?; @debug != false; end
231
269
  end
232
- # Returns the current debug status (true or false)
233
- def self.debug?; @@gibbler_debug; end
234
- def self.enable_debug; @@gibbler_debug = true; end
235
- def self.disable_debug; @@gibbler_debug = false; end
236
- def self.debug=(v); @@gibbler_debug = v; end
237
- # Returns the current digest class.
238
- def self.digest_type; @@gibbler_digest_type; end
239
270
 
240
- # Sends +str+ to Digest::SHA1.hexdigest. If another digest class
271
+ # Sends +input+ to Digest::SHA1.hexdigest. If another digest class
241
272
  # has been specified, that class will be used instead.
242
273
  # If Gibbler.secret is set, +str+ will be prepended with the
243
274
  # value.
244
275
  #
276
+ # If +input+ is an Array, it will be flattened and joined.
277
+ #
245
278
  # See: digest_type
246
- def self.digest(str, digest_type=nil)
247
- digest_type ||= @@gibbler_digest_type
248
- str = [Gibbler.secret, str].join(':') unless Gibbler.secret.nil?
249
- dig = digest_type.hexdigest(str)
279
+ def self.digest(input, digest_type=nil)
280
+ input = input.flatten.collect(&:to_s).join(delimiter) if ::Array === input
281
+ return if input.empty?
282
+ digest_type ||= @digest_type
283
+ input = [Gibbler.secret, input].join(delimiter) unless Gibbler.secret.nil?
284
+ dig = digest_type.hexdigest(input)
250
285
  dig = dig.to_i(16).to_s(Gibbler.default_base) if 16 != Gibbler.default_base
251
286
  dig
252
287
  end
@@ -265,8 +300,9 @@ module Gibbler
265
300
  raise "You probably want to include Gibbler::Complex or Gibbler::Object"
266
301
  end
267
302
 
303
+
268
304
  # Creates a digest based on:
269
- # * An Array of instance variable names and values in the format: <tt>CLASS:LENGTH:VALUE</tt>
305
+ # * An Array of instance variable names or method names and values in the format: <tt>CLASS:LENGTH:VALUE</tt>
270
306
  # * The gibbler method is called on each element so if it is a Hash or Array etc it
271
307
  # will be parsed recursively according to the gibbler method for that class type.
272
308
  # * Digest the Array of digests
@@ -324,14 +360,14 @@ module Gibbler
324
360
  d = []
325
361
  gibbler_debug :gibbler_fields, gibbler_fields
326
362
  gibbler_fields.each do |n|
327
- value = instance_variable_get("@#{n}")
363
+ value = respond_to?(n) ? send(n) : instance_variable_get("@#{n}")
328
364
  unless value.respond_to? :__gibbler
329
365
  gibbler_debug klass, :skipping, n
330
366
  next
331
367
  end
332
368
  d << '%s:%s:%s' % [value.class, n, value.__gibbler(digest_type)]
333
369
  end
334
- d = d.join(':').__gibbler(digest_type)
370
+ d = d.join(Gibbler.delimiter).__gibbler(digest_type)
335
371
  a = Gibbler.digest "%s:%d:%s" % [klass, d.size, d], digest_type
336
372
  gibbler_debug klass, a, [klass, d.size, d]
337
373
  a
@@ -344,7 +380,6 @@ module Gibbler
344
380
  self.instance_variable_set v
345
381
  end
346
382
  end
347
-
348
383
  end
349
384
 
350
385
  # Creates a digest based on: <tt>CLASS:LENGTH:VALUE</tt>.
@@ -417,7 +452,7 @@ module Gibbler
417
452
  end
418
453
  '%s:%s:%s' % [value.class, name, value.__gibbler(digest_type)]
419
454
  end
420
- d = d.join(':').__gibbler(digest_type)
455
+ d = d.join(Gibbler.delimiter).__gibbler(digest_type)
421
456
  a = Gibbler.digest '%s:%s:%s' % [klass, d.size, d], digest_type
422
457
  gibbler_debug klass, a, [klass, d.size, d]
423
458
  a
@@ -461,7 +496,7 @@ module Gibbler
461
496
  d << '%s:%s:%s' % [value.class, index, value.__gibbler(digest_type)]
462
497
  index += 1
463
498
  end
464
- d = d.join(':').__gibbler(digest_type)
499
+ d = d.join(Gibbler.delimiter).__gibbler(digest_type)
465
500
  a = Gibbler.digest '%s:%s:%s' % [klass, d.size, d], digest_type
466
501
  gibbler_debug klass, a, [klass, d.size, d]
467
502
  a
@@ -652,34 +687,15 @@ module Gibbler
652
687
 
653
688
  end
654
689
 
690
+ class String
691
+ unless method_defined? :clear
692
+ def clear
693
+ replace ""
694
+ end
695
+ end
696
+ end
655
697
 
656
- class NilClass; include Gibbler::Nil; end
657
- class Class; include Gibbler::Object; end
658
- class Module; include Gibbler::Object; end
659
- class Proc; include Gibbler::Object; end
660
- class String; include Gibbler::String; end
661
- class Regexp; include Gibbler::String; end
662
- class Fixnum; include Gibbler::String; end
663
- class Bignum; include Gibbler::String; end
664
- class TrueClass; include Gibbler::String; end
665
- class FalseClass; include Gibbler::String; end
666
- class Float; include Gibbler::String; end
667
- class Symbol; include Gibbler::String; end
668
- class Date; include Gibbler::String; end
669
- class Hash; include Gibbler::Hash; end
670
- class Array; include Gibbler::Array; end
671
- class Time; include Gibbler::Time; end
672
- class DateTime < Date; include Gibbler::DateTime; end
673
- class Range; include Gibbler::Range; end
674
- class File; include Gibbler::File; end
675
- class TempFile; include Gibbler::File; end
676
-
677
- # URI::Generic must be included towards the
678
- # end b/c it runs Object#freeze statically.
679
- module URI; class Generic; include Gibbler::String; end; end
680
698
 
681
- # Bundler calls freeze on an instance of Gem::Platform
682
- module Gem; class Platform; include Gibbler::Complex; end; end
683
699
 
684
700
 
685
701
 
@@ -1,7 +1,7 @@
1
1
 
2
- require 'gibbler'
2
+ require 'gibbler/mixins'
3
3
 
4
- module Gibbler
4
+ class Gibbler < String
5
5
 
6
6
  module Object
7
7
  alias :digest :gibbler
@@ -1,7 +1,7 @@
1
1
 
2
2
 
3
3
 
4
- module Gibbler
4
+ class Gibbler < String
5
5
  class NoRevert < Gibbler::Error
6
6
  def message; "Revert not implemented for #{@obj}" end
7
7
  end
@@ -1,9 +1,34 @@
1
+ require 'gibbler'
1
2
 
3
+ class NilClass; include Gibbler::Nil; end
4
+ class String; include Gibbler::String; end
5
+ class Symbol; include Gibbler::String; end
6
+ class Fixnum; include Gibbler::String; end
7
+ class Bignum; include Gibbler::String; end
8
+ class TrueClass; include Gibbler::String; end
9
+ class FalseClass; include Gibbler::String; end
10
+ class Class; include Gibbler::Object; end
11
+ class Module; include Gibbler::Object; end
12
+ class Proc; include Gibbler::Object; end
13
+ class Regexp; include Gibbler::String; end
14
+ class Float; include Gibbler::String; end
15
+ class Date; include Gibbler::String; end
16
+ class Hash; include Gibbler::Hash; end
17
+ class Array; include Gibbler::Array; end
18
+ class Time; include Gibbler::Time; end
19
+ class DateTime < Date; include Gibbler::DateTime; end
20
+ class Range; include Gibbler::Range; end
21
+ class File; include Gibbler::File; end
22
+ class TempFile; include Gibbler::File; end
23
+ class MatchData; include Gibbler::String; end
24
+ class OpenStruct; include Gibbler::Object; end
25
+
26
+ # URI::Generic must be included towards the
27
+ # end b/c it runs Object#freeze statically.
28
+ module URI; class Generic; include Gibbler::String; end; end
29
+
30
+ # Bundler calls freeze on an instance of Gem::Platform
31
+ module Gem; class Platform; include Gibbler::Complex; end; end
32
+
33
+ module Addressable; class URI; include Gibbler::String; end; end
2
34
 
3
- class String
4
- unless method_defined? :clear
5
- def clear
6
- replace ""
7
- end
8
- end
9
- end
@@ -1,4 +1,4 @@
1
- require 'gibbler'
1
+ require 'gibbler/mixins'
2
2
 
3
3
  ## has String#clear
4
4
  "".respond_to? :clear
@@ -1,4 +1,4 @@
1
- require 'gibbler'
1
+ require 'gibbler/mixins'
2
2
 
3
3
  ## Gibbler Objects have gibbler_cache method
4
4
  "kimmy".respond_to? :gibbler_cache
@@ -1,4 +1,4 @@
1
- require 'gibbler'
1
+ require 'gibbler/mixins'
2
2
 
3
3
  ## has short method
4
4
  "kimmy".gibbler.short
@@ -0,0 +1,49 @@
1
+ require 'gibbler'
2
+
3
+ @sha256_digest = if Tryouts.sysinfo.vm == :java
4
+ require 'openssl'
5
+ OpenSSL::Digest::SHA256
6
+ else
7
+ Digest::SHA256
8
+ end
9
+
10
+ ## Default delimiter
11
+ Gibbler.delimiter
12
+ #=> ':'
13
+
14
+ ## Create a digest from flattened Array
15
+ Gibbler.digest [1, :sym, ['string', 2,3]].flatten.join(':')
16
+ #=> 'd84d6ad2bd5c9589842fb02cf3c384e4924b1d3f'
17
+
18
+ ## Create a digest from Array
19
+ Gibbler.digest [1, :sym, ['string', 2,3]]
20
+ #=> 'd84d6ad2bd5c9589842fb02cf3c384e4924b1d3f'
21
+
22
+ ## Create an instance
23
+ Gibbler.new 1, :sym, 'string', 2,3
24
+ #=> 'd84d6ad2bd5c9589842fb02cf3c384e4924b1d3f'
25
+
26
+ ## Can modify base
27
+ g = Gibbler.new 1, :sym, 'string', 2,3
28
+ g.base(36)
29
+ #=> 'p9lffkbfkgpf7j71ho5cvxxcvx8gv27'
30
+
31
+ ## Maintains class
32
+ g = Gibbler.new 1, :sym, 'string', 2,3
33
+ g.base(36).class
34
+ #=> Gibbler
35
+
36
+ ## Can change digest type by class
37
+ Gibbler.digest_type = @sha256_digest
38
+ g = Gibbler.new 1, :sym, 'string', 2,3
39
+ #=> '204aacebb816bc2c8675f3490bf5a1a908988fb72f3dfd6774e963bbb9e26a26'
40
+
41
+ ## Can change digest type per instance
42
+ Gibbler.digest_type = Digest::SHA1
43
+ g = Gibbler.new
44
+ g.digest_type = @sha256_digest
45
+ g.digest 1, :sym, 'string', 2,3
46
+ g
47
+ #=> '204aacebb816bc2c8675f3490bf5a1a908988fb72f3dfd6774e963bbb9e26a26'
48
+
49
+ Gibbler.digest_type = Digest::SHA1
@@ -1,4 +1,4 @@
1
- require 'gibbler'
1
+ require 'gibbler/mixins'
2
2
 
3
3
  #Gibbler.enable_debug
4
4
 
@@ -6,7 +6,7 @@ require 'gibbler'
6
6
  begin
7
7
  a = Class.new
8
8
  a.send :include, Gibbler
9
- rescue RuntimeError
9
+ rescue TypeError
10
10
  :success
11
11
  end
12
12
  #=> :success
@@ -1,4 +1,4 @@
1
- require 'gibbler'
1
+ require 'gibbler/mixins'
2
2
 
3
3
  # NOTE: JRuby requires that we use OpenSSL::Digest::SHA256
4
4
  if Tryouts.sysinfo.vm == :java
@@ -1,4 +1,4 @@
1
- require 'gibbler'
1
+ require 'gibbler/mixins'
2
2
 
3
3
  ## true can gibbler
4
4
  true.gibbler
@@ -1,5 +1,5 @@
1
1
  require 'tempfile'
2
- require 'gibbler'
2
+ require 'gibbler/mixins'
3
3
 
4
4
  @tempfile = "tryouts-9000-awesome.txt"
5
5
 
@@ -1,5 +1,5 @@
1
1
  require 'uri'
2
- require 'gibbler'
2
+ require 'gibbler/mixins'
3
3
 
4
4
  # "URI::HTTP can gibbler"
5
5
  uri = URI.parse "http://localhost:3114/spaceship"
@@ -1,4 +1,5 @@
1
- require 'gibbler'
1
+ require 'gibbler/mixins'
2
+ require 'time'
2
3
 
3
4
  # arbitrary objects can specify instance variables to gibbler
4
5
  class ::FullHouse
@@ -18,10 +19,12 @@ require 'gibbler'
18
19
  # arbitrary objects can append more instance variables later on
19
20
  class ::FullHouse
20
21
  gibbler :stamp, :ready
22
+ def stamp
23
+ Time.parse('2009-08-25 16:43:53 UTC')
24
+ end
21
25
  end
22
26
  a = FullHouse.new
23
27
  a.roles = [:jesse, :joey, :danny, :kimmy, :michelle, :dj, :stephanie]
24
- a.stamp = Time.parse('2009-08-25 16:43:53 UTC')
25
28
  a.ready = true
26
29
  a.gibbler
27
30
  #=> "fbdce0d97a856e7106bec418d585c914914b8aa5"
@@ -1,4 +1,4 @@
1
- require 'gibbler'
1
+ require 'gibbler/mixins'
2
2
 
3
3
  class ::MyProc < Proc; end
4
4
 
@@ -1,5 +1,5 @@
1
1
  require 'date'
2
- require 'gibbler'
2
+ require 'gibbler/mixins'
3
3
 
4
4
  # "Date instance can gibbler
5
5
  Date.parse('2009-08-25').gibbler
@@ -1,5 +1,5 @@
1
1
  require 'uri'
2
- require 'gibbler'
2
+ require 'gibbler/mixins'
3
3
 
4
4
  # "Can set a sexy global secret
5
5
  Gibbler.secret = 'kimmy'.gibbler
@@ -1,4 +1,4 @@
1
- require 'gibbler'
1
+ require 'gibbler/mixins'
2
2
  require 'gibbler/history'
3
3
 
4
4
  # can convert short digest into long
@@ -1,4 +1,4 @@
1
- require 'gibbler'
1
+ require 'gibbler/mixins'
2
2
  require 'gibbler/history'
3
3
 
4
4
  class ::Hash
@@ -1,4 +1,4 @@
1
- require 'gibbler'
1
+ require 'gibbler/mixins'
2
2
  require 'gibbler/history'
3
3
 
4
4
  class Array
@@ -1,4 +1,4 @@
1
- require 'gibbler'
1
+ require 'gibbler/mixins'
2
2
  require 'gibbler/history'
3
3
 
4
4
  class String
@@ -1,4 +1,4 @@
1
- require 'gibbler'
1
+ require 'gibbler/mixins'
2
2
  require 'gibbler/history'
3
3
 
4
4
  class ::FullHouse
@@ -1,4 +1,4 @@
1
- require 'gibbler'
1
+ require 'gibbler/mixins'
2
2
  require 'gibbler/history'
3
3
 
4
4
 
metadata CHANGED
@@ -1,38 +1,24 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: gibbler
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
4
5
  prerelease:
5
- version: 0.8.10
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Delano Mandelbaum
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
-
13
- date: 2011-10-23 00:00:00 Z
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: attic
17
- prerelease: false
18
- requirement: &id001 !ruby/object:Gem::Requirement
19
- none: false
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: 0.4.0
24
- type: :runtime
25
- version_requirements: *id001
26
- description: "Gibbler: Git-like hashes for Ruby objects"
12
+ date: 2013-01-08 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Git-like hashes for Ruby objects
27
15
  email: delano@solutious.com
28
16
  executables: []
29
-
30
17
  extensions: []
31
-
32
- extra_rdoc_files:
18
+ extra_rdoc_files:
33
19
  - LICENSE.txt
34
20
  - README.rdoc
35
- files:
21
+ files:
36
22
  - CHANGES.txt
37
23
  - LICENSE.txt
38
24
  - README.rdoc
@@ -43,11 +29,12 @@ files:
43
29
  - lib/gibbler/aliases.rb
44
30
  - lib/gibbler/history.rb
45
31
  - lib/gibbler/mixins.rb
46
- - try/01_mixins_try.rb
32
+ - try/01_core_ext_try.rb
47
33
  - try/02_compat_try.rb
48
34
  - try/05_gibbler_digest_try.rb
49
- - try/10_basic_try.rb
50
- - try/11_basic_sha256_try.rb
35
+ - try/10_standalone_try.rb
36
+ - try/11_basic_try.rb
37
+ - try/12_basic_sha256_try.rb
51
38
  - try/14_extended_try.rb
52
39
  - try/15_file_try.rb
53
40
  - try/16_uri_try.rb
@@ -65,30 +52,26 @@ files:
65
52
  - try/90_alias_try.rb
66
53
  homepage: http://github.com/delano/gibbler
67
54
  licenses: []
68
-
69
55
  post_install_message:
70
56
  rdoc_options: []
71
-
72
- require_paths:
57
+ require_paths:
73
58
  - lib
74
- required_ruby_version: !ruby/object:Gem::Requirement
59
+ required_ruby_version: !ruby/object:Gem::Requirement
75
60
  none: false
76
- requirements:
77
- - - ">="
78
- - !ruby/object:Gem::Version
79
- version: "0"
80
- required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
66
  none: false
82
- requirements:
83
- - - ">="
84
- - !ruby/object:Gem::Version
85
- version: "0"
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
86
71
  requirements: []
87
-
88
72
  rubyforge_project: gibbler
89
73
  rubygems_version: 1.8.10
90
74
  signing_key:
91
75
  specification_version: 3
92
- summary: "Gibbler: Git-like hashes for Ruby objects"
76
+ summary: Git-like hashes for Ruby objects
93
77
  test_files: []
94
-