rsanheim-beholder 0.5.5
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.
- data/LICENSE +20 -0
- data/README.textile +65 -0
- data/Rakefile +66 -0
- data/TODO +1 -0
- data/bin/beholder +4 -0
- data/examples/example_helper.rb +17 -0
- data/examples/lib/beholder_example.rb +84 -0
- data/lib/beholder.rb +165 -0
- metadata +72 -0
data/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2008-2009 Chad Humphries
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
h1. Beholder
|
|
2
|
+
|
|
3
|
+
An ancient beholder that watches your treasure, and deals with thiefs.
|
|
4
|
+
|
|
5
|
+
h2. What does it do?
|
|
6
|
+
|
|
7
|
+
Think autotest, but powered by fseventd.
|
|
8
|
+
|
|
9
|
+
h2. Requirements
|
|
10
|
+
|
|
11
|
+
# OSX 10.5 or higher
|
|
12
|
+
# RubyCocoa
|
|
13
|
+
# fsevents gem
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
The default treasure map:
|
|
18
|
+
|
|
19
|
+
map_for(:default_dungeon) do |wizard|
|
|
20
|
+
|
|
21
|
+
wizard.keep_a_watchful_eye_for 'app', 'config', 'lib', 'examples'
|
|
22
|
+
|
|
23
|
+
wizard.prepare_spell_for /\/app\/(.*)\.rb/ do |spell_component|
|
|
24
|
+
["examples/#{spell_component[1]}.rb"]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
wizard.prepare_spell_for /\/lib\/(.*)\.rb/ do |spell_component|
|
|
28
|
+
["examples/lib/#{spell_component[1]}_example.rb"]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
wizard.prepare_spell_for /\/examples\/(.*)_example\.rb/ do |spell_component|
|
|
32
|
+
["examples/#{spell_component[1]}_example.rb"]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
wizard.prepare_spell_for /\/examples\/example_helper\.rb/ do |spell_component|
|
|
36
|
+
Dir["examples/**/*_example.rb"]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
wizard.prepare_spell_for /\/config/ do
|
|
40
|
+
Dir["examples/**/*_example.rb"]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
In your own treasure map (stored as treasure_map.rb, .treasure_map.rb, or config/treasure_map.rb) you could do:
|
|
47
|
+
|
|
48
|
+
map_for(:beholders_lair) do |wizard|
|
|
49
|
+
|
|
50
|
+
# Clear all watched paths => wizard.paths_to_watch.clear
|
|
51
|
+
# Add these paths to the paths to watch
|
|
52
|
+
wizard.keep_a_watchful_eye_for 'coverage'
|
|
53
|
+
|
|
54
|
+
# Forget all other treasure maps loaded
|
|
55
|
+
# wizard.clear_maps
|
|
56
|
+
|
|
57
|
+
# Add your own rules
|
|
58
|
+
# wizard.prepare_spell_for /\/foobar/ do
|
|
59
|
+
# Dir["examples/foobar/*_example.rb"]
|
|
60
|
+
# end
|
|
61
|
+
|
|
62
|
+
# You could set the list of all examples to be run after pressing ctrl-c once
|
|
63
|
+
# it defaults to any files in examples, spec, and test
|
|
64
|
+
wizard.all_examples = Dir['your/path/**/*_here.rb']
|
|
65
|
+
end
|
data/Rakefile
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rake/gempackagetask'
|
|
3
|
+
require 'rubygems/specification'
|
|
4
|
+
require 'date'
|
|
5
|
+
require 'micronaut/rake_task'
|
|
6
|
+
|
|
7
|
+
GEM = "beholder"
|
|
8
|
+
GEM_VERSION = "0.5.5"
|
|
9
|
+
AUTHOR = "Chad Humphries"
|
|
10
|
+
EMAIL = "chad@spicycode.com"
|
|
11
|
+
HOMEPAGE = "http://github.com/spicycode/beholder"
|
|
12
|
+
SUMMARY = "An ancient beholder that watches your treasure, and deals with thiefs"
|
|
13
|
+
|
|
14
|
+
spec = Gem::Specification.new do |s|
|
|
15
|
+
s.name = GEM
|
|
16
|
+
s.version = GEM_VERSION
|
|
17
|
+
s.platform = Gem::Platform::RUBY
|
|
18
|
+
s.has_rdoc = true
|
|
19
|
+
s.extra_rdoc_files = ["README.textile", "LICENSE", 'TODO']
|
|
20
|
+
s.summary = SUMMARY
|
|
21
|
+
s.description = s.summary
|
|
22
|
+
s.author = AUTHOR
|
|
23
|
+
s.email = EMAIL
|
|
24
|
+
s.homepage = HOMEPAGE
|
|
25
|
+
s.add_dependency "fsevents"
|
|
26
|
+
s.bindir = 'bin'
|
|
27
|
+
s.default_executable = 'beholder'
|
|
28
|
+
s.executables = ["beholder"]
|
|
29
|
+
s.require_path = 'lib'
|
|
30
|
+
s.autorequire = GEM
|
|
31
|
+
s.files = %w(LICENSE README.textile Rakefile TODO) + Dir.glob("{lib,examples}/**/*")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
|
35
|
+
pkg.gem_spec = spec
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
desc "install the gem locally"
|
|
39
|
+
task :install => [:package] do
|
|
40
|
+
sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
desc "create a gemspec file"
|
|
44
|
+
task :make_gemspec do
|
|
45
|
+
File.open("#{GEM}.gemspec", "w") do |file|
|
|
46
|
+
file.puts spec.to_ruby
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
desc "Run all micronaut examples"
|
|
51
|
+
Micronaut::RakeTask.new :examples do |t|
|
|
52
|
+
t.pattern = "examples/**/*_example.rb"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
namespace :examples do
|
|
56
|
+
|
|
57
|
+
desc "Run all micronaut examples using rcov"
|
|
58
|
+
Micronaut::RakeTask.new :coverage do |t|
|
|
59
|
+
t.pattern = "examples/**/*_example.rb"
|
|
60
|
+
t.rcov = true
|
|
61
|
+
t.rcov_opts = "--exclude \"examples/*,gems/*,db/*,/Library/Frameworks/*,/Library/Ruby/*,config/*\" --text-summary --sort coverage --no-validator-links"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
task :default => 'examples:coverage'
|
data/bin/beholder
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
lib_path = File.expand_path(File.dirname(__FILE__) + "/../lib")
|
|
2
|
+
$LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
|
|
3
|
+
|
|
4
|
+
require 'beholder'
|
|
5
|
+
require 'rubygems'
|
|
6
|
+
require 'micronaut'
|
|
7
|
+
gem :rr, '=0.7.0'
|
|
8
|
+
|
|
9
|
+
def not_in_editor?
|
|
10
|
+
['TM_MODE', 'EMACS', 'VIM'].all? { |k| !ENV.has_key?(k) }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
Micronaut.configure do |c|
|
|
14
|
+
c.formatter = :documentation
|
|
15
|
+
c.mock_with :rr
|
|
16
|
+
c.color_enabled = not_in_editor?
|
|
17
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../example_helper")
|
|
2
|
+
|
|
3
|
+
describe Beholder do
|
|
4
|
+
|
|
5
|
+
describe "when run is called" do
|
|
6
|
+
|
|
7
|
+
it "should create a new beholder" do
|
|
8
|
+
beholder = stub(Beholder.new) { prepare; start }
|
|
9
|
+
mock(Beholder).new { beholder }
|
|
10
|
+
|
|
11
|
+
Beholder.run
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should prepare" do
|
|
15
|
+
beholder = Beholder.new
|
|
16
|
+
stub(beholder).start
|
|
17
|
+
mock(beholder).prepare
|
|
18
|
+
stub(Beholder).new { beholder }
|
|
19
|
+
|
|
20
|
+
Beholder.run
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should start" do
|
|
24
|
+
beholder = Beholder.new
|
|
25
|
+
mock(beholder).start
|
|
26
|
+
stub(beholder).prepare
|
|
27
|
+
stub(Beholder).new { beholder }
|
|
28
|
+
|
|
29
|
+
Beholder.run
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe "when it notices file(s) changed" do
|
|
35
|
+
|
|
36
|
+
it "should identify what was changed" do
|
|
37
|
+
treasures = ['pot_o_gold']
|
|
38
|
+
beholder = Beholder.new
|
|
39
|
+
mock(beholder).identify_stolen_treasure('pot_o_gold') { nil }
|
|
40
|
+
beholder.something_changed treasures
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should run tests for the file that changed" do
|
|
44
|
+
treasures = ['pot_o_gold']
|
|
45
|
+
beholder = Beholder.new
|
|
46
|
+
stub(beholder).identify_stolen_treasure('pot_o_gold') { 'x marks the spot' }
|
|
47
|
+
mock(beholder).run_tests(['x marks the spot'])
|
|
48
|
+
beholder.something_changed treasures
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe "when blinking it's eye" do
|
|
54
|
+
|
|
55
|
+
it "should forget about any interlopers" do
|
|
56
|
+
beholder = Beholder.new
|
|
57
|
+
beholder.instance_variable_set("@sent_an_int", true) # Not so hot, but I'm tired
|
|
58
|
+
|
|
59
|
+
beholder.sent_an_int.should be_true
|
|
60
|
+
beholder.blink
|
|
61
|
+
beholder.sent_an_int.should be_false
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
describe "when shutting down" do
|
|
67
|
+
|
|
68
|
+
it "should stop watching for changes" do
|
|
69
|
+
beholder = Beholder.new
|
|
70
|
+
stub(beholder).exit
|
|
71
|
+
stub(beholder).watcher { mock!.shutdown }
|
|
72
|
+
beholder.shutdown
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "should exit" do
|
|
76
|
+
beholder = Beholder.new
|
|
77
|
+
stub(beholder).watcher { stub!.shutdown }
|
|
78
|
+
mock(beholder).exit
|
|
79
|
+
beholder.shutdown
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
data/lib/beholder.rb
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
gem :fsevents
|
|
3
|
+
require 'fsevents'
|
|
4
|
+
|
|
5
|
+
class Beholder
|
|
6
|
+
|
|
7
|
+
attr_reader :paths_to_watch, :sent_an_int, :mappings, :working_directory, :verbose
|
|
8
|
+
attr_reader :watcher, :treasure_maps, :possible_map_locations, :all_examples
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@paths_to_watch, @all_examples = [], []
|
|
12
|
+
@mappings, @treasure_maps = {}, {}
|
|
13
|
+
@sent_an_int = false
|
|
14
|
+
@working_directory = Dir.pwd
|
|
15
|
+
@verbose = ARGV.include?("-v") || ARGV.include?("--verbose")
|
|
16
|
+
@possible_map_locations = ["#{@working_directory}/.treasure_map.rb", "#{@working_directory}/treasure_map.rb", "#{@working_directory}/config/treasure_map.rb"]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.run
|
|
20
|
+
beholder = new
|
|
21
|
+
beholder.read_all_maps
|
|
22
|
+
beholder.set_all_examples if beholder.all_examples.empty?
|
|
23
|
+
beholder.prepare
|
|
24
|
+
beholder.start
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def read_all_maps
|
|
28
|
+
read_default_map
|
|
29
|
+
|
|
30
|
+
possible_map_locations.each do |map_location|
|
|
31
|
+
if File.exist?(map_location)
|
|
32
|
+
say "Found a treasure map at #{map_location}"
|
|
33
|
+
instance_eval(File.readlines(map_location).join("\n"))
|
|
34
|
+
return
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def prepare
|
|
40
|
+
trap 'INT' do
|
|
41
|
+
if @sent_an_int then
|
|
42
|
+
puts " A second INT? Ok, I get the message. Shutting down now."
|
|
43
|
+
shutdown
|
|
44
|
+
else
|
|
45
|
+
puts " Did you just send me an INT? Ugh. I'll quit for real if you do it again."
|
|
46
|
+
@sent_an_int = true
|
|
47
|
+
Kernel.sleep 1.5
|
|
48
|
+
run_tests all_examples
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def start
|
|
54
|
+
say("Watching the following locations:\n #{paths_to_watch.join(", ")}")
|
|
55
|
+
@watcher = FSEvents::Stream.watch(paths_to_watch) do |treasure_chest|
|
|
56
|
+
something_changed(treasure_chest.modified_files)
|
|
57
|
+
puts "\n\nWaiting to hear from the disk since #{Time.now}"
|
|
58
|
+
end
|
|
59
|
+
@watcher.run
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def read_default_map
|
|
63
|
+
map_for(:default) do |m|
|
|
64
|
+
|
|
65
|
+
m.watch 'lib', 'examples'
|
|
66
|
+
|
|
67
|
+
m.add_mapping %r%examples/(.*)_example\.rb% do |match|
|
|
68
|
+
["examples/#{match[1]}_example.rb"]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
m.add_mapping %r%examples/example_helper\.rb% do |match|
|
|
72
|
+
Dir["examples/**/*_example.rb"]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
m.add_mapping %r%lib/(.*)\.rb% do |file|
|
|
76
|
+
["examples/lib/#{match[1]}_example.rb"]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def map_for(map_name)
|
|
83
|
+
@treasure_maps[map_name] ||= []
|
|
84
|
+
@current_map = @treasure_maps[map_name]
|
|
85
|
+
yield self if block_given?
|
|
86
|
+
ensure
|
|
87
|
+
@current_map = nil
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def add_mapping(arcane_enemy, &spell)
|
|
91
|
+
@current_map << [arcane_enemy, spell]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def clear_maps
|
|
95
|
+
@treasure_maps = {}
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def set_all_examples
|
|
99
|
+
if paths_to_watch.include?('examples')
|
|
100
|
+
@all_examples += Dir['examples/**/*_example.rb']
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
if paths_to_watch.include?('test')
|
|
104
|
+
@all_examples += Dir['test/**/*_test.rb']
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
if paths_to_watch.include?('spec')
|
|
108
|
+
@all_examples += Dir['spec/**/*_spec.rb']
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def watch(*paths)
|
|
113
|
+
@paths_to_watch.concat(paths)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def blink
|
|
117
|
+
@sent_an_int = false
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def shutdown
|
|
121
|
+
watcher.shutdown
|
|
122
|
+
exit
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def identify_stolen_treasure(treasure)
|
|
126
|
+
treasure_maps.each do |name, treasure_locations|
|
|
127
|
+
treasure_locations.each do |stolen_by_enemy, spell|
|
|
128
|
+
if spell_components = treasure.match(stolen_by_enemy)
|
|
129
|
+
say "Found the stolen treasure using the #{name} map "
|
|
130
|
+
return spell.call(spell_components)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
puts "Unknown file: #{treasure}"
|
|
136
|
+
return []
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def run_tests(coordinates)
|
|
140
|
+
coordinates.flatten!
|
|
141
|
+
|
|
142
|
+
coordinates.reject! do |coordinate|
|
|
143
|
+
found_treasure = File.exist?(coordinate)
|
|
144
|
+
puts "#{coordinate} does not exist." unless found_treasure
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
return if coordinates.empty?
|
|
148
|
+
|
|
149
|
+
puts "\nRunning #{coordinates.join(', ').inspect}"
|
|
150
|
+
system "ruby #{coordinates.join(' ')}"
|
|
151
|
+
blink
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def something_changed(treasure)
|
|
155
|
+
say "#{treasure} changed" unless treasure.empty?
|
|
156
|
+
coordinates = treasure.map { |t| identify_stolen_treasure(t) }.uniq.compact
|
|
157
|
+
run_tests coordinates
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
private
|
|
161
|
+
def say(msg)
|
|
162
|
+
puts msg if verbose
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rsanheim-beholder
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.5.5
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Chad Humphries
|
|
8
|
+
autorequire: beholder
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
|
|
12
|
+
date: 2009-02-27 00:00:00 -08:00
|
|
13
|
+
default_executable: beholder
|
|
14
|
+
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
16
|
+
name: fsevents
|
|
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:
|
|
25
|
+
description: An ancient beholder that watches your treasure, and deals with thiefs
|
|
26
|
+
email: chad@spicycode.com
|
|
27
|
+
executables:
|
|
28
|
+
- beholder
|
|
29
|
+
extensions: []
|
|
30
|
+
|
|
31
|
+
extra_rdoc_files:
|
|
32
|
+
- README.textile
|
|
33
|
+
- LICENSE
|
|
34
|
+
- TODO
|
|
35
|
+
files:
|
|
36
|
+
- LICENSE
|
|
37
|
+
- README.textile
|
|
38
|
+
- Rakefile
|
|
39
|
+
- TODO
|
|
40
|
+
- lib/beholder.rb
|
|
41
|
+
- examples/example_helper.rb
|
|
42
|
+
- examples/lib
|
|
43
|
+
- examples/lib/beholder_example.rb
|
|
44
|
+
- bin/beholder
|
|
45
|
+
has_rdoc: true
|
|
46
|
+
homepage: http://github.com/spicycode/beholder
|
|
47
|
+
post_install_message:
|
|
48
|
+
rdoc_options: []
|
|
49
|
+
|
|
50
|
+
require_paths:
|
|
51
|
+
- lib
|
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
53
|
+
requirements:
|
|
54
|
+
- - ">="
|
|
55
|
+
- !ruby/object:Gem::Version
|
|
56
|
+
version: "0"
|
|
57
|
+
version:
|
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
|
+
requirements:
|
|
60
|
+
- - ">="
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: "0"
|
|
63
|
+
version:
|
|
64
|
+
requirements: []
|
|
65
|
+
|
|
66
|
+
rubyforge_project:
|
|
67
|
+
rubygems_version: 1.2.0
|
|
68
|
+
signing_key:
|
|
69
|
+
specification_version: 2
|
|
70
|
+
summary: An ancient beholder that watches your treasure, and deals with thiefs
|
|
71
|
+
test_files: []
|
|
72
|
+
|