gibbler 0.5.2 → 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +8 -1
- data/README.rdoc +14 -0
- data/gibbler.gemspec +7 -1
- data/lib/gibbler/aliases.rb +29 -0
- data/lib/gibbler/history.rb +22 -19
- data/lib/gibbler/object.rb +39 -0
- data/lib/gibbler.rb +10 -2
- data/tryouts/10_basic_tryouts.rb +14 -1
- data/tryouts/51_hash_history_tryouts.rb +2 -2
- data/tryouts/80_performance_tryouts.rb +1 -1
- data/tryouts/90_alias_tryouts.rb +60 -0
- metadata +16 -4
data/CHANGES.txt
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
GIBBLER, CHANGES
|
2
2
|
|
3
|
+
#### 0.5.3 (2009-07-12) #################################
|
3
4
|
|
4
|
-
|
5
|
+
* FIXED: Updated gemspec to fix missing files (aliases)
|
6
|
+
* CHANGE: conversion to attic instead of weirdo instance
|
7
|
+
variables (@__gibbler__ and @__gibbler_history)
|
8
|
+
* NEW DEPENDENCY: attic
|
9
|
+
|
10
|
+
|
11
|
+
#### 0.5.2 (2009-07-07) #################################
|
5
12
|
|
6
13
|
* CHANGE: Moved Gibbler instance methods to Gibbler::Object
|
7
14
|
* ADDED: Proc.gibbler which is included by default
|
data/README.rdoc
CHANGED
@@ -144,6 +144,20 @@ The gibbler_revert! method modifies the object in place so this was an important
|
|
144
144
|
* 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)
|
145
145
|
|
146
146
|
|
147
|
+
== Installation
|
148
|
+
|
149
|
+
Via Rubygems, one of:
|
150
|
+
|
151
|
+
$ gem install gibbler
|
152
|
+
$ gem install delano-gibbler
|
153
|
+
|
154
|
+
|
155
|
+
or via download:
|
156
|
+
* gibbler-latest.tar.gz[http://github.com/delano/gibbler/tarball/latest]
|
157
|
+
* gibbler-latest.zip[http://github.com/delano/gibbler/zipball/latest]
|
158
|
+
|
159
|
+
|
160
|
+
|
147
161
|
== More Info
|
148
162
|
|
149
163
|
* Codes[http://github.com/delano/gibbler]
|
data/gibbler.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
@spec = Gem::Specification.new do |s|
|
2
2
|
s.name = "gibbler"
|
3
3
|
s.rubyforge_project = "gibbler"
|
4
|
-
s.version = "0.5.
|
4
|
+
s.version = "0.5.3"
|
5
5
|
s.summary = "Gibbler: Git-like hashes for Ruby objects"
|
6
6
|
s.description = s.summary
|
7
7
|
s.author = "Delano Mandelbaum"
|
@@ -23,6 +23,9 @@
|
|
23
23
|
# Update --main to reflect the default page to display
|
24
24
|
s.rdoc_options = ["--line-numbers", "--title", s.summary, "--main", "README.rdoc"]
|
25
25
|
|
26
|
+
# = DEPENDENCIES =
|
27
|
+
s.add_dependency 'attic'
|
28
|
+
|
26
29
|
# = MANIFEST =
|
27
30
|
s.files = %w(
|
28
31
|
CHANGES.txt
|
@@ -31,10 +34,12 @@
|
|
31
34
|
Rakefile
|
32
35
|
gibbler.gemspec
|
33
36
|
lib/gibbler.rb
|
37
|
+
lib/gibbler/aliases.rb
|
34
38
|
lib/gibbler/digest.rb
|
35
39
|
lib/gibbler/history.rb
|
36
40
|
lib/gibbler/mixins.rb
|
37
41
|
lib/gibbler/mixins/string.rb
|
42
|
+
lib/gibbler/object.rb
|
38
43
|
tryouts/01_mixins_tryouts.rb
|
39
44
|
tryouts/05_gibbler_digest_tryouts.rb
|
40
45
|
tryouts/10_basic_tryouts.rb
|
@@ -46,6 +51,7 @@
|
|
46
51
|
tryouts/57_arbitrary_history_tryouts.rb
|
47
52
|
tryouts/59_history_exceptions_tryouts.rb
|
48
53
|
tryouts/80_performance_tryouts.rb
|
54
|
+
tryouts/90_alias_tryouts.rb
|
49
55
|
tryouts/object_hash_demo.rb
|
50
56
|
)
|
51
57
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Gibbler
|
4
|
+
|
5
|
+
|
6
|
+
module Object
|
7
|
+
alias :digest :gibbler
|
8
|
+
alias :changed? :gibbled?
|
9
|
+
end
|
10
|
+
|
11
|
+
#--
|
12
|
+
# Aliases for Gibbler::History methods
|
13
|
+
#
|
14
|
+
# NOTE: we explicitly define the methods rather than use "alias"
|
15
|
+
# in the event that the require 'gibbler/aliases' appears before
|
16
|
+
# require 'gibbler/history' (alias complains about unknown methods)
|
17
|
+
#++
|
18
|
+
module History
|
19
|
+
def history(*args, &b); gibbler_history(*args, &b); end
|
20
|
+
def commit; gibbler_commit; end
|
21
|
+
def object(*args, &b); gibbler_object(*args, &b); end
|
22
|
+
def stamp(*args, &b); gibbler_stamp(*args, &b); end
|
23
|
+
def revert!(*args, &b); gibbler_revert!(*args, &b); end
|
24
|
+
def history?; gibbler_history?; end
|
25
|
+
def valid?(*args, &b); gibbler_valid?(*args, &b); end
|
26
|
+
def find_long(*args, &b); gibbler_find_long(*args, &b); end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/lib/gibbler/history.rb
CHANGED
@@ -13,6 +13,9 @@ module Gibbler
|
|
13
13
|
end
|
14
14
|
|
15
15
|
module History
|
16
|
+
extend Attic
|
17
|
+
|
18
|
+
attic :__gibbler_history
|
16
19
|
|
17
20
|
@@mutex = Mutex.new
|
18
21
|
|
@@ -23,15 +26,15 @@ module Gibbler
|
|
23
26
|
# to the short 8 character digests.
|
24
27
|
def gibbler_history(short=false)
|
25
28
|
# Only a single thread should attempt to initialize the store.
|
26
|
-
if
|
29
|
+
if self.__gibbler_history.nil?
|
27
30
|
@@mutex.synchronize {
|
28
|
-
|
31
|
+
self.__gibbler_history ||= { :history => [], :objects => {}, :stamp => {} }
|
29
32
|
}
|
30
33
|
end
|
31
34
|
if short == false
|
32
|
-
|
35
|
+
self.__gibbler_history[:history]
|
33
36
|
else
|
34
|
-
|
37
|
+
self.__gibbler_history[:history].collect { |g| g.short }
|
35
38
|
end
|
36
39
|
end
|
37
40
|
|
@@ -42,7 +45,7 @@ module Gibbler
|
|
42
45
|
g = self.gibbler_history.last if g.nil?
|
43
46
|
|
44
47
|
return unless gibbler_valid? g
|
45
|
-
|
48
|
+
self.__gibbler_history[:objects][ g ]
|
46
49
|
end
|
47
50
|
|
48
51
|
# Returns the timestamp (a Time object) when the digest +g+ was committed.
|
@@ -51,7 +54,7 @@ module Gibbler
|
|
51
54
|
g = gibbler_find_long g
|
52
55
|
g = self.gibbler_history.last if g.nil?
|
53
56
|
return unless gibbler_valid? g
|
54
|
-
|
57
|
+
self.__gibbler_history[:stamp][ g ]
|
55
58
|
end
|
56
59
|
|
57
60
|
# Stores a clone of the current object instance using the current
|
@@ -68,17 +71,17 @@ module Gibbler
|
|
68
71
|
def gibbler_commit
|
69
72
|
now, digest, point = nil,nil,nil
|
70
73
|
|
71
|
-
if
|
74
|
+
if self.__gibbler_history.nil?
|
72
75
|
@@mutex.synchronize {
|
73
|
-
|
76
|
+
self.__gibbler_history ||= { :history => [], :objects => {}, :stamp => {} }
|
74
77
|
}
|
75
78
|
end
|
76
79
|
|
77
80
|
@@mutex.synchronize {
|
78
81
|
now, digest, point = Time.now, self.gibbler, self.clone
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
+
self.__gibbler_history[:history] << digest
|
83
|
+
self.__gibbler_history[:stamp][digest] = now
|
84
|
+
self.__gibbler_history[:objects][digest] = point
|
82
85
|
}
|
83
86
|
|
84
87
|
digest
|
@@ -101,7 +104,7 @@ module Gibbler
|
|
101
104
|
#
|
102
105
|
# Returns the new digest (+g+).
|
103
106
|
def gibbler_revert!(g=nil)
|
104
|
-
raise NoRevert unless self.respond_to?
|
107
|
+
raise NoRevert unless self.respond_to? :__gibbler_revert!
|
105
108
|
raise NoHistory, self.class unless gibbler_history?
|
106
109
|
raise BadDigest, g if !g.nil? && !gibbler_valid?(g)
|
107
110
|
|
@@ -109,16 +112,16 @@ module Gibbler
|
|
109
112
|
g = gibbler_find_long g
|
110
113
|
|
111
114
|
# Do nothing if the given digest matches the current gibble.
|
112
|
-
# NOTE: We use __gibbler b/c it doesn't update
|
115
|
+
# NOTE: We use __gibbler b/c it doesn't update self.__gibbler_cache.
|
113
116
|
unless self.__gibbler == g
|
114
117
|
@@mutex.synchronize {
|
115
|
-
# Always make sure
|
116
|
-
|
118
|
+
# Always make sure self.gibbler_digest is a Gibbler::Digest
|
119
|
+
self.__gibbler_cache = g.is_a?(Gibbler::Digest) ? g : Gibbler::Digest.new(g)
|
117
120
|
self.__gibbler_revert!
|
118
121
|
}
|
119
122
|
end
|
120
123
|
|
121
|
-
|
124
|
+
self.__gibbler_cache
|
122
125
|
end
|
123
126
|
|
124
127
|
# Is the given digest +g+ contained in the history for this object?
|
@@ -147,7 +150,7 @@ class Hash
|
|
147
150
|
include Gibbler::History
|
148
151
|
def __gibbler_revert!
|
149
152
|
self.clear
|
150
|
-
self.merge! self.gibbler_object
|
153
|
+
self.merge! self.gibbler_object(self.__gibbler_cache)
|
151
154
|
end
|
152
155
|
end
|
153
156
|
|
@@ -155,7 +158,7 @@ class Array
|
|
155
158
|
include Gibbler::History
|
156
159
|
def __gibbler_revert!
|
157
160
|
self.clear
|
158
|
-
self.push *(self.gibbler_object
|
161
|
+
self.push *(self.gibbler_object self.__gibbler_cache)
|
159
162
|
end
|
160
163
|
end
|
161
164
|
|
@@ -163,7 +166,7 @@ class String
|
|
163
166
|
include Gibbler::History
|
164
167
|
def __gibbler_revert!
|
165
168
|
self.clear
|
166
|
-
self << (self.gibbler_object
|
169
|
+
self << (self.gibbler_object self.__gibbler_cache)
|
167
170
|
end
|
168
171
|
end
|
169
172
|
|
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Gibbler
|
4
|
+
|
5
|
+
module Object
|
6
|
+
extend Attic
|
7
|
+
|
8
|
+
attic :__gibbler_cache
|
9
|
+
|
10
|
+
# Calculates a digest for the current object instance.
|
11
|
+
# Objects that are a kind of Hash or Array are processed
|
12
|
+
# recursively. The length of the returned String depends
|
13
|
+
# on the digest type.
|
14
|
+
def gibbler
|
15
|
+
gibbler_debug :GIBBLER, self.class, self
|
16
|
+
self.__gibbler_cache = Gibbler::Digest.new self.__gibbler
|
17
|
+
end
|
18
|
+
|
19
|
+
# Has this object been modified?
|
20
|
+
#
|
21
|
+
# This method compares the return value from digest with the
|
22
|
+
# previous value returned by gibbler (the value is stored in
|
23
|
+
# the attic as <tt>__gibbler_cache</tt>).
|
24
|
+
# See Attic[http://github.com/delano/attic]
|
25
|
+
def gibbled?
|
26
|
+
self.__gibbler_cache ||= self.gibbler
|
27
|
+
was, now = self.__gibbler_cache.clone, self.gibbler
|
28
|
+
gibbler_debug :gibbled?, was, now
|
29
|
+
was != now
|
30
|
+
end
|
31
|
+
|
32
|
+
def gibbler_debug(*args)
|
33
|
+
return unless Gibbler.debug?
|
34
|
+
p args
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/lib/gibbler.rb
CHANGED
@@ -1,12 +1,19 @@
|
|
1
1
|
|
2
|
+
local_libs = %w{attic}
|
3
|
+
local_libs.each { |dir| $:.unshift File.join(File.dirname(__FILE__), '..', '..', dir, 'lib') }
|
4
|
+
|
2
5
|
require 'digest/sha1'
|
6
|
+
require 'attic'
|
3
7
|
|
4
8
|
# = Gibbler
|
5
9
|
#
|
6
10
|
# "Hola, Tanneritos"
|
7
11
|
#
|
8
12
|
module Gibbler
|
9
|
-
|
13
|
+
#include Attic
|
14
|
+
extend Attic
|
15
|
+
|
16
|
+
VERSION = "0.5.3"
|
10
17
|
|
11
18
|
require 'gibbler/object'
|
12
19
|
require 'gibbler/digest'
|
@@ -75,7 +82,7 @@ module Gibbler
|
|
75
82
|
end
|
76
83
|
|
77
84
|
def __gibbler_revert!
|
78
|
-
state = self.gibbler_object
|
85
|
+
state = self.gibbler_object self.__gibbler_cache
|
79
86
|
state.instance_variables do |n|
|
80
87
|
v = state.instance_variable_get n
|
81
88
|
self.instance_variable_set v
|
@@ -86,6 +93,7 @@ module Gibbler
|
|
86
93
|
|
87
94
|
module String
|
88
95
|
include Gibbler::Object
|
96
|
+
|
89
97
|
# Creates a digest based on: <tt>CLASS:LENGTH:VALUE</tt>.
|
90
98
|
# This method can be used for any class where the <tt>to_s</tt>
|
91
99
|
# method returns an appropriate unique value for this instance.
|
data/tryouts/10_basic_tryouts.rb
CHANGED
@@ -52,7 +52,7 @@ tryouts "Basic syntax with SHA1" do
|
|
52
52
|
|
53
53
|
dream :gibbler, "884e5713aa70468333459f80aea1bb05394ca4ba"
|
54
54
|
drill "Populated Array instance" do
|
55
|
-
[1,
|
55
|
+
[1, 2, :runtime, [3, "four", [Object, true]]]
|
56
56
|
end
|
57
57
|
|
58
58
|
drill "Knows when a Hash has not changed", false do
|
@@ -84,9 +84,22 @@ tryouts "Basic syntax with SHA1" do
|
|
84
84
|
a = {}
|
85
85
|
a.gibbler # We need to gibbler first so it sets a value to the instance var
|
86
86
|
val = Tryouts.sysinfo.ruby[1] == 9 ? :'@__gibbler_digest__' : '@__gibbler_digest__'
|
87
|
+
stash :ivars, a.instance_variables
|
88
|
+
stash :smeths, Gibbler.singleton_methods
|
87
89
|
a.instance_variables.member? val
|
88
90
|
end
|
89
91
|
|
92
|
+
drill "previous digest", 'c8027100ecc54945ab15ddac529230e38b1ba6a1' do
|
93
|
+
a = "kimmy"
|
94
|
+
a.gibbler
|
95
|
+
#stash :methods, a.methods.sort
|
96
|
+
#
|
97
|
+
#stash :string_methods, String.methods.sort
|
98
|
+
#stash :gstring_methods, Gibbler::String.methods.sort
|
99
|
+
#stash :class_methods, a.class.methods.sort
|
100
|
+
stash :ivars, a.instance_variables
|
101
|
+
a.__gibbler_cache
|
102
|
+
end
|
90
103
|
|
91
104
|
end
|
92
105
|
|
@@ -16,10 +16,10 @@ tryouts "Hash History" do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
drill "doesn't reveal
|
19
|
+
drill "doesn't reveal self.__gibbler_history instance variable", false do
|
20
20
|
a = {}
|
21
21
|
a.gibbler # We need to gibbler first so it sets a value to the instance var
|
22
|
-
val = Tryouts.sysinfo.ruby[1] == 9 ? :'
|
22
|
+
val = Tryouts.sysinfo.ruby[1] == 9 ? :'self.__gibbler_history' : 'self.__gibbler_history'
|
23
23
|
a.instance_variables.member? val
|
24
24
|
end
|
25
25
|
|
@@ -0,0 +1,60 @@
|
|
1
|
+
|
2
|
+
group "Aliases"
|
3
|
+
|
4
|
+
library :gibbler, 'lib'
|
5
|
+
library 'gibbler/aliases', 'lib'
|
6
|
+
library 'gibbler/history', 'lib'
|
7
|
+
|
8
|
+
tryouts "Gibbler::Object Aliases" do
|
9
|
+
|
10
|
+
drill "has digest", true do
|
11
|
+
:kimmy.gibbler == :kimmy.digest
|
12
|
+
end
|
13
|
+
|
14
|
+
drill "has changed?", true do
|
15
|
+
a = "kimmy"
|
16
|
+
a.digest
|
17
|
+
a << '+ dj'
|
18
|
+
a.gibbled?
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
tryouts "Gibbler::History Aliases" do
|
25
|
+
|
26
|
+
dream "d7049916ddb25e6cc438b1028fb957e5139f9910"
|
27
|
+
drill "can convert short digest into long" do
|
28
|
+
a = { :magic => :original }
|
29
|
+
g = a.commit.short
|
30
|
+
stash :short, g
|
31
|
+
a.find_long g
|
32
|
+
end
|
33
|
+
|
34
|
+
dream :class, Time
|
35
|
+
drill "can return most recent stamp" do
|
36
|
+
a = { :magic => :original }
|
37
|
+
a.commit
|
38
|
+
stash :hist, a.history
|
39
|
+
a.stamp
|
40
|
+
end
|
41
|
+
|
42
|
+
dream ["d7049916ddb25e6cc438b1028fb957e5139f9910", "0b11c377fccd44554a601e5d2b135c46dc1c4cb1"]
|
43
|
+
drill "can return history" do
|
44
|
+
a = { :magic => :original }
|
45
|
+
a.commit
|
46
|
+
a[:magic] = :changed
|
47
|
+
a.commit
|
48
|
+
a.history
|
49
|
+
end
|
50
|
+
|
51
|
+
dream ["d7049916", "0b11c377"]
|
52
|
+
drill "can return history (short)" do
|
53
|
+
a = { :magic => :original }
|
54
|
+
a.commit
|
55
|
+
a[:magic] = :changed
|
56
|
+
a.commit
|
57
|
+
a.history(:short)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gibbler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Delano Mandelbaum
|
@@ -9,10 +9,19 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-07-
|
12
|
+
date: 2009-07-12 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: attic
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
16
25
|
description: "Gibbler: Git-like hashes for Ruby objects"
|
17
26
|
email: delano@solutious.com
|
18
27
|
executables: []
|
@@ -29,10 +38,12 @@ files:
|
|
29
38
|
- Rakefile
|
30
39
|
- gibbler.gemspec
|
31
40
|
- lib/gibbler.rb
|
41
|
+
- lib/gibbler/aliases.rb
|
32
42
|
- lib/gibbler/digest.rb
|
33
43
|
- lib/gibbler/history.rb
|
34
44
|
- lib/gibbler/mixins.rb
|
35
45
|
- lib/gibbler/mixins/string.rb
|
46
|
+
- lib/gibbler/object.rb
|
36
47
|
- tryouts/01_mixins_tryouts.rb
|
37
48
|
- tryouts/05_gibbler_digest_tryouts.rb
|
38
49
|
- tryouts/10_basic_tryouts.rb
|
@@ -44,6 +55,7 @@ files:
|
|
44
55
|
- tryouts/57_arbitrary_history_tryouts.rb
|
45
56
|
- tryouts/59_history_exceptions_tryouts.rb
|
46
57
|
- tryouts/80_performance_tryouts.rb
|
58
|
+
- tryouts/90_alias_tryouts.rb
|
47
59
|
- tryouts/object_hash_demo.rb
|
48
60
|
has_rdoc: true
|
49
61
|
homepage: http://github.com/delano/gibbler
|