beeta 0.0.1
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/Rakefile +147 -0
- data/bin/install_gitolite.sh +32 -0
- data/doc/LICENSE +19 -0
- data/doc/TODO +0 -0
- data/doc/project.vim +15 -0
- data/lib/beeta.rb +41 -0
- data/lib/beeta/config.rb +35 -0
- data/lib/beeta/model.rb +98 -0
- data/lib/beeta/resource.rb +116 -0
- data/lib/version.rb +3 -0
- metadata +144 -0
data/Rakefile
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'rake/gempackagetask'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require './lib/beeta/config'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bundler'
|
7
|
+
Bundler::GemHelper.install_tasks
|
8
|
+
rescue LoadError => e
|
9
|
+
$stderr.puts(' Bundler is not installed. Its rake tasks won\'t work. '.
|
10
|
+
center((ENV['COLUMNS'] || 80).to_i, '*'))
|
11
|
+
end
|
12
|
+
|
13
|
+
$: << "#{File.dirname(__FILE__)}/lib"
|
14
|
+
|
15
|
+
Rake::RDocTask.new(:doc) { |t|
|
16
|
+
t.main = 'doc/README'
|
17
|
+
t.rdoc_files.include 'lib/**/*.rb', 'doc/*', 'bin/*', 'ext/**/*.c',
|
18
|
+
'ext/**/*.rb'
|
19
|
+
t.options << '-S' << '-N'
|
20
|
+
t.rdoc_dir = 'doc/rdoc'
|
21
|
+
}
|
22
|
+
|
23
|
+
desc "Runs IRB, automatically require()ing beeta."
|
24
|
+
task(:irb) {
|
25
|
+
exec "irb -Ilib -rbeeta"
|
26
|
+
}
|
27
|
+
|
28
|
+
desc "Runs tests."
|
29
|
+
task(:test) {
|
30
|
+
system "ruby -Ilib -Itest test/*_test.rb"
|
31
|
+
}
|
32
|
+
|
33
|
+
task :default => :test
|
34
|
+
|
35
|
+
task(:gitolite_setup) {
|
36
|
+
require 'fileutils'
|
37
|
+
Beeta::Config.load
|
38
|
+
dir = Beeta::Config.gitolite_repo_path
|
39
|
+
location = "git@#{Beeta::Config.gitolite_host}:gitolite-admin"
|
40
|
+
FileUtils.mkdir_p File.dirname(dir)
|
41
|
+
if File.exists? dir
|
42
|
+
system "git pull #{dir}"
|
43
|
+
else
|
44
|
+
system "git clone #{location} #{dir}"
|
45
|
+
end
|
46
|
+
}
|
47
|
+
|
48
|
+
desc "Update the database with the latest schema."
|
49
|
+
task(:migrate) {
|
50
|
+
require 'sequel'
|
51
|
+
require 'sequel/extensions/migration'
|
52
|
+
Beeta::Config.load
|
53
|
+
Sequel.connect(Beeta::Config.db) { |db|
|
54
|
+
Sequel::Migrator.apply(db, './migrations')
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
desc "Run beeta with unicorn"
|
59
|
+
task(:unicorn) {
|
60
|
+
sh "unicorn -c conf/unicorn.rb"
|
61
|
+
}
|
62
|
+
|
63
|
+
desc "Run beeta with unicorn in daemon mode"
|
64
|
+
task(:daemon) {
|
65
|
+
sh "unicorn -D -c conf/unicorn.rb"
|
66
|
+
}
|
67
|
+
|
68
|
+
task(:install_gitolite) {
|
69
|
+
if File.exists? File.expand_path "~git/bin/gl-setup"
|
70
|
+
puts "Gitolite appears to be installed"
|
71
|
+
else
|
72
|
+
puts "Installing Gitolite"
|
73
|
+
tmpidrsa = "/tmp/#{ENV['USER']}-#{rand(10000)}.pub"
|
74
|
+
sh "cp ~/.ssh/id_rsa.pub #{tmpidrsa} && chmod 644 #{tmpidrsa}"
|
75
|
+
install_script = File.expand_path(File.join(File.dirname(__FILE__), 'bin/install_gitolite.sh'))
|
76
|
+
sh "su git -c '#{install_script} #{tmpidrsa}'"
|
77
|
+
sh "rm #{tmpidrsa}"
|
78
|
+
end
|
79
|
+
}
|
80
|
+
|
81
|
+
task(:install_deps) {
|
82
|
+
sh 'gem install bundler'
|
83
|
+
sh 'bundle'
|
84
|
+
}
|
85
|
+
|
86
|
+
desc "Perform all initial setup functions."
|
87
|
+
task(:newb) {
|
88
|
+
# automatic gitolite installation isn't working
|
89
|
+
# #Rake::Task["install_gitolite"].invoke
|
90
|
+
%w(gitolite_setup install_gitolite_gem install_deps migrate test
|
91
|
+
).each do |task|
|
92
|
+
Rake::Task[task].invoke
|
93
|
+
end
|
94
|
+
|
95
|
+
puts <<MSG
|
96
|
+
==============================
|
97
|
+
So, what have you done?
|
98
|
+
Configured gitolite, installed the gitolite gem, bundle installed gems,
|
99
|
+
run db migrations and executed tests.
|
100
|
+
|
101
|
+
What now?
|
102
|
+
1. README
|
103
|
+
2. Code stuff
|
104
|
+
3. Submit back
|
105
|
+
4. ???
|
106
|
+
5. Profit!
|
107
|
+
MSG
|
108
|
+
}
|
109
|
+
|
110
|
+
desc "Perform project release check-in and tag with a version number. Each new release version will be automatically."
|
111
|
+
task(:release) {
|
112
|
+
puts 'Running release task, may take a few minutes'
|
113
|
+
new_version = increment_ver
|
114
|
+
run_commands(
|
115
|
+
"git add lib/version.rb" &&
|
116
|
+
"git commit -am 'Bump to Beeta version #{new_version}'" &&
|
117
|
+
"git tag v#{new_version} HEAD^" &&
|
118
|
+
"gem build beeta.gemspec")
|
119
|
+
|
120
|
+
puts '********************************************************************************'
|
121
|
+
puts
|
122
|
+
puts "Don't forget to `gem push` and `git push --tags`!"
|
123
|
+
puts
|
124
|
+
puts '********************************************************************************'
|
125
|
+
}
|
126
|
+
|
127
|
+
def increment_ver
|
128
|
+
puts "Reading the current Beeta version"
|
129
|
+
specs = Gem::SpecFetcher.fetcher.fetch(Gem::Dependency.new("beeta"))
|
130
|
+
versions = specs.map {|spec,| spec.version}.sort
|
131
|
+
new_version = versions.last.to_s
|
132
|
+
puts "New Version is going to be #{new_version}"
|
133
|
+
version_file =<<-EOT
|
134
|
+
module Beeta
|
135
|
+
VERSION = "#{new_version}"
|
136
|
+
end
|
137
|
+
EOT
|
138
|
+
|
139
|
+
puts "Using Beeta version #{new_version}"
|
140
|
+
File.open('lib/version.rb', 'w') do |f|
|
141
|
+
f.write version_file
|
142
|
+
end
|
143
|
+
new_version
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env sh
|
2
|
+
|
3
|
+
# This script will install gitolite under the current user's account. Normally it is expected that you would install gitolite
|
4
|
+
# to a 'git' user. Therefore, you should probably copy your public key into /tmp and su/sudo into the git account and run the
|
5
|
+
# script from there.
|
6
|
+
#
|
7
|
+
# For more information see: http://sitaramc.github.com/gitolite/doc/1-INSTALL.html
|
8
|
+
|
9
|
+
GITOLITE_DIR=/tmp/gitolite-source
|
10
|
+
TMPKEY=$1
|
11
|
+
VER=v1.5.9.1
|
12
|
+
KEY_ERROR_MSG='Please provide a public key to import into gitolite.'
|
13
|
+
|
14
|
+
if [ -z $TMPKEY ]; then
|
15
|
+
echo $KEY_ERROR_MSG
|
16
|
+
exit
|
17
|
+
fi
|
18
|
+
|
19
|
+
if [ ! -f $TMPKEY ]; then
|
20
|
+
echo $TMPKEY 'does not exist. ' $KEY_ERROR_MSG
|
21
|
+
exit
|
22
|
+
fi
|
23
|
+
|
24
|
+
if [ ! -d $GITOLITE_DIR ]; then
|
25
|
+
git clone git://github.com/sitaramc/gitolite $GITOLITE_DIR
|
26
|
+
fi
|
27
|
+
|
28
|
+
cd $GITOLITE_DIR && git checkout $VER
|
29
|
+
mkdir -p $HOME/bin $HOME/share/gitolite/conf $HOME/share/gitolite/hooks
|
30
|
+
$GITOLITE_DIR/src/gl-system-install $HOME/bin $HOME/share/gitolite/conf $HOME/share/gitolite/hooks
|
31
|
+
$HOME/bin/gl-setup $TMPKEY
|
32
|
+
|
data/doc/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2011 AT&T
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
4
|
+
copy of this software and associated documentation files (the "Software"),
|
5
|
+
to deal in the Software without restriction, including without limitation
|
6
|
+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
7
|
+
and/or sell copies of the Software, and to permit persons to whom the
|
8
|
+
Software is furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
16
|
+
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
18
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
19
|
+
DEALINGS IN THE SOFTWARE.
|
data/doc/TODO
ADDED
File without changes
|
data/doc/project.vim
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
" For as long as I can get away with it, here are the code formatting standards
|
2
|
+
" for the codebase. I don't know how to do this in Emacs or TextMate, but feel
|
3
|
+
" free to add equivalent files.
|
4
|
+
|
5
|
+
" Tabs and shifts rendered as 4 spaces; change it if you want!
|
6
|
+
set ts=4
|
7
|
+
set sw=4
|
8
|
+
|
9
|
+
" Hard tabs for indentation, soft tabs for alignment if that is needed for some
|
10
|
+
" reason:
|
11
|
+
set noexpandtab
|
12
|
+
set sts=0
|
13
|
+
|
14
|
+
" Wrap at 80 characters:
|
15
|
+
set tw=80
|
data/lib/beeta.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
%w(
|
2
|
+
watts
|
3
|
+
json
|
4
|
+
sequel
|
5
|
+
gitolite
|
6
|
+
).each &method(:require)
|
7
|
+
|
8
|
+
module Beeta
|
9
|
+
def self.init
|
10
|
+
# First off, we need to load the configuration file:
|
11
|
+
Beeta::Config.load
|
12
|
+
|
13
|
+
# Before the models are loaded, we need to connect to the DB:
|
14
|
+
Sequel::Model.db = Sequel.connect Beeta::Config.db
|
15
|
+
|
16
|
+
const_set(:GitoliteRepo,
|
17
|
+
Gitolite::GitoliteAdmin.new(Beeta::Config.gitolite_repo_path))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'beeta/config'
|
22
|
+
Beeta.init
|
23
|
+
|
24
|
+
%w(
|
25
|
+
beeta/resource
|
26
|
+
beeta/model
|
27
|
+
).each &method(:require)
|
28
|
+
|
29
|
+
class Beeta::App < Watts::App
|
30
|
+
include Beeta::Resource
|
31
|
+
|
32
|
+
resource('/', Discovery) {
|
33
|
+
resource("app", AppList) {
|
34
|
+
resource(/^[-0-9a-z]+$/i, App)
|
35
|
+
}
|
36
|
+
|
37
|
+
resource("user", UserList) {
|
38
|
+
resource(/^[0-9a-z]+$/i, User)
|
39
|
+
}
|
40
|
+
}
|
41
|
+
end
|
data/lib/beeta/config.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Beeta
|
4
|
+
module Config
|
5
|
+
ConfigFile = %W(
|
6
|
+
#{ENV['BEETA_CONF']}
|
7
|
+
./beeta.json
|
8
|
+
#{ENV['HOME']}/.beeta.json
|
9
|
+
/etc/beeta.json
|
10
|
+
).select { |fn| File.exist? fn }.first
|
11
|
+
|
12
|
+
class << self; attr_accessor :config, :loaded; end
|
13
|
+
|
14
|
+
def self.load(fn = nil, force = false)
|
15
|
+
fn ||= ConfigFile
|
16
|
+
return false if(fn.nil? || (!force && loaded))
|
17
|
+
|
18
|
+
self.config = JSON.parse File.read(fn)
|
19
|
+
# TODO: When the config solidifies reasonably, get rid of the
|
20
|
+
# overly metaprogrammed bits here, and replace with regular
|
21
|
+
# methods. It's just a little easier for now to be able to add
|
22
|
+
# values to the config file and have the methods appear out of
|
23
|
+
# nowhere.
|
24
|
+
config.each { |k,v|
|
25
|
+
class << self; self; end.module_eval {
|
26
|
+
define_method(k) { v }
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
self.loaded = true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
Beeta::Config.load
|
data/lib/beeta/model.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'sequel/model'
|
2
|
+
require 'digest/sha1'
|
3
|
+
|
4
|
+
module Beeta::Model
|
5
|
+
module Mixin
|
6
|
+
def to_json
|
7
|
+
h = {}
|
8
|
+
self.class::PublicProperties.each { |p| h[p] = send(p) }
|
9
|
+
h.to_json
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class User < Sequel::Model
|
14
|
+
include Mixin
|
15
|
+
set_dataset :user
|
16
|
+
|
17
|
+
PublicProperties = [
|
18
|
+
:email,
|
19
|
+
:created,
|
20
|
+
:app_uris,
|
21
|
+
]
|
22
|
+
|
23
|
+
def self.random_salt
|
24
|
+
rand.to_s[2..-1]
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.hash_password salt, pw
|
28
|
+
Digest::SHA1.hexdigest "#{salt}#{pw}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.authenticate email, pw
|
32
|
+
u = self[:email => email]
|
33
|
+
return unless u
|
34
|
+
return u if hash_password(u.salt, pw) == u.hashed_password
|
35
|
+
end
|
36
|
+
|
37
|
+
def before_create
|
38
|
+
self.created = Time.now
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
def app_uris
|
43
|
+
[]
|
44
|
+
end
|
45
|
+
|
46
|
+
def password=(pw)
|
47
|
+
self.salt = self.class.random_salt
|
48
|
+
self.hashed_password = self.class.hash_password salt, pw
|
49
|
+
pw
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class App < Sequel::Model
|
54
|
+
include Mixin
|
55
|
+
set_dataset :app
|
56
|
+
|
57
|
+
many_to_one :owner, :class => User
|
58
|
+
one_to_many :instances
|
59
|
+
|
60
|
+
PublicProperties = [
|
61
|
+
:owner,
|
62
|
+
:name,
|
63
|
+
:max_instances,
|
64
|
+
:min_instances,
|
65
|
+
:git_repo,
|
66
|
+
]
|
67
|
+
|
68
|
+
# The address of the git repository.
|
69
|
+
def git_repo
|
70
|
+
# TODO: Don't hard-code the git user? For the sake of simplicity,
|
71
|
+
# I think it's okay to say that the gitolite user has to be named
|
72
|
+
# 'git' for now.
|
73
|
+
"git@#{Beeta::Config.gitolite_host}:#{name}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def validate
|
77
|
+
super
|
78
|
+
errors.add(:name, "can't be empty.") if(name.nil? || name.empty?)
|
79
|
+
if(((App[:name => name].id != id) rescue nil))
|
80
|
+
errors.add(:name, "must be unique.")
|
81
|
+
end
|
82
|
+
|
83
|
+
errors.add(:owner, "can't be blank.") unless owner
|
84
|
+
|
85
|
+
errors.empty?
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Currently unused placeholder. The idea is that we have N instances
|
90
|
+
# (running Unicorn/Rainbows/etc.) that can be routed to. We're going to
|
91
|
+
# punt on the routing for now, but this will need to be hooked in so that
|
92
|
+
# we can keep track of pid/host/port to pass back through the API.
|
93
|
+
class Instance < Sequel::Model
|
94
|
+
set_dataset :instance
|
95
|
+
|
96
|
+
many_to_one :app
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'beeta/model'
|
2
|
+
|
3
|
+
# TODO: These are all pretty short, but will get bigger and should be split.
|
4
|
+
# While most resources are under 10 lines, though, this is a little easier.
|
5
|
+
module Beeta::Resource
|
6
|
+
include Beeta
|
7
|
+
|
8
|
+
# The Generic resource, with some utility methods for the other Beeta
|
9
|
+
# resources.
|
10
|
+
class Generic < Watts::Resource
|
11
|
+
include Beeta
|
12
|
+
|
13
|
+
def error_404
|
14
|
+
@error_404 ||= json_resp({'error'=>'Not Found'}, 404)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the body given with the request, as with a POST or PUT.
|
18
|
+
def req_body
|
19
|
+
@req_body ||= env['rack.input'].read
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the req_body, run through the JSON parser. Returns nil if we
|
23
|
+
# can't parse it.
|
24
|
+
def json_body
|
25
|
+
@json_body ||=
|
26
|
+
begin
|
27
|
+
JSON.parse(req_body)
|
28
|
+
rescue JSON::ParserError
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def json_resp body, status = 200
|
34
|
+
js = JSON.unparse body
|
35
|
+
[status,
|
36
|
+
{ 'Content-Type' => 'application/json',
|
37
|
+
'Content-Length' => js.size.to_s,
|
38
|
+
},
|
39
|
+
[js]]
|
40
|
+
end
|
41
|
+
|
42
|
+
def json_error str, status = 400
|
43
|
+
json_resp({'error' => str}, status)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Discovery < Generic
|
48
|
+
get { |*_|
|
49
|
+
json_resp 'apps' => '/app', 'users' => '/users'
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
# TODO: These are all pretty similar; maybe a CRUD and a CRUDList
|
54
|
+
# superclass, but that depends on if we call gitolite from the models (I'm
|
55
|
+
# leaning towards yes) or we manage that through an intermediary, and also
|
56
|
+
# on auth. We'll be using SSO ideally, although we may skip that for now.
|
57
|
+
|
58
|
+
class App < Generic
|
59
|
+
get { |name| json_resp Models::App[:name => name] }
|
60
|
+
put { |name|
|
61
|
+
# TODO: Authorization.
|
62
|
+
a = Models::App[:name => name]
|
63
|
+
return error_404 unless a
|
64
|
+
a.set json_body
|
65
|
+
return json_resp(a) if a.save
|
66
|
+
# TODO: Restart the app.
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
class AppList < Generic
|
71
|
+
get { json_resp Model::App.all }
|
72
|
+
|
73
|
+
# Not particularly married to POSTing to the app list, as a name must
|
74
|
+
# be supplied anyway, so just a PUT to /app/name might be more
|
75
|
+
# appropriate.
|
76
|
+
post {
|
77
|
+
# TODO: Authentication, tagging the App as owned by the user that
|
78
|
+
# is posting the data.
|
79
|
+
unless json_body
|
80
|
+
return json_error('No body provided, or could not parse body.')
|
81
|
+
end
|
82
|
+
|
83
|
+
a = Model::App.new json_body
|
84
|
+
if !a.valid?
|
85
|
+
# TODO: 409 when the name is taken.
|
86
|
+
return json_resp(a.errors, 400)
|
87
|
+
end
|
88
|
+
|
89
|
+
# TODO: Make this the model's responsibility(?)
|
90
|
+
repo = Gitolite::Config::Repo.new a.name
|
91
|
+
# TODO: After auth stuff, the below:
|
92
|
+
repo.add_permission('RW+C', '', `id -nu`.strip)
|
93
|
+
Beeta::GitoliteRepo.config.add_repo repo
|
94
|
+
Beeta::GitoliteRepo.save_and_apply
|
95
|
+
|
96
|
+
return json_resp(a) if a.save
|
97
|
+
# TODO: Provide git URI.
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
class UserList < Generic
|
102
|
+
get { |name| json_resp Models::User.all }
|
103
|
+
# TODO: Use SSO.
|
104
|
+
end
|
105
|
+
|
106
|
+
class User < Generic
|
107
|
+
get { |name| json_resp Models::User[:name => name] }
|
108
|
+
put { |name|
|
109
|
+
a = Models::App[:name => name]
|
110
|
+
return error_404 unless a
|
111
|
+
a.set json_body
|
112
|
+
return json_resp(a) if a.save
|
113
|
+
# TODO: Restart the app.
|
114
|
+
}
|
115
|
+
end
|
116
|
+
end
|
data/lib/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: beeta
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Pete Elmore
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-03-11 00:00:00 -08:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: watts
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :runtime
|
32
|
+
version_requirements: *id001
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: json
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
44
|
+
type: :runtime
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: sequel
|
48
|
+
prerelease: false
|
49
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
type: :runtime
|
58
|
+
version_requirements: *id003
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: sqlite3
|
61
|
+
prerelease: false
|
62
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
segments:
|
68
|
+
- 0
|
69
|
+
version: "0"
|
70
|
+
type: :runtime
|
71
|
+
version_requirements: *id004
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: gitolite
|
74
|
+
prerelease: false
|
75
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - "="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
- 0
|
83
|
+
- 2
|
84
|
+
- alpha
|
85
|
+
version: 0.0.2.alpha
|
86
|
+
type: :runtime
|
87
|
+
version_requirements: *id005
|
88
|
+
description:
|
89
|
+
email: pete@debu.gs
|
90
|
+
executables:
|
91
|
+
- install_gitolite.sh
|
92
|
+
extensions: []
|
93
|
+
|
94
|
+
extra_rdoc_files:
|
95
|
+
- doc/TODO
|
96
|
+
- doc/project.vim
|
97
|
+
- doc/LICENSE
|
98
|
+
files:
|
99
|
+
- lib/beeta/resource.rb
|
100
|
+
- lib/beeta/config.rb
|
101
|
+
- lib/beeta/model.rb
|
102
|
+
- lib/version.rb
|
103
|
+
- lib/beeta.rb
|
104
|
+
- doc/TODO
|
105
|
+
- doc/project.vim
|
106
|
+
- doc/LICENSE
|
107
|
+
- bin/install_gitolite.sh
|
108
|
+
- Rakefile
|
109
|
+
has_rdoc: true
|
110
|
+
homepage: http://github.com/pete/beeta
|
111
|
+
licenses: []
|
112
|
+
|
113
|
+
post_install_message:
|
114
|
+
rdoc_options: []
|
115
|
+
|
116
|
+
require_paths:
|
117
|
+
- lib
|
118
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
119
|
+
none: false
|
120
|
+
requirements:
|
121
|
+
- - ~>
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
segments:
|
124
|
+
- 1
|
125
|
+
- 6
|
126
|
+
- 8
|
127
|
+
version: 1.6.8
|
128
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
segments:
|
134
|
+
- 0
|
135
|
+
version: "0"
|
136
|
+
requirements: []
|
137
|
+
|
138
|
+
rubyforge_project:
|
139
|
+
rubygems_version: 1.3.7
|
140
|
+
signing_key:
|
141
|
+
specification_version: 3
|
142
|
+
summary: Platform in the form of a service.
|
143
|
+
test_files: []
|
144
|
+
|