gibbler 0.9.0 → 0.10.0.pre.RC1
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 +7 -0
- data/.github/workflows/main.yml +27 -0
- data/.github/workflows/ruby-rake.yaml +38 -0
- data/.gitignore +16 -0
- data/.pre-commit-config.yaml +60 -0
- data/.rubocop.yml +27 -0
- data/{CHANGES.txt → CHANGELOG.md} +65 -82
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +16 -0
- data/LICENSE.txt +4 -2
- data/{README.rdoc → README.md} +134 -120
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/img/whoababy.gif +0 -0
- data/lib/gibbler/history.rb +39 -41
- data/lib/gibbler/mixins.rb +3 -4
- data/lib/gibbler/version.rb +17 -0
- data/lib/gibbler.rb +145 -188
- data/sig/gibbler.rbs +4 -0
- data/try/11_basic_try.rb +11 -12
- metadata +75 -27
- data/Rakefile +0 -39
- data/gibbler.gemspec +0 -71
data/{README.rdoc → README.md}
RENAMED
@@ -1,236 +1,250 @@
|
|
1
|
-
|
1
|
+
# Gibbler - v0.10.0
|
2
2
|
|
3
|
-
Git-like hashes and history for Ruby objects for Ruby
|
3
|
+
Git-like hashes and history for Ruby objects for Ruby 3.1+.
|
4
4
|
|
5
|
-
Check out
|
5
|
+
Check out [this post on RubyInside](http://www.rubyinside.com/gibbler-git-like-hashes-and-history-for-ruby-objects-1980.html).
|
6
6
|
|
7
|
-
|
7
|
+
* [Repo](https://github.com/delano/gibbler)
|
8
|
+
* [Docs](https://delanotes.com/gibbler)
|
9
|
+
* [Sponsor](https://solutious.com/)
|
10
|
+
* [Inspiration](https://www.youtube.com/watch?v=fipD4DdV48g)
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Install the gem and add to the application's Gemfile by executing:
|
15
|
+
|
16
|
+
$ bundle add gibbler
|
17
|
+
|
18
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
19
|
+
|
20
|
+
$ gem install gibbler
|
21
|
+
|
22
|
+
## Usage
|
12
23
|
|
24
|
+
### Example 1 -- Standalone Usage
|
13
25
|
|
14
|
-
|
15
|
-
|
26
|
+
```ruby
|
16
27
|
require 'gibbler'
|
17
|
-
|
28
|
+
|
18
29
|
g = Gibbler.new 'id', 1001 # => f4fb3796ababa3788d1bded8fdc589ab1ccb1c3d
|
19
30
|
g.base(36) # => sm71s7eam4hm5jlsuzlqkbuktwpe5h9
|
20
|
-
|
31
|
+
|
21
32
|
g == 'f4fb3796ababa3788d1bded8fdc589ab1ccb1c3d' # => true
|
22
33
|
g === 'f4fb379' # => true
|
23
|
-
|
24
|
-
|
25
|
-
|
34
|
+
```
|
35
|
+
|
36
|
+
### Example 2 -- Mixins Usage
|
37
|
+
|
38
|
+
```ruby
|
26
39
|
require 'gibbler/mixins'
|
27
|
-
|
40
|
+
|
28
41
|
"kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
|
29
42
|
:kimmy.gibbler # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df
|
30
|
-
|
43
|
+
|
31
44
|
config = {}
|
32
45
|
config.gibbler # => 4fdcadc66a38feb9c57faf3c5a18d5e76a6d29bf
|
33
46
|
config.gibbled? # => false
|
34
|
-
|
35
|
-
config[:server] = {
|
36
|
-
:users => [:dave, :ali],
|
37
|
-
:ports => [22, 80, 443]
|
38
|
-
}
|
47
|
+
|
48
|
+
config[:server] = {
|
49
|
+
:users => [:dave, :ali],
|
50
|
+
:ports => [22, 80, 443]
|
51
|
+
}
|
39
52
|
config.gibbled? # => true
|
40
|
-
config.gibbler # => ef23d605f8c4fc80a8e580f9a0e8dab8426454a8
|
41
|
-
|
53
|
+
config.gibbler # => ef23d605f8c4fc80a8e580f9a0e8dab8426454a8
|
54
|
+
|
42
55
|
config[:server][:users] << :yanni
|
43
|
-
|
56
|
+
|
44
57
|
config.gibbler # => 4c558a56bc2abf5f8a845a69e47ceb5e0003683f
|
45
|
-
|
58
|
+
|
46
59
|
config.gibbler.short # => 4c558a56
|
47
60
|
|
48
61
|
config.gibbler.base36 # => 8x00l83jov4j80i9vfzpaxr9jag23wf
|
49
|
-
|
62
|
+
|
50
63
|
config.gibbler.base36.short # => 8x00l83j
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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.
|
64
|
+
```
|
65
|
+
|
66
|
+
### Example 3 -- Object History
|
56
67
|
|
68
|
+
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 `gibbler_commit` method creates a clone of the current object and stores in an instance variable using the current hash digest as the key.
|
69
|
+
|
70
|
+
```ruby
|
57
71
|
require 'gibbler/mixins'
|
58
72
|
require 'gibbler/history'
|
59
|
-
|
60
|
-
a = { :magic => :original }
|
73
|
+
|
74
|
+
a = { :magic => :original }
|
61
75
|
a.gibbler_commit # => d7049916ddb25e6cc438b1028fb957e5139f9910
|
62
|
-
|
63
|
-
a[:magic] = :updated
|
76
|
+
|
77
|
+
a[:magic] = :updated
|
64
78
|
a.gibbler_commit # => b668098e16d08898532bf3aa33ce2253a3a4150e
|
65
|
-
|
66
|
-
a[:magic] = :changed
|
79
|
+
|
80
|
+
a[:magic] = :changed
|
67
81
|
a.gibbler_commit # => 0b11c377fccd44554a601e5d2b135c46dc1c4cb1
|
68
|
-
|
82
|
+
|
69
83
|
a.gibbler_history # => d7049916, b668098e, 0b11c377
|
70
|
-
|
84
|
+
|
71
85
|
a.gibbler_revert! 'd7049916' # Return to a specific commit
|
72
86
|
a.gibbler # => d7049916ddb25e6cc438b1028fb957e5139f9910
|
73
|
-
a # => { :magic => :original }
|
74
|
-
|
87
|
+
a # => { :magic => :original }
|
88
|
+
|
75
89
|
a.delete :magic
|
76
|
-
|
77
|
-
a.gibbler_revert! # Return to the previous commit
|
90
|
+
|
91
|
+
a.gibbler_revert! # Return to the previous commit
|
78
92
|
a.gibbler # => 0b11c377fccd44554a601e5d2b135c46dc1c4cb1
|
79
93
|
a # => { :magic => :changed }
|
80
|
-
|
81
|
-
|
94
|
+
|
95
|
+
|
82
96
|
a.gibbler_object 'b668098e' # => { :magic => :updated }
|
83
97
|
a.gibbler_stamp # => 2009-07-01 18:56:52 -0400
|
84
|
-
|
85
|
-
|
98
|
+
```
|
99
|
+
|
100
|
+

|
86
101
|
|
87
102
|
|
88
|
-
|
103
|
+
### Example 4 -- Method Aliases
|
89
104
|
|
90
105
|
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.)
|
91
|
-
|
106
|
+
|
107
|
+
```ruby
|
92
108
|
require 'gibbler/aliases'
|
93
|
-
|
109
|
+
|
94
110
|
"kimmy".digest # => c8027100ecc54945ab15ddac529230e38b1ba6a1
|
95
111
|
:kimmy.digest # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df
|
96
|
-
|
112
|
+
|
97
113
|
a = [:a, :b, :c]
|
98
114
|
a.digest # => e554061823b8f06367555d1ee4c25b4ffee61944
|
99
115
|
a << :d
|
100
116
|
a.changed? # => true
|
101
117
|
|
102
|
-
|
103
118
|
The history methods also have aliases which remove the "gibbler_" prefix.
|
104
|
-
|
119
|
+
|
105
120
|
require 'gibbler/aliases'
|
106
121
|
require 'gibbler/history'
|
107
|
-
|
108
|
-
a = { :magic => :original }
|
109
|
-
a.commit
|
110
|
-
a.history
|
111
|
-
a.revert!
|
122
|
+
|
123
|
+
a = { :magic => :original }
|
124
|
+
a.commit
|
125
|
+
a.history
|
126
|
+
a.revert!
|
112
127
|
# etc...
|
113
|
-
|
114
|
-
== Example 5 -- Different Digest types
|
128
|
+
```
|
115
129
|
|
116
|
-
|
130
|
+
### Example 5 -- Different Digest types
|
117
131
|
|
132
|
+
By default Gibbler creates SHA1 hashes. You can change this globally or per instance.
|
133
|
+
|
134
|
+
```ruby
|
118
135
|
require 'gibbler/mixins'
|
119
|
-
|
136
|
+
|
120
137
|
Gibbler.digest_type = Digest::MD5
|
121
|
-
|
138
|
+
|
122
139
|
:kimmy.gibbler # => 0c61ff17f46223f355759934154d5dcb
|
123
|
-
|
140
|
+
|
124
141
|
:kimmy.gibbler(Digest::SHA1) # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df
|
125
|
-
|
142
|
+
```
|
126
143
|
|
127
|
-
In Jruby, you can grab the digest types from the openssl library.
|
144
|
+
In Jruby, you can grab the digest types from the openssl library.
|
128
145
|
|
146
|
+
```ruby
|
129
147
|
require 'openssl'
|
130
|
-
|
148
|
+
|
131
149
|
Gibbler.digest_type = OpenSSL::Digest::SHA256
|
132
|
-
|
150
|
+
|
133
151
|
:kimmy.gibbler # => 1069428e6273cf329436c3dce9b680d4d4e229d7b7...
|
134
|
-
|
135
|
-
|
136
|
-
== Example 6 -- All your base
|
152
|
+
```
|
137
153
|
|
154
|
+
### Example 6 -- All your base
|
155
|
+
|
156
|
+
```ruby
|
138
157
|
require 'gibbler/mixins'
|
139
|
-
|
158
|
+
|
140
159
|
:kimmy.gibbler # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df
|
141
160
|
:kimmy.gibbler.base(16) # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df
|
142
161
|
:kimmy.gibbler.base(36) # => 9nydr6mpv6w4k8ngo3jtx0jz1n97h7j
|
143
162
|
|
144
163
|
:kimmy.gibbler.base(10) # => 472384540402900668368761869477227308873774630879
|
145
164
|
:kimmy.gibbler.to_i # => 472384540402900668368761869477227308873774630879
|
165
|
+
```
|
146
166
|
|
167
|
+
### Example 7 -- Global secret
|
147
168
|
|
148
|
-
|
149
|
-
|
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.
|
169
|
+
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.
|
151
170
|
|
171
|
+
```ruby
|
152
172
|
require 'gibbler/mixins'
|
153
|
-
|
173
|
+
|
154
174
|
:kimmy.gibbler # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df
|
155
|
-
|
175
|
+
|
156
176
|
Gibbler.secret = "sUp0r5ekRu7"
|
157
|
-
|
177
|
+
|
158
178
|
:kimmy.gibbler # => 6c5f5aff4d809cec7e7da091214a35a2698489f8
|
159
|
-
|
179
|
+
```
|
160
180
|
|
161
|
-
|
181
|
+
### Supported Classes
|
162
182
|
|
163
|
-
Gibbler methods are available only to the classes which explicitly include them
|
183
|
+
Gibbler methods are available only to the classes which explicitly include them [see docs'(https://delanotes.com/gibbler) for details on which classes are supported by default). You can also extend custom objects:
|
164
184
|
|
185
|
+
```ruby
|
165
186
|
class FullHouse
|
166
187
|
include Gibbler::Complex
|
167
188
|
attr_accessor :roles
|
168
189
|
end
|
169
|
-
|
190
|
+
|
170
191
|
a = FullHouse.new
|
171
192
|
a.gibbler # => 4192d4cb59975813f117a51dcd4454ac16df6703
|
172
|
-
|
193
|
+
|
173
194
|
a.roles = [:jesse, :joey, :danny, :kimmy, :michelle, :dj, :stephanie]
|
174
195
|
a.gibbler # => 6ea546919dc4caa2bab69799b71d48810a1b48fa
|
175
|
-
|
176
|
-
|
196
|
+
```
|
197
|
+
|
198
|
+
`Gibbler::Complex` creates a digest based on the name of the class and the names and values of the instance variables. See the RDocs[http://delano.github.com/gibbler] for other Gibbler::* types.
|
177
199
|
|
178
200
|
If you want to support all Ruby objects, add the following to your application:
|
179
201
|
|
202
|
+
```ruby
|
180
203
|
class Object
|
181
204
|
include Gibbler::String
|
182
205
|
end
|
206
|
+
```
|
183
207
|
|
184
|
-
Gibbler::String creates a digest based on the name of the class and the output of the to_s method. This is a reasonable default for most objects however any object that includes the object address in to_s (e.g. "Object:0x0x4ac9f0...") will produce unreliable digests (because the address can change).
|
185
|
-
|
186
|
-
As of 0.7 all Proc objects have the same digest: <tt>12075835e94be34438376cd7a54c8db7e746f15d</tt>.
|
187
|
-
|
208
|
+
`Gibbler::String` creates a digest based on the name of the class and the output of the to_s method. This is a reasonable default for most objects however any object that includes the object address in to_s (e.g. "Object:0x0x4ac9f0...") will produce unreliable digests (because the address can change).
|
188
209
|
|
210
|
+
As of 0.7 all Proc objects have the same digest: `12075835e94be34438376cd7a54c8db7e746f15d`.
|
189
211
|
|
190
|
-
|
212
|
+
### Some things to keep in mind
|
191
213
|
|
192
|
-
*
|
193
|
-
*
|
194
|
-
*
|
195
|
-
|
196
|
-
|
197
|
-
== Installation
|
198
|
-
|
199
|
-
Via Rubygems:
|
200
|
-
|
201
|
-
$ gem install gibbler
|
214
|
+
* Digest calculation may change between minor releases (as it did between 0.6 and 0.7)
|
215
|
+
* 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.
|
216
|
+
* Don't forget to enjoy your life!
|
202
217
|
|
203
|
-
|
204
|
-
* gibbler-latest.tar.gz[http://github.com/delano/gibbler/tarball/latest]
|
205
|
-
* gibbler-latest.zip[http://github.com/delano/gibbler/zipball/latest]
|
218
|
+
## What People Are Saying
|
206
219
|
|
220
|
+
* "nice approach - everything is an object, every object is 'gittish'" -- [@olgen_morten](https://twitter.com/olgen_morten/statuses/2629909133)
|
221
|
+
* "gibbler is just awesome" -- [@TomK32](https://twitter.com/TomK32/statuses/2618542872)
|
222
|
+
* "wie cool ist Gibbler eigentlich?" -- [@we5](https://twitter.com/we5/statuses/2615274279)
|
223
|
+
* "it's nice idea and implementation!" --[HristoHristov](https://www.rubyinside.com/gibbler-git-like-hashes-and-history-for-ruby-objects-1980.html#comment-39092)
|
207
224
|
|
208
|
-
|
225
|
+
## Development
|
209
226
|
|
210
|
-
|
211
|
-
* "gibbler is just awesome" -- @TomK32[http://twitter.com/TomK32/statuses/2618542872]
|
212
|
-
* "wie cool ist Gibbler eigentlich?" -- @we5[http://twitter.com/we5/statuses/2615274279]
|
213
|
-
* "it's nice idea and implementation!" -- HristoHristov[http://www.rubyinside.com/gibbler-git-like-hashes-and-history-for-ruby-objects-1980.html#comment-39092]
|
227
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
214
228
|
|
215
|
-
|
229
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
216
230
|
|
217
|
-
|
218
|
-
* RDocs[http://delano.github.com/gibbler]
|
219
|
-
* Sponsor[http://solutious.com/]
|
220
|
-
* Inspiration[http://www.youtube.com/watch?v=fipD4DdV48g]
|
231
|
+
### Contributing
|
221
232
|
|
233
|
+
Bug reports and pull requests are welcome [GitHub Issues](https://github.com/delano/gibbler/issues). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/delano/gibbler/blob/main/CODE_OF_CONDUCT.md).
|
222
234
|
|
223
|
-
|
235
|
+
### Thanks
|
224
236
|
|
225
|
-
* Kalin Harvey (krrh
|
226
|
-
* Alex Peuchert (aaalex
|
237
|
+
* Kalin Harvey ([krrh](https://github.com/kalin)) for the early feedback and artistic direction.
|
238
|
+
* Alex Peuchert ([aaalex](https://github.com/aaalex)) for creating the screencast.
|
227
239
|
|
240
|
+
## Code of Conduct
|
228
241
|
|
229
|
-
|
242
|
+
Everyone interacting in the Gibbler project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/delano/gibbler/blob/main/CODE_OF_CONDUCT.md).
|
230
243
|
|
231
|
-
|
244
|
+
## Credits
|
232
245
|
|
246
|
+
Gibbler was created by [Delano Mandelbaum](https://delanotes.com/).
|
233
247
|
|
234
|
-
|
248
|
+
## License
|
235
249
|
|
236
|
-
|
250
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/bin/console
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "gibbler"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
require "irb"
|
11
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/img/whoababy.gif
ADDED
Binary file
|
data/lib/gibbler/history.rb
CHANGED
@@ -11,17 +11,17 @@ class Gibbler < String
|
|
11
11
|
class BadDigest < Gibbler::Error
|
12
12
|
def message; "Unknown digest: #{@obj}"; end
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
module History
|
16
16
|
extend Attic
|
17
|
-
|
17
|
+
|
18
18
|
attic :__gibbler_history
|
19
|
-
|
19
|
+
|
20
20
|
@@mutex = Mutex.new
|
21
|
-
|
21
|
+
|
22
22
|
def self.mutex; @@mutex; end
|
23
|
-
|
24
|
-
# Returns an Array of digests in the order they were committed.
|
23
|
+
|
24
|
+
# Returns an Array of digests in the order they were committed.
|
25
25
|
# If +short+ is anything but false, the digests will be converted
|
26
26
|
# to the short 8 character digests.
|
27
27
|
def gibbler_history(short=false)
|
@@ -37,104 +37,104 @@ class Gibbler < String
|
|
37
37
|
self.__gibbler_history[:history].collect { |g| g.short }
|
38
38
|
end
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
# Returns the object stored under the given digest +g+.
|
42
|
-
# If +g+ is not a valid digest, returns nil.
|
43
|
-
def gibbler_object(g=nil)
|
42
|
+
# If +g+ is not a valid digest, returns nil.
|
43
|
+
def gibbler_object(g=nil)
|
44
44
|
g = gibbler_find_long g
|
45
45
|
g = self.gibbler_history.last if g.nil?
|
46
46
|
|
47
47
|
return unless gibbler_valid? g
|
48
48
|
self.__gibbler_history[:objects][ g ]
|
49
49
|
end
|
50
|
-
|
51
|
-
# Returns the timestamp (a Time object) when the digest +g+ was committed.
|
52
|
-
# If +g+ is not a valid gibble, returns nil.
|
50
|
+
|
51
|
+
# Returns the timestamp (a Time object) when the digest +g+ was committed.
|
52
|
+
# If +g+ is not a valid gibble, returns nil.
|
53
53
|
def gibbler_stamp(g=nil)
|
54
54
|
g = gibbler_find_long g
|
55
55
|
g = self.gibbler_history.last if g.nil?
|
56
56
|
return unless gibbler_valid? g
|
57
57
|
self.__gibbler_history[:stamp][ g ]
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
# Stores a clone of the current object instance using the current
|
61
61
|
# digest value. If the object was not changed, this method does
|
62
|
-
# nothing but return the gibble.
|
62
|
+
# nothing but return the gibble.
|
63
63
|
#
|
64
64
|
# NOTE: This method is not fully thread safe. It uses a Mutex.synchronize
|
65
|
-
# but there's a race condition where two threads can attempt to commit at
|
66
|
-
# near the same time. The first will get the lock and create the commit.
|
67
|
-
# The second will get the lock and create another commit immediately
|
68
|
-
# after. What we probably want is for the second thread to return the
|
65
|
+
# but there's a race condition where two threads can attempt to commit at
|
66
|
+
# near the same time. The first will get the lock and create the commit.
|
67
|
+
# The second will get the lock and create another commit immediately
|
68
|
+
# after. What we probably want is for the second thread to return the
|
69
69
|
# digest for that first snapshot, but how do we know this was a result
|
70
70
|
# of the race conditioon rather than two legitimate calls for a snapshot?
|
71
71
|
def gibbler_commit
|
72
72
|
now, digest, point = nil,nil,nil
|
73
|
-
|
73
|
+
|
74
74
|
if self.__gibbler_history.nil?
|
75
75
|
@@mutex.synchronize {
|
76
76
|
self.__gibbler_history ||= { :history => [], :objects => {}, :stamp => {} }
|
77
77
|
}
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
@@mutex.synchronize {
|
81
81
|
now, digest, point = ::Time.now, self.gibbler, self.clone
|
82
82
|
self.__gibbler_history[:history] << digest
|
83
83
|
self.__gibbler_history[:stamp][digest] = now
|
84
84
|
self.__gibbler_history[:objects][digest] = point
|
85
85
|
}
|
86
|
-
|
86
|
+
|
87
87
|
digest
|
88
88
|
end
|
89
|
-
|
89
|
+
|
90
90
|
# Revert this object to a previously known state. If called without arguments
|
91
91
|
# it will revert to the most recent commit. If a digest is specified +g+, it
|
92
|
-
# will revert to that point.
|
92
|
+
# will revert to that point.
|
93
93
|
#
|
94
|
-
# Ruby does not support replacing self (
|
94
|
+
# Ruby does not support replacing self (`self = previous_self`) so each
|
95
95
|
# object type needs to implement its own __gibbler_revert! method. This default
|
96
|
-
# run some common checks and then defers to self.__gibbler_revert!.
|
97
|
-
#
|
96
|
+
# run some common checks and then defers to self.__gibbler_revert!.
|
97
|
+
#
|
98
98
|
# Raise the following exceptions:
|
99
99
|
# * NoRevert: if this object doesn't have a __gibbler_revert! method
|
100
100
|
# * NoHistory: This object has no commits
|
101
101
|
# * BadDigest: The given digest is not in the history for this object
|
102
102
|
#
|
103
|
-
# If +g+ matches the current digest value this method does nothing.
|
103
|
+
# If +g+ matches the current digest value this method does nothing.
|
104
104
|
#
|
105
|
-
# Returns the new digest (+g+).
|
105
|
+
# Returns the new digest (+g+).
|
106
106
|
def gibbler_revert!(g=nil)
|
107
107
|
raise NoRevert unless self.respond_to? :__gibbler_revert!
|
108
108
|
raise NoHistory, self.class unless gibbler_history?
|
109
109
|
raise BadDigest, g if !g.nil? && !gibbler_valid?(g)
|
110
|
-
|
110
|
+
|
111
111
|
g = self.gibbler_history.last if g.nil?
|
112
|
-
g = gibbler_find_long g
|
113
|
-
|
114
|
-
# Do nothing if the given digest matches the current gibble.
|
112
|
+
g = gibbler_find_long g
|
113
|
+
|
114
|
+
# Do nothing if the given digest matches the current gibble.
|
115
115
|
# NOTE: We use __gibbler b/c it doesn't update self.gibbler_cache.
|
116
116
|
unless self.__gibbler == g
|
117
117
|
@@mutex.synchronize {
|
118
|
-
# Always make sure self.gibbler_digest is a Gibbler::Digest
|
118
|
+
# Always make sure self.gibbler_digest is a Gibbler::Digest
|
119
119
|
self.gibbler_cache = g.is_a?(Gibbler::Digest) ? g : Gibbler::Digest.new(g)
|
120
120
|
self.__gibbler_revert!
|
121
121
|
}
|
122
122
|
end
|
123
|
-
|
123
|
+
|
124
124
|
self.gibbler_cache
|
125
125
|
end
|
126
|
-
|
126
|
+
|
127
127
|
# Is the given digest +g+ contained in the history for this object?
|
128
128
|
def gibbler_valid?(g)
|
129
129
|
return false unless gibbler_history?
|
130
130
|
gibbler_history.member? gibbler_find_long(g)
|
131
131
|
end
|
132
|
-
|
132
|
+
|
133
133
|
# Does the current object have any history?
|
134
134
|
def gibbler_history?
|
135
135
|
!gibbler_history.empty?
|
136
136
|
end
|
137
|
-
|
137
|
+
|
138
138
|
# Returns the long digest associated to the short digest +g+.
|
139
139
|
# If g is longer than 8 characters it returns the value of +g+.
|
140
140
|
def gibbler_find_long(g)
|
@@ -143,7 +143,7 @@ class Gibbler < String
|
|
143
143
|
gibbler_history.select { |d| d.match /\A#{g}/ }.first
|
144
144
|
end
|
145
145
|
end
|
146
|
-
|
146
|
+
|
147
147
|
end
|
148
148
|
|
149
149
|
class Hash
|
@@ -161,7 +161,7 @@ class Array
|
|
161
161
|
self.push *(self.gibbler_object self.gibbler_cache)
|
162
162
|
end
|
163
163
|
end
|
164
|
-
|
164
|
+
|
165
165
|
class String
|
166
166
|
include Gibbler::History
|
167
167
|
def __gibbler_revert!
|
@@ -169,5 +169,3 @@ class String
|
|
169
169
|
self << (self.gibbler_object self.gibbler_cache)
|
170
170
|
end
|
171
171
|
end
|
172
|
-
|
173
|
-
|
data/lib/gibbler/mixins.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
+
# rubocop:disable all
|
1
2
|
require 'gibbler'
|
2
3
|
|
3
4
|
class NilClass; include Gibbler::Nil; end
|
4
5
|
class String; include Gibbler::String; end
|
5
6
|
class Symbol; include Gibbler::String; end
|
6
|
-
class
|
7
|
-
class Bignum; include Gibbler::String; end
|
7
|
+
class Integer; include Gibbler::String; end
|
8
8
|
class TrueClass; include Gibbler::String; end
|
9
9
|
class FalseClass; include Gibbler::String; end
|
10
10
|
class Class; include Gibbler::Object; end
|
@@ -23,7 +23,7 @@ class TempFile; include Gibbler::File; end
|
|
23
23
|
class MatchData; include Gibbler::String; end
|
24
24
|
class OpenStruct; include Gibbler::Object; end
|
25
25
|
|
26
|
-
# URI::Generic must be included towards the
|
26
|
+
# URI::Generic must be included towards the
|
27
27
|
# end b/c it runs Object#freeze statically.
|
28
28
|
module URI; class Generic; include Gibbler::String; end; end
|
29
29
|
|
@@ -31,4 +31,3 @@ module URI; class Generic; include Gibbler::String; end; end
|
|
31
31
|
module Gem; class Platform; include Gibbler::Complex; end; end
|
32
32
|
|
33
33
|
module Addressable; class URI; include Gibbler::String; end; end
|
34
|
-
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gibbler
|
4
|
+
|
5
|
+
module VERSION
|
6
|
+
def self.to_s
|
7
|
+
load_config
|
8
|
+
[@version[:MAJOR], @version[:MINOR], @version[:PATCH]].join('.')
|
9
|
+
end
|
10
|
+
alias_method :inspect, :to_s
|
11
|
+
def self.load_config
|
12
|
+
require 'yaml'
|
13
|
+
@version ||= YAML.load_file(::File.join(GIBBLER_LIB_HOME, '..', 'VERSION.yml'))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|