zbatery 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/GNUmakefile ADDED
@@ -0,0 +1,169 @@
1
+ # use GNU Make to run tests in parallel, and without depending on RubyGems
2
+ all::
3
+ RUBY = ruby
4
+ RAKE = rake
5
+ GIT_URL = git://git.bogomips.org/zbatery.git
6
+
7
+ GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
8
+ @./GIT-VERSION-GEN
9
+ -include GIT-VERSION-FILE
10
+ -include local.mk
11
+ ifeq ($(DLEXT),) # "so" for Linux
12
+ DLEXT := $(shell $(RUBY) -rrbconfig -e 'puts Config::CONFIG["DLEXT"]')
13
+ endif
14
+ ifeq ($(RUBY_VERSION),)
15
+ RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
16
+ endif
17
+
18
+ base_bins := zbatery
19
+ bins := $(addprefix bin/, $(base_bins))
20
+ man1_bins := $(addsuffix .1, $(base_bins))
21
+ man1_paths := $(addprefix man/man1/, $(man1_bins))
22
+
23
+ install: $(bins)
24
+ $(prep_setup_rb)
25
+ $(RM) -r .install-tmp
26
+ mkdir .install-tmp
27
+ cp -p bin/* .install-tmp
28
+ $(RUBY) setup.rb all
29
+ $(RM) $^
30
+ mv .install-tmp/* bin/
31
+ $(RM) -r .install-tmp
32
+ $(prep_setup_rb)
33
+
34
+ setup_rb_files := .config InstalledFiles
35
+ prep_setup_rb := @-$(RM) $(setup_rb_files);$(MAKE) -C $(ext) clean
36
+
37
+ clean:
38
+ -$(MAKE) -C $(ext) clean
39
+ -$(MAKE) -C Documentation clean
40
+ $(RM) $(setup_rb_files) $(t_log)
41
+
42
+ man:
43
+ $(MAKE) -C Documentation install-man
44
+
45
+ pkg_extra := GIT-VERSION-FILE NEWS ChangeLog
46
+ manifest: $(pkg_extra) man
47
+ $(RM) .manifest
48
+ $(MAKE) .manifest
49
+
50
+ .manifest:
51
+ (git ls-files && \
52
+ for i in $@ $(pkg_extra) $(man1_paths); \
53
+ do echo $$i; done) | LC_ALL=C sort > $@+
54
+ cmp $@+ $@ || mv $@+ $@
55
+ $(RM) $@+
56
+
57
+ NEWS: GIT-VERSION-FILE
58
+ $(RAKE) -s news_rdoc > $@+
59
+ mv $@+ $@
60
+
61
+ SINCE =
62
+ ChangeLog: LOG_VERSION = \
63
+ $(shell git rev-parse -q "$(GIT_VERSION)" >/dev/null 2>&1 && \
64
+ echo $(GIT_VERSION) || git describe)
65
+ ifneq ($(SINCE),)
66
+ ChangeLog: log_range = v$(SINCE)..$(LOG_VERSION)
67
+ endif
68
+ ChangeLog: GIT-VERSION-FILE
69
+ @echo "ChangeLog from $(GIT_URL) ($(log_range))" > $@+
70
+ @echo >> $@+
71
+ git log $(log_range) | sed -e 's/^/ /' >> $@+
72
+ mv $@+ $@
73
+
74
+ news_atom := http://zbatery.bogomip.org/NEWS.atom.xml
75
+ cgit_atom := http://git.bogomips.org/cgit/zbatery.git/atom/?h=master
76
+ atom = <link rel="alternate" title="Atom feed" href="$(1)" \
77
+ type="application/atom+xml"/>
78
+
79
+ # using rdoc 2.4.1+
80
+ doc: .document NEWS ChangeLog
81
+ for i in $(man1_bins); do > $$i; done
82
+ rdoc -Na -t "$(shell sed -ne '1s/^= //p' README)"
83
+ install -m644 COPYING doc/COPYING
84
+ install -m644 $(shell grep '^[A-Z]' .document) doc/
85
+ $(MAKE) -C Documentation install-html install-man
86
+ install -m644 $(man1_paths) doc/
87
+ cd doc && for i in $(base_bins); do \
88
+ sed -e '/"documentation">/r man1/'$$i'.1.html' \
89
+ < $${i}_1.html > tmp && mv tmp $${i}_1.html; done
90
+ $(RUBY) -i -p -e \
91
+ '$$_.gsub!("</title>",%q{\&$(call atom,$(cgit_atom))})' \
92
+ doc/ChangeLog.html
93
+ $(RUBY) -i -p -e \
94
+ '$$_.gsub!("</title>",%q{\&$(call atom,$(news_atom))})' \
95
+ doc/NEWS.html doc/README.html
96
+ $(RAKE) -s news_atom > doc/NEWS.atom.xml
97
+ cd doc && ln README.html tmp && mv tmp index.html
98
+ $(RM) $(man1_bins)
99
+
100
+ ifneq ($(VERSION),)
101
+ rfproject := rainbows
102
+ rfpackage := zbatery
103
+ pkggem := pkg/$(rfpackage)-$(VERSION).gem
104
+ pkgtgz := pkg/$(rfpackage)-$(VERSION).tgz
105
+ release_notes := release_notes-$(VERSION)
106
+ release_changes := release_changes-$(VERSION)
107
+
108
+ release-notes: $(release_notes)
109
+ release-changes: $(release_changes)
110
+ $(release_changes):
111
+ $(RAKE) -s release_changes > $@+
112
+ $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
113
+ $(release_notes):
114
+ GIT_URL=$(GIT_URL) $(RAKE) -s release_notes > $@+
115
+ $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
116
+
117
+ # ensures we're actually on the tagged $(VERSION), only used for release
118
+ verify:
119
+ test x"$(shell umask)" = x0022
120
+ git rev-parse --verify refs/tags/v$(VERSION)^{}
121
+ git diff-index --quiet HEAD^0
122
+ test `git rev-parse --verify HEAD^0` = \
123
+ `git rev-parse --verify refs/tags/v$(VERSION)^{}`
124
+
125
+ fix-perms:
126
+ -git ls-tree -r HEAD | awk '/^100644 / {print $$NF}' | xargs chmod 644
127
+ -git ls-tree -r HEAD | awk '/^100755 / {print $$NF}' | xargs chmod 755
128
+
129
+ gem: $(pkggem)
130
+
131
+ install-gem: $(pkggem)
132
+ gem install $(CURDIR)/$<
133
+
134
+ $(pkggem): manifest fix-perms
135
+ gem build $(rfpackage).gemspec
136
+ mkdir -p pkg
137
+ mv $(@F) $@
138
+
139
+ $(pkgtgz): distdir = $(basename $@)
140
+ $(pkgtgz): HEAD = v$(VERSION)
141
+ $(pkgtgz): manifest fix-perms
142
+ @test -n "$(distdir)"
143
+ $(RM) -r $(distdir)
144
+ mkdir -p $(distdir)
145
+ tar c `cat .manifest` | (cd $(distdir) && tar x)
146
+ cd pkg && tar c $(basename $(@F)) | gzip -9 > $(@F)+
147
+ mv $@+ $@
148
+
149
+ package: $(pkgtgz) $(pkggem)
150
+
151
+ release: verify package $(release_notes) $(release_changes)
152
+ # make tgz release on RubyForge
153
+ rubyforge add_release -f -n $(release_notes) -a $(release_changes) \
154
+ $(rfproject) $(rfpackage) $(VERSION) $(pkggem)
155
+ # push gem to Gemcutter
156
+ gem push $(pkggem)
157
+ # in case of gem downloads from RubyForge releases page
158
+ -rubyforge add_file \
159
+ $(rfproject) $(rfpackage) $(VERSION) $(pkggem)
160
+ else
161
+ gem install-gem: GIT-VERSION-FILE
162
+ $(MAKE) $@ VERSION=$(GIT_VERSION)
163
+ endif
164
+
165
+ all:: test
166
+ test:
167
+ $(MAKE) -C t
168
+
169
+ .PHONY: .FORCE-GIT-VERSION-FILE doc manifest man test
data/LICENSE ADDED
@@ -0,0 +1,55 @@
1
+ Zbatery is copyrighted Free Software by all contributors, see the
2
+ logs in revision control for all of them. You can redistribute it
3
+ and/or modify it under either the terms of the
4
+ {GPL2}[http://www.gnu.org/licenses/gpl-2.0.txt] (see link:COPYING) or
5
+ the conditions below:
6
+
7
+ 1. You may make and give away verbatim copies of the source form of the
8
+ software without restriction, provided that you duplicate all of the
9
+ original copyright notices and associated disclaimers.
10
+
11
+ 2. You may modify your copy of the software in any way, provided that
12
+ you do at least ONE of the following:
13
+
14
+ a) place your modifications in the Public Domain or otherwise make them
15
+ Freely Available, such as by posting said modifications to Usenet or an
16
+ equivalent medium, or by allowing the author to include your
17
+ modifications in the software.
18
+
19
+ b) use the modified software only within your corporation or
20
+ organization.
21
+
22
+ c) rename any non-standard executables so the names do not conflict with
23
+ standard executables, which must also be provided.
24
+
25
+ d) make other distribution arrangements with the author.
26
+
27
+ 3. You may distribute the software in object code or executable
28
+ form, provided that you do at least ONE of the following:
29
+
30
+ a) distribute the executables and library files of the software,
31
+ together with instructions (in the manual page or equivalent) on where
32
+ to get the original distribution.
33
+
34
+ b) accompany the distribution with the machine-readable source of the
35
+ software.
36
+
37
+ c) give non-standard executables non-standard names, with
38
+ instructions on where to get the original software distribution.
39
+
40
+ d) make other distribution arrangements with the author.
41
+
42
+ 4. You may modify and include the part of the software into any other
43
+ software (possibly commercial). But some files in the distribution
44
+ are not written by the author, so that they are not under this terms.
45
+
46
+ 5. The scripts and library files supplied as input to or produced as
47
+ output from the software do not automatically fall under the
48
+ copyright of the software, but belong to whomever generated them,
49
+ and may be sold commercially, and may be aggregated with this
50
+ software.
51
+
52
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
53
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
54
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
55
+ PURPOSE.
data/NEWS ADDED
@@ -0,0 +1,4 @@
1
+ === 0.0.0 / 2009-12-10 08:49 UTC
2
+
3
+ Initial release of Rainbows! without fork()
4
+
data/README ADDED
@@ -0,0 +1,130 @@
1
+ = Zbatery: Rack HTTP server without a fork stuck in it
2
+
3
+ Zbatery is an HTTP server for Rack applications on systems that either
4
+ do not support fork(), or have no memory (nor need) to run the
5
+ master/worker model. It is based on Rainbows! (which is based on
6
+ Unicorn (which is based on Mongrel)) and inherits parts of each.
7
+ Zbatery supports your choice of all the thread/fiber/event/actor-based
8
+ concurrency models and Rack middleware that Rainbows! supports (or will
9
+ ever support) in a single process.
10
+
11
+ Zbatery will still exploit certain features of Unix for transparent
12
+ upgrades, log reopening, and graceful stops, but does not rely on them
13
+ for basic functionality.
14
+
15
+ == Features
16
+
17
+ * Designed for {Rack}[http://rack.rubyforge.org/], the standard for
18
+ modern Ruby HTTP applications.
19
+
20
+ * Configuration files are compatible with Rainbows!, a superset
21
+ of the Unicorn
22
+ {DSL}[http://unicorn.bogomips.org/Unicorn/Configurator.html].
23
+
24
+ * Inherits all features and concurrency models Rainbows! supports
25
+ (and ever will support): http://rainbows.rubyforge.org/Summary.html
26
+
27
+ * -Untested- Works under operating systems that don't support signals,
28
+ pipe and fork(). Unicorn 0.95.2+ has rake-compiler support, so
29
+ compiling the HTTP parser should be easier at least.
30
+
31
+ * -Untested- HTML 5 Web Sockets support
32
+
33
+ == License
34
+
35
+ Zbatery is copyright 2009 by all contributors (see logs in git).
36
+ It is ultimately based on Mongrel and carries the same license.
37
+
38
+ Mongrel is copyright 2007 Zed A. Shaw and contributors. It is licensed
39
+ under the Ruby license and the GPL2. See the included LICENSE file for
40
+ details.
41
+
42
+ Zbatery is 100% Free Software.
43
+
44
+ == Install
45
+
46
+ You may download the tarball from the Rainbows project page on Rubyforge
47
+ and run setup.rb after unpacking it:
48
+
49
+ http://rubyforge.org/frs/?group_id=8977
50
+
51
+ You may also install it via RubyGems on Gemcutter:
52
+
53
+ gem install zbatery
54
+
55
+ == Usage
56
+
57
+ === for Rack applications
58
+
59
+ In APP_ROOT (where config.ru is located), run:
60
+
61
+ zbatery
62
+
63
+ Zbatery will bind to all interfaces on TCP port 8080 by default.
64
+
65
+ === Configuration File(s)
66
+
67
+ Zbatery will look for the config.ru file used by rackup in APP_ROOT.
68
+
69
+ For deployments, it can use a config file for Unicorn and
70
+ Rainbows!-specific options specified by the +--config-file/-c+
71
+ command-line switch. Zbatery accepts all options found in
72
+ {Unicorn::Configurator}[http://unicorn.bogomips.org/Unicorn/Configurator.html]
73
+ as well as the "Rainbows!" block, so you can have the following in your
74
+ config file:
75
+
76
+ Rainbows! do
77
+ use :FiberSpawn
78
+ worker_connections 400
79
+ end
80
+
81
+ See the Rainbows! configuration
82
+ {documentation}[http://rainbows.rubyforge.org/Rainbows.html#M000001]
83
+ for more details.
84
+
85
+ == Disclaimer
86
+
87
+ There is NO WARRANTY whatsoever if anything goes wrong, but let us know
88
+ and we'll try our best to fix it.
89
+
90
+ This project may be temporary and may eventually have its name encoded
91
+ with uncrackable ROT13 encryption leaving you with no way to upgrade.
92
+
93
+ == Development
94
+
95
+ Most of the work is done in Rainbows!, Zbatery is just a shim to
96
+ allow access to Rainbows! without requiring fork() or signals.
97
+
98
+ You can get the latest source via git from the following locations:
99
+
100
+ git://git.bogomips.org/zbatery.git
101
+ git://repo.or.cz/zbatery.git (mirror)
102
+
103
+ You may browse the code from the web and download the latest snapshot
104
+ tarballs here:
105
+
106
+ * http://git.bogomips.org/cgit/zbatery.git (cgit)
107
+ * http://repo.or.cz/w/zbatery.git (gitweb)
108
+
109
+ Inline patches (from "git format-patch") to the mailing list are
110
+ preferred because they allow code review and comments in the reply to
111
+ the patch.
112
+
113
+ We will adhere to mostly the same conventions for patch submissions as
114
+ git itself. See the Documentation/SubmittingPatches document
115
+ distributed with git on on patch submission guidelines to follow. Just
116
+ don't email the git mailing list or maintainer with Zbatery patches.
117
+
118
+ == Tests
119
+
120
+ There currently are no tests specific to Zbatery. Keep in mind that
121
+ Zbatery is only a small shim to drive Rainbows! (and Unicorn)
122
+ underneath. Rainbows! and Unicorn both have extensive (but very
123
+ UNIX-specific) test suites.
124
+
125
+ == Contact
126
+
127
+ All feedback (bug reports, user/development dicussion, patches, pull
128
+ requests) go to the mailing list/newsgroup. We are currently
129
+ borrowing the Rainbows! mailing list since most of our code (and
130
+ problems) are related to Rainbows! mailto:rainbows-talk@rubyforge.org.
data/Rakefile ADDED
@@ -0,0 +1,158 @@
1
+ # -*- encoding: binary -*-
2
+
3
+ # most tasks are in the GNUmakefile which offers better parallelism
4
+
5
+ def tags
6
+ timefmt = '%Y-%m-%dT%H:%M:%SZ'
7
+ @tags ||= `git tag -l`.split(/\n/).map do |tag|
8
+ if %r{\Av[\d\.]+\z} =~ tag
9
+ header, subject, body = `git cat-file tag #{tag}`.split(/\n\n/, 3)
10
+ header = header.split(/\n/)
11
+ tagger = header.grep(/\Atagger /).first
12
+ body ||= "initial"
13
+ {
14
+ :time => Time.at(tagger.split(/ /)[-2].to_i).utc.strftime(timefmt),
15
+ :tagger_name => %r{^tagger ([^<]+)}.match(tagger)[1].strip,
16
+ :tagger_email => %r{<([^>]+)>}.match(tagger)[1].strip,
17
+ :id => `git rev-parse refs/tags/#{tag}`.chomp!,
18
+ :tag => tag,
19
+ :subject => subject,
20
+ :body => body,
21
+ }
22
+ end
23
+ end.compact.sort { |a,b| b[:time] <=> a[:time] }
24
+ end
25
+
26
+ cgit_url = "http://git.bogomips.org/cgit/zbatery.git"
27
+ git_url = ENV['GIT_URL'] || 'git://git.bogomips.org/zbatery.git'
28
+
29
+ desc 'prints news as an Atom feed'
30
+ task :news_atom do
31
+ require 'nokogiri'
32
+ new_tags = tags[0,10]
33
+ puts(Nokogiri::XML::Builder.new do
34
+ feed :xmlns => "http://www.w3.org/2005/Atom" do
35
+ id! "http://zbatery.bogomip.org/NEWS.atom.xml"
36
+ title "Zbatery news"
37
+ subtitle "HTTP server without a fork stuck in it"
38
+ link! :rel => 'alternate', :type => 'text/html',
39
+ :href => 'http://zbatery.bogomip.org/NEWS.html'
40
+ updated(new_tags.empty? ? "1970-01-01T00:00:00Z" : new_tags.first[:time])
41
+ new_tags.each do |tag|
42
+ entry do
43
+ title tag[:subject]
44
+ updated tag[:time]
45
+ published tag[:time]
46
+ author {
47
+ name tag[:tagger_name]
48
+ email tag[:tagger_email]
49
+ }
50
+ url = "#{cgit_url}/tag/?id=#{tag[:tag]}"
51
+ link! :rel => "alternate", :type => "text/html", :href =>url
52
+ id! url
53
+ message_only = tag[:body].split(/\n.+\(\d+\):\n {6}/s).first.strip
54
+ content({:type =>:text}, message_only)
55
+ content(:type =>:xhtml) { pre tag[:body] }
56
+ end
57
+ end
58
+ end
59
+ end.to_xml)
60
+ end
61
+
62
+ desc 'prints RDoc-formatted news'
63
+ task :news_rdoc do
64
+ tags.each do |tag|
65
+ time = tag[:time].tr!('T', ' ').gsub!(/:\d\dZ/, ' UTC')
66
+ puts "=== #{tag[:tag].sub(/^v/, '')} / #{time}"
67
+ puts ""
68
+
69
+ body = tag[:body]
70
+ puts tag[:body].gsub(/^/sm, " ").gsub(/[ \t]+$/sm, "")
71
+ puts ""
72
+ end
73
+ end
74
+
75
+ desc "print release changelog for Rubyforge"
76
+ task :release_changes do
77
+ version = ENV['VERSION'] or abort "VERSION= needed"
78
+ version = "v#{version}"
79
+ vtags = tags.map { |tag| tag[:tag] =~ /\Av/ and tag[:tag] }.sort
80
+ prev = vtags[vtags.index(version) - 1]
81
+ if prev
82
+ system('git', 'diff', '--stat', prev, version) or abort $?
83
+ puts ""
84
+ system('git', 'log', "#{prev}..#{version}") or abort $?
85
+ else
86
+ system('git', 'log', version) or abort $?
87
+ end
88
+ end
89
+
90
+ desc "print release notes for Rubyforge"
91
+ task :release_notes do
92
+ require 'rubygems'
93
+
94
+ spec = Gem::Specification.load('zbatery.gemspec')
95
+ puts spec.description.strip
96
+ puts ""
97
+ puts "* #{spec.homepage}"
98
+ puts "* #{spec.email}"
99
+ puts "* #{git_url}"
100
+
101
+ _, _, body = `git cat-file tag v#{spec.version}`.split(/\n\n/, 3)
102
+ print "\nChanges:\n\n"
103
+ puts body
104
+ end
105
+
106
+ desc "read news article from STDIN and post to rubyforge"
107
+ task :publish_news do
108
+ require 'rubyforge'
109
+ IO.select([STDIN], nil, nil, 1) or abort "E: news must be read from stdin"
110
+ msg = STDIN.readlines
111
+ subject = msg.shift
112
+ blank = msg.shift
113
+ blank == "\n" or abort "no newline after subject!"
114
+ subject.strip!
115
+ body = msg.join("").strip!
116
+
117
+ rf = RubyForge.new.configure
118
+ rf.login
119
+ rf.post_news('rainbows', subject, body)
120
+ end
121
+
122
+ desc "post to RAA"
123
+ task :raa_update do
124
+ require 'rubygems'
125
+ require 'net/http'
126
+ require 'net/netrc'
127
+ rc = Net::Netrc.locate('zbatery-raa') or abort "~/.netrc not found"
128
+ password = rc.password
129
+
130
+ s = Gem::Specification.load('zbatery.gemspec')
131
+ desc = [ s.description.strip ]
132
+ desc << ""
133
+ desc << "* #{s.email}"
134
+ desc << "* #{git_url}"
135
+ desc << "* #{cgit_url}"
136
+ desc = desc.join("\n")
137
+ uri = URI.parse('http://raa.ruby-lang.org/regist.rhtml')
138
+ form = {
139
+ :name => s.name,
140
+ :short_description => s.summary,
141
+ :version => s.version.to_s,
142
+ :status => 'experimental',
143
+ :owner => s.authors.first,
144
+ :email => s.email,
145
+ :category_major => 'Library',
146
+ :category_minor => 'Web',
147
+ :url => s.homepage,
148
+ :download => "http://rubyforge.org/frs/?group_id=8977",
149
+ :license => "Ruby's",
150
+ :description_style => 'Plain',
151
+ :description => desc,
152
+ :pass => password,
153
+ :submit => "Update",
154
+ }
155
+ res = Net::HTTP.post_form(uri, form)
156
+ p res
157
+ puts res.body
158
+ end
data/bin/zbatery ADDED
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/ruby
2
+ # -*- encoding: binary -*-
3
+ require 'unicorn/launcher'
4
+ require 'zbatery'
5
+ require 'optparse'
6
+
7
+ ENV["RACK_ENV"] ||= "development"
8
+ daemonize = false
9
+ listeners = []
10
+ options = { :listeners => listeners }
11
+ host, port = Unicorn::Const::DEFAULT_HOST, Unicorn::Const::DEFAULT_PORT
12
+ set_listener = false
13
+
14
+ opts = OptionParser.new("", 24, ' ') do |opts|
15
+ opts.banner = "Usage: #{File.basename($0)} " \
16
+ "[ruby options] [zbatery options] [rackup config file]"
17
+
18
+ opts.separator "Ruby options:"
19
+
20
+ lineno = 1
21
+ opts.on("-e", "--eval LINE", "evaluate a LINE of code") do |line|
22
+ eval line, TOPLEVEL_BINDING, "-e", lineno
23
+ lineno += 1
24
+ end
25
+
26
+ opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") do
27
+ $DEBUG = true
28
+ end
29
+
30
+ opts.on("-w", "--warn", "turn warnings on for your script") do
31
+ $-w = true
32
+ end
33
+
34
+ opts.on("-I", "--include PATH",
35
+ "specify $LOAD_PATH (may be used more than once)") do |path|
36
+ $LOAD_PATH.unshift(*path.split(/:/))
37
+ end
38
+
39
+ opts.on("-r", "--require LIBRARY",
40
+ "require the library, before executing your script") do |library|
41
+ require library
42
+ end
43
+
44
+ opts.separator "Zbatery options:"
45
+
46
+ # some of these switches exist for rackup command-line compatibility,
47
+
48
+ opts.on("-o", "--host HOST",
49
+ "listen on HOST (default: #{Unicorn::Const::DEFAULT_HOST})") do |h|
50
+ host = h
51
+ set_listener = true
52
+ end
53
+
54
+ opts.on("-p", "--port PORT",
55
+ "use PORT (default: #{Unicorn::Const::DEFAULT_PORT})") do |p|
56
+ port = p.to_i
57
+ set_listener = true
58
+ end
59
+
60
+ opts.on("-E", "--env ENVIRONMENT",
61
+ "use ENVIRONMENT for defaults (default: development)") do |e|
62
+ ENV["RACK_ENV"] = e
63
+ end
64
+
65
+ opts.on("-D", "--daemonize", "run daemonized in the background") do |d|
66
+ daemonize = d ? true : false
67
+ end
68
+
69
+ opts.on("-P", "--pid FILE", "DEPRECATED") do |f|
70
+ warn %q{Use of --pid/-P is strongly discouraged}
71
+ warn %q{Use the 'pid' directive in the Zbatery config file instead}
72
+ options[:pid] = f
73
+ end
74
+
75
+ opts.on("-s", "--server SERVER",
76
+ "this flag only exists for compatibility") do |s|
77
+ warn "-s/--server only exists for compatibility with rackup"
78
+ end
79
+
80
+ # Zbatery/Unicorn-specific stuff
81
+ opts.on("-l", "--listen {HOST:PORT|PATH}",
82
+ "listen on HOST:PORT or PATH",
83
+ "this may be specified multiple times",
84
+ "(default: #{Unicorn::Const::DEFAULT_LISTEN})") do |address|
85
+ listeners << address
86
+ end
87
+
88
+ opts.on("-c", "--config-file FILE", "Unicorn-specific config file") do |f|
89
+ options[:config_file] = f
90
+ end
91
+
92
+ # I'm avoiding Unicorn-specific config options on the command-line.
93
+ # IMNSHO, config options on the command-line are redundant given
94
+ # config files and make things unnecessarily complicated with multiple
95
+ # places to look for a config option.
96
+
97
+ opts.separator "Common options:"
98
+
99
+ opts.on_tail("-h", "--help", "Show this message") do
100
+ puts opts.to_s.gsub(/^.*DEPRECATED.*$/s, '')
101
+ exit
102
+ end
103
+
104
+ opts.on_tail("-v", "--version", "Show version") do
105
+ puts "zbatery v#{Zbatery::VERSION}"
106
+ exit
107
+ end
108
+
109
+ opts.parse! ARGV
110
+ end
111
+
112
+ config = ARGV[0] || "config.ru"
113
+ abort "configuration file #{config} not found" unless File.exist?(config)
114
+
115
+ if config =~ /\.ru$/
116
+ # parse embedded command-line options in config.ru comments
117
+ if File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) } =~ /^#\\(.*)/
118
+ opts.parse! $1.split(/\s+/)
119
+ end
120
+ end
121
+
122
+ require 'pp' if $DEBUG
123
+
124
+ app = lambda do ||
125
+ # require Rack as late as possible in case $LOAD_PATH is modified
126
+ # in config.ru or command-line
127
+ inner_app = case config
128
+ when /\.ru$/
129
+ raw = File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) }
130
+ raw.sub!(/^__END__\n.*/, '')
131
+ eval("Rack::Builder.new {(#{raw}\n)}.to_app", nil, config)
132
+ else
133
+ require config
134
+ Object.const_get(File.basename(config, '.rb').capitalize)
135
+ end
136
+ pp({ :inner_app => inner_app }) if $DEBUG
137
+ case ENV["RACK_ENV"]
138
+ when "development"
139
+ Rack::Builder.new do
140
+ use Rack::CommonLogger, $stderr
141
+ use Rack::ShowExceptions
142
+ use Rack::Lint
143
+ run inner_app
144
+ end.to_app
145
+ when "deployment"
146
+ Rack::Builder.new do
147
+ use Rack::CommonLogger, $stderr
148
+ run inner_app
149
+ end.to_app
150
+ else
151
+ inner_app
152
+ end
153
+ end
154
+
155
+ listeners << "#{host}:#{port}" if set_listener
156
+
157
+ if $DEBUG
158
+ pp({
159
+ :zbatery_options => options,
160
+ :app => app,
161
+ :daemonize => daemonize,
162
+ })
163
+ end
164
+
165
+ Unicorn::Launcher.daemonize! if daemonize
166
+ Zbatery.run(app, options)