# This patch file was generated by NetBeans IDE
# This patch can be applied using context Tools: Apply Diff Patch action on respective folder.
# It uses platform neutral UTF-8 encoding.
# Above lines and this line are ignored by the patching process.
Index: hudson/hudson/main/core/src/main/java/hudson/org/apache/tools/ant/taskdefs/AbstractCvsTask.java
--- hudson/hudson/main/core/src/main/java/hudson/org/apache/tools/ant/taskdefs/AbstractCvsTask.java Base (1.3)
+++ hudson/hudson/main/core/src/main/java/hudson/org/apache/tools/ant/taskdefs/AbstractCvsTask.java Locally Modified (Based On 1.3)
@@ -18,12 +18,17 @@
 package hudson.org.apache.tools.ant.taskdefs;
 
 import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintStream;
 import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
@@ -142,7 +147,6 @@
      * Create accessors for the following, to allow different handling of
      * the output.
      */
-    private ExecuteStreamHandler executeStreamHandler;
     private OutputStream outputStream;
     private OutputStream errorStream;
     private String cvsExe = "cvs";
@@ -157,27 +161,13 @@
     }
 
     /**
-     * sets the handler
-     * @param handler a handler able of processing the output and error streams from the cvs exe
-     */
-    public void setExecuteStreamHandler(ExecuteStreamHandler handler) {
-        this.executeStreamHandler = handler;
-    }
-
-    /**
      * find the handler and instantiate it if it does not exist yet
      * @return handler for output and error streams
      */
-    protected ExecuteStreamHandler getExecuteStreamHandler() {
-
-        if (this.executeStreamHandler == null) {
-            setExecuteStreamHandler(new PumpStreamHandler(getOutputStream(),
-                                                          getErrorStream()));
+    protected ExecuteStreamHandler getExecuteStreamHandler(InputStream input) {
+        return new PumpStreamHandler(getOutputStream(), getErrorStream(), input);
         }
 
-        return this.executeStreamHandler;
-    }
-
     /**
      * sets a stream to which the output from the cvs executable should be sent
      * @param outputStream stream to which the stdout from cvs should go
@@ -324,7 +314,43 @@
         // Just call the getExecuteStreamHandler() and let it handle
         //     the semantics of instantiation or retrieval.
         //
-        Execute exe = new Execute(getExecuteStreamHandler(), null);
+        String[] argv = toExecute.getCommandline();
+        InputStream input = null;
+        String inputText = null;
+        if (new File("/usr/bin/xargs").isFile()) {
+            // Hudson workaround #864. Check for very long command lines and use xargs whenever possible.
+            int sz = 0;
+            for (String arg : argv) {
+                sz += arg.length() + /*NUL*/1;
+            }
+            if (sz > 125000) {
+                // We are in the danger zone for Linux, which imposes a 128Kb kernel buffer max by default.
+                // (Need to leave some room open for ENVP.)
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                LOAD: for (int i = 1; i < argv.length; i++) {
+                    String s = argv[i];
+                    for (byte b : s.getBytes()) {
+                        if (b < 0) {
+                            // XXX we cannot handle non-ASCII chars here, probably. Punt.
+                            baos = null;
+                            break LOAD;
+                        }
+                        // GNU xargs accepts -0, which would be nice, but this is unfortunately not universal.
+                        // The safest approach is to backslash every char, then use \n for separator.
+                        baos.write('\\');
+                        baos.write(b);
+                    }
+                    baos.write('\n');
+                }
+                if (baos != null) {
+                    Logger.getLogger(AbstractCvsTask.class.getName()).log(Level.INFO, "Using xargs to run very long command line ({0} bytes)", sz);
+                    input = new ByteArrayInputStream(baos.toByteArray());
+                    inputText = baos.toString();
+                    argv = new String[] {"/usr/bin/xargs", argv[0]};
+                }
+            }
+        }
+        Execute exe = new Execute(getExecuteStreamHandler(input), null);
 
         exe.setAntRun(getProject());
         if (dest == null) {
@@ -336,7 +362,7 @@
         }
 
         exe.setWorkingDirectory(dest);
