Author: vborja
Date: Sun Oct 19 16:05:30 2008
New Revision: 706080
URL: http://svn.apache.org/viewvc?rev=706080&view=rev
Log:
Simplified Nailgun a LOT by using the DRbApplication module defined on
buildr/drb.
Now there's no more need for application_cli.rb
Added:
incubator/buildr/trunk/addon/buildr/drb.rb (with props)
Modified:
incubator/buildr/trunk/addon/buildr/nailgun.rb
Added: incubator/buildr/trunk/addon/buildr/drb.rb
URL:
http://svn.apache.org/viewvc/incubator/buildr/trunk/addon/buildr/drb.rb?rev=706080&view=auto
==============================================================================
--- incubator/buildr/trunk/addon/buildr/drb.rb (added)
+++ incubator/buildr/trunk/addon/buildr/drb.rb Sun Oct 19 16:05:30 2008
@@ -0,0 +1,199 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with this
+# work for additional information regarding copyright ownership. The ASF
+# licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+
+require 'drb/drb'
+
+
+module Buildr
+
+ # This addon allows you start a DRb server hosting a buildfile, so that
+ # you can later invoke tasks on it without having to load
+ # the complete buildr runtime again.
+ #
+ # Usage:
+ #
+ # buildr -r buildr/drb drb:start
+ #
+ # Once the server has been started you can invoke tasks using a simple
script:
+ #
+ # #!/usr/bin/env ruby
+ # require 'rubygems'
+ # require 'buildr'
+ # require 'buildr/drb'
+ # Buildr::DRbApplication.run
+ #
+ # Save this script as 'dbuildr', make it executable and use it to invoke
tasks.
+ #
+ # dbuildr clean compile
+ #
+ # The 'dbuildr' will start the server if there isn't one already running.
+ # Subsequent calls to dbuildr will act as the client and invoke the tasks you
+ # provide to the server.
+ # If the buildfile has been modified it will be reloaded on the server app.
+ #
+ # JRuby users can use a nailgun client to invoke tasks as fast as possible
+ # without having to incur JVM startup time.
+ # See the documentation for buildr/nailgun.
+ module DRbApplication
+
+ port = ENV['DRB_PORT'] || 2111
+ PORT = port.to_i
+
+ # save the tasks,rules,layout defined by buildr
+ # based on the code from the sandbox
+ @tasks = Buildr.application.tasks.collect do |original|
+ prerequisites = original.send(:prerequisites).map(&:to_s)
+ actions = original.instance_eval { @actions }.clone
+ lambda do
+ original.class.send(:define_task, original.name=>prerequisites).tap do
|task|
+ task.comment = original.comment
+ actions.each { |action| task.enhance &action }
+ end
+ end
+ end
+ @rules = Buildr.application.instance_variable_get(:@rules)
+ @layout = Layout.default.clone
+
+ class << self
+ attr_accessor :tasks, :rules, :layout
+
+ def server_uri
+ "druby://:#{PORT}"
+ end
+
+ def client_uri
+ "druby://:#{PORT + 1}"
+ end
+
+ def run
+ begin
+ run_client
+ rescue DRb::DRbConnError
+ run_server!
+ end
+ end
+
+ def run_client
+ buildr = DRbObject.new(nil, server_uri)
+ buildr.remote_ping # test if the server is running
+ DRb.start_service(client_uri)
+ buildr.remote_run :dir => Dir.pwd,
+ :in => $stdin,
+ :out => $stdout,
+ :err => $stderr,
+ :argv => ARGV
+ end
+
+ def run_server
+ Application.module_eval { include DRbApplication }
+ DRb.start_service(server_uri, self)
+ puts "#{self} waiting on #{server_uri}"
+ end
+
+ def run_server!
+ if RUBY_PLATFORM[/java/]
+ require 'buildr/nailgun'
+ info ''
+ info 'Running in JRuby, a nailgun server will be started so that'
+ info 'you can use your nailgun client to invoke buildr tasks: '
+ info ''
+ info ' '+Nailgun.installed_bin.to_s
+ info ''
+ Buildr.application['nailgun:start'].invoke
+ else
+ run_server
+ end
+ DRb.thread.join
+ end
+
+ def with_config(remote)
+ set = lambda do |env|
+ ARGV.replace env[:argv]
+ $stdin, $stdout, $stderr = env.values_at(:in, :out, :err)
+ Buildr.application.instance_variable_set :@original_dir, env[:dir]
+ end
+ original = {
+ :dir => Buildr.application.instance_variable_get(:@original_dir),
+ :in => $stdin,
+ :out => $stdout,
+ :err => $stderr,
+ :argv => ARGV
+ }
+ begin
+ set[remote]
+ yield
+ ensure
+ set[original]
+ end
+ end
+
+ def remote_run(cfg)
+ with_config(cfg) { Buildr.application.remote_run }
+ rescue => e
+ puts e
+ end
+
+ end # class << DRbApplication
+
+ def remote_run
+ init 'Distributed Buildr'
+ if @rakefile
+ if [EMAIL PROTECTED] || buildfile.timestamp > @last_loaded
+ # buildfile updated, need to reload
+ Project.clear
+ @tasks = {}
+ DRbApplication.tasks.each { |block| block.call }
+ @rules = DRbApplication.rules.clone
+ Layout.default = DRbApplication.layout.clone
+ @last_loaded = buildfile.timestamp
+ load_buildfile
+ else
+ clear_invoked_tasks
+ end
+ else
+ load_buildfile
+ @last_loaded = buildfile.timestamp
+ end
+ top_level
+ end
+
+ def clear_invoked_tasks
+ lookup('buildr:initialize').instance_eval do
+ @already_invoked = true
+ @actions = []
+ end
+ projects = Project.instance_variable_get(:@projects) || {}
+ @tasks.each_pair do |name, task|
+ is_project = projects.key?(task.name)
+ task.instance_variable_set(:@already_invoked, false) unless is_project
+ end
+ end
+
+ drb_tasks = lambda do
+ task('start') { run_server! }
+ end
+
+ if Buildr.respond_to?(:application)
+ Buildr.application.instance_eval do
+ @rakefile = "" unless @rakefile
+ in_namespace(:drb, &drb_tasks)
+ end
+ end
+
+ end # DRbApplication
+
+end
+
Propchange: incubator/buildr/trunk/addon/buildr/drb.rb
------------------------------------------------------------------------------
svn:executable = *
Modified: incubator/buildr/trunk/addon/buildr/nailgun.rb
URL:
http://svn.apache.org/viewvc/incubator/buildr/trunk/addon/buildr/nailgun.rb?rev=706080&r1=706079&r2=706080&view=diff
==============================================================================
--- incubator/buildr/trunk/addon/buildr/nailgun.rb (original)
+++ incubator/buildr/trunk/addon/buildr/nailgun.rb Sun Oct 19 16:05:30 2008
@@ -13,104 +13,38 @@
# License for the specific language governing permissions and limitations under
# the License.
-require 'benchmark'
+
require 'jruby'
-require 'monitor'
-require 'ostruct'
require 'rbconfig'
-require 'thread'
-require 'buildr/core/application_cli'
-require 'tempfile'
+require 'buildr/drb'
-module Buildr #:nodoc:
+module Buildr
+
+ # This addon is provided for fast interaction with a DRb BuildrServer
(buildr/drb).
+ #
+ # This module delegates task invocation to the BuildrServer, it only
implements
+ # nailgun required logic (server/client).
+ #
+ # Usage:
+ #
+ # buildr -r buildr/nailgun nailgun:start
+ #
+ # Once the server has been started you can invoke tasks using the nailgun
client
+ # installed on $JRUBY_HOME/tool/nailgun. It's recommended to add this path
to
+ # your PATH environment variable, so that the ng command is available at any
dir.
+ #
+ # ng build # invoke the build task
+ #
module Nailgun
-
extend self
-
- attr_reader :ng
- @ng ||= OpenStruct.new
VERSION = '0.7.1'
NAME = "nailgun-#{VERSION}"
URL = "http://downloads.sourceforge.net/nailgun/#{NAME}.zip"
ARTIFACT_SPEC = "com.martiansoftware:nailgun:jar:#{VERSION}"
-
- # Paths used to initialize a buildr runtime
- BUILDR_PATHS = [File.expand_path('../', File.dirname(__FILE__)),
- File.expand_path('../../lib', File.dirname(__FILE__))]
-
- HELP = <<-HELP.strip.gsub(/ *\n +/, "\n ")
- NailGun is a client, protocol, and server for running Java
- programs from the command line without incurring the JVM
- startup overhead. Nailgun integration is currently available
- only when running Buildr with JRuby.
-
- Buildr provides a custom nailgun server, allowing you to
- start a single JVM and let buildr create a queue of runtimes.
- These JRuby runtimes can be cached (indexed by buildfile path)
- and are automatically reloaded when the buildfile has been modified.
- Runtime caching allows you to execute tasks without
- spending time creating the buildr environment. Some nailgun
- tasks have been provided to manage the cached runtimes.
-
- To start the buildr server execute the following task:
-
- nailgun:start
-
- Server output will display a message when it becomes ready, you
- will also see messages when the JRuby runtimes are being created,
- or when a new buildr environment is being loaded on them.
- After the runtime queues have been populated, you can start calling
- buildr as you normally do, by invoking the $NAILGUN_HOME/ng binary:
-
- # on another terminal, change directory to a project.
- # if this project is the same nailgun:start was invoked on, it's
- # runtime has been cached, so no loading is performed unless
- # the buildfile has been modified. otherwise the buildfile
- # will be loaded on a previously loaded fresh-buildr runtime
- # and it will be cached.
- cd /some/buildr/project
- ng nailgun:help # display nailgun help
- ng nailgun:tasks # display overview of ng tasks
- ng clean compile # just invoke those two tasks
-
- Configuration and Environment Variables.
-
- Before starting the server, buildr will check if you have
- nailgun already installed by seeking the nailgun jar under
-
- $NAILGUN_HOME
-
- You can override this environment variable to tell buildr where
- to find or where to install nailgun. If missing, NAILGUN_HOME
- defaults to the $JRUBY_HOME/tool/nailgun directory.
-
- Buildr will also check that the nailgun client binary (ng.exe for
- Windows systems, ng otherwise) is installed on NAILGUN_HOME.
- If no binary is found, buildr will download nailgun and
- compile+install it.
-
- The buildr server binds itself to localhost, port 2113. You can
- override this when starting the nailgun server:
-
- buildr nailgun:start[4444,127.0.0.1]
-
- If you provided custom host/port settings you need
- to tell the nailgun client where to connect:
-
- ng --nailgun-server 127.0.0.1 --nailgun-port 4444 nailgun:tasks
-
- The buildr server starts a RuntimeFactory responsible for providing
- a pool of preloaded Buildr runtimes ready for task execution.
- You can provide a third argument to the nailgun:start task, to set
- the buildr queue size. You may want to increase this value if you
- need to load many buildfiles on the same server.
-
- Execute nailgun:tasks get an overview of available nailgun tasks.
- HELP
-
- private
+ PORT = DRbApplication::PORT + 2
+ ADDON_BIN = File.dirname(__FILE__)
# Returns the path to JRUBY_HOME.
def jruby_home
@@ -126,152 +60,9 @@
File.join(Dir.tmpdir, 'nailgun', *paths)
end
- file_tasks = lambda do
-
- dist_zip = Buildr.download(tmp_path(NAME + '.zip') => URL)
- dist_dir = Buildr.unzip(tmp_path(NAME) => dist_zip)
-
- nailgun_jar = file(tmp_path(NAME, NAME, NAME + '.jar'))
- ng.artifact = Buildr.artifact(ARTIFACT_SPEC).from(nailgun_jar)
- unless File.exist?(nailgun_jar.to_s)
- nailgun_jar.enhance [dist_dir]
- end
-
- compiled_bin = file(tmp_path(NAME, NAME, 'ng' +
Config::CONFIG['EXEEXT']) => dist_dir.target) do |task|
- unless task.to_s.pathmap('%x') == '.exe'
- Dir.chdir(task.to_s.pathmap('%d')) do
- info "Compiling #{task.to_s}"
- system('make', task.to_s.pathmap('%f')) or
- fail "Nailgun binary compilation failed."
- end
- end
- end
-
- ng.installed_bin =
file(File.expand_path(compiled_bin.to_s.pathmap('%f'), nailgun_home) =>
compiled_bin) do |task|
- mkpath task.to_s.pathmap('%d'), :verbose => false
- cp compiled_bin.to_s, task.to_s, :verbose => false
- end
-
- end # file_tasks
-
- server_tasks = lambda do
-
- desc 'Start the nailgun server'
- task('start', :port, :iface, :queue_size) do |task, args|
-
- [ng.installed_bin, ng.artifact].map(&:invoke)
-
- iface = args[:iface].to_s.empty? ? '127.0.0.1' : args[:iface]
- port = args[:port].to_s.empty? ? 2113 : args[:port].to_i
- queue_size = args[:queue_size].to_s.empty? ? 3 : args[:queue_size].to_i
-
- fail "Already running on Nailgun server: #{ng.server || ng.nail}" if
ng.server || ng.client
-
- info 'Booting Buildr nailgun server...'
- top_level = Buildr.application.instance_eval { @top_level_tasks.dup }
- top_level.delete_if { |t| t[/nailgun/] }
- unless top_level.empty?
- raise 'Don\'t specify more targets when starting Nailgun server:
#{top_level}'
- end
- ng.server_setup.call
-
- factory = RuntimeFactory.new(queue_size, queue_size)
- ng.server = NGServer.new(iface, port, factory)
-
- ng.server.start
- end
-
- desc 'Show nailgun help'
- task('help') do
- info HELP
- exit(0)
- end
-
- desc 'List nailgun tasks'
- task('tasks') do
- task_hash = Buildr.application.instance_variable_get(:@tasks)
- tasks = task_hash.keys.select { |k| k =~ /^nailgun:/ }
- width = [tasks.map { |t| task_hash[t].name_with_args.size },
20].flatten.max
- tasks.each do |name|
- task = task_hash[name]
- title = task.name_with_args
- comment = task.full_comment
- info comment.empty? ? title : (" %-#{width}s # %s" % [title,
comment])
- end
- exit(0)
- end
-
- desc 'List currently cached runtimes'
- task('list') do
- if Nailgun.ng.server
- Nailgun.ng.server.cached_stamps.each_pair do |bf, time|
- loaded = Nailgun.ng.server.loaded_times[bf]
- ary = [bf, "Load Timestamp", loaded, "Modification Timestamp",
time]
- info("* %s\n %-25s %s\n %-25s %s\n\n" % ary)
- end
- else
- info "Not running on nailgun server"
- end
- exit(0)
- end
-
- desc 'Remove all cached runtimes'
- task('clear') do
- if Nailgun.ng.server
- Nailgun.ng.server.cached_runtimes.clear
- Nailgun.ng.server.cached_stamps.clear
- Nailgun.ng.server.loaded_times.clear
- info "Cleared all cached runtimes"
- else
- info "Not running on nailgun server"
- end
- exit(0)
- end
-
- desc 'Remove runtime for this buildfile'
- task('delete', :buildfile) do |task, args|
- if Nailgun.ng.server
- if args[:buildfile]
- buildfile = File.expand_path(args[:buildfile])
- else
- buildfile = Buildr.application.buildfile.to_s
- end
- Nailgun.ng.server.cached_runtimes.delete(buildfile)
- Nailgun.ng.server.cached_stamps.delete(buildfile)
- Nailgun.ng.server.loaded_times.delete(buildfile)
- info "Deleted #{buildfile} from runtime cache"
- else
- info "Not running on nailgun server"
- end
- exit(0)
- end
-
- end # server_tasks
-
- # Load java classes on server side.
- ng.server_setup = lambda do
-
- module Util
- include Buildr::Util
- end
-
- Util.add_to_sysloader ng.artifact.to_s
- Util.add_to_sysloader File.dirname(__FILE__)
-
- class NGClient
- include org.apache.buildr.BuildrNail
- include Client
- end
-
- class NGServer < com.martiansoftware.nailgun.NGServer
- include Server
- end
-
- end # server_setup
-
module Util
extend self
-
+
def add_to_sysloader(path)
sysloader = java.lang.ClassLoader.getSystemClassLoader
add_url_method = java.lang.Class.forName('java.net.URLClassLoader').
@@ -280,43 +71,6 @@
add_url_method.invoke(sysloader,
[java.io.File.new(path).toURI.toURL].to_java(java.net.URL))
end
- def benchmark(action = ['Completed'], verbose = true)
- result = nil
- times = Benchmark.measure do
- result = yield(action)
- end
- if verbose
- real = []
- real << ("%ih" % (times.real / 3600)) if times.real >= 3600
- real << ("%im" % ((times.real / 60) % 60)) if times.real >= 60
- real << ("%.3fs" % (times.real % 60))
- trace "#{[action].flatten.join(' ')} in #{real.join}"
- end
- result
- end
-
- def find_file(pwd, candidates, nosearch=false)
- candidates = [candidates].flatten
- buildfile = candidates.find { |c| File.file?(File.expand_path(c, pwd))
}
- return File.expand_path(buildfile, pwd) if buildfile
- return nil if nosearch
- updir = File.dirname(pwd)
- return nil if File.expand_path(updir) == File.expand_path(pwd)
- find_file(updir, candidates)
- end
-
- def exception_handling(raise_again = true, show_error = true)
- begin
- yield
- rescue => e
- if show_error
- error "#{e.backtrace.shift}: #{e.message}"
- e.backtrace.each { |i| error "\tfrom #{i}" }
- end
- raise if raise_again
- end
- end
-
# invoke a java constructor
def ctor(on_class, *args)
parameters = []
@@ -342,300 +96,36 @@
ctor.newInstance(parameters.to_java(java.lang.Object))
end
- def on_runtime(runtime, *args, &block)
- raise_error = lambda do |cls, msg, trace|
- raise RuntimeError.new(cls + ": "+ msg.to_s).tap { |e|
e.set_backtrace(trace.map(&:to_s)) }
- end
- executor = runtime.object.const_get(:Module).new do
- extend self
- def runtime_exec(*args, &prc)
- define_method(:runtime_exec, &prc)
- runtime_exec(*args)
- rescue => e
- [:error, e.class.name, e.message, e.backtrace]
- end
- end
- result = executor.runtime_exec(*args, &block)
- raise_error.call(*result[1..-1]) if result.kind_of?(Array) &&
result.first == :error
- result
- end
-
- def set_stdio(runtime, dev)
- set_global = lambda do |global, constant, stream|
- runtime.global_variables.set(global, stream)
- runtime.object.send(:remove_const, constant)
- runtime.object.send(:const_set, constant, stream)
- end
- stdin = runtime.global_variables.get('$stdin')
- stdout = runtime.global_variables.get('$stdout')
- stderr = runtime.global_variables.get('$stderr')
- #stdin.close; stdout.close; stderr.close;
- output = Util.ctor(org.jruby.RubyIO, runtime, java.io.OutputStream =>
dev.out)
- error = Util.ctor(org.jruby.RubyIO, runtime, java.io.OutputStream =>
dev.err)
- input = Util.ctor(org.jruby.RubyIO, runtime, java.io.InputStream =>
dev.in)
- #stdin.reopen(input, 'r') # not working on jruby, :(
- #stdout.reopen(output, 'w')
- #stderr.reopen(error, 'w')
- set_global.call('$stdin', 'STDIN', input)
- set_global.call('$stdout', 'STDOUT', output)
- set_global.call('$stderr', 'STDERR', error)
- end
-
- end # module Util
-
- class FieldAccessor
- def initialize(obj, clazz = nil)
- @obj = obj
- clazz ||= obj.class
- @cls = [clazz.java_class].to_java(java.lang.Class)[0]
- end
-
- def [](name)
- field = @cls.getDeclaredField(name.to_s)
- field.setAccessible(true)
- field.get(@obj)
- end
-
- def []=(name, value)
- field = @cls.getDeclaredField(name.to_s)
- field.setAccessible(true)
- field.set(@obj, value)
- end
-
- def method_missing(name, value =nil)
- if name.to_s =~ /=$/
- self[name.to_s.chomp('=')] = value
- else
- self[name]
- end
- end
- end
-
- module NailMethods
-
- def self.extend_object(obj)
- super
- (class << obj; self; end).module_eval do
- alias_method :pwd, :getWorkingDirectory
- alias_method :server, :getNGServer
- end
- end
-
- def argv
- [command] + args
- end
-
- def attach_runtime(runtime)
- runtime.extend RuntimeMixin
- runtime.evalScriptlet %q{
- require 'ostruct'
- module Buildr
- module Nailgun
- extend self
- attr_reader :ng
- @ng = OpenStruct.new
- end
- end
- }
- runtime.Buildr::Nailgun.ng.nail = self
- runtime.load_service.require __FILE__
- runtime
- end
- private :attach_runtime
-
- def jruby
- @jruby ||= server.runtime_factory.new_jruby.tap do |runtime|
- attach_runtime(runtime)
- end
- end
-
- def buildr
- @buildr ||= server.runtime_factory.new_buildr.tap do |runtime|
- attach_runtime(runtime)
- end
- end
-
- def options
- @options ||= OpenStruct.new
- end
-
- end # NailMethods
-
- module RuntimeMixin
- def Buildr
- object.const_get(:Buildr)
- end
- end
-
- module AppMixin
- def load_tasks
- trace "Not loading tasks again"
- end
-
- def load_buildfile
- trace "Not loading buildfile again"
- end
- end
+ end # Util
module Client
- class << self
- include Buildr::CommandLineInterface
-
- def options
- Nailgun.ng.nail.options
- end
-
- def rakefiles
- Nailgun.ng.nail.options.rakefiles
- end
-
- def requires
- Nailgun.ng.nail.options.requires
- end
-
- def help
- super
- puts
- puts 'To get a summary of Nailgun features use'
- puts ' nailgun:help'
- end
-
- def version
- puts super
- end
+ def main(nail)
+ nail.out.println "Connected to #{nail.getNGServer}"
- def do_option(opt, value)
- case opt
- when '--help'
- options.exit = :help
- when '--version'
- options.exit = :version
- when '--nosearch'
- options.nosearch = true
- else
- super
- end
- end
+ runtime = JRuby.runtime
- def sBuildr
- Nailgun.ng.nail.server.runtime.object.const_get(:Buildr)
- end
+ stdout = Util.ctor(org.jruby.RubyIO, runtime, java.io.OutputStream =>
nail.out)
+ stderr = Util.ctor(org.jruby.RubyIO, runtime, java.io.OutputStream =>
nail.err)
+ stdin = Util.ctor(org.jruby.RubyIO, runtime, java.io.InputStream =>
nail.in)
- def attach_runtime
- nail = Nailgun.ng.nail
- ARGV.replace nail.argv
- Dir.chdir nail.pwd
- nail.env.each { |k, v| ENV[k.to_s] = v.to_s }
-
- Buildr.const_set(:VERSION, sBuildr::VERSION) unless
Buildr.const_defined?(:VERSION)
- nail.options.rakefiles = sBuildr::Application::DEFAULT_BUILDFILES.dup
- nail.options.requires = []
- end
+ dir = nail.getWorkingDirectory
+ argv = [nail.command] + nail.args
- def client(runtime, nail, &block)
- Util.set_stdio(runtime, nail)
- nailgun_module = runtime.Buildr::Nailgun
- nailgun_module.ng.nail = nail
- nailgun_module::Client.attach_runtime
- nailgun_module::Client.instance_eval(&block)
- end
- end
-
- def main(nail)
- nail.extend NailMethods
- info "Got connection from #{nail.pwd}"
-
- Client.client(nail.jruby, nail) do
-
- parse_options
- if options.exit
- send(options.exit)
- nail.exit(0)
- end
-
- if options.project && File.directory?(options.project)
- Dir.chdir(options.project)
- end
-
- bf = Util.find_file(Dir.pwd, options.rakefiles, options.nosearch)
- unless bf
- nail.out.println "No buildfile found at #{Dir.pwd}"
- nail.exit(0)
- end
-
- rt = nail.server.cached_runtimes[bf]
- old_stamp = nail.server.cached_stamps[bf] || Rake::EARLY
- new_stamp = rt ? rt.Buildr.application.buildfile.timestamp :
Rake::EARLY
-
- if rt.nil? || new_stamp > old_stamp
- rt = nail.buildr
- app = rt.Buildr.application
- app.instance_variable_set(:@rakefile, bf)
- nail.out.println "Currently nailgun has issues reloading
buildfiles, will get fixed in next release."
- nail.out.println "Restart your nailgun server."
- return nail.exit(1)
- else
- app = rt.Buildr.application.extend AppMixin
- app.lookup('buildr:initialize').instance_eval do
- @already_invoked = false
- @actions = []
- end
- app.instance_eval do
- @tasks.values.each do |task|
- is_project =
rt.Buildr::Project.instance_variable_get(:@projects).key?(task.name)
- task.instance_variable_set(:@already_invoked, false) unless
is_project
- end
- end
- end
-
- app.instance_eval do
- @original_dir = nail.pwd
- end
-
- Client.client(rt, nail) do
- Util.exception_handling do
- begin
- app.parse_options
- app.collect_tasks
- app.run
- rescue SystemExit => e
- nail.exit(1)
- end
- end
- end
-
- nail.server.cache(rt, app.buildfile)
- end
+ DRbApplication.remote_run :dir => dir, :argv => argv,
+ :in => stdin, :out => stdout, :err => stderr
+ rescue => e
+ nail.err.println e unless SystemExit === e
+ nail.exit 1
end
- end # class Client
+ end # Client
module Server
-
- attr_reader :runtime_factory
- attr_reader :cached_runtimes
- attr_reader :cached_stamps
- attr_reader :loaded_times
-
- def initialize(host = 'localhost', port = 2113, buildr_factory = nil)
- super(java.net.InetAddress.get_by_name(host), port)
- @cached_runtimes = {}
- @cached_stamps = {}
- @loaded_times = {}
- cache(runtime, Buildr.application.buildfile)
- @runtime_factory = buildr_factory
- @host, @port = host, port
- end
-
- def cache(runtime, buildfile)
- cached_runtimes[buildfile.to_s] = runtime
- cached_stamps[buildfile.to_s] = buildfile.timestamp
- loaded_times[buildfile.to_s] = Time.now
- end
-
- def runtime
- JRuby.runtime.extend RuntimeMixin
+ def initialize(host, port)
+ @host = host || "*"
+ @port = port
+ super(host, port)
end
def start
@@ -643,7 +133,6 @@
NGClient::Main.nail = NGClient.new
self.default_nail_class = NGClient::Main
- runtime_factory.start
@thread = java.lang.Thread.new(self)
@thread.setName(to_s)
@@ -654,165 +143,76 @@
end
def stop
- runtime_factory.stop
@thread.kill
end
def to_s
- self.class.name+'('+[Buildr.application.version, @host, @port].join(',
')+')'
+ version = "Buildr #{Buildr::VERSION} #{RUBY_PLATFORM[/java/] &&
'(JRuby '+JRUBY_VERSION+')'}"
+ self.class.name+'('+[version, @host, @port].join(', ')+')'
end
- end # module Server
-
- class RuntimeFactory
-
- attr_accessor :buildrs_size, :jrubys_size
-
- def initialize(buildrs_size = 1, jrubys_size = nil)
- # jrubys_size ||= buildrs_size
- @buildrs_size = buildrs_size < 1 ? 1 : buildrs_size
- # @jrubys_size = jrubys_size < 1 ? 1 : jrubys_size
-
- @buildrs = [].extend(MonitorMixin)
- @buildrs_ready = @buildrs.new_cond
- @buildrs_needed = @buildrs.new_cond
-
- @buildrs_creators = [].extend(MonitorMixin)
+ end # Server
- # @jrubys = [].extend(MonitorMixin)
- # @jrubys_ready = @jrubys.new_cond
- # @jrubys_needed = @jrubys.new_cond
-
- # @jrubys_creators = [].extend(MonitorMixin)
- end
-
- def new_buildr
- get(:buildr)
+ server_setup = lambda do
+ module Util
+ include Buildr::Util
end
- def new_jruby(&block)
- # get(:jruby)
- create_jruby(0, &block)
+ Util.add_to_sysloader artifact.to_s
+ Util.add_to_sysloader ADDON_BIN
+
+ class NGClient
+ include org.apache.buildr.BuildrNail
+ include Client
end
- def start
- trace "Starting Buildr runtime factory"
- # @jruby_creator = Thread.new { loop { create :jruby } }
- # @jruby_creator.priority = -2
- @buildr_creator = Thread.new { loop { create :buildr } }
- @buildr_creator.priority = 1
- end
+ class NGServer < com.martiansoftware.nailgun.NGServer
+ include Server
+ end
+ end
- def stop
- @buildr_creator.kill if @buildr_creator
- # @jruby_creator.kill if @jruby_creator
- end
+ ng_tasks = lambda do
- private
- def get(thing)
- collection = instance_variable_get("@#{thing}s")
- needs = instance_variable_get("@#{thing}s_needed")
- ready = instance_variable_get("@#{thing}s_ready")
- result = nil
- collection.synchronize do
- if collection.empty?
- trace "no #{thing} available, ask to create more"
- needs.broadcast
- trace "should be creating #{thing}"
- ready.wait_while { collection.empty? }
- end
- trace "Getting my #{thing}"
- result = collection.shift
- trace "would need more #{thing}s"
- needs.broadcast
- trace "got my #{thing}: #{result.inspect}"
- Thread.pass
- end
- trace "returning #{result.inspect}"
- result
- end
+ dist_zip = Buildr.download(tmp_path(NAME + '.zip') => URL)
+ dist_dir = Buildr.unzip(tmp_path(NAME) => dist_zip)
+
+ nailgun_jar = file(tmp_path(NAME, NAME, NAME + '.jar'))
+ nailgun_jar.enhance [dist_dir] unless File.exist?(nailgun_jar.to_s)
- def create(thing, *args, &block)
- Util.exception_handling do
- creator = needed(thing)
- collection = instance_variable_get("@#{thing}s")
- ready = instance_variable_get("@#{thing}s_ready")
- needs = instance_variable_get("@#{thing}s_needed")
- unless creator
- collection.synchronize do
- trace "awake those wanting a #{thing}"
- ready.broadcast
- Thread.pass
- trace "wait until more #{thing}s are needed"
- # needs.wait(1); return
- needs.wait_until { creator = needed(thing) }
- end
- end
- trace "About to create #{thing} # #{creator}"
- method = "create_#{thing}"
- creators = instance_variable_get("@#{thing}s_creators")
- trace "registering creator for #{thing} #{creator}"
- creators.synchronize { creators << creator }
- result = send(method, creator, *args, &block)
- trace "created #{thing}[#{creator}] => #{result.inspect}"
- creators.synchronize do
- trace "unregistering creator for #{thing} #{creator}"
- creators.delete(creator)
- collection.synchronize do
- trace "adding object on queue for #{thing} #{creator}"
- collection << result
- end
- end
- end
- end
+ attr_reader :artifact
+ @artifact = Buildr.artifact(ARTIFACT_SPEC).from(nailgun_jar)
- def needed(thing)
- collection = instance_variable_get("@#{thing}s")
- creators = instance_variable_get("@#{thing}s_creators")
- size = instance_variable_get("@#{thing}s_size")
- collection.synchronize do
- count = collection.size
- if count < size
- count += creators.synchronize { creators.size }
+ compiled_bin = file(tmp_path(NAME, NAME, 'ng' +
Config::CONFIG['EXEEXT']) => dist_dir.target) do |task|
+ unless task.to_s.pathmap('%x') == '.exe'
+ Dir.chdir(task.to_s.pathmap('%d')) do
+ info "Compiling #{task.to_s}"
+ system('make', task.to_s.pathmap('%f')) or
+ fail "Nailgun binary compilation failed."
end
- count if count < size
end
end
-
- def create_jruby(creator, &block)
- Util.exception_handling do
- trace "Creating jruby[#{creator}]"
- Util.benchmark do |header|
- cfg = org.jruby.RubyInstanceConfig.new
- yield cfg if block_given?
- jruby = org.jruby.Ruby.newInstance(cfg)
- jruby.load_service.load_path.unshift *BUILDR_PATHS
- header.replace ["Created jruby[#{creator}]", jruby]
- jruby
- end
- end
+
+ attr_reader :installed_bin
+ @installed_bin = file(File.expand_path(compiled_bin.to_s.pathmap('%f'),
nailgun_home) => compiled_bin) do |task|
+ mkpath task.to_s.pathmap('%d'), :verbose => false
+ cp compiled_bin.to_s, task.to_s, :verbose => false
end
- def create_buildr(creator)
- Util.exception_handling do
- trace "Obtaining jruby to load buildr[#{creator}] on it"
- jruby = new_jruby
- trace "Loading buildr[#{creator}] on #{jruby} ..."
- Util.benchmark ["Loaded buildr[#{creator}] on #{jruby}"] do
- load_service = jruby.load_service
- load_service.require 'rubygems'
- load_service.require 'buildr'
- end
- jruby
- end
+ desc 'Start the nailgun server'
+ task('start' => [installed_bin, artifact]) do |task|
+ server_setup.call
+ server = NGServer.new(nil, PORT)
+ server.start
+ DRbApplication.run_server
end
-
- end # RuntimeFactory
- if Buildr.respond_to?(:application) && ng.nail.nil?
- Buildr.application.in_namespace(:nailgun, &file_tasks)
- Buildr.application.in_namespace(:nailgun, &server_tasks)
+ end # ng_tasks
+
+ if Buildr.respond_to?(:application)
+ Buildr.application.instance_eval do
+ @rakefile = "" unless @rakefile
+ in_namespace(:nailgun, &ng_tasks)
+ end
end
-
+
end # module Nailgun
-
end