I saw you're going to fix the last remaining issues, but I'm going to have a look at the patch tonight. Anything that cleans up my hacks will be an improvement.

FYI, if you send patches in the future try to attach them rather than including them inline...some of us use email clients (GMail) that tend to mangle patches pretty severely.

On 4/3/06, Marc Hadley <[EMAIL PROTECTED]> wrote:
Here's a patch for Kernel#system that executes ruby scripts in the
current jruby process rather than forking a new JVM and adds support
for the multi-argument variant of Kernel#system. Its based in large
part on a patch provided by Charles.

The new code still fails one of the rubicon tests due to some shell
wildcard expansion differences that I haven't yet figured out.

Marc.

---
Marc Hadley <marc.hadley at sun.com>

Index: RubyKernel.java
*** /Users/mh124079/Development/Ruby/jruby/src/org/jruby/
RubyKernel.java Base (1.45)
--- /Users/mh124079/Development/Ruby/jruby/src/org/jruby/
RubyKernel.java Locally Modified (Based On 1.45)
***************
*** 40,46 ****
--- 40,48 ----
   import java.io.IOException;
   import java.io.InputStreamReader;
   import java.util.Iterator;
+ import java.util.Stack;
   import java.util.StringTokenizer ;
+ import java.util.Vector;
   import java.util.regex.Pattern;

   import org.jruby.ast.util.ArgsUtil;
***************
*** 686,692 ****
           StringBuffer output = new StringBuffer();
           IRuby runtime = recv.getRuntime();
           runtime.getGlobalVariables().set("$?", runtime.newFixnum(
!             runInShell(runtime, aString.toString(), output)));

           return recv.getRuntime().newString( output.toString());
       }
--- 688,694 ----
           StringBuffer output = new StringBuffer();
           IRuby runtime = recv.getRuntime();
           runtime.getGlobalVariables().set("$?", runtime.newFixnum (
!             runInShell(runtime, new IRubyObject[] {aString},
output)));

           return recv.getRuntime().newString(output.toString());
       }
***************
*** 745,770 ****
           return PATH_SEPARATORS.matcher(executable).replaceAll
(replacement) + remainder;
       }

