ruwiki 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme.rubygems +86 -0
- data/Readme.tarfile +65 -0
- data/bin/ruwiki +58 -0
- data/bin/ruwiki.cgi +87 -0
- data/bin/ruwiki_convert +56 -0
- data/bin/ruwiki_service.rb +82 -0
- data/bin/ruwiki_servlet +53 -0
- data/contrib/enscript-token.rb +55 -0
- data/contrib/rublog_integrator.rb +68 -0
- data/data/Default/ProjectIndex.ruwiki +49 -0
- data/data/Ruwiki/Antispam.ruwiki +65 -0
- data/data/Ruwiki/BugTracking.ruwiki +33 -0
- data/data/Ruwiki/ChangeLog.ruwiki +102 -0
- data/data/Ruwiki/Configuring_Ruwiki.ruwiki +151 -0
- data/data/Ruwiki/Extending_Ruwiki.ruwiki +317 -0
- data/data/Ruwiki/LicenseAndAuthorInfo.ruwiki +30 -0
- data/data/Ruwiki/ProjectIndex.ruwiki +84 -0
- data/data/Ruwiki/Roadmap.ruwiki +225 -0
- data/data/Ruwiki/RuwikiTemplatingLibrary.ruwiki +156 -0
- data/data/Ruwiki/RuwikiUtilities.ruwiki +157 -0
- data/data/Ruwiki/SandBox.ruwiki +9 -0
- data/data/Ruwiki/To_Do.ruwiki +51 -0
- data/data/Ruwiki/TroubleShooting.ruwiki +33 -0
- data/data/Ruwiki/WikiFeatures.ruwiki +17 -0
- data/data/Ruwiki/WikiMarkup.ruwiki +261 -0
- data/data/Tutorial/AddingPages.ruwiki +16 -0
- data/data/Tutorial/AddingProjects.ruwiki +16 -0
- data/data/Tutorial/ProjectIndex.ruwiki +11 -0
- data/data/Tutorial/SandBox.ruwiki +9 -0
- data/data/agents.banned +60 -0
- data/data/agents.readonly +321 -0
- data/data/hostip.banned +30 -0
- data/data/hostip.readonly +28 -0
- data/lib/ruwiki.rb +622 -0
- data/lib/ruwiki/auth.rb +56 -0
- data/lib/ruwiki/auth/gforge.rb +73 -0
- data/lib/ruwiki/backend.rb +318 -0
- data/lib/ruwiki/backend/flatfiles.rb +217 -0
- data/lib/ruwiki/config.rb +244 -0
- data/lib/ruwiki/exportable.rb +192 -0
- data/lib/ruwiki/handler.rb +342 -0
- data/lib/ruwiki/lang/de.rb +339 -0
- data/lib/ruwiki/lang/en.rb +334 -0
- data/lib/ruwiki/lang/es.rb +339 -0
- data/lib/ruwiki/page.rb +262 -0
- data/lib/ruwiki/servlet.rb +38 -0
- data/lib/ruwiki/template.rb +553 -0
- data/lib/ruwiki/utils.rb +24 -0
- data/lib/ruwiki/utils/command.rb +102 -0
- data/lib/ruwiki/utils/converter.rb +297 -0
- data/lib/ruwiki/utils/manager.rb +639 -0
- data/lib/ruwiki/utils/servletrunner.rb +295 -0
- data/lib/ruwiki/wiki.rb +147 -0
- data/lib/ruwiki/wiki/tokens.rb +136 -0
- data/lib/ruwiki/wiki/tokens/00default.rb +211 -0
- data/lib/ruwiki/wiki/tokens/01wikilinks.rb +166 -0
- data/lib/ruwiki/wiki/tokens/02actions.rb +63 -0
- data/lib/ruwiki/wiki/tokens/abbreviations.rb +40 -0
- data/lib/ruwiki/wiki/tokens/calendar.rb +147 -0
- data/lib/ruwiki/wiki/tokens/headings.rb +43 -0
- data/lib/ruwiki/wiki/tokens/lists.rb +112 -0
- data/lib/ruwiki/wiki/tokens/rubylists.rb +48 -0
- data/ruwiki.conf +22 -0
- data/ruwiki.pkg +0 -0
- data/templates/default/body.tmpl +19 -0
- data/templates/default/content.tmpl +7 -0
- data/templates/default/controls.tmpl +23 -0
- data/templates/default/edit.tmpl +27 -0
- data/templates/default/error.tmpl +14 -0
- data/templates/default/footer.tmpl +23 -0
- data/templates/default/ruwiki.css +297 -0
- data/templates/default/save.tmpl +8 -0
- data/templates/sidebar/body.tmpl +19 -0
- data/templates/sidebar/content.tmpl +8 -0
- data/templates/sidebar/controls.tmpl +8 -0
- data/templates/sidebar/edit.tmpl +27 -0
- data/templates/sidebar/error.tmpl +13 -0
- data/templates/sidebar/footer.tmpl +22 -0
- data/templates/sidebar/ruwiki.css +347 -0
- data/templates/sidebar/save.tmpl +10 -0
- data/templates/simple/body.tmpl +13 -0
- data/templates/simple/content.tmpl +7 -0
- data/templates/simple/controls.tmpl +8 -0
- data/templates/simple/edit.tmpl +25 -0
- data/templates/simple/error.tmpl +10 -0
- data/templates/simple/footer.tmpl +10 -0
- data/templates/simple/ruwiki.css +192 -0
- data/templates/simple/save.tmpl +8 -0
- data/tests/harness.rb +52 -0
- data/tests/tc_backend_flatfile.rb +103 -0
- data/tests/tc_bugs.rb +74 -0
- data/tests/tc_exportable.rb +64 -0
- data/tests/tc_template.rb +145 -0
- data/tests/tc_tokens.rb +335 -0
- data/tests/testall.rb +20 -0
- metadata +182 -0
data/lib/ruwiki/utils.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#--
|
3
|
+
# Ruwiki
|
4
|
+
# Copyright � 2002 - 2004, Digikata and HaloStatue
|
5
|
+
# Alan Chen (alan@digikata.com)
|
6
|
+
# Austin Ziegler (ruwiki@halostatue.ca)
|
7
|
+
#
|
8
|
+
# Licensed under the same terms as Ruby.
|
9
|
+
#
|
10
|
+
# This file may be renamed to change the URI for the wiki.
|
11
|
+
#
|
12
|
+
# $Id: utils.rb,v 1.2 2004/09/27 04:48:27 austin Exp $
|
13
|
+
#++
|
14
|
+
|
15
|
+
# So that Ruwiki doesn't have to be loaded in full to use the bloody thing.
|
16
|
+
unless defined?(Ruwiki)
|
17
|
+
class Ruwiki
|
18
|
+
VERSION = "0.9.0"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module Ruwiki::Utils
|
23
|
+
RUN_PATH = Dir.pwd
|
24
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#--
|
3
|
+
# Ruwiki
|
4
|
+
# Copyright � 2002 - 2004, Digikata and HaloStatue
|
5
|
+
# Alan Chen (alan@digikata.com)
|
6
|
+
# Austin Ziegler (ruwiki@halostatue.ca)
|
7
|
+
#
|
8
|
+
# Licensed under the same terms as Ruby.
|
9
|
+
#
|
10
|
+
# This file may be renamed to change the URI for the wiki.
|
11
|
+
#
|
12
|
+
# $Id: command.rb,v 1.3 2004/11/09 14:55:35 austin Exp $
|
13
|
+
#++
|
14
|
+
|
15
|
+
# Implements the command pattern. Commands are used by the command-line
|
16
|
+
class Ruwiki::Utils::CommandPattern
|
17
|
+
class AbstractCommandError < Exception; end
|
18
|
+
class UnknownCommandError < RuntimeError; end
|
19
|
+
class CommandAlreadyExists < RuntimeError; end
|
20
|
+
class MissingParameterError < ArgumentError
|
21
|
+
def initialize(argument)
|
22
|
+
@argument = argument
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :argument
|
26
|
+
end
|
27
|
+
|
28
|
+
class << self
|
29
|
+
def add(command)
|
30
|
+
command = command.new if command.kind_of?(Class)
|
31
|
+
|
32
|
+
@commands ||= {}
|
33
|
+
if @commands.has_key?(command.name)
|
34
|
+
raise CommandAlreadyExists
|
35
|
+
else
|
36
|
+
@commands[command.name] = command
|
37
|
+
end
|
38
|
+
|
39
|
+
if command.respond_to?(:altname)
|
40
|
+
unless @commands.has_key?(command.altname)
|
41
|
+
@commands[command.altname] = command
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def <<(command)
|
47
|
+
add(command)
|
48
|
+
end
|
49
|
+
|
50
|
+
attr_accessor :default
|
51
|
+
def default=(command) #:nodoc:
|
52
|
+
if command.kind_of?(Ruwiki::Utils::CommandPattern)
|
53
|
+
@default = command
|
54
|
+
elsif command.kind_of?(Class)
|
55
|
+
@default = command.new
|
56
|
+
elsif @commands.has_key?(command)
|
57
|
+
@default = @commands[command]
|
58
|
+
else
|
59
|
+
raise UnknownCommandError
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def command?(command)
|
64
|
+
@commands.has_key?(command)
|
65
|
+
end
|
66
|
+
|
67
|
+
def command(command)
|
68
|
+
if command?(command)
|
69
|
+
@commands[command]
|
70
|
+
else
|
71
|
+
@default
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def [](cmd)
|
76
|
+
self.command(cmd)
|
77
|
+
end
|
78
|
+
|
79
|
+
def default_ioe(ioe = {})
|
80
|
+
ioe[:input] ||= $stdin
|
81
|
+
ioe[:output] ||= $stdout
|
82
|
+
ioe[:error] ||= $stderr
|
83
|
+
ioe
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def [](args, opts = {}, ioe = {})
|
88
|
+
call(args, opts, ioe)
|
89
|
+
end
|
90
|
+
|
91
|
+
def name
|
92
|
+
raise AbstractCommandError
|
93
|
+
end
|
94
|
+
|
95
|
+
def call(args, opts = {}, ioe = {})
|
96
|
+
raise AbstractCommandError
|
97
|
+
end
|
98
|
+
|
99
|
+
def help
|
100
|
+
raise AbstractCommandError
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,297 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#--
|
3
|
+
# Ruwiki
|
4
|
+
# Copyright � 2002 - 2004, Digikata and HaloStatue
|
5
|
+
# Alan Chen (alan@digikata.com)
|
6
|
+
# Austin Ziegler (ruwiki@halostatue.ca)
|
7
|
+
#
|
8
|
+
# Licensed under the same terms as Ruby.
|
9
|
+
#
|
10
|
+
# This file may be renamed to change the URI for the wiki.
|
11
|
+
#
|
12
|
+
# $Id: converter.rb,v 1.5 2004/11/26 12:18:47 austin Exp $
|
13
|
+
#++
|
14
|
+
|
15
|
+
require 'optparse'
|
16
|
+
require 'ostruct'
|
17
|
+
require 'fileutils'
|
18
|
+
|
19
|
+
module Ruwiki::Utils::Converter
|
20
|
+
class << self
|
21
|
+
TARGETS = %w(flatfiles yaml marshal)
|
22
|
+
|
23
|
+
# Create the regular expressions that are used in Ruwiki 0.6.2
|
24
|
+
OLD_HEADER_RE = /^\s*([a-z]+)\s*:\s*(.*)$/
|
25
|
+
OLD_HEADER_END_RE = /^#EHDR$/
|
26
|
+
DATA_HEADER_END_RE = /\A#EHDR\z/
|
27
|
+
NL_RE = /\n/
|
28
|
+
|
29
|
+
def with(obj)
|
30
|
+
yield obj if block_given?
|
31
|
+
end
|
32
|
+
|
33
|
+
# Only allow this to be run once. Silently fail otherwise.
|
34
|
+
def set_defaults
|
35
|
+
return unless @options.nil?
|
36
|
+
@options = OpenStruct.new
|
37
|
+
|
38
|
+
with @options do |oo|
|
39
|
+
oo.traverse_directories = true
|
40
|
+
oo.backup_old_files = true
|
41
|
+
oo.backup_extension = "~"
|
42
|
+
oo.quiet = false
|
43
|
+
oo.verbose = false
|
44
|
+
oo.extension = 'ruwiki'
|
45
|
+
oo.target_format = 'flatfiles'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def message=(lang)
|
50
|
+
if lang.kind_of?(Hash)
|
51
|
+
@message = lang
|
52
|
+
elsif "constant" == defined?(lang::Message)
|
53
|
+
@message = lang::Message
|
54
|
+
else
|
55
|
+
raise ArgumentError
|
56
|
+
end
|
57
|
+
end
|
58
|
+
def message(id)
|
59
|
+
if @message[id].nil?
|
60
|
+
[]
|
61
|
+
else
|
62
|
+
@message[id]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def display_options
|
67
|
+
end
|
68
|
+
|
69
|
+
def summary
|
70
|
+
end
|
71
|
+
|
72
|
+
def run(argv, input = $stdin, output = $stdout, error = $stderr)
|
73
|
+
set_defaults
|
74
|
+
|
75
|
+
@input = input
|
76
|
+
@output = output
|
77
|
+
@error = error
|
78
|
+
|
79
|
+
language = 'en'
|
80
|
+
find_lang = argv.grep(%r{^--lang})
|
81
|
+
find_lang.each do |ee|
|
82
|
+
if ee =~ %r{^--lang=}
|
83
|
+
language = ee.sub(%r{^--lang=}, '')
|
84
|
+
else
|
85
|
+
language = argv[argv.index(ee).succ]
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
require "ruwiki/lang/#{language.downcase}"
|
90
|
+
self.message = Ruwiki::Lang.const_get(language.upcase)
|
91
|
+
|
92
|
+
argv.options do |opts|
|
93
|
+
opts.banner = message(:converter_usage) % File.basename($0)
|
94
|
+
opts.separator ''
|
95
|
+
opts.on('--format=FORMAT', *message(:converter_format_desc)) do |ff|
|
96
|
+
@options.target_format = ff
|
97
|
+
end
|
98
|
+
opts.on('--[no-]backup', *message(:converter_backup_desc)) do |bb|
|
99
|
+
@options.backup_old_files = bb
|
100
|
+
end
|
101
|
+
opts.on('--backup-extension=EXTENSION', *message(:converter_backupext_desc)) do |ee|
|
102
|
+
if ee.nil? or ee.empty?
|
103
|
+
@error << message(:converter_backupext_error) << "\n" if ee.nil? or ee.empty?
|
104
|
+
@error << "#{opts}\n"
|
105
|
+
return 0
|
106
|
+
end
|
107
|
+
@options.backup_extension = ee
|
108
|
+
end
|
109
|
+
opts.on('--extension=EXTENSION', *message(:converter_extension_desc)) do |ee|
|
110
|
+
if ee.nil? or ee.empty?
|
111
|
+
@error << message(:converter_extension_error) << "\n" if ee.nil? or ee.empty?
|
112
|
+
@error << "#{opts}\n"
|
113
|
+
return 0
|
114
|
+
end
|
115
|
+
@options.extension = ee
|
116
|
+
end
|
117
|
+
opts.on('--no-extension', *message(:converter_noextension_desc)) do
|
118
|
+
@options.extension = nil
|
119
|
+
end
|
120
|
+
opts.on('--lang=LANG', *message(:converter_language_desc)) do |lang|
|
121
|
+
self.message = Ruwiki::Lang.const_get(lang.upcase)
|
122
|
+
end
|
123
|
+
opts.on('--quiet', *message(:converter_quiet_desc)) do |qq|
|
124
|
+
@options.quiet = qq
|
125
|
+
@options.verbose = (not qq)
|
126
|
+
end
|
127
|
+
opts.on('--verbose', *message(:converter_verbose_desc)) do |vv|
|
128
|
+
@options.quiet = (not vv)
|
129
|
+
@options.verbose = vv
|
130
|
+
end
|
131
|
+
opts.separator ''
|
132
|
+
opts.on_tail('--help', *message(:converter_help_desc)) do
|
133
|
+
@error << "#{opts}\n"
|
134
|
+
return 0
|
135
|
+
end
|
136
|
+
|
137
|
+
opts.parse!
|
138
|
+
end
|
139
|
+
|
140
|
+
if argv.empty?
|
141
|
+
@error << message(:converter_num_arguments) << "\n#{argv.options}\n" unless @options.quiet
|
142
|
+
return 127
|
143
|
+
end
|
144
|
+
|
145
|
+
display_options if @options.verbose
|
146
|
+
|
147
|
+
@options.target_format.capitalize!
|
148
|
+
@options.target_format_class = Ruwiki::Backend.const_get(@options.target_format)
|
149
|
+
|
150
|
+
argv.each { |file| process_file(file) }
|
151
|
+
|
152
|
+
summary if not @options.quiet
|
153
|
+
end
|
154
|
+
|
155
|
+
# Process a single file.
|
156
|
+
def process_file(file)
|
157
|
+
if @options.backup_old_files
|
158
|
+
return if file =~ /#{@options.backup_extension}/
|
159
|
+
end
|
160
|
+
@out << "#{file}: " unless @options.quiet
|
161
|
+
|
162
|
+
if File.directory?(file) and @options.traverse_directories
|
163
|
+
@out << message(:converter_directory) << "\n" unless @options.quiet
|
164
|
+
Dir.chdir(file) { Dir['*'].each { |entry| process_file(entry) } }
|
165
|
+
else
|
166
|
+
begin
|
167
|
+
page, page_format = load_page(file)
|
168
|
+
@out << message(:converter_converting_from) % [ page_format, @options.target_format ] if @options.verbose
|
169
|
+
save_page(file, page)
|
170
|
+
@out << message(:converter_done) << "\n" unless @options.quiet
|
171
|
+
rescue PageLoadException
|
172
|
+
@out << message(:converter_not_ruwiki) << "\n" unless @options.quiet
|
173
|
+
rescue PageSaveException
|
174
|
+
@out << message(:cannot_nosave_modified) << "\n" % [ file ] unless @options.quiet
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def load_page(file)
|
180
|
+
data = File.read(file)
|
181
|
+
page_format = nil
|
182
|
+
|
183
|
+
if data =~ OLD_HEADER_END_RE
|
184
|
+
page_format = 'OldFlatfiles'
|
185
|
+
|
186
|
+
page = Ruwiki::Page::NULL_PAGE.dup
|
187
|
+
|
188
|
+
unless data.empty?
|
189
|
+
rawbuf = data.split(NL_RE).map { |ee| ee.chomp }
|
190
|
+
|
191
|
+
loop do
|
192
|
+
if rawbuf[0] =~ OLD_HEADER_END_RE
|
193
|
+
rawbuf.shift
|
194
|
+
break
|
195
|
+
end
|
196
|
+
|
197
|
+
match = OLD_HEADER_RE.match(rawbuf[0])
|
198
|
+
|
199
|
+
unless match.nil?
|
200
|
+
case match.captures[0]
|
201
|
+
when 'topic'
|
202
|
+
page['properties']['topic'] = match.captures[1]
|
203
|
+
page['properties']['title'] = match.captures[1]
|
204
|
+
when 'version'
|
205
|
+
page['properties']['version'] = match.captures[1].to_i
|
206
|
+
else
|
207
|
+
nil
|
208
|
+
end
|
209
|
+
end
|
210
|
+
rawbuf.shift
|
211
|
+
end
|
212
|
+
|
213
|
+
page['page']['content'] = rawbuf.join("\n")
|
214
|
+
|
215
|
+
with page['properties'] do |pp|
|
216
|
+
pp['project'] = File.basename(File.dirname(File.expand_path(file)))
|
217
|
+
pp['editable'] = true
|
218
|
+
pp['indexable'] = true
|
219
|
+
pp['entropy'] = 0.0
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
# Try Marshal
|
225
|
+
if page_format.nil?
|
226
|
+
begin
|
227
|
+
page = ::Marshal.load(data)
|
228
|
+
page_format = 'Marshal'
|
229
|
+
rescue Exception
|
230
|
+
nil
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
# Try YAML
|
235
|
+
if page_format.nil?
|
236
|
+
begin
|
237
|
+
page = ::YAML.load(data)
|
238
|
+
page_format = 'YAML'
|
239
|
+
rescue Exception
|
240
|
+
nil
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
# Try the Flatfiles format
|
245
|
+
if page_format.nil?
|
246
|
+
begin
|
247
|
+
page = Ruwiki::Backend::Flatfiles.load(data)
|
248
|
+
page_format = 'Exportable'
|
249
|
+
rescue Exception => ex
|
250
|
+
nil
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
if page_format.nil? # Cannot detect page type.
|
255
|
+
@error << @message[:converter_page_format_error] << "\n"
|
256
|
+
raise PageLoadException
|
257
|
+
end
|
258
|
+
[page, page_format]
|
259
|
+
rescue PageLoadException
|
260
|
+
raise
|
261
|
+
rescue Exception => ex
|
262
|
+
@error << %Q|#{ex.message}\n#{ex.backtrace.join("\n")}\n| if @options.verbose
|
263
|
+
raise PageLoadException
|
264
|
+
end
|
265
|
+
|
266
|
+
def save_page(file, page)
|
267
|
+
if @options.backup_extension != '~'
|
268
|
+
backup = "#{file}.#{@options.backup_extension}"
|
269
|
+
else
|
270
|
+
backup = "#{file}#{@options.backup_extension}"
|
271
|
+
end
|
272
|
+
|
273
|
+
# Always backup the file -- we are transactional.
|
274
|
+
FileUtils.cp(file, backup)
|
275
|
+
|
276
|
+
if @options.target_format == 'Marshal'
|
277
|
+
method = :print
|
278
|
+
else
|
279
|
+
method = :puts
|
280
|
+
end
|
281
|
+
File.open(file, 'wb') { |ff| ff.__send__(method, @options.target_format_class.dump(page)) }
|
282
|
+
rescue Exception => ex
|
283
|
+
FileUtils.mv(backup, file) if File.exists?(backup)
|
284
|
+
@error << %Q|#{ex.message}\n#{ex.backtrace.join("\n")}\n| if @options.verbose
|
285
|
+
raise PageSaveException
|
286
|
+
ensure
|
287
|
+
# If we aren't *supposed* to back up the file, then get rid of the
|
288
|
+
# backup.
|
289
|
+
if File.exists?(backup) and (not @options.backup_old_files)
|
290
|
+
FileUtils.rm(backup)
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
class PageLoadException < RuntimeError; end
|
295
|
+
class PageSaveException < RuntimeError; end
|
296
|
+
end
|
297
|
+
end
|
@@ -0,0 +1,639 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#--
|
3
|
+
# Ruwiki
|
4
|
+
# Copyright � 2002 - 2004, Digikata and HaloStatue
|
5
|
+
# Alan Chen (alan@digikata.com)
|
6
|
+
# Austin Ziegler (ruwiki@halostatue.ca)
|
7
|
+
#
|
8
|
+
# Licensed under the same terms as Ruby.
|
9
|
+
#
|
10
|
+
# This file may be renamed to change the URI for the wiki.
|
11
|
+
#
|
12
|
+
# $Id: manager.rb,v 1.10 2004/11/28 02:26:57 austin Exp $
|
13
|
+
#++
|
14
|
+
|
15
|
+
require 'optparse'
|
16
|
+
require 'ostruct'
|
17
|
+
require 'fileutils'
|
18
|
+
require 'stringio'
|
19
|
+
require 'zlib'
|
20
|
+
require 'ruwiki/exportable'
|
21
|
+
require 'ruwiki/utils/command'
|
22
|
+
require 'ruwiki/config'
|
23
|
+
|
24
|
+
begin
|
25
|
+
if defined?(Gem::Cache)
|
26
|
+
require_gem 'archive-tar-minitar', '~> 0.5.1'
|
27
|
+
else
|
28
|
+
require 'archive/tar/minitar'
|
29
|
+
end
|
30
|
+
rescue LoadError => ex
|
31
|
+
$stderr.puts ex.message
|
32
|
+
raise
|
33
|
+
end
|
34
|
+
|
35
|
+
module Ruwiki::Utils::Manager
|
36
|
+
DEFAULT_PACKAGE_NAME = 'ruwiki.pkg'
|
37
|
+
|
38
|
+
def self.message=(lang)
|
39
|
+
if lang.kind_of?(Hash)
|
40
|
+
@message = lang
|
41
|
+
elsif "constant" == defined?(lang::Message)
|
42
|
+
@message = lang::Message
|
43
|
+
else
|
44
|
+
raise ArgumentError
|
45
|
+
end
|
46
|
+
end
|
47
|
+
def self.message(id)
|
48
|
+
@message[id]
|
49
|
+
end
|
50
|
+
|
51
|
+
class ManagerError < RuntimeError; end
|
52
|
+
|
53
|
+
EXECUTABLES = %w(ruwiki.cgi ruwiki_servlet ruwiki_servlet.bat \
|
54
|
+
ruwiki_servlet.cmd ruwiki_service.rb)
|
55
|
+
|
56
|
+
class ManagerHelp < Ruwiki::Utils::CommandPattern
|
57
|
+
def name
|
58
|
+
"help"
|
59
|
+
end
|
60
|
+
|
61
|
+
def call(args, opts = {}, ioe = {})
|
62
|
+
ioe = Ruwiki::Utils::CommandPattern.default_ioe(ioe)
|
63
|
+
help_on = args.shift
|
64
|
+
output = ""
|
65
|
+
|
66
|
+
if Ruwiki::Utils::CommandPattern.command?(help_on)
|
67
|
+
ioe[:output] << Ruwiki::Utils::CommandPattern[help_on].help
|
68
|
+
elsif help_on == "commands"
|
69
|
+
ioe[:output] << Ruwiki::Utils::Manager.message(:manager_help_commands)
|
70
|
+
else
|
71
|
+
ioe[:output] << Ruwiki::Utils::Manager.message(:manager_unknown_command) % [ help_on ] << "\n" % [ help_on ] unless help_on.nil? or help_on.empty?
|
72
|
+
ioe[:output] << self.help
|
73
|
+
end
|
74
|
+
|
75
|
+
0
|
76
|
+
end
|
77
|
+
|
78
|
+
def help
|
79
|
+
Ruwiki::Utils::Manager.message(:manager_help_help)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class ManagerInstall < Ruwiki::Utils::CommandPattern
|
84
|
+
def name
|
85
|
+
"install"
|
86
|
+
end
|
87
|
+
|
88
|
+
def call(args, opts = {}, ioe = {})
|
89
|
+
argv = []
|
90
|
+
|
91
|
+
replace = false
|
92
|
+
dest = "."
|
93
|
+
name = nil
|
94
|
+
|
95
|
+
while (arg = args.shift)
|
96
|
+
case arg
|
97
|
+
when '--to'
|
98
|
+
dir = args.shift
|
99
|
+
raise Ruwiki::Utils::CommandPattern::MissingParameterError.new(arg) if dir.nil?
|
100
|
+
if File.exist?(dir)
|
101
|
+
if not File.directory?(dir)
|
102
|
+
raise ArgumentError, Ruwiki::Utils::Manager.message(:manager_dest_not_directory)
|
103
|
+
end
|
104
|
+
else
|
105
|
+
FileUtils.mkdir_p(dir)
|
106
|
+
end
|
107
|
+
dest = dir
|
108
|
+
when /;/o
|
109
|
+
argv.push(*(arg.split(/;/o)))
|
110
|
+
when /,/o
|
111
|
+
argv.push(*(arg.split(/,/o)))
|
112
|
+
else
|
113
|
+
argv << arg
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
options = { 'data' => true }
|
118
|
+
|
119
|
+
while (arg = argv.shift)
|
120
|
+
case arg
|
121
|
+
when /^(?:-|no)(.*$)/
|
122
|
+
options.delete($1)
|
123
|
+
else
|
124
|
+
options[arg] = true
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
Ruwiki::Utils::Manager.install(dest, options)
|
129
|
+
|
130
|
+
0
|
131
|
+
end
|
132
|
+
|
133
|
+
def help
|
134
|
+
Ruwiki::Utils::Manager.message(:manager_install_help)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class ManagerPackage < Ruwiki::Utils::CommandPattern
|
139
|
+
def name
|
140
|
+
"package"
|
141
|
+
end
|
142
|
+
|
143
|
+
def call(args, opts = {}, ioe = {})
|
144
|
+
ioe = Ruwiki::Utils::CommandPattern.default_ioe(ioe)
|
145
|
+
argv = []
|
146
|
+
replace = false
|
147
|
+
dest = "."
|
148
|
+
name = nil
|
149
|
+
|
150
|
+
while (arg = args.shift)
|
151
|
+
case arg
|
152
|
+
when '--replace'
|
153
|
+
replace = true
|
154
|
+
when '-o', '--output'
|
155
|
+
name = args.shift
|
156
|
+
raise Ruwiki::Utils::CommandPattern::MissingParameterError.new(arg) if name.nil?
|
157
|
+
dest = File.dirname(name)
|
158
|
+
name = File.basename(name)
|
159
|
+
else
|
160
|
+
argv << arg
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
if argv.size > 1
|
165
|
+
ioe[:output] << Ruwiki::Utils::Manager.message(:manager_service_hi_argcount) % [ args.join(" ") ] << "\n"
|
166
|
+
ioe[:output] << self.help
|
167
|
+
return 1
|
168
|
+
end
|
169
|
+
source = argv.shift || "."
|
170
|
+
|
171
|
+
Ruwiki::Utils::Manager.package(source, dest, name, replace)
|
172
|
+
0
|
173
|
+
end
|
174
|
+
|
175
|
+
def help
|
176
|
+
Ruwiki::Utils::Manager.message(:manager_package_help) % [ "./#{Ruwiki::Utils::Manager::DEFAULT_PACKAGE_NAME}",
|
177
|
+
Ruwiki::Config::CONFIG_NAME ]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
class ManagerUnpackage < Ruwiki::Utils::CommandPattern
|
182
|
+
def name
|
183
|
+
"unpackage"
|
184
|
+
end
|
185
|
+
|
186
|
+
def call(args, opts = {}, ioe = {})
|
187
|
+
ioe = Ruwiki::Utils::CommandPattern.default_ioe(ioe)
|
188
|
+
argv = []
|
189
|
+
dir = "."
|
190
|
+
|
191
|
+
while (arg = args.shift)
|
192
|
+
case arg
|
193
|
+
when '-o', '--output'
|
194
|
+
dir = args.shift
|
195
|
+
raise Ruwiki::Utils::CommandPatter::MissingParameterError.new(arg) if dir.nil? or not File.directory?(dir)
|
196
|
+
else
|
197
|
+
argv << arg
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
if argv.size > 1
|
202
|
+
ioe[:output] << Ruwiki::Utils::Manager.message(:manager_service_hi_argcount) % [ args.join(" ") ] << "\n"
|
203
|
+
ioe[:output] << self.help
|
204
|
+
return 1
|
205
|
+
end
|
206
|
+
source = argv.shift || Ruwiki::Utils::Manager::DEFAULT_PACKAGE_NAME
|
207
|
+
|
208
|
+
Ruwiki::Utils::Manager.unpackage(source, dir)
|
209
|
+
|
210
|
+
0
|
211
|
+
end
|
212
|
+
|
213
|
+
def help
|
214
|
+
Ruwiki::Utils::Manager.message(:manager_unpackage_help) % [ "./#{Ruwiki::Utils::Manager::DEFAULT_PACKAGE_NAME}" ]
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
if RUBY_PLATFORM =~ /win32/
|
219
|
+
class ManagerService < Ruwiki::Utils::CommandPattern
|
220
|
+
def name
|
221
|
+
"service"
|
222
|
+
end
|
223
|
+
|
224
|
+
def call(args, opts = {}, ioe = {})
|
225
|
+
ioe = Ruwiki::Utils::CommandPattern.default_ioe(ioe)
|
226
|
+
|
227
|
+
if args.size < 2
|
228
|
+
ioe[:output] << Ruwiki::Utils::Manager.message(:manager_service_lo_argcount) % [ args.join(" ") ] << "\n"
|
229
|
+
ioe[:output] << self.help
|
230
|
+
return 0
|
231
|
+
end
|
232
|
+
|
233
|
+
command = args.shift
|
234
|
+
service = args.shift
|
235
|
+
|
236
|
+
options ||= {}
|
237
|
+
options[:service_name] = service
|
238
|
+
options[:service_home] = File.expand_path(".")
|
239
|
+
|
240
|
+
argv = []
|
241
|
+
while (arg = args.shift)
|
242
|
+
case arg
|
243
|
+
when "--rubybin"
|
244
|
+
options[:ruby_bin] = args.shift
|
245
|
+
raise Ruwiki::Utils::CommandPattern::MissingParameterError.new(arg) if options[:ruby_bin].nil?
|
246
|
+
when "--exec"
|
247
|
+
options[:service_bin] = args.shift
|
248
|
+
raise Ruwiki::Utils::CommandPattern::MissingParameterError.new(arg) if options[:service_bin].nil?
|
249
|
+
when "--home"
|
250
|
+
options[:service_home] = args.shift
|
251
|
+
raise Ruwiki::Utils::CommandPattern::MissingParameterError.new(arg) if options[:service_home].nil?
|
252
|
+
else
|
253
|
+
argv << arg
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
options[:service_desc] = args.join(" ") if args.size > 0
|
258
|
+
|
259
|
+
case command
|
260
|
+
when "install"
|
261
|
+
options[:service_install] = true
|
262
|
+
when "start"
|
263
|
+
options[:service_start] = true
|
264
|
+
when "stop"
|
265
|
+
options[:service_stop] = true
|
266
|
+
when "delete"
|
267
|
+
options[:service_delete] = true
|
268
|
+
else
|
269
|
+
raise ArgumentError, Ruwiki::Utils::Manager.message(:manager_unknown_command) % [ command ]
|
270
|
+
end
|
271
|
+
|
272
|
+
Ruwiki::Utils::Manager.manage_windows_service(options, ioe)
|
273
|
+
|
274
|
+
0
|
275
|
+
end
|
276
|
+
|
277
|
+
def help
|
278
|
+
Ruwiki::Utils::Manager.message(:manager_service_help)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
Ruwiki::Utils::CommandPattern << ManagerService
|
282
|
+
end
|
283
|
+
|
284
|
+
Ruwiki::Utils::CommandPattern << ManagerHelp
|
285
|
+
Ruwiki::Utils::CommandPattern << ManagerInstall
|
286
|
+
Ruwiki::Utils::CommandPattern << ManagerPackage
|
287
|
+
Ruwiki::Utils::CommandPattern << ManagerUnpackage
|
288
|
+
Ruwiki::Utils::CommandPattern.default = Ruwiki::Utils::CommandPattern["help"]
|
289
|
+
|
290
|
+
class << self
|
291
|
+
attr_accessor :shared
|
292
|
+
attr_reader :ruwiki_servlet
|
293
|
+
attr_reader :ruwiki_servlet_bat
|
294
|
+
attr_reader :ruwiki_servlet_cmd
|
295
|
+
attr_reader :ruwiki_service
|
296
|
+
attr_reader :ruwiki_cgi
|
297
|
+
attr_reader :ruwiki_pkg
|
298
|
+
def shared=(shared)
|
299
|
+
@shared = shared
|
300
|
+
@ruwiki_servlet = File.join(@shared, "bin", "ruwiki_servlet")
|
301
|
+
@ruwiki_servlet_bat = File.join(@shared, "bin", "ruwiki_servlet.bat")
|
302
|
+
@ruwiki_servlet_cmd = File.join(@shared, "bin", "ruwiki_servlet.cmd")
|
303
|
+
@ruwiki_service = File.join(@shared, "bin", "ruwiki_service.rb")
|
304
|
+
@ruwiki_cgi = File.join(@shared, "bin", "ruwiki.cgi")
|
305
|
+
@ruwiki_pkg = File.join(@shared, Ruwiki::Utils::Manager::DEFAULT_PACKAGE_NAME)
|
306
|
+
end
|
307
|
+
|
308
|
+
def with(obj)
|
309
|
+
yield obj if block_given?
|
310
|
+
end
|
311
|
+
|
312
|
+
def tar_files(list, name)
|
313
|
+
ff = StringIO.new
|
314
|
+
gz = Zlib::GzipWriter.new(ff)
|
315
|
+
to = Archive::Tar::Minitar::Output.new(gz)
|
316
|
+
list.each { |item| Archive::Tar::Minitar.pack_file(item, to) }
|
317
|
+
data = ff.string
|
318
|
+
group = {
|
319
|
+
:name => name,
|
320
|
+
:data => data,
|
321
|
+
:mode => 0644,
|
322
|
+
}
|
323
|
+
return group
|
324
|
+
rescue Exception => ex
|
325
|
+
puts ex.message, ex.backtrace.join("\n")
|
326
|
+
ensure
|
327
|
+
to.close
|
328
|
+
group[:size] = group[:data].size
|
329
|
+
end
|
330
|
+
|
331
|
+
def package(source, dest, name = nil, replace = false)
|
332
|
+
# If the package name is nil, use the default name. If replace is
|
333
|
+
# false, then append a number on the end if the file already exists.
|
334
|
+
# Increment the number until we have a unique filename.
|
335
|
+
if name.nil?
|
336
|
+
pkg = File.join(dest, DEFAULT_PACKAGE_NAME)
|
337
|
+
if File.exists?(pkg) and (not replace)
|
338
|
+
pbn = "#{File.basename(DEFAULT_PACKAGE_NAME, '.pkg')}-%02d.pkg"
|
339
|
+
ii = 1
|
340
|
+
while File.exists?(pkg)
|
341
|
+
pkg = File.join(dest, pbn % ii)
|
342
|
+
ii += 1
|
343
|
+
end
|
344
|
+
end
|
345
|
+
else
|
346
|
+
pkg = File.join(dest, name)
|
347
|
+
if File.exists?(pkg) and (not replace)
|
348
|
+
raise ManagerError, Ruwiki::Utils::Manager.message(:manager_package_exists)
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
files = []
|
353
|
+
|
354
|
+
if File.directory?(source)
|
355
|
+
Dir.chdir(source) do
|
356
|
+
if File.exists?(Ruwiki::Config::CONFIG_NAME)
|
357
|
+
cs = File.stat(Ruwiki::Config::CONFIG_NAME)
|
358
|
+
files << {
|
359
|
+
:name => Ruwiki::Config::CONFIG_NAME,
|
360
|
+
:data => File.read(Ruwiki::Config::CONFIG_NAME),
|
361
|
+
:mtime => cs.mtime,
|
362
|
+
:mode => 0644,
|
363
|
+
:size => cs.size
|
364
|
+
}
|
365
|
+
end
|
366
|
+
|
367
|
+
EXECUTABLES.each do |ff|
|
368
|
+
if File.exists?(ff)
|
369
|
+
cs = File.stat(ff)
|
370
|
+
files << {
|
371
|
+
:name => ff,
|
372
|
+
:data => File.read(ff),
|
373
|
+
:mtime => cs.mtime,
|
374
|
+
:mode => 0755,
|
375
|
+
:size => cs.size
|
376
|
+
}
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
f_data = Dir["data/**/**"].select { |dd| dd !~ /CVS\// }
|
381
|
+
f_data.unshift("data")
|
382
|
+
f_data.map! do |dd|
|
383
|
+
res = { :name => dd, :mode => 0644 }
|
384
|
+
if File.directory?(dd)
|
385
|
+
res[:mode] = 0755
|
386
|
+
res[:dir] = true
|
387
|
+
end
|
388
|
+
res
|
389
|
+
end
|
390
|
+
|
391
|
+
f_tmpl = Dir["templates/**/**"].select { |tt| tt !~ /CVS\// }
|
392
|
+
f_tmpl.unshift("templates")
|
393
|
+
f_tmpl.map! do |tt|
|
394
|
+
res = { :name => tt, :mode => 0644 }
|
395
|
+
if File.directory?(tt)
|
396
|
+
res[:mode] = 0755
|
397
|
+
res[:dir] = true
|
398
|
+
end
|
399
|
+
res
|
400
|
+
end
|
401
|
+
|
402
|
+
files << tar_files(f_data, "data.pkg")
|
403
|
+
files << tar_files(f_tmpl, "tmpl.pkg")
|
404
|
+
end
|
405
|
+
else
|
406
|
+
stat = File.stat(source)
|
407
|
+
files << {
|
408
|
+
:name => File.basename(source),
|
409
|
+
:data => File.read(source),
|
410
|
+
:mtime => stat.mtime,
|
411
|
+
:mode => 0644,
|
412
|
+
:size => stat.size
|
413
|
+
}
|
414
|
+
|
415
|
+
EXECUTABLES.each do |ff|
|
416
|
+
ff = File.join(File.dirname(source), ff)
|
417
|
+
if File.exists?(ff)
|
418
|
+
cs = File.stat(ff)
|
419
|
+
files << {
|
420
|
+
:name => ff,
|
421
|
+
:data => File.read(ff),
|
422
|
+
:mtime => cs.mtime,
|
423
|
+
:mode => 0755,
|
424
|
+
:size => cs.size
|
425
|
+
}
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
cc = Ruwiki::Exportable.load(files[0][:data])
|
430
|
+
tp = cc['ruwiki-config']['template-path']
|
431
|
+
tp = "./templates" if tp.nil? or tp.empty?
|
432
|
+
so = cc['ruwiki-config']['storage-options']
|
433
|
+
|
434
|
+
if so.nil? or so.empty?
|
435
|
+
dp = "./data"
|
436
|
+
else
|
437
|
+
so = Ruwiki::Exportable.load(so)
|
438
|
+
key = 'flatfiles'
|
439
|
+
dp = so[key]['data-path']
|
440
|
+
end
|
441
|
+
|
442
|
+
dp = "./data" if dp.nil? or dp.empty?
|
443
|
+
bndp = File.basename(dp)
|
444
|
+
bntp = File.basename(tp)
|
445
|
+
|
446
|
+
so[key]['data-path'] = bndp
|
447
|
+
cc['ruwiki-config']['storage-options'] = Ruwiki::Exportable.dump(so)
|
448
|
+
cc['ruwiki-config']['template-path'] = bntp
|
449
|
+
files[0][:data] = Ruwiki::Exportable.dump(cc)
|
450
|
+
files[0][:size] = files[0][:data].size
|
451
|
+
|
452
|
+
Dir.chdir(File.dirname(dp)) do
|
453
|
+
f_data = Dir["#{bndp}/**/**"].select { |dd| dd !~ /CVS\// }
|
454
|
+
f_data.map! { |dd| { :name => dd, :mode => 0644 } }
|
455
|
+
files << tar_files(f_data, "data.pkg")
|
456
|
+
end
|
457
|
+
|
458
|
+
Dir.chdir(File.dirname(tp)) do
|
459
|
+
f_tmpl = Dir["#{bntp}/**/**"].select { |tt| tt !~ /CVS\// }
|
460
|
+
f_tmpl.map! { |tt| { :name => tt, :mode => 0644 } }
|
461
|
+
files << tar_files(f_tmpl, "tmpl.pkg")
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
ff = File.open(pkg, "wb")
|
466
|
+
gz = Zlib::GzipWriter.new(ff)
|
467
|
+
tw = Archive::Tar::Minitar::Writer.new(gz)
|
468
|
+
|
469
|
+
files.each do |entry|
|
470
|
+
tw.add_file_simple(entry[:name], entry) { |os| os.write(entry[:data]) }
|
471
|
+
end
|
472
|
+
|
473
|
+
nil
|
474
|
+
rescue Exception => ex
|
475
|
+
puts ex, ex.backtrace.join("\n")
|
476
|
+
ensure
|
477
|
+
tw.close if tw
|
478
|
+
gz.close if gz
|
479
|
+
end
|
480
|
+
|
481
|
+
def unpackage(source, dest)
|
482
|
+
ff = File.open(source, "rb")
|
483
|
+
gz = Zlib::GzipReader.new(ff)
|
484
|
+
Archive::Tar::Minitar::Input.open(gz) do |it|
|
485
|
+
it.each do |entry|
|
486
|
+
case entry.full_name
|
487
|
+
when "data.pkg", "tmpl.pkg"
|
488
|
+
pkg = StringIO.new(entry.read)
|
489
|
+
pkgz = Zlib::GzipReader.new(pkg)
|
490
|
+
Archive::Tar::Minitar::Input.open(pkgz) do |inner|
|
491
|
+
inner.each { |item| inner.extract_entry(dest, item) }
|
492
|
+
end
|
493
|
+
else
|
494
|
+
it.extract_entry(dest, entry)
|
495
|
+
end
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
nil
|
500
|
+
end
|
501
|
+
|
502
|
+
def install(dest, options = {})
|
503
|
+
if options['servlet']
|
504
|
+
FileUtils.install(Ruwiki::Utils::Manager.ruwiki_servlet, dest, :mode => 0755)
|
505
|
+
if RUBY_PLATFORM =~ /win32/
|
506
|
+
if File.exists?(Ruwiki::Utils::Manager.ruwiki_servlet_bat)
|
507
|
+
FileUtils.install(Ruwiki::Utils::Manager.ruwiki_servlet_bat, dest, :mode => 0755)
|
508
|
+
end
|
509
|
+
if File.exists?(Ruwiki::Utils::Manager.ruwiki_servlet_cmd)
|
510
|
+
FileUtils.install(Ruwiki::Utils::Manager.ruwiki_servlet_cmd, dest, :mode => 0755)
|
511
|
+
end
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
515
|
+
if RUBY_PLATFORM =~ /win32/ and options['service']
|
516
|
+
FileUtils.install(Ruwiki::Utils::Manager.ruwiki_service, dest, :mode => 0755)
|
517
|
+
end
|
518
|
+
|
519
|
+
if options['cgi']
|
520
|
+
FileUtils.install(Ruwiki::Utils::Manager.ruwiki_cgi, dest, :mode => 0755)
|
521
|
+
end
|
522
|
+
|
523
|
+
if options['data']
|
524
|
+
unpackage(Ruwiki::Utils::Manager.ruwiki_pkg, dest)
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
if RUBY_PLATFORM =~ /win32/
|
529
|
+
begin
|
530
|
+
require 'win32/service'
|
531
|
+
require 'rbconfig'
|
532
|
+
HasWin32Service = true
|
533
|
+
rescue LoadError
|
534
|
+
HasWin32Service = false
|
535
|
+
end
|
536
|
+
|
537
|
+
# The work here is based on Daniel Berger's Instiki Service Tutorial.
|
538
|
+
# http://rubyforge.org/docman/view.php/85/107/instiki_service_tutorial.txt
|
539
|
+
def manage_windows_service(options, ioe)
|
540
|
+
raise Ruwiki::Utils::Manager.message(:manager_service_broken) unless HasWin32Service
|
541
|
+
|
542
|
+
service_name = options[:service_name] || 'RuwikiSvc'
|
543
|
+
|
544
|
+
if options[:service_install]
|
545
|
+
service_home = options[:service_home]
|
546
|
+
|
547
|
+
program = options[:service_bin]
|
548
|
+
if program.nil? or program.empty?
|
549
|
+
program = File.join(service_home, "ruwiki_service.rb")
|
550
|
+
elsif program !~ %r{[/\\]}
|
551
|
+
program = File.join(service_home, program)
|
552
|
+
end
|
553
|
+
program = %<"#{program}">
|
554
|
+
|
555
|
+
ruby = options[:ruby_bin] || %<"#{File.join(Config::CONFIG['bindir'], 'ruby.exe')}">
|
556
|
+
|
557
|
+
service_desc = options[:service_desc] || 'Ruwiki'
|
558
|
+
|
559
|
+
binpath = "#{ruby} #{program}".tr('/', '\\')
|
560
|
+
|
561
|
+
service = Win32::Service.new
|
562
|
+
service.create_service do |svc|
|
563
|
+
svc.service_name = service_name
|
564
|
+
svc.display_name = service_desc
|
565
|
+
svc.binary_path_name = binpath
|
566
|
+
svc.dependencies = [] # Required because of a bug in Win32::Service
|
567
|
+
end
|
568
|
+
service.close
|
569
|
+
ioe[:output] << Manager.manager(:manager_service_installed) % [ service_name ] << "\n"
|
570
|
+
end
|
571
|
+
|
572
|
+
if options[:service_start]
|
573
|
+
Win32::Service.start(service_name)
|
574
|
+
started = false
|
575
|
+
while (not started)
|
576
|
+
status = Win32::Service.status(service_name)
|
577
|
+
started = (status.current_state == "running")
|
578
|
+
break if started
|
579
|
+
ioe[:output] << Ruwiki::Utils::Manager.message(:manager_one_moment) % [ status.current_state ] << "\n"
|
580
|
+
sleep 1
|
581
|
+
end
|
582
|
+
ioe[:output] << Ruwiki::Utils::Manager.message(:manager_service_started) % [ service_name ] << "\n"
|
583
|
+
end
|
584
|
+
|
585
|
+
if options[:service_stop]
|
586
|
+
Win32::Service.stop(service_name)
|
587
|
+
stopped = false
|
588
|
+
while (not stopped)
|
589
|
+
status = Win32::Service.status(service_name)
|
590
|
+
stopped = (status.current_state == "stopped")
|
591
|
+
break if stopped
|
592
|
+
ioe[:output] << Ruwiki::Utils::Manager.message(:manager_one_moment) % [ status.current_state ] << "\n"
|
593
|
+
sleep 1
|
594
|
+
end
|
595
|
+
ioe[:output] << Ruwiki::Utils::Manager.message(:manager_service_stopped) % [ service_name ] << "\n"
|
596
|
+
end
|
597
|
+
|
598
|
+
if options[:service_delete]
|
599
|
+
Win32::Service.stop(service_name) rescue nil
|
600
|
+
Win32::Service.delete(service_name)
|
601
|
+
ioe[:output] << Ruwiki::Utils::Manager.message(:manager_service_deleted) % [ service_name ] << "\n"
|
602
|
+
end
|
603
|
+
end
|
604
|
+
end
|
605
|
+
|
606
|
+
def run(argv, input = $stdin, output = $stdout, error = $stderr)
|
607
|
+
ioe = {
|
608
|
+
:input => input,
|
609
|
+
:output => output,
|
610
|
+
:error => error
|
611
|
+
}
|
612
|
+
|
613
|
+
language = 'en'
|
614
|
+
find_lang = argv.grep(%r{^--lang})
|
615
|
+
find_lang.each do |ee|
|
616
|
+
eepos = argv.index(ee)
|
617
|
+
if ee =~ %r{^--lang=}
|
618
|
+
language = ee.sub(%r{^--lang=}, '')
|
619
|
+
else
|
620
|
+
language = argv[eepos.succ]
|
621
|
+
argv.delete_at(eepos.succ)
|
622
|
+
end
|
623
|
+
argv.delete_at(eepos)
|
624
|
+
end
|
625
|
+
|
626
|
+
require "ruwiki/lang/#{language.downcase}"
|
627
|
+
Ruwiki::Utils::Manager.message = Ruwiki::Lang.const_get(language.upcase)
|
628
|
+
|
629
|
+
command = Ruwiki::Utils::CommandPattern[(argv.shift or "").downcase]
|
630
|
+
return command[argv, {}, ioe]
|
631
|
+
rescue Ruwiki::Utils::CommandPattern::MissingParameterError => ee
|
632
|
+
ioe[:error] << Ruwiki::Utils::Manager.message(:manager_missing_parameter) % [ ee.argument ] << "\n"
|
633
|
+
return 1
|
634
|
+
rescue ArgumentError, ManagerError => ee
|
635
|
+
ioe[:error] << ee.message << "\n"
|
636
|
+
return 1
|
637
|
+
end
|
638
|
+
end
|
639
|
+
end
|