-        exe.setCommandline(toExecute.getCommandline());
+        exe.setCommandline(argv);
         exe.setEnvironment(env.getVariables());
 
         try {
@@ -350,7 +376,8 @@
                                          + retCode
                                          + StringUtils.LINE_SEP
                                          + "Command line was ["
-                                         + actualCommandLine + "]", getLocation());
\ No newline at end of file
+                                         + actualCommandLine + "] in " + dest +
+                                         "\nInput text:\nSTART==>" + inputText + "<==END", getLocation());
\ No newline at end of file
             }
         } catch (IOException e) {
             if (failOnError) {
Index: hudson/hudson/main/core/src/main/java/hudson/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java
--- hudson/hudson/main/core/src/main/java/hudson/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java Base (1.12)
+++ hudson/hudson/main/core/src/main/java/hudson/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java Locally Modified (Based On 1.12)
@@ -26,6 +26,7 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
@@ -38,6 +39,7 @@
 import java.util.Properties;
 import java.util.Vector;
 import java.util.StringTokenizer;
+import org.apache.tools.ant.taskdefs.ExecuteStreamHandler;
 
 /**
  * Examines the output of cvs log and group related changes together.
@@ -197,6 +199,9 @@
     }
 
 
+    // XXX crude but how else to track the parser & handler and still pass to super impl?
+    private ChangeLogParser parser;
+    private RedirectingStreamHandler handler;
     /**
      * Execute task
      *
@@ -278,16 +283,11 @@
                 }
             }
 
-            final ChangeLogParser parser = new ChangeLogParser(this);
-            RedirectingStreamHandler handler;
-            handler = new RedirectingStreamHandler(
-                new ForkOutputStream(new RedirectingOutputStream(parser),
-                    new LogOutputStream(this,Project.MSG_VERBOSE)));
+            parser = new ChangeLogParser(this);
 
             log("Running "+getCommand()+" at "+m_dir, Project.MSG_VERBOSE);
 
             setDest(m_dir);
-            setExecuteStreamHandler(handler);
             try {
                 super.execute();
             } finally {
@@ -309,6 +309,12 @@
             m_dir = savedDir;
         }
     }
+    protected @Override ExecuteStreamHandler getExecuteStreamHandler(InputStream input) {
+        return handler = new RedirectingStreamHandler(
+                new ForkOutputStream(new RedirectingOutputStream(parser),
+                    new LogOutputStream(this,Project.MSG_VERBOSE)),
+                    input);
+    }
\ No newline at end of file
 
     private static final long VERSION_1_11_2 = 11102;
     private static final long MULTIPLY = 100;
Index: hudson/hudson/main/core/src/main/java/hudson/org/apache/tools/ant/taskdefs/cvslib/RedirectingStreamHandler.java
--- hudson/hudson/main/core/src/main/java/hudson/org/apache/tools/ant/taskdefs/cvslib/RedirectingStreamHandler.java Base (1.2)
+++ hudson/hudson/main/core/src/main/java/hudson/org/apache/tools/ant/taskdefs/cvslib/RedirectingStreamHandler.java Locally Modified (Based On 1.2)
@@ -21,6 +21,7 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 
 /**
@@ -30,11 +31,11 @@
  */
 class RedirectingStreamHandler extends PumpStreamHandler {
     RedirectingStreamHandler(final ChangeLogParser parser) {
-        this(new RedirectingOutputStream(parser));
+        this(new RedirectingOutputStream(parser), null);
     }
 
-    RedirectingStreamHandler(OutputStream out) {
-        super(out, new ByteArrayOutputStream());
+    RedirectingStreamHandler(OutputStream out, InputStream in) {
+        super(out, new ByteArrayOutputStream(), in);
     }
 
     String getErrors() {