!     private static int runInShell(IRuby runtime, String command,
StringBuffer output) {
           try {
               String shell = System.getProperty(" jruby.shell");
!             Process aProcess;
!             String shellSwitch = "-c";

!             command = repairDirSeps(command);

!             if (shell != null) {
!                 if (!shell.endsWith("sh")) {
!                     shellSwitch = "/c";
                   }
!                 aProcess = Runtime.getRuntime().exec(new String[]
{ shell, shellSwitch, command });
               } else {
!                 aProcess = Runtime.getRuntime().exec(command);
               }

               final BufferedReader reader = new BufferedReader(new
InputStreamReader(aProcess.getInputStream()));

--- 747,845 ----
           return PATH_SEPARATORS.matcher(executable).replaceAll
(replacement) + remainder;
       }

!     private static Vector parseCommandLine(IRubyObject[] rawArgs) {
!         // first parse the first element of rawArgs since this may
contain
!         // the whole command line
!         String command = rawArgs[0].toString();
!         Stack args = new Stack();
!         StringTokenizer st = new StringTokenizer(command, " ");
!         String quoteChar = null;
!
!         while ( st.hasMoreTokens()) {
!             String token = st.nextToken();
!             if (quoteChar == null) {
!                 // not currently in the middle of a quoted token
!                 if (token.startsWith ("'") || token.startsWith("\"")) {
!                     // note quote char and remove from beginning of
token
!                     quoteChar = token.substring(0, 1);
!                     token = token.substring(1);
!                 }
!                 if (quoteChar!=null && token.endsWith(quoteChar)) {
!                     // quoted token self contained, remove from end
of token
!                     token = token.substring(0, token.length()-1);
!                     quoteChar = null;
!                 }
!                 // add new token to list
!                 args.push(token);
!             } else {
!                 // in the middle of quoted token
!                 if (token.endsWith(quoteChar)) {
!                     // end of quoted token
!                     token = token.substring(0, token.length()-1);
!                     quoteChar = null;
!                 }
!                 // update token at end of list
!                 token = args.pop() + " " + token;
!                 args.push(token);
!             }
!         }
!
!         // now append the remaining raw args to the cooked arg list
!         for (int i=1;i<rawArgs.length;i++) {
!             args.push(rawArgs[i].toString());
!         }
!
!         return args;
!     }
!
!     private static int runInShell(IRuby runtime, IRubyObject[]
rawArgs, StringBuffer output) {
           try {
+             // startup scripts set jruby.shell to /bin/sh for Unix,
cmd.exe for Windows
               String shell = System.getProperty("jruby.shell ");
!             Process aProcess = null;

!             final Vector args = parseCommandLine(rawArgs);
!             String command = (String)args.get(0);

!             // this will match ruby anywhere in the path to the
command.
!             // it might be better to restrict matches to the final
token after
!             // tokenizing with '/'
!             if (command.contains("ruby") || command.endsWith(".rb")) {
!                 // use existing JRuby process to execute command
!                 Thread t = new Thread() {
!                     public void run() {
!                         try {
!                             String[] argArray = new String[ args.size
()-1];
!                             // snip off ruby or jruby command from
list of arguments
!                             args.subList(1,args.size()).toArray
(argArray);
!                             org.jruby.Main.main(argArray);
!                         } catch (Throwable t) {
                           }
!                     }
!                 };
!                 t.start();
!                 t.join ();
!             } else if (shell != null) {
!                 // execute command with sh -c or cmd.exe /c
!                 String shellSwitch = shell.endsWith("sh") ? "-c" :
"/c";
!                 String[] argArray = new String[3];
!                 argArray[0] = shell;
!                 argArray[1] = shellSwitch;
!                 StringBuffer buf = new StringBuffer();
!                 for (int i=0;i< args.size();i++) {
!                     buf.append(args.get(i));
!                     buf.append(' ');
!                 }
!                 argArray[2] = buf.toString();
!                 aProcess = Runtime.getRuntime ().exec(argArray);
               } else {
!                 // execute command directly
!                 String[] argArray = new String[args.size()];
!                 args.toArray(argArray);
!                 aProcess = Runtime.getRuntime().exec(argArray);
               }

+             if (aProcess != null) {
                   final BufferedReader reader = new BufferedReader
(new InputStreamReader(aProcess.getInputStream ()));

                   // Fairly innefficient impl, but readLine is
unable to tell
***************
*** 789,794 ****
--- 867,875 ----
                   reader.close();

                   return aProcess.waitFor();
+             } else {
+                 return 0;
+             }
           } catch (IOException e) {
               throw runtime.newIOErrorFromException(e);
           } catch (InterruptedException e) {
***************
*** 839,849 ****

       public static RubyBoolean system(IRubyObject recv, IRubyObject
[] args) {
           IRuby runtime = recv.getRuntime();
-         if (args.length > 1) {
-             throw runtime.newArgumentError("more arguments not yet
supported");
-         }
           StringBuffer output = new StringBuffer();
!         int resultCode = runInShell(runtime, args[0].toString(),
output);
           recv.getRuntime().getGlobalVariables().set("$?",
runtime.newFixnum(resultCode));
           return runtime.newBoolean(resultCode == 0);
       }
--- 920,928 ----

       public static RubyBoolean system(IRubyObject recv, IRubyObject
[] args) {
           IRuby runtime = recv.getRuntime();
           StringBuffer output = new StringBuffer();
!         int resultCode = runInShell(runtime, args, output);
!         System.out.println(output.toString ());
           recv.getRuntime().getGlobalVariables().set("$?",
runtime.newFixnum(resultCode));
           return runtime.newBoolean(resultCode == 0);
       }



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
_______________________________________________
Jruby-devel mailing list
Jruby-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jruby-devel



--
Charles Oliver Nutter @ headius.blogspot.com
JRuby Developer @ jruby.sourceforge.net
Application Architect @ www.ventera.com

Reply via email to