billy_the_tool 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +20 -0
- data/README.md +28 -0
- data/bin/billy +7 -0
- data/lib/billy/commands/command.rb +36 -0
- data/lib/billy/commands/config.rb +25 -0
- data/lib/billy/commands/eat.rb +68 -0
- data/lib/billy/commands/hello.rb +79 -0
- data/lib/billy/commands/walk.rb +130 -0
- data/lib/billy/commands.rb +24 -0
- data/lib/billy/config.rb +117 -0
- data/lib/billy/session.rb +29 -0
- data/lib/billy.rb +7 -0
- metadata +199 -0
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 4pcbr
|
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.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Billy the tool
|
2
|
+
|
3
|
+
## Commands
|
4
|
+
|
5
|
+
### Setup existing project
|
6
|
+
* billy hello
|
7
|
+
* billy eat {billy_config}
|
8
|
+
|
9
|
+
### Deploy existing project
|
10
|
+
* billy walk {app_name}
|
11
|
+
|
12
|
+
## Sample config file
|
13
|
+
|
14
|
+
```
|
15
|
+
deploy_to: /var/web/
|
16
|
+
user: user
|
17
|
+
server: 192.168.216.93
|
18
|
+
```
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
```bash
|
23
|
+
cd ~
|
24
|
+
billy eat http://192.168.216.93/billy.cfg
|
25
|
+
cd project_name
|
26
|
+
billy walk project_name
|
27
|
+
open http://192.168.216.93/project_name/index.html
|
28
|
+
```
|
data/bin/billy
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'billy/commands'
|
2
|
+
|
3
|
+
class Billy
|
4
|
+
class Commands
|
5
|
+
class Command
|
6
|
+
|
7
|
+
def name
|
8
|
+
self.class.to_s.split( "::" ).last.downcase
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_confirmation
|
17
|
+
gets.chomp.downcase == "y"
|
18
|
+
end
|
19
|
+
|
20
|
+
class << self
|
21
|
+
|
22
|
+
attr_accessor :_instance
|
23
|
+
|
24
|
+
def instance
|
25
|
+
self._instance ||= self.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def register_self!
|
29
|
+
Billy::Commands.register_command!( instance )
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'billy/commands/command'
|
2
|
+
|
3
|
+
class Billy
|
4
|
+
class Commands
|
5
|
+
class Config < Command
|
6
|
+
|
7
|
+
def proceed!( arguments = nil )
|
8
|
+
dir = Dir.pwd
|
9
|
+
if !Billy::Config.config_exists?( dir )
|
10
|
+
print "Billy config file could not be found here. Say Billy hello."
|
11
|
+
exit 1
|
12
|
+
else
|
13
|
+
Billy::Config.load!( dir )
|
14
|
+
print "Current Billy settings: \n"
|
15
|
+
Billy::Config.settings.each_pair do |k, v|
|
16
|
+
print "#{k}:\t\t\t#{v}\n"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
Billy::Commands::Config.register_self!
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'billy/commands/command'
|
4
|
+
|
5
|
+
class Billy
|
6
|
+
class Commands
|
7
|
+
class Eat < Command
|
8
|
+
|
9
|
+
def proceed!( arguments )
|
10
|
+
( path = arguments.shift ) unless arguments.nil?
|
11
|
+
begin
|
12
|
+
if path.nil? || path.empty?
|
13
|
+
raise "No config path given. \nYou have to provide some settings path, e.g. in your local filesystem or direct link to blob file in repository etc.\n"
|
14
|
+
elsif uri?( path ) && ( result = load_remote_config( path ) ).nil?
|
15
|
+
raise "Remote config file could not be loaded"
|
16
|
+
elsif file?( path ) && ( !File.exists?( path ) || ( result = File.read( path ) ).nil? )
|
17
|
+
raise "Config File not found: #{path}"
|
18
|
+
end
|
19
|
+
rescue Exception => e
|
20
|
+
print e.message
|
21
|
+
exit 1
|
22
|
+
end
|
23
|
+
eat_config( result )
|
24
|
+
save_config
|
25
|
+
end
|
26
|
+
|
27
|
+
def eat_config( config_string )
|
28
|
+
Billy::Config.instance.eat_string_config( config_string )
|
29
|
+
end
|
30
|
+
|
31
|
+
def save_config
|
32
|
+
print "Parsed config data:\n"
|
33
|
+
Billy::Config.settings.each_pair do |k, v|
|
34
|
+
print "#{k}: #{v}\n"
|
35
|
+
end
|
36
|
+
print "Save this settings?(y/n): "
|
37
|
+
confirm = get_confirmation
|
38
|
+
if !confirm
|
39
|
+
print "Billy didn't save config file. Skipping\n"
|
40
|
+
exit 1
|
41
|
+
end
|
42
|
+
Billy::Config.save
|
43
|
+
print "Billy saved config file to #{Billy::Config::BILLYRC}\n"
|
44
|
+
end
|
45
|
+
|
46
|
+
def uri?( str )
|
47
|
+
begin
|
48
|
+
uri = URI.parse( str )
|
49
|
+
%w( http https ).include?( uri.scheme )
|
50
|
+
rescue
|
51
|
+
false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def file?( str )
|
56
|
+
!uri?( str )
|
57
|
+
end
|
58
|
+
|
59
|
+
def load_remote_config( path )
|
60
|
+
uri = URI( path )
|
61
|
+
Net::HTTP.get( uri )
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
Billy::Commands::Eat.register_self!
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'billy/commands/command'
|
2
|
+
|
3
|
+
class Billy
|
4
|
+
class Commands
|
5
|
+
class Hello < Command
|
6
|
+
|
7
|
+
def proceed!( arguments = nil )
|
8
|
+
billy_say_hello
|
9
|
+
path = get_init_path( arguments )
|
10
|
+
config = Billy::Config.instance
|
11
|
+
config.save!( path, true )
|
12
|
+
if !ssh_command_exists?
|
13
|
+
suggest_install_ssh
|
14
|
+
exit 1
|
15
|
+
end
|
16
|
+
offer_ssh_keygen unless ssh_key_exists?
|
17
|
+
print "All done!\n"
|
18
|
+
end
|
19
|
+
|
20
|
+
def billy_say_hello
|
21
|
+
print "Hi! I'm Billy, simple deploy tool.\n"
|
22
|
+
print "Usage:\n"
|
23
|
+
print " * billy hello (path) -- init billy in {path} folder. Inites in current if no one given.\n"
|
24
|
+
print " * billy eat {cfg_path} -- parse and save billy config in current folder. {cfg_path} here means remote file url or local one.\n"
|
25
|
+
print " * billy walk {application_name} -- deploy HEAD version in repository to remote server.\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
def ssh_command_exists?
|
29
|
+
res = true
|
30
|
+
%w(ssh ssh-keygen).each do |cmd|
|
31
|
+
res &= system( "which #{cmd} 2>&1 > /dev/null" )
|
32
|
+
end
|
33
|
+
res
|
34
|
+
end
|
35
|
+
|
36
|
+
def ssh_key_exists?
|
37
|
+
ssh_root_path = File.expand_path( "~/.ssh" )
|
38
|
+
res = true
|
39
|
+
res &= File.exists?( ssh_root_path )
|
40
|
+
res &= File.directory?( ssh_root_path )
|
41
|
+
res &= Dir[ ssh_root_path + "/*.pub" ].any?
|
42
|
+
res
|
43
|
+
end
|
44
|
+
|
45
|
+
def suggest_install_ssh
|
46
|
+
print "Billy wants you to install ssh command. Please do it first.\n"
|
47
|
+
end
|
48
|
+
|
49
|
+
def offer_ssh_keygen
|
50
|
+
print "Billy did not find your ssh key. Would you like to create it now?(y/n): "
|
51
|
+
confirm = get_confirmation
|
52
|
+
if !confirm
|
53
|
+
print "Ssh key should be generated before we continue. Please generate it.\n"
|
54
|
+
exit 1
|
55
|
+
end
|
56
|
+
enc_type = 'rsa'
|
57
|
+
print "Billy creates ssh keys for you...\n"
|
58
|
+
system "ssh-keygen -t #{enc_type} -N '' -f ~/.ssh/id_#{enc_type}"
|
59
|
+
print "All done!"
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_init_path( arguments )
|
63
|
+
( path = arguments.shift ) unless arguments.nil?
|
64
|
+
if path.nil? || path.empty?
|
65
|
+
print "Billy will be inited in current directory. Proceed?(y/n): "
|
66
|
+
confirm = get_confirmation
|
67
|
+
if !confirm
|
68
|
+
print "Billy has nothing to do. Bye-bye."
|
69
|
+
end
|
70
|
+
path = Dir.pwd
|
71
|
+
end
|
72
|
+
File.expand_path( path )
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
Billy::Commands::Hello.register_self!
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'billy/commands/command'
|
2
|
+
require 'capistrano'
|
3
|
+
|
4
|
+
class Billy
|
5
|
+
class Commands
|
6
|
+
class Walk < Command
|
7
|
+
|
8
|
+
GIT_PATH = ".git"
|
9
|
+
|
10
|
+
def proceed!( arguments = nil )
|
11
|
+
|
12
|
+
if !Billy::Config.load
|
13
|
+
print "Billy config could not be found. Say Billy hello."
|
14
|
+
exit 1
|
15
|
+
end
|
16
|
+
|
17
|
+
destination = ( arguments.shift rescue nil ) || Billy::Config.instance.destination
|
18
|
+
|
19
|
+
if destination.nil?
|
20
|
+
print "Billy doesn't know where to walk."
|
21
|
+
print "You have to provide deploy folder, e.g.: billy walk my_super_project.\n"
|
22
|
+
exit 1
|
23
|
+
end
|
24
|
+
|
25
|
+
cap = prepare_capistrano( destination )
|
26
|
+
%w(deploy:setup deploy).each do |command|
|
27
|
+
cap.find_and_execute_task(command, :before => :start, :after => :finish)
|
28
|
+
end
|
29
|
+
cap.trigger( :exit )
|
30
|
+
|
31
|
+
print "All done! Billy is a clever boy!\n"
|
32
|
+
end
|
33
|
+
|
34
|
+
def prepare_capistrano( destination )
|
35
|
+
|
36
|
+
cap = Capistrano::Configuration.new
|
37
|
+
cap.load "standard"
|
38
|
+
cap.load "deploy"
|
39
|
+
cap.trigger( :load )
|
40
|
+
config = Billy::Config.instance
|
41
|
+
|
42
|
+
if config.deploy_to.nil?
|
43
|
+
print "Billy doesn't know remote deploy path. Please provide it in config under deploy_to key.\n"
|
44
|
+
exit 1
|
45
|
+
end
|
46
|
+
|
47
|
+
cap.set :scm, "git"
|
48
|
+
cap.set :use_sudo, false
|
49
|
+
cap.set :deploy_via, :remote_cache
|
50
|
+
cap.set :application, destination
|
51
|
+
cap.set :deploy_to, File.join( config.deploy_to, destination )
|
52
|
+
cap.server config.server, :app, :web, :db, :primary => true
|
53
|
+
cap.set :user, config.user
|
54
|
+
|
55
|
+
repository = config.repository || get_repository_path
|
56
|
+
|
57
|
+
cap.set :repository, repository
|
58
|
+
cap.set :normalize_asset_timestamps, false
|
59
|
+
|
60
|
+
cap.namespace :deploy do
|
61
|
+
cap.task :start, :roles => :app do; end
|
62
|
+
cap.task :stop, :roles => :app do; end
|
63
|
+
cap.task :restart, :roles => :app do; end
|
64
|
+
end
|
65
|
+
|
66
|
+
cap
|
67
|
+
end
|
68
|
+
|
69
|
+
def get_repository_path
|
70
|
+
if !local_repository_exists?
|
71
|
+
print "Git repository was not created. Do you want Billy to create it now?\n"
|
72
|
+
confirm = get_confirmation
|
73
|
+
if !confirm
|
74
|
+
print "Billy could not proceed without git repository.\n"
|
75
|
+
exit 1
|
76
|
+
else
|
77
|
+
print "Creating git repository.\n"
|
78
|
+
init_git_repository
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
config = get_git_config
|
83
|
+
|
84
|
+
if !remote_repository_exists?( config )
|
85
|
+
print "Billy could not find remote repository for your project.\n"
|
86
|
+
print "Please add some remote, e.g. git remote add git@github.com:myUsername/myProject.git.\n"
|
87
|
+
exit 1
|
88
|
+
end
|
89
|
+
|
90
|
+
idx = 1
|
91
|
+
i = 0
|
92
|
+
|
93
|
+
match_data = get_remotes( config )
|
94
|
+
|
95
|
+
if match_data.length > 1
|
96
|
+
print "Billy found several remotes in repository. Choose one to deploy from:"
|
97
|
+
match_data.each do |remote|
|
98
|
+
i += 1
|
99
|
+
print "#{i}: #{remote[0]}\t\t#{remote[1]}\n"
|
100
|
+
end
|
101
|
+
while ( idx = gets.chomp.to_i ) > match_data.length; end
|
102
|
+
end
|
103
|
+
match_data[ idx - 1 ][ 1 ]
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_git_config
|
107
|
+
File.read( File.expand_path( GIT_PATH + "/config" ) )
|
108
|
+
end
|
109
|
+
|
110
|
+
def local_repository_exists?
|
111
|
+
File.exists?( File.expand_path( GIT_PATH ) )
|
112
|
+
end
|
113
|
+
|
114
|
+
def remote_repository_exists?( config )
|
115
|
+
get_remotes( config ).any?
|
116
|
+
end
|
117
|
+
|
118
|
+
def get_remotes( config )
|
119
|
+
config.gsub( /\n/, ';' ).scan /\[remote\s+\"([^"]+)\"\][^\[]+url\s*=\s*([^;]+)/
|
120
|
+
end
|
121
|
+
|
122
|
+
def init_git_repository
|
123
|
+
system "git init ."
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
Billy::Commands::Walk.register_self!
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Billy
|
2
|
+
class Commands
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
attr_accessor :pool
|
7
|
+
|
8
|
+
def load_pool!
|
9
|
+
self.pool ||= Hash.new
|
10
|
+
commands_path = File.expand_path( File.dirname(__FILE__) + '/commands/**/*.rb' )
|
11
|
+
Dir[ commands_path ].each do |file|
|
12
|
+
require file
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def register_command!( command )
|
17
|
+
load_pool! unless !pool.nil?
|
18
|
+
( pool[ command.name ] = command ) unless pool.values.include?( command )
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
data/lib/billy/config.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
class Billy
|
2
|
+
class Config
|
3
|
+
|
4
|
+
BILLYRC = '.billyrc'
|
5
|
+
SEPARATOR = ': '
|
6
|
+
|
7
|
+
attr_accessor :storage
|
8
|
+
attr_accessor :storage_path
|
9
|
+
|
10
|
+
def method_missing( m, *args, &block )
|
11
|
+
if m.to_s[ /=$/ ].nil?
|
12
|
+
self.storage[ m.to_s ]
|
13
|
+
else
|
14
|
+
key = ( m.to_s )[ /^([^=]+)/ ]
|
15
|
+
val = args.shift
|
16
|
+
( self.storage[ key ] = val ) unless key.nil? && key.empty?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def config_exists?( dir )
|
21
|
+
File.exists?( File.expand_path( dir + "/#{BILLYRC}" ) )
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
[].tap { |res|
|
26
|
+
self.storage.each_pair do |k, v|
|
27
|
+
res.push "#{k}#{SEPARATOR}#{v}"
|
28
|
+
end
|
29
|
+
}.push( "" ).join( "\n" )
|
30
|
+
end
|
31
|
+
|
32
|
+
def load
|
33
|
+
%w(. ~).each do |path|
|
34
|
+
begin
|
35
|
+
load!( File.expand_path( path ) )
|
36
|
+
return true
|
37
|
+
rescue
|
38
|
+
next
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
def load!( dir )
|
46
|
+
self.storage_path = File.expand_path( dir )
|
47
|
+
file_path = storage_path + "/#{BILLYRC}"
|
48
|
+
raise "Config was not found in #{path}" unless File.exists?( file_path )
|
49
|
+
eat_string_config( File.read( file_path ) )
|
50
|
+
end
|
51
|
+
|
52
|
+
def clear
|
53
|
+
self.storage.clear
|
54
|
+
end
|
55
|
+
|
56
|
+
def reload!( dir = nil )
|
57
|
+
dir ||= storage_path
|
58
|
+
clear
|
59
|
+
load!( dir )
|
60
|
+
end
|
61
|
+
|
62
|
+
def save( dir = nil )
|
63
|
+
dir ||= Dir.pwd
|
64
|
+
begin
|
65
|
+
save!( dir, true )
|
66
|
+
true
|
67
|
+
rescue
|
68
|
+
false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def save!( dir, force = false )
|
73
|
+
raise 'Directory name should not be empty' unless !dir.empty?
|
74
|
+
raise "Directory #{dir.to_s} doesn't exist" unless File.exist?( File.expand_path( dir ) )
|
75
|
+
billyrc_path = File.expand_path( dir + "/#{BILLYRC}" )
|
76
|
+
raise "Config already exists in #{billyrc_path}" unless !File.exists?( billyrc_path ) || force
|
77
|
+
File.open( billyrc_path, 'w' ) { |file|
|
78
|
+
file.flush
|
79
|
+
file.write( self.to_s )
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
def eat_string_config( string_config )
|
84
|
+
clear
|
85
|
+
string_config.each_line do |line|
|
86
|
+
next unless !line.empty?
|
87
|
+
items = line.split( SEPARATOR )
|
88
|
+
k = items.shift
|
89
|
+
v = items.join( SEPARATOR ).strip
|
90
|
+
( self.storage[ k.to_s ] = v ) unless k.nil? || k.empty? || v.nil? || v.empty?
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
protected
|
95
|
+
|
96
|
+
def initialize
|
97
|
+
self.storage = Hash.new
|
98
|
+
end
|
99
|
+
|
100
|
+
class << self
|
101
|
+
|
102
|
+
def instance
|
103
|
+
@@instance ||= self.new
|
104
|
+
end
|
105
|
+
|
106
|
+
def settings
|
107
|
+
instance.storage
|
108
|
+
end
|
109
|
+
|
110
|
+
def method_missing( m, *args, &block )
|
111
|
+
instance.send( m, *args, &block ) if instance.respond_to?( m )
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Billy
|
2
|
+
class Session
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def run!( args )
|
6
|
+
Billy::Commands.load_pool!
|
7
|
+
command = ARGV.shift
|
8
|
+
arguments = ARGV
|
9
|
+
if command.nil?
|
10
|
+
print "Billy has nothing to do. Yay!\n"
|
11
|
+
exit 0
|
12
|
+
end
|
13
|
+
status = proceed_command!( command, arguments )
|
14
|
+
exit status
|
15
|
+
end
|
16
|
+
|
17
|
+
def proceed_command!( command_name, arguments )
|
18
|
+
cmd = Billy::Commands.pool[ command_name.to_s ]
|
19
|
+
if cmd.nil?
|
20
|
+
print "Billy doesn't know this command: #{command_name}. Say billy hello.\n"
|
21
|
+
return 1
|
22
|
+
end
|
23
|
+
cmd.proceed!( arguments )
|
24
|
+
0
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/billy.rb
ADDED
metadata
ADDED
@@ -0,0 +1,199 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: billy_the_tool
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 31
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 2
|
10
|
+
version: 0.1.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- 4pcbr
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-11-29 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
prerelease: false
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
hash: 49
|
28
|
+
segments:
|
29
|
+
- 2
|
30
|
+
- 13
|
31
|
+
- 5
|
32
|
+
version: 2.13.5
|
33
|
+
type: :runtime
|
34
|
+
name: capistrano
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
name: shoulda
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ~>
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 31
|
58
|
+
segments:
|
59
|
+
- 3
|
60
|
+
- 12
|
61
|
+
version: "3.12"
|
62
|
+
type: :development
|
63
|
+
name: rdoc
|
64
|
+
version_requirements: *id003
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
prerelease: false
|
67
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ~>
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
hash: 27
|
73
|
+
segments:
|
74
|
+
- 1
|
75
|
+
- 2
|
76
|
+
- 2
|
77
|
+
version: 1.2.2
|
78
|
+
type: :development
|
79
|
+
name: bundler
|
80
|
+
version_requirements: *id004
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
prerelease: false
|
83
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ~>
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
hash: 63
|
89
|
+
segments:
|
90
|
+
- 1
|
91
|
+
- 8
|
92
|
+
- 4
|
93
|
+
version: 1.8.4
|
94
|
+
type: :development
|
95
|
+
name: jeweler
|
96
|
+
version_requirements: *id005
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
prerelease: false
|
99
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
hash: 3
|
105
|
+
segments:
|
106
|
+
- 0
|
107
|
+
version: "0"
|
108
|
+
type: :development
|
109
|
+
name: rcov
|
110
|
+
version_requirements: *id006
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
prerelease: false
|
113
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ~>
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
hash: 63
|
119
|
+
segments:
|
120
|
+
- 2
|
121
|
+
- 12
|
122
|
+
- 0
|
123
|
+
version: 2.12.0
|
124
|
+
type: :development
|
125
|
+
name: rspec
|
126
|
+
version_requirements: *id007
|
127
|
+
- !ruby/object:Gem::Dependency
|
128
|
+
prerelease: false
|
129
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
130
|
+
none: false
|
131
|
+
requirements:
|
132
|
+
- - ~>
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
hash: 49
|
135
|
+
segments:
|
136
|
+
- 2
|
137
|
+
- 13
|
138
|
+
- 5
|
139
|
+
version: 2.13.5
|
140
|
+
type: :runtime
|
141
|
+
name: capistrano
|
142
|
+
version_requirements: *id008
|
143
|
+
description: Billy is simplified deploy system based on top of capistrano
|
144
|
+
email: me@4pcbr.com
|
145
|
+
executables:
|
146
|
+
- billy
|
147
|
+
extensions: []
|
148
|
+
|
149
|
+
extra_rdoc_files:
|
150
|
+
- LICENSE.txt
|
151
|
+
- README.md
|
152
|
+
files:
|
153
|
+
- bin/billy
|
154
|
+
- lib/billy.rb
|
155
|
+
- lib/billy/commands.rb
|
156
|
+
- lib/billy/commands/command.rb
|
157
|
+
- lib/billy/commands/config.rb
|
158
|
+
- lib/billy/commands/eat.rb
|
159
|
+
- lib/billy/commands/hello.rb
|
160
|
+
- lib/billy/commands/walk.rb
|
161
|
+
- lib/billy/config.rb
|
162
|
+
- lib/billy/session.rb
|
163
|
+
- LICENSE.txt
|
164
|
+
- README.md
|
165
|
+
homepage: http://github.com/AltSpace/billy
|
166
|
+
licenses:
|
167
|
+
- MIT
|
168
|
+
post_install_message:
|
169
|
+
rdoc_options: []
|
170
|
+
|
171
|
+
require_paths:
|
172
|
+
- lib
|
173
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
174
|
+
none: false
|
175
|
+
requirements:
|
176
|
+
- - ">="
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
hash: 3
|
179
|
+
segments:
|
180
|
+
- 0
|
181
|
+
version: "0"
|
182
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
183
|
+
none: false
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
hash: 3
|
188
|
+
segments:
|
189
|
+
- 0
|
190
|
+
version: "0"
|
191
|
+
requirements: []
|
192
|
+
|
193
|
+
rubyforge_project:
|
194
|
+
rubygems_version: 1.8.24
|
195
|
+
signing_key:
|
196
|
+
specification_version: 3
|
197
|
+
summary: Billy the tool
|
198
|
+
test_files: []
|
199
|
+
|