backnob 0.0.1 → 0.0.2
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/History.txt +4 -0
- data/Manifest.txt +23 -0
- data/README.txt +181 -2
- data/Rakefile +7 -124
- data/config/hoe.rb +70 -0
- data/config/requirements.rb +17 -0
- data/lib/backnob/client.rb +25 -1
- data/lib/backnob/hash.rb +11 -1
- data/lib/backnob/options.rb +2 -2
- data/lib/backnob/server.rb +64 -43
- data/lib/backnob/version.rb +1 -1
- data/lib/backnob/worker.rb +93 -29
- data/lib/backnob_control.rb +7 -2
- data/log/debug.log +0 -0
- data/plugin/LICENSE +18 -0
- data/plugin/README +3 -0
- data/plugin/conf/backnob.yml +0 -0
- data/plugin/conf/test_worker.rb +12 -0
- data/plugin/init.rb +5 -0
- data/plugin/lib/backnob_ext.rb +5 -0
- data/plugin/tasks/backnob_tasks.rake +41 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +76 -0
- data/scripts/txt2html +3 -1
- data/tasks/deployment.rake +27 -0
- data/tasks/environment.rake +7 -0
- data/tasks/website.rake +17 -0
- data/test/single_worker.rb +15 -0
- data/test/test_client.rb +2 -2
- data/test/test_server.rb +23 -13
- data/test/test_worker.rb +7 -0
- data/website/index.html +87 -0
- data/website/index.txt +30 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +137 -0
- data/website/template.rhtml +47 -0
- data.tar.gz.sig +0 -0
- metadata +38 -6
- metadata.gz.sig +2 -1
data/lib/backnob/server.rb
CHANGED
@@ -11,7 +11,8 @@ require 'yaml'
|
|
11
11
|
require File.dirname(__FILE__) + '/options'
|
12
12
|
require File.dirname(__FILE__) + '/worker'
|
13
13
|
|
14
|
-
module Backnob
|
14
|
+
module Backnob
|
15
|
+
# Backnob server.
|
15
16
|
class Server
|
16
17
|
include Singleton
|
17
18
|
|
@@ -24,7 +25,7 @@ module Backnob
|
|
24
25
|
WORKER_KLASSES = []
|
25
26
|
|
26
27
|
# Pass any calls to class to instance
|
27
|
-
def self.method_missing(method, *args, &block)
|
28
|
+
def self.method_missing(method, *args, &block) # :nodoc:
|
28
29
|
self.instance.__send__(method, *args)
|
29
30
|
end
|
30
31
|
|
@@ -32,20 +33,24 @@ module Backnob
|
|
32
33
|
# If receieved twice then stops even if
|
33
34
|
# workers are still running
|
34
35
|
def stop
|
35
|
-
|
36
|
-
|
37
|
-
logger.info "Waiting for workers to exit"
|
38
|
-
@workers.values.each{|w| w.wait}
|
39
|
-
else
|
40
|
-
logger.info "Forcing workers to exit"
|
41
|
-
@workers.values.each{|w| w.shutdown}
|
42
|
-
end
|
36
|
+
@stopping = true
|
37
|
+
@rqueue << :stop
|
43
38
|
|
39
|
+
logger.info "Sending stop to all active workers"
|
40
|
+
@workers.each{|w| w.object.stop rescue nil }
|
41
|
+
@workers.each{|w| w.slave.shutdown rescue nil }
|
44
42
|
logger.info "Stopping DRb service"
|
45
43
|
DRb.stop_service
|
44
|
+
|
45
|
+
exit!
|
46
46
|
end
|
47
47
|
|
48
|
-
# Start the server
|
48
|
+
# Start the server with given options.
|
49
|
+
#
|
50
|
+
# Options:
|
51
|
+
# [:path] Path to chdir to after starting
|
52
|
+
# [:workers] Array of worker files or directories
|
53
|
+
# [:listen] Address to listen on. Defaults to 127.0.0.1:6444
|
49
54
|
def start(options = {})
|
50
55
|
options.symbolize_keys!
|
51
56
|
|
@@ -62,7 +67,7 @@ module Backnob
|
|
62
67
|
add_file File.dirname(__FILE__) + '/workers'
|
63
68
|
|
64
69
|
# Set default variables
|
65
|
-
@workers =
|
70
|
+
@workers = []
|
66
71
|
@results = {}
|
67
72
|
@rqueue = Queue.new
|
68
73
|
|
@@ -84,27 +89,20 @@ module Backnob
|
|
84
89
|
# This thread now waits for exit, and also
|
85
90
|
# caches results off the results queue.
|
86
91
|
# It also cleans up workers that have quit.
|
87
|
-
while DRb.thread && DRb.thread.alive?
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
# Unmarshal results
|
92
|
-
data = ::Marshal.load(@rqueue.pop)
|
92
|
+
while DRb.thread && DRb.thread.alive? && !@stopping
|
93
|
+
rqueue = @rqueue.pop
|
94
|
+
unless rqueue == :stop
|
95
|
+
data = ::Marshal.load(rqueue)
|
93
96
|
key = data[0]
|
94
|
-
|
97
|
+
|
95
98
|
@results[key] = {} unless @results.has_key?(key)
|
96
99
|
@results[key][data[1]] = data[2]
|
97
|
-
|
100
|
+
|
98
101
|
if data[1] == :error
|
99
102
|
logger.debug "Error occurred in worker #{key}"
|
100
103
|
logger.debug data[2].to_s
|
101
104
|
logger.debug data[2].backtrace if data[2].backtrace
|
102
105
|
end
|
103
|
-
|
104
|
-
if data[1] == :running && data[2] == false
|
105
|
-
@workers[key].shutdown(:quiet => true)
|
106
|
-
@workers.delete(key)
|
107
|
-
end
|
108
106
|
end
|
109
107
|
end
|
110
108
|
end
|
@@ -112,12 +110,12 @@ module Backnob
|
|
112
110
|
# Get results from a worker. Results are cached
|
113
111
|
# if possible
|
114
112
|
def results(key, hk = nil)
|
115
|
-
results =
|
116
|
-
if @results[key]
|
117
|
-
|
118
|
-
else
|
119
|
-
|
120
|
-
end
|
113
|
+
results = @results[key]
|
114
|
+
# if @results[key]
|
115
|
+
# results = @results[key]
|
116
|
+
# else
|
117
|
+
# results = get_worker(key).object.results() rescue {}
|
118
|
+
# end
|
121
119
|
(hk ? results[hk] : results)
|
122
120
|
end
|
123
121
|
|
@@ -147,28 +145,46 @@ module Backnob
|
|
147
145
|
klass = WORKER_KLASSES.detect do |w|
|
148
146
|
w.name =~ /#{name}/i
|
149
147
|
end
|
150
|
-
|
148
|
+
|
151
149
|
if klass
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
worker.
|
159
|
-
|
150
|
+
# Generate a key
|
151
|
+
begin
|
152
|
+
key = Digest::SHA1.hexdigest(rand.to_s + Time.now.to_i.to_s + klass.name)
|
153
|
+
end until !get_worker(key)
|
154
|
+
|
155
|
+
# If the class is marked as single then find an existing one if possible
|
156
|
+
if klass.single && worker = @workers.detect{|w| w.klass == klass}
|
157
|
+
worker.keys << key
|
158
|
+
worker.object.enqueue(key, options)
|
159
|
+
logger.debug "Adding work to worker #{klass.name} with key #{key}"
|
160
|
+
else
|
161
|
+
logger.debug "Creating worker #{klass.name} with key #{key}"
|
162
|
+
|
163
|
+
slave = Slave.new :object => klass.new(key, options)
|
164
|
+
worker = AttrHash.new
|
165
|
+
worker[:slave] = slave
|
166
|
+
worker[:object] = slave.object
|
167
|
+
worker[:klass] = klass
|
168
|
+
worker[:keys] = [key]
|
169
|
+
slave.object.add_observer(self)
|
170
|
+
slave.object.start
|
171
|
+
@workers << worker
|
172
|
+
end
|
160
173
|
|
161
174
|
key
|
175
|
+
else
|
176
|
+
raise Exception.new("Invalid worker class: #{name}")
|
162
177
|
end
|
163
178
|
end
|
164
|
-
|
179
|
+
|
165
180
|
# Register a class as a worker
|
166
181
|
def register(klass)
|
167
182
|
WORKER_KLASSES.delete(klass) rescue nil
|
168
183
|
WORKER_KLASSES << klass
|
169
184
|
end
|
170
185
|
|
171
|
-
# Add a worker file
|
186
|
+
# Add a worker file or a directory of
|
187
|
+
# worker files
|
172
188
|
def add_file(file)
|
173
189
|
@options[:workers] ||= []
|
174
190
|
|
@@ -184,9 +200,14 @@ module Backnob
|
|
184
200
|
|
185
201
|
private
|
186
202
|
|
203
|
+
# Get the worker with a given key
|
204
|
+
def get_worker(key)
|
205
|
+
@workers.detect{|w| w.keys.include?(key)}
|
206
|
+
end
|
207
|
+
|
187
208
|
# Load each worker file. Worker files should
|
188
209
|
# have calls to register their classes.
|
189
|
-
def load_workers
|
210
|
+
def load_workers
|
190
211
|
@options[:workers].each do |file|
|
191
212
|
if File.exists?(file)
|
192
213
|
# If the file is a directory then load all
|
data/lib/backnob/version.rb
CHANGED
data/lib/backnob/worker.rb
CHANGED
@@ -1,30 +1,69 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'slave'
|
3
3
|
require 'thread'
|
4
|
-
require 'active_support'
|
4
|
+
#require 'active_support'
|
5
5
|
require 'monitor'
|
6
6
|
require 'thread'
|
7
7
|
require 'drb/observer'
|
8
8
|
|
9
|
-
module Kernel
|
9
|
+
module Kernel # :nodoc:
|
10
10
|
def singleton_class
|
11
11
|
class << self; self; end
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
module Backnob
|
16
|
+
# Worker class. Workers should inherit from this class
|
17
|
+
# and implement the execute method.
|
18
|
+
#
|
19
|
+
# Example of a simple worker:
|
20
|
+
# class SimpleWorker < Backnob::Worker
|
21
|
+
# def execute
|
22
|
+
# contents = File.read(@options[:file])
|
23
|
+
# File.open('simple.txt', 'a') do |file|
|
24
|
+
# file.write contents
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# results(:size, File.size('simple.txt'))
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# Usage:
|
32
|
+
# client = Backnob::Client.new
|
33
|
+
# client.add_worker('simple.rb')
|
34
|
+
# key = client.create_worker('simple', :file => '/tmp/to_be_read.txt')
|
35
|
+
# while !client.results(key, :finished)
|
36
|
+
# sleep 1
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# unless client.results(key, :error)
|
40
|
+
# puts "File length is now: #{client.results(key, :size)}"
|
41
|
+
# else
|
42
|
+
# puts client.results(key, :error).to_s
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# Worker adds the key :running to the results automatically and sets it to
|
46
|
+
# true when it starts.
|
47
|
+
#
|
48
|
+
# If an error occurs during execution the worker will place the error object
|
49
|
+
# into the results under the key :error.
|
16
50
|
class Worker
|
17
51
|
include DRb::DRbObservable
|
52
|
+
attr_reader :key
|
18
53
|
|
19
|
-
def self.define_attr_method(name, value)
|
20
|
-
class_eval do
|
54
|
+
def self.define_attr_method(name, value) # :nodoc:
|
55
|
+
class_eval do
|
21
56
|
define_method(name) do
|
22
57
|
value
|
23
58
|
end
|
24
59
|
end
|
60
|
+
|
61
|
+
self.singleton_class.send :define_method, name do
|
62
|
+
value
|
63
|
+
end
|
25
64
|
end
|
26
65
|
|
27
|
-
def self.define_class_attr(name, default)
|
66
|
+
def self.define_class_attr(name, default) # :nodoc:
|
28
67
|
define_attr_method name, default
|
29
68
|
self.singleton_class.send :define_method, name do |value|
|
30
69
|
define_attr_method name, value
|
@@ -32,66 +71,91 @@ module Backnob
|
|
32
71
|
end
|
33
72
|
|
34
73
|
define_class_attr :rails, false
|
74
|
+
define_class_attr :single, false
|
35
75
|
|
76
|
+
# Server creates a new worker passing its key and
|
77
|
+
# any user options as a hash
|
36
78
|
def initialize(key, options = {})
|
37
|
-
@key = key
|
38
79
|
@options = options
|
39
80
|
@results = {}
|
40
81
|
@results.extend(MonitorMixin)
|
82
|
+
|
83
|
+
@wqueue = Queue.new
|
84
|
+
enqueue(key, options)
|
41
85
|
end
|
42
|
-
|
86
|
+
|
87
|
+
# Access to the logger
|
43
88
|
def logger
|
44
89
|
@logger ||= Logger.new($stdout)
|
45
90
|
end
|
46
91
|
|
92
|
+
def enqueue(key, options = {})
|
93
|
+
@wqueue << [key, options]
|
94
|
+
end
|
95
|
+
|
47
96
|
# Start this worker. Starts a new thread and calls execute
|
48
97
|
# for work to be performed.
|
49
98
|
def start
|
50
99
|
@thread = Thread.new do
|
51
|
-
Thread.pass
|
52
|
-
|
53
|
-
logger.debug "Starting #{self.class.name} with key #{@key}"
|
54
|
-
|
55
|
-
results(:running, true)
|
100
|
+
Thread.pass
|
101
|
+
@running = true
|
56
102
|
|
57
103
|
if rails
|
58
104
|
require 'config/environment'
|
59
105
|
ActiveRecord::Base.logger = logger
|
60
106
|
end
|
61
|
-
|
62
|
-
# require File.dirname(__FILE__) + "/../../config/environment"
|
63
|
-
# ActiveRecord::Base.logger = logger
|
64
107
|
|
65
108
|
begin
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
109
|
+
# Get work item off queue
|
110
|
+
@key, @options = @wqueue.pop
|
111
|
+
logger.debug "Starting #{self.class.name} with key #{@key}"
|
112
|
+
|
113
|
+
begin
|
114
|
+
execute unless @key == :stop
|
115
|
+
rescue Exception => e
|
116
|
+
results(:error, e)
|
117
|
+
ensure
|
118
|
+
results(:finished, true)
|
119
|
+
logger.debug "Finished #{self.class.name} with key #{@key}"
|
120
|
+
end
|
121
|
+
end while @running && self.single
|
122
|
+
|
123
|
+
logger.debug "Worker #{self.class.name} exiting"
|
124
|
+
exit!
|
73
125
|
end
|
74
126
|
end
|
75
127
|
|
128
|
+
# Stop this worker.
|
129
|
+
def stop
|
130
|
+
@running = false
|
131
|
+
@wqueue << [:stop, {}]
|
132
|
+
end
|
133
|
+
|
76
134
|
# Get or set results. Workers should access results
|
77
|
-
# through this method as it is synchronized
|
78
|
-
|
135
|
+
# through this method as it is synchronized.
|
136
|
+
#
|
137
|
+
# Results are marshalled back to the client, so if
|
138
|
+
# you are passing non-standard classes be sure to
|
139
|
+
# require the appropriate files on the client side.
|
140
|
+
def results(key = nil,value = nil)
|
79
141
|
res = nil
|
80
142
|
|
81
143
|
@results.synchronize do
|
144
|
+
@results[@key] ||= {}
|
145
|
+
|
82
146
|
if key.nil?
|
83
|
-
res = @results.dup
|
147
|
+
res = @results[@key].dup
|
84
148
|
elsif value.nil?
|
85
|
-
res = @results[key]
|
149
|
+
res = @results[@key][key]
|
86
150
|
else
|
87
|
-
if value != @results[key]
|
88
|
-
@results[key] = value
|
151
|
+
if value != @results[@key][key]
|
152
|
+
@results[@key][key] = value
|
89
153
|
changed(true) # I've changed
|
90
154
|
|
91
155
|
# Marshal results into string
|
92
156
|
# for some reason marshal doesn't like hash, so
|
93
157
|
# convert to array and convert back on server side
|
94
|
-
obo = ::Marshal.dump([@key, key, value])
|
158
|
+
obo = ::Marshal.dump([@key, key, value])
|
95
159
|
notify_observers(obo)
|
96
160
|
end
|
97
161
|
end
|
data/lib/backnob_control.rb
CHANGED
@@ -17,7 +17,7 @@ require 'yaml'
|
|
17
17
|
require File.dirname(__FILE__) + '/backnob/options'
|
18
18
|
require File.dirname(__FILE__) + '/backnob/version'
|
19
19
|
|
20
|
-
OPTIONS = {:path => Pathname.new('.').realpath.to_s}
|
20
|
+
OPTIONS = {:path => Pathname.new('.').realpath.to_s, :pid => '/tmp'}
|
21
21
|
OPTIONS.extend(Backnob::Options)
|
22
22
|
|
23
23
|
parser = OptionParser.new do |opts|
|
@@ -47,6 +47,7 @@ BANNER
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
opts.on("-lADDRESS", "--listen=ADDRESS", "Set the listen address. Defaults to 127.0.0.1:6444") {|l| OPTIONS[:listen] = l }
|
50
|
+
opts.on("-pDIR", "--pid=DIR", "Set the directory to store the pid and log files. Defaults to /tmp") {|p| OPTIONS[:pid] = p }
|
50
51
|
opts.on("-v", "--version", "Show the version") { puts "Backnob server version #{Backnob::VERSION::STRING}"; exit }
|
51
52
|
opts.parse!(ARGV)
|
52
53
|
|
@@ -54,7 +55,11 @@ BANNER
|
|
54
55
|
|
55
56
|
case ARGV.first.to_s.downcase
|
56
57
|
when 'start', 'stop', 'run', 'restart'
|
57
|
-
|
58
|
+
pid_dir = OPTIONS.delete(:pid)
|
59
|
+
Daemons.run(File.dirname(__FILE__) + '/backnob/server.rb', :dir_mode => :normal,
|
60
|
+
:dir => pid_dir,
|
61
|
+
:mode => :load,
|
62
|
+
:log_output => true)
|
58
63
|
when 'create', 'generate', 'results'
|
59
64
|
require 'backnob/client'
|
60
65
|
client = Backnob::Client.new
|
data/log/debug.log
ADDED
File without changes
|
data/plugin/LICENSE
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2007 Jeremy Wells, Boost New Media Ltd.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
5
|
+
the Software without restriction, including without limitation the rights to
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
7
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
8
|
+
subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
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, FITNESS
|
15
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
16
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/plugin/README
ADDED
File without changes
|
data/plugin/init.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
def run
|
4
|
+
begin
|
5
|
+
require 'rubygems'
|
6
|
+
rescue LoadError
|
7
|
+
# no rubygems to load, so we fail silently
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'backnob_control'
|
11
|
+
end
|
12
|
+
|
13
|
+
namespace :backnob do
|
14
|
+
desc "Start a backnob server"
|
15
|
+
task :start do
|
16
|
+
ARGV = ['-c', RAILS_ROOT + '/config/backnob.yml', 'start']
|
17
|
+
run
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Stop a backnob server"
|
21
|
+
task :stop do
|
22
|
+
ARGV = ['stop']
|
23
|
+
run
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Restart a backnob server"
|
27
|
+
task :restart do
|
28
|
+
ARGV = ['-c', RAILS_ROOT + '/config/backnob.yml', 'restart']
|
29
|
+
run
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "Set up the backnob plugin"
|
33
|
+
task :setup do
|
34
|
+
unless File.exists?(RAILS_ROOT + '/config/backnob.yml')
|
35
|
+
FileUtils.cp File.dirname(__FILE__) + '/../conf/backnob.yml', RAILS_ROOT + '/config/backnob.yml'
|
36
|
+
end
|
37
|
+
|
38
|
+
FileUtils.mkdir_p RAILS_ROOT + '/lib/backnob_workers'
|
39
|
+
FileUtils.cp File.dirname(__FILE__) + '/../conf/test_worker.rb', RAILS_ROOT + '/lib/backnob_workers'
|
40
|
+
end
|
41
|
+
end
|
data/script/destroy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.join(File.dirname(__FILE__), '..')
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/destroy'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme]
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.join(File.dirname(__FILE__), '..')
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/generate'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme]
|
14
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|
data/script/txt2html
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
begin
|
5
|
+
require 'newgem'
|
6
|
+
rescue LoadError
|
7
|
+
puts "\n\nGenerating the website requires the newgem RubyGem"
|
8
|
+
puts "Install: gem install newgem\n\n"
|
9
|
+
exit(1)
|
10
|
+
end
|
11
|
+
require 'redcloth'
|
12
|
+
require 'syntax/convertors/html'
|
13
|
+
require 'erb'
|
14
|
+
require File.dirname(__FILE__) + '/../lib/backnob/version.rb'
|
15
|
+
|
16
|
+
version = Backnob::VERSION::STRING
|
17
|
+
download = 'http://rubyforge.org/projects/backnob'
|
18
|
+
|
19
|
+
class Fixnum
|
20
|
+
def ordinal
|
21
|
+
# teens
|
22
|
+
return 'th' if (10..19).include?(self % 100)
|
23
|
+
# others
|
24
|
+
case self % 10
|
25
|
+
when 1: return 'st'
|
26
|
+
when 2: return 'nd'
|
27
|
+
when 3: return 'rd'
|
28
|
+
else return 'th'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Time
|
34
|
+
def pretty
|
35
|
+
return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def convert_syntax(syntax, source)
|
40
|
+
return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
|
41
|
+
end
|
42
|
+
|
43
|
+
if ARGV.length >= 1
|
44
|
+
src, template = ARGV
|
45
|
+
template ||= File.join(File.dirname(__FILE__), '/../website/template.rhtml')
|
46
|
+
|
47
|
+
else
|
48
|
+
puts("Usage: #{File.split($0).last} source.txt [template.rhtml] > output.html")
|
49
|
+
exit!
|
50
|
+
end
|
51
|
+
|
52
|
+
template = ERB.new(File.open(template).read)
|
53
|
+
|
54
|
+
title = nil
|
55
|
+
title_text = nil
|
56
|
+
body = nil
|
57
|
+
File.open(src) do |fsrc|
|
58
|
+
title_text = fsrc.readline
|
59
|
+
body_text = fsrc.read
|
60
|
+
syntax_items = []
|
61
|
+
body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
|
62
|
+
ident = syntax_items.length
|
63
|
+
element, syntax, source = $1, $2, $3
|
64
|
+
syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
|
65
|
+
"syntax-temp-#{ident}"
|
66
|
+
}
|
67
|
+
title = RedCloth.new(title_text).to_html.strip
|
68
|
+
title_text = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
|
69
|
+
body = RedCloth.new(body_text).to_html
|
70
|
+
body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
|
71
|
+
end
|
72
|
+
stat = File.stat(src)
|
73
|
+
created = stat.ctime
|
74
|
+
modified = stat.mtime
|
75
|
+
|
76
|
+
$stdout << template.result(binding)
|
data/scripts/txt2html
CHANGED
@@ -45,6 +45,7 @@ end
|
|
45
45
|
template = ERB.new(File.open(template).read)
|
46
46
|
|
47
47
|
title = nil
|
48
|
+
title_text = nil
|
48
49
|
body = nil
|
49
50
|
File.open(src) do |fsrc|
|
50
51
|
title_text = fsrc.readline
|
@@ -56,7 +57,8 @@ File.open(src) do |fsrc|
|
|
56
57
|
syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
|
57
58
|
"syntax-temp-#{ident}"
|
58
59
|
}
|
59
|
-
title = RedCloth.new(title_text).to_html.
|
60
|
+
title = RedCloth.new(title_text).to_html.strip
|
61
|
+
title_text = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
|
60
62
|
body = RedCloth.new(body_text).to_html
|
61
63
|
body.gsub!(%r!(?:<pre><code>)?syntax-temp-(d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
|
62
64
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
desc 'Release the website and new gem version'
|
2
|
+
task :deploy => [:check_version, :website, :release] do
|
3
|
+
puts "Remember to create SVN tag:"
|
4
|
+
puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " +
|
5
|
+
"svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} "
|
6
|
+
puts "Suggested comment:"
|
7
|
+
puts "Tagging release #{CHANGES}"
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'Runs tasks website_generate and install_gem as a local deployment of the gem'
|
11
|
+
task :local_deploy => [:website_generate, :install_gem]
|
12
|
+
|
13
|
+
task :check_version do
|
14
|
+
unless ENV['VERSION']
|
15
|
+
puts 'Must pass a VERSION=x.y.z release version'
|
16
|
+
exit
|
17
|
+
end
|
18
|
+
unless ENV['VERSION'] == VERS
|
19
|
+
puts "Please update your version.rb to match the release version, currently #{VERS}"
|
20
|
+
exit
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'Install the package as a gem, without generating documentation(ri/rdoc)'
|
25
|
+
task :install_gem_no_doc => [:clean, :package] do
|
26
|
+
sh "#{'sudo ' unless Hoe::WINDOZE }gem install pkg/*.gem --no-rdoc --no-ri"
|
27
|
+
end
|