autumn 3.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +11 -0
- data/CHANGELOG +567 -0
- data/MANIFEST +110 -0
- data/README +1114 -0
- data/README.textile +1153 -0
- data/Rakefile +75 -0
- data/autumn.gemspec +44 -0
- data/bin/autumn +11 -0
- data/lib/autumn.rb +8 -0
- data/lib/autumn/authentication.rb +238 -0
- data/lib/autumn/channel_leaf.rb +107 -0
- data/lib/autumn/coder.rb +166 -0
- data/lib/autumn/console_boot.rb +10 -0
- data/lib/autumn/ctcp.rb +250 -0
- data/lib/autumn/daemon.rb +207 -0
- data/lib/autumn/datamapper_hacks.rb +290 -0
- data/lib/autumn/foliater.rb +231 -0
- data/lib/autumn/formatting.rb +236 -0
- data/lib/autumn/generator.rb +231 -0
- data/lib/autumn/genesis.rb +190 -0
- data/lib/autumn/inheritable_attributes.rb +162 -0
- data/lib/autumn/leaf.rb +738 -0
- data/lib/autumn/log_facade.rb +49 -0
- data/lib/autumn/misc.rb +87 -0
- data/lib/autumn/resources/daemons/Anothernet.yml +3 -0
- data/lib/autumn/resources/daemons/AustHex.yml +29 -0
- data/lib/autumn/resources/daemons/Bahamut.yml +67 -0
- data/lib/autumn/resources/daemons/Dancer.yml +3 -0
- data/lib/autumn/resources/daemons/GameSurge.yml +3 -0
- data/lib/autumn/resources/daemons/IRCnet.yml +3 -0
- data/lib/autumn/resources/daemons/Ithildin.yml +7 -0
- data/lib/autumn/resources/daemons/KineIRCd.yml +56 -0
- data/lib/autumn/resources/daemons/PTlink.yml +6 -0
- data/lib/autumn/resources/daemons/QuakeNet.yml +20 -0
- data/lib/autumn/resources/daemons/RFC1459.yml +158 -0
- data/lib/autumn/resources/daemons/RFC2811.yml +16 -0
- data/lib/autumn/resources/daemons/RFC2812.yml +36 -0
- data/lib/autumn/resources/daemons/RatBox.yml +25 -0
- data/lib/autumn/resources/daemons/Ultimate.yml +24 -0
- data/lib/autumn/resources/daemons/Undernet.yml +6 -0
- data/lib/autumn/resources/daemons/Unreal.yml +110 -0
- data/lib/autumn/resources/daemons/_Other.yml +7 -0
- data/lib/autumn/resources/daemons/aircd.yml +33 -0
- data/lib/autumn/resources/daemons/bdq-ircd.yml +3 -0
- data/lib/autumn/resources/daemons/hybrid.yml +38 -0
- data/lib/autumn/resources/daemons/ircu.yml +67 -0
- data/lib/autumn/resources/daemons/tr-ircd.yml +8 -0
- data/lib/autumn/script.rb +74 -0
- data/lib/autumn/speciator.rb +165 -0
- data/lib/autumn/stem.rb +919 -0
- data/lib/autumn/stem_facade.rb +176 -0
- data/lib/autumn/tool/bin.rb +301 -0
- data/lib/autumn/tool/create.rb +48 -0
- data/lib/autumn/tool/project_creator.rb +110 -0
- data/lib/autumn/version.rb +3 -0
- data/lib/skel/Rakefile +163 -0
- data/lib/skel/config/global.yml +2 -0
- data/lib/skel/config/seasons/testing/database.yml +4 -0
- data/lib/skel/config/seasons/testing/leaves.yml +9 -0
- data/lib/skel/config/seasons/testing/season.yml +2 -0
- data/lib/skel/config/seasons/testing/stems.yml +10 -0
- data/lib/skel/leaves/administrator/README +20 -0
- data/lib/skel/leaves/administrator/controller.rb +67 -0
- data/lib/skel/leaves/administrator/views/autumn.txt.erb +1 -0
- data/lib/skel/leaves/administrator/views/reload.txt.erb +11 -0
- data/lib/skel/leaves/insulter/README +17 -0
- data/lib/skel/leaves/insulter/controller.rb +65 -0
- data/lib/skel/leaves/insulter/views/about.txt.erb +1 -0
- data/lib/skel/leaves/insulter/views/help.txt.erb +1 -0
- data/lib/skel/leaves/insulter/views/insult.txt.erb +1 -0
- data/lib/skel/leaves/scorekeeper/README +34 -0
- data/lib/skel/leaves/scorekeeper/config.yml +2 -0
- data/lib/skel/leaves/scorekeeper/controller.rb +104 -0
- data/lib/skel/leaves/scorekeeper/helpers/general.rb +64 -0
- data/lib/skel/leaves/scorekeeper/models/channel.rb +12 -0
- data/lib/skel/leaves/scorekeeper/models/person.rb +14 -0
- data/lib/skel/leaves/scorekeeper/models/pseudonym.rb +11 -0
- data/lib/skel/leaves/scorekeeper/models/score.rb +14 -0
- data/lib/skel/leaves/scorekeeper/tasks/stats.rake +17 -0
- data/lib/skel/leaves/scorekeeper/views/about.txt.erb +1 -0
- data/lib/skel/leaves/scorekeeper/views/change.txt.erb +5 -0
- data/lib/skel/leaves/scorekeeper/views/history.txt.erb +11 -0
- data/lib/skel/leaves/scorekeeper/views/points.txt.erb +5 -0
- data/lib/skel/leaves/scorekeeper/views/usage.txt.erb +1 -0
- data/lib/skel/log/README +1 -0
- data/lib/skel/script/console +28 -0
- data/lib/skel/script/destroy +48 -0
- data/lib/skel/script/generate +48 -0
- data/lib/skel/shared/README +1 -0
- data/lib/skel/tmp/README +1 -0
- data/spec/authentication_spec.rb +328 -0
- data/spec/channel_leaf_spec.rb +142 -0
- data/spec/coder_spec.rb +146 -0
- data/spec/ctcp_spec.rb +222 -0
- data/spec/daemon_spec.rb +202 -0
- data/spec/datamapper_hacks_spec.rb +164 -0
- data/tasks/authors.rake +30 -0
- data/tasks/changelog.rake +18 -0
- data/tasks/copyright.rake +21 -0
- data/tasks/doc.rake +7 -0
- data/tasks/gem.rake +23 -0
- data/tasks/gem_installer.rake +76 -0
- data/tasks/install_dependencies.rake +6 -0
- data/tasks/manifest.rake +4 -0
- data/tasks/rcov.rake +23 -0
- data/tasks/release.rake +52 -0
- data/tasks/reversion.rake +8 -0
- data/tasks/setup.rake +24 -0
- data/tasks/spec.rake +7 -0
- data/tasks/yard.rake +4 -0
- metadata +188 -0
@@ -0,0 +1,176 @@
|
|
1
|
+
# Defines the Autumn::StemFacade class, which provides additional convenience
|
2
|
+
# methods to Autumn::Stem.
|
3
|
+
|
4
|
+
module Autumn
|
5
|
+
|
6
|
+
# A collection of convenience methods that are added to the Stem class. These
|
7
|
+
# methods serve two purposes; one, to allow easier backwards compatibility
|
8
|
+
# with Autumn Leaves 1.0 (which had a simpler one-stem-per-leaf approach), and
|
9
|
+
# two, to make it easier or more Ruby-like to perform certain IRC actions.
|
10
|
+
|
11
|
+
module StemFacade
|
12
|
+
|
13
|
+
# Sends a message to one or more channels or nicks. If no channels or nicks
|
14
|
+
# are specified, broadcasts the message to every channel the stem is in. If
|
15
|
+
# you are sending a message to a channel you must prefix it correctly; the
|
16
|
+
# "#" will not be added before the channel name for you.
|
17
|
+
#
|
18
|
+
# message "Look at me!" # Broadcasts to all channels
|
19
|
+
# message "I love kitties", '#kitties' # Sends a message to one channel or person
|
20
|
+
# message "Learn to RTFM", '#help', 'NoobGuy' # Sends a message to two channels or people
|
21
|
+
|
22
|
+
def message(msg, *chans)
|
23
|
+
return if msg.nil? or msg.empty?
|
24
|
+
chans = channels if chans.empty?
|
25
|
+
if @throttle then
|
26
|
+
Thread.exclusive { msg.each_line { |line| privmsgt chans.to_a, line.strip unless line.strip.empty? } }
|
27
|
+
else
|
28
|
+
msg.each_line { |line| privmsg chans.to_a, line.strip unless line.strip.empty? }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Sets the topic for one or more channels. If no channels are specified,
|
33
|
+
# sets the topic of every channel the stem is in.
|
34
|
+
#
|
35
|
+
# set_topic "Bots sure are fun!", 'bots', 'morebots'
|
36
|
+
|
37
|
+
def set_topic(motd, *chans)
|
38
|
+
return if motd.nil?
|
39
|
+
chans = chans.empty? ? channels : chans.map { |chan| normalized_channel_name chan }
|
40
|
+
chans.each { |chan| topic chan, motd }
|
41
|
+
end
|
42
|
+
|
43
|
+
# Joins a channel by name. If the channel is password-protected, specify the
|
44
|
+
# +password+ parameter. Of course, you could always just call the +join+
|
45
|
+
# method (since each IRC command has a method named after it), but the
|
46
|
+
# advantage to using this method is that it will also update the
|
47
|
+
# <tt>@channel_passwords</tt> instance variable. Internal consistency is a
|
48
|
+
# good thing, so please use this method.
|
49
|
+
|
50
|
+
def join_channel(channel, password=nil)
|
51
|
+
channel = normalized_channel_name(channel)
|
52
|
+
return if channels.include? channel
|
53
|
+
join channel, password
|
54
|
+
@channel_passwords[channel] = password if password
|
55
|
+
end
|
56
|
+
|
57
|
+
# Leaves a channel, specified by name.
|
58
|
+
|
59
|
+
def leave_channel(channel)
|
60
|
+
channel = normalized_channel_name(channel)
|
61
|
+
return unless channels.include? channel
|
62
|
+
part channel
|
63
|
+
end
|
64
|
+
|
65
|
+
# Changes this stem's IRC nick. Note that the stem's original nick will
|
66
|
+
# still be used by the logger.
|
67
|
+
|
68
|
+
def change_nick(new_nick)
|
69
|
+
nick new_nick
|
70
|
+
end
|
71
|
+
|
72
|
+
# Grants a privilege to a channel member, such as voicing a member. The stem
|
73
|
+
# must have the required privilege level to perform this command.
|
74
|
+
# +privilege+ can either be a symbol from the Daemon instance or a string
|
75
|
+
# with the letter code for the privilege.
|
76
|
+
#
|
77
|
+
# grant_user_privilege 'mychannel', 'Somedude', :operator
|
78
|
+
# grant_user_privilege '#mychannel', 'Somedude', 'oa'
|
79
|
+
|
80
|
+
def grant_user_privilege(channel, nick, privilege)
|
81
|
+
channel = normalized_channel_name(channel)
|
82
|
+
privcode = server_type.privilege.index(privilege).chr if server_type.privilege.value? privilege
|
83
|
+
privcode ||= privilege
|
84
|
+
mode channel, "+#{privcode}", nick
|
85
|
+
end
|
86
|
+
|
87
|
+
# Removes a privilege to a channel member, such as voicing a member. The
|
88
|
+
# stem must have the required privilege level to perform this command.
|
89
|
+
# +privilege+ can either be a symbol from the Daemon instance or a string
|
90
|
+
# with the letter code for the privilege.
|
91
|
+
|
92
|
+
def remove_user_privilege(channel, nick, privilege)
|
93
|
+
channel = normalized_channel_name(channel)
|
94
|
+
privcode = server_type.privilege.index(privilege).chr if server_type.privilege.value? privilege
|
95
|
+
privcode ||= privilege
|
96
|
+
mode channel, "-#{privcode}", nick
|
97
|
+
end
|
98
|
+
|
99
|
+
# Grants a usermode to an IRC nick, such as making a nick invisible.
|
100
|
+
# The stem must have the required privilege level to perform this command.
|
101
|
+
# (Generally, one can only change his own usermode unless he is a server
|
102
|
+
# op.) +mode+ can either be a symbol from the Daemon instance or a string
|
103
|
+
# with the letter code for the usermode.
|
104
|
+
#
|
105
|
+
# grant_usermode 'Spycloak', :invisible
|
106
|
+
# grant_usermode 'UpMobility', 'os'
|
107
|
+
|
108
|
+
def grant_usermode(nick, property)
|
109
|
+
propcode = server_type.usermode.index(property).chr if server_type.usermode.value? property
|
110
|
+
propcode ||= property
|
111
|
+
mode nick, "+#{property}"
|
112
|
+
end
|
113
|
+
|
114
|
+
# Revokes a usermode from an IRC nick, such as removing invisibility. The
|
115
|
+
# stem must have the required privilege level to perform this command.
|
116
|
+
# (Generally, one can only change his own usermode unless he is a server
|
117
|
+
# op.) +mode+ can either be a symbol from the Daemon instance or a string
|
118
|
+
# with the letter code for the usermode.
|
119
|
+
|
120
|
+
def remove_usermode(nick, property)
|
121
|
+
propcode = server_type.usermode.index(property).chr if server_type.usermode.value? property
|
122
|
+
propcode ||= property
|
123
|
+
mode nick, "-#{property}"
|
124
|
+
end
|
125
|
+
|
126
|
+
# Sets a property of a channel, such as moderated. The stem must have the
|
127
|
+
# required privilege level to perform this command. +property+ can either be
|
128
|
+
# a symbol from the Daemon instance or a string with the letter code for the
|
129
|
+
# property. If the property takes an argument (such as when setting a
|
130
|
+
# channel password), pass it as the +argument+ paramter.
|
131
|
+
#
|
132
|
+
# set_channel_property '#mychannel', :secret
|
133
|
+
# set_channel_property 'mychannel', :keylock, 'mypassword'
|
134
|
+
# set_channel_property '#mychannel', 'ntr'
|
135
|
+
|
136
|
+
def set_channel_property(channel, property, argument=nil)
|
137
|
+
channel = normalized_channel_name(channel)
|
138
|
+
propcode = server_type.channel_property.index(property).chr if server_type.channel_property.value? property
|
139
|
+
propcode ||= property
|
140
|
+
mode channel, "+#{propcode}", argument
|
141
|
+
end
|
142
|
+
|
143
|
+
# Removes a property of a channel, such as moderated. The stem must have the
|
144
|
+
# required privilege level to perform this command. +property+ can either be
|
145
|
+
# a symbol from the Daemon instance or a string with the letter code for the
|
146
|
+
# property. If the property takes an argument (such as when removing a
|
147
|
+
# channel password), pass it as the +argument+ paramter.
|
148
|
+
|
149
|
+
def unset_channel_property(channel, property, argument=nil)
|
150
|
+
channel = normalized_channel_name(channel)
|
151
|
+
propcode = server_type.channel_property.index(property).chr if server_type.channel_property.value? property
|
152
|
+
propcode ||= property
|
153
|
+
mode channel, "-#{propcode}", argument
|
154
|
+
end
|
155
|
+
|
156
|
+
# Returns an array of nicks for users that are in a channel.
|
157
|
+
|
158
|
+
def users(channel)
|
159
|
+
channel = normalized_channel_name(channel)
|
160
|
+
@chan_mutex.synchronize { @channel_members[channel] && @channel_members[channel].keys }
|
161
|
+
end
|
162
|
+
|
163
|
+
# Returns the privilege level of a channel member. The privilege level will
|
164
|
+
# be a symbol from the Daemon instance. Returns nil if the channel member
|
165
|
+
# doesn't exist or if the bot is not on the given channel. Returns an array
|
166
|
+
# of privileges if the server supports multiple privileges per user, and the
|
167
|
+
# user has more than one privilege.
|
168
|
+
#
|
169
|
+
# +user+ can be a nick or a sender hash.
|
170
|
+
|
171
|
+
def privilege(channel, user)
|
172
|
+
user = user[:nick] if user.kind_of? Hash
|
173
|
+
@chan_mutex.synchronize { @channel_members[channel] && @channel_members[channel][user] }
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,301 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
### This module offers the functionality to start, stop, restart, create,
|
4
|
+
### Check status, or run a console of an autumn application
|
5
|
+
### see autumn -h for usage
|
6
|
+
module Autumn
|
7
|
+
module Tool
|
8
|
+
module Bin
|
9
|
+
module Helpers # Helper methods {{{
|
10
|
+
|
11
|
+
def default_pidfile # {{{
|
12
|
+
return @default_pidfile if @default_pidfile
|
13
|
+
al_root
|
14
|
+
pn = Pathname.new(AL_ROOT)
|
15
|
+
@default_pidfile = (pn.expand_path.join("tmp", pn.basename.to_s + ".pid")).strip
|
16
|
+
end # }}}
|
17
|
+
|
18
|
+
# We're really only concerned about win32ole, so we focus our check on its
|
19
|
+
# ability to load that
|
20
|
+
def is_windows? # {{{
|
21
|
+
return @is_win if @is_win
|
22
|
+
begin
|
23
|
+
require "win32ole"
|
24
|
+
rescue LoadError
|
25
|
+
end
|
26
|
+
@is_win ||= Object.const_defined?("WIN32OLE")
|
27
|
+
end # }}}
|
28
|
+
|
29
|
+
def is_running?(pid) # {{{
|
30
|
+
if is_windows?
|
31
|
+
wmi = WIN32OLE.connect("winmgmts://")
|
32
|
+
processes, ours = wmi.ExecQuery("select * from win32_process where ProcessId = #{pid}"), []
|
33
|
+
processes.each { |process| ours << process.Name }
|
34
|
+
ours.first.nil?
|
35
|
+
else
|
36
|
+
begin
|
37
|
+
prio = Process.getpriority(Process::PRIO_PROCESS, pid)
|
38
|
+
true
|
39
|
+
rescue Errno::ESRCH
|
40
|
+
false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end # }}}
|
44
|
+
|
45
|
+
def check_running?(pid_file) # {{{
|
46
|
+
return false unless File.file?(pid_file)
|
47
|
+
is_running?(File.read(pid_file).to_i)
|
48
|
+
end # }}}
|
49
|
+
|
50
|
+
def find_pid(pid_file) # {{{
|
51
|
+
if pid_file.nil? or not File.file?(pid_file)
|
52
|
+
pid_file = default_pidfile
|
53
|
+
end
|
54
|
+
unless File.file?(pid_file)
|
55
|
+
$stderr.puts "Could not find running process id."
|
56
|
+
return false
|
57
|
+
end
|
58
|
+
pid_file
|
59
|
+
end # }}}
|
60
|
+
end # End helper methods }}}
|
61
|
+
|
62
|
+
class Cmd # This class contains the command methods {{{
|
63
|
+
include Helpers
|
64
|
+
attr_accessor :command
|
65
|
+
|
66
|
+
def initialize(args = nil)
|
67
|
+
args ||= ARGV
|
68
|
+
raise "arguments must be an array!" unless args.respond_to?(:detect)
|
69
|
+
@ourargs = args.dup
|
70
|
+
@command = args.detect { |arg| arg.match(/^(?:--?)?(?:start|stop|restart|create|h(?:elp)?|v(?:ersion)?|console|status)/) }
|
71
|
+
if command.nil?
|
72
|
+
@command = ""
|
73
|
+
else
|
74
|
+
args.delete(@command)
|
75
|
+
end
|
76
|
+
ARGV.replace(args)
|
77
|
+
end
|
78
|
+
|
79
|
+
# {{{ #run is called when we're interactive ($0 == __FILE__)
|
80
|
+
def self.run(args = nil)
|
81
|
+
cmd = new(args)
|
82
|
+
case cmd.command
|
83
|
+
when /^(?:--?)?status$/
|
84
|
+
cmd.status(cmd.command)
|
85
|
+
when /^(?:--?)?restart$/
|
86
|
+
cmd.stop(cmd.command)
|
87
|
+
cmd.start
|
88
|
+
when /^(?:--?)?start$/
|
89
|
+
cmd.start
|
90
|
+
when /^(?:--?)?create$/
|
91
|
+
cmd.create(cmd.command)
|
92
|
+
when /^(?:--?)?stop$/
|
93
|
+
if cmd.stop(cmd.command)
|
94
|
+
puts "Autumn session has ended."
|
95
|
+
$stdout.flush
|
96
|
+
else
|
97
|
+
puts "Autumn failed to stop (or was not running)"
|
98
|
+
end
|
99
|
+
when /^(?:--?)?console$/
|
100
|
+
require "irb"
|
101
|
+
require "irb/completion"
|
102
|
+
cmd.include_autumn
|
103
|
+
require "lib/genesis"
|
104
|
+
IRB.start
|
105
|
+
puts "Autumn session has ended."
|
106
|
+
when /^(?:--?)?h(elp)?$/
|
107
|
+
puts cmd.usage
|
108
|
+
when /^(?:--?)?v(ersion)?$/
|
109
|
+
cmd.include_autumn
|
110
|
+
puts Autumn::VERSION
|
111
|
+
exit
|
112
|
+
when /^$/
|
113
|
+
puts "Must supply a valid command"
|
114
|
+
puts cmd.usage
|
115
|
+
exit 1
|
116
|
+
else
|
117
|
+
puts "#{command} not implemented"
|
118
|
+
puts cmd.usage
|
119
|
+
exit 1
|
120
|
+
end
|
121
|
+
end # }}}
|
122
|
+
|
123
|
+
def include_autumn # {{{
|
124
|
+
begin
|
125
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '/../lib')
|
126
|
+
require 'autumn'
|
127
|
+
rescue LoadError
|
128
|
+
$LOAD_PATH.shift
|
129
|
+
|
130
|
+
begin
|
131
|
+
require 'rubygems'
|
132
|
+
rescue LoadError
|
133
|
+
end
|
134
|
+
require 'autumn'
|
135
|
+
end
|
136
|
+
end # }}}
|
137
|
+
|
138
|
+
def usage # {{{
|
139
|
+
txt = [
|
140
|
+
"\n Usage:",
|
141
|
+
"autumn <start|stop|restart|status|create|console> PROJECT [options]\n",
|
142
|
+
"Commands:\n",
|
143
|
+
" start - Starts an instance of this application.\n",
|
144
|
+
" stop - Stops a running instance of this application.\n",
|
145
|
+
" restart - Stops running instance of this application, then starts it back up. Pidfile",
|
146
|
+
" (if supplied) is used for both stop and start.\n",
|
147
|
+
" status - Gives status of a running autumn instance\n",
|
148
|
+
" create - Creates a new prototype Autumn application in a directory named PROJECT in",
|
149
|
+
" the current directory. autumn create foo would make ./foo containing an",
|
150
|
+
" application prototype.\n",
|
151
|
+
" console - Starts an irb console with autumn (and irb completion) loaded.",
|
152
|
+
" ARGV is passed on to IRB.\n\n"
|
153
|
+
].join("\n\t")
|
154
|
+
|
155
|
+
txt << "* All commands take PROJECT as the directory the autumn bot lives in.\n\n"
|
156
|
+
txt << start_options.to_s << "\n"
|
157
|
+
txt << create_options.to_s << "\n"
|
158
|
+
#if is_windows?
|
159
|
+
#txt << %x{ruby #{rackup_path} --help}.split("\n").reject { |line| line.match(/^Usage:/) }.join("\n\t")
|
160
|
+
#else
|
161
|
+
#txt << %x{#{rackup_path} --help}.split("\n").reject { |line| line.match(/^Usage:/) }.join("\n\t")
|
162
|
+
#end
|
163
|
+
end # }}}
|
164
|
+
|
165
|
+
def start_options
|
166
|
+
@start_opts ||= OptionParser.new do |o|
|
167
|
+
o.banner = "Start/Restart Options"
|
168
|
+
o.on("-D", "--daemonize", "Daemonize the process") { |daem| @daemonize = true }
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def al_root
|
173
|
+
require "pathname"
|
174
|
+
dir = nil
|
175
|
+
if ARGV.size == 1
|
176
|
+
dir = Pathname.new(ARGV.shift)
|
177
|
+
elsif ARGV.size > 1
|
178
|
+
$stderr.puts "Unknown options given #{ARGV.join(" ")}"
|
179
|
+
puts usage
|
180
|
+
exit 1
|
181
|
+
end
|
182
|
+
if dir.nil? or not dir.directory?
|
183
|
+
dir = Pathname.new(ENV["PWD"]).expand_path
|
184
|
+
$stderr.puts "Path to autumn tree not given or invalid, using #{dir}"
|
185
|
+
end
|
186
|
+
Object.const_set("AL_ROOT", dir.expand_path.to_s)
|
187
|
+
Dir.chdir(AL_ROOT)
|
188
|
+
end
|
189
|
+
|
190
|
+
### Methods for commands {{{
|
191
|
+
def start # {{{
|
192
|
+
start_options.parse!(ARGV)
|
193
|
+
al_root
|
194
|
+
|
195
|
+
# Find the name of this app
|
196
|
+
puts "starting autumn"
|
197
|
+
if @daemonize
|
198
|
+
require "daemons"
|
199
|
+
Daemons.run_proc(Pathname.new(AL_ROOT).basename, :ARGV => ["start"], :dir_mode => :normal, :dir => "tmp", :multiple => false) do
|
200
|
+
start_autumn
|
201
|
+
end
|
202
|
+
puts "Autumn started in the background"
|
203
|
+
else
|
204
|
+
start_autumn
|
205
|
+
end
|
206
|
+
end # }}}
|
207
|
+
|
208
|
+
def start_autumn
|
209
|
+
require "autumn/genesis"
|
210
|
+
puts "Loading Autumn #{Autumn::VERSION}"
|
211
|
+
Autumn::Genesis.new.boot!
|
212
|
+
end
|
213
|
+
|
214
|
+
def create_options(opts = {})
|
215
|
+
@create_opts ||= OptionParser.new do |o|
|
216
|
+
o.banner = "Create Options"
|
217
|
+
o.on("-f", "--force", "Force creation if dir already exists") { |yn| opts[:force] = true }
|
218
|
+
o.on("-a", "--amend", "Update a tree") { |yn| opts[:amend] = true }
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def create(command) # {{{
|
223
|
+
create_options(opts = {}).parse!(ARGV)
|
224
|
+
unless ARGV.size == 1
|
225
|
+
$stderr.puts "Invalid options given: #{ARGV.join(" ")}"
|
226
|
+
exit 1
|
227
|
+
end
|
228
|
+
project_name = ARGV.shift
|
229
|
+
if project_name.nil?
|
230
|
+
$stderr.puts "Must supply a valid project name, you gave none."
|
231
|
+
puts usage
|
232
|
+
exit 1
|
233
|
+
end
|
234
|
+
include_autumn
|
235
|
+
require 'autumn/tool/create'
|
236
|
+
Autumn::Tool::Create.create(project_name, opts)
|
237
|
+
end # }}}
|
238
|
+
|
239
|
+
def stop(command) # {{{
|
240
|
+
al_root
|
241
|
+
require "daemons"
|
242
|
+
Daemons.run_proc(Pathname.new(AL_ROOT).basename, :ARGV => ["stop"], :dir_mode => :normal, :dir => "tmp", :multiple => false) do
|
243
|
+
start_autumn
|
244
|
+
end
|
245
|
+
end # }}}
|
246
|
+
|
247
|
+
def status(command) # {{{
|
248
|
+
al_root
|
249
|
+
pn = Pathname.new(AL_ROOT)
|
250
|
+
unless pid_file = find_pid(pn.join("tmp", pn.basename.to_s + ".pid"))
|
251
|
+
$stderr.puts "No pid_file found! Autumn may not be started."
|
252
|
+
exit 1
|
253
|
+
end
|
254
|
+
puts "Pid file #{pid_file} found, PID is #{pid = File.read(pid_file).chomp}"
|
255
|
+
unless is_running?(pid.to_i)
|
256
|
+
$stderr.puts "PID #{pid} is not running"
|
257
|
+
exit 1
|
258
|
+
end
|
259
|
+
if is_windows?
|
260
|
+
wmi = WIN32OLE.connect("winmgmts://")
|
261
|
+
processes, ours = wmi.ExecQuery("select * from win32_process where ProcessId = #{pid}"), []
|
262
|
+
processes.each { |p| ours << [p.Name, p.CommandLine, p.VirtualSize, p.CreationDate, p.ExecutablePath, p.Status ] }
|
263
|
+
puts "Autumn is running!\n\tName: %s\n\tCommand Line: %s\n\tVirtual Size: %s\n\tStarted: %s\n\tExec Path: %s\n\tStatus: %s" % ours.first
|
264
|
+
else
|
265
|
+
require "pathname"
|
266
|
+
# Check for /proc
|
267
|
+
if File.directory?(proc_dir = Pathname.new("/proc"))
|
268
|
+
proc_dir = proc_dir.join(pid)
|
269
|
+
# If we have a "stat" file, we'll assume linux and get as much info
|
270
|
+
# as we can
|
271
|
+
if stat_file = proc_dir.join("stat") and stat_file.file?
|
272
|
+
stats = File.read(stat_file).split
|
273
|
+
puts "Autumn is running!\n\tCommand Line: %s\n\tVirtual Size: %s\n\tStarted: %s\n\tExec Path: %s\n\tStatus: %s" % [
|
274
|
+
File.read(proc_dir.join("cmdline")).split("\000").join(" "),
|
275
|
+
"%s k" % (stats[22].to_f / 1024),
|
276
|
+
File.mtime(proc_dir),
|
277
|
+
File.readlink(proc_dir.join("exe")),
|
278
|
+
stats[2]
|
279
|
+
]
|
280
|
+
exit
|
281
|
+
end
|
282
|
+
end
|
283
|
+
# Fallthrough status, just print a ps
|
284
|
+
puts "Autumn process #{pid} is running!"
|
285
|
+
begin
|
286
|
+
puts %x{ps l #{pid}}
|
287
|
+
rescue
|
288
|
+
puts "No further information available"
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end # }}}
|
292
|
+
|
293
|
+
### End of command methods }}}
|
294
|
+
end # }}}
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
if $0 == __FILE__
|
300
|
+
Autumn::Tool::Bin::Cmd.run(ARGV)
|
301
|
+
end
|