buildr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From vbo...@apache.org
Subject svn commit: r706080 - in /incubator/buildr/trunk/addon/buildr: drb.rb nailgun.rb
Date Sun, 19 Oct 2008 23:05:31 GMT
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 !@last_loaded || 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



Mime
View raw message