mirror of https://github.com/jenkinsci/jenkins.git
				
				
				
			rolling back my earlier change that seems to be breaking tests. will revisit this change later
git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@19332 71c3de6d-444a-0410-be80-ed276b4c234a
This commit is contained in:
		
							parent
							
								
									b26cfc7b56
								
							
						
					
					
						commit
						b7a52ff7ba
					
				|  | @ -73,7 +73,6 @@ import java.io.OutputStream; | ||||||
| import java.io.Serializable; | import java.io.Serializable; | ||||||
| import java.io.Writer; | import java.io.Writer; | ||||||
| import java.io.OutputStreamWriter; | import java.io.OutputStreamWriter; | ||||||
| import java.io.Closeable; |  | ||||||
| import java.net.URI; | import java.net.URI; | ||||||
| import java.net.URL; | import java.net.URL; | ||||||
| import java.net.URLConnection; | import java.net.URLConnection; | ||||||
|  | @ -247,31 +246,44 @@ public final class FilePath implements Serializable { | ||||||
|      * Creates a zip file from this directory or a file and sends that to the given output stream. |      * Creates a zip file from this directory or a file and sends that to the given output stream. | ||||||
|      */ |      */ | ||||||
|     public void createZipArchive(OutputStream os) throws IOException, InterruptedException { |     public void createZipArchive(OutputStream os) throws IOException, InterruptedException { | ||||||
|         createZipArchive(os,(FileFilter)null); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Creates a zip file from this directory by using the specified filter, |  | ||||||
|      * and sends the result to the given output stream. |  | ||||||
|      * |  | ||||||
|      * @param filter |  | ||||||
|      *      Must be serializable since it may be executed remotely. Can be null to add all files. |  | ||||||
|      * |  | ||||||
|      * @since 1.314 |  | ||||||
|      */ |  | ||||||
|     public void createZipArchive(OutputStream os, final FileFilter filter) throws IOException, InterruptedException { |  | ||||||
|         final OutputStream out = (channel!=null)?new RemoteOutputStream(os):os; |         final OutputStream out = (channel!=null)?new RemoteOutputStream(os):os; | ||||||
|         act(new FileCallable<Void>() { |         act(new FileCallable<Void>() { | ||||||
|  |             private transient byte[] buf; | ||||||
|             public Void invoke(File f, VirtualChannel channel) throws IOException { |             public Void invoke(File f, VirtualChannel channel) throws IOException { | ||||||
|                 ZipWriter zw = new ZipWriter(out); |                 buf = new byte[8192]; | ||||||
|                 try { | 
 | ||||||
|                     accept(f,zw.with(filter)); |                 ZipOutputStream zip = new ZipOutputStream(out); | ||||||
|                 } finally { |                 zip.setEncoding(System.getProperty("file.encoding")); | ||||||
|                     zw.close(); |                 scan(f,zip,""); | ||||||
|                 } |                 zip.close(); | ||||||
|                 return null; |                 return null; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |             private void scan(File f, ZipOutputStream zip, String path) throws IOException { | ||||||
|  |                 // Bitmask indicating directories in 'external attributes' of a ZIP archive entry. | ||||||
|  |                 final long BITMASK_IS_DIRECTORY = 1<<4; | ||||||
|  |                | ||||||
|  |                 if (f.canRead()) { | ||||||
|  |                     if(f.isDirectory()) { | ||||||
|  |                         ZipEntry dirZipEntry = new ZipEntry(path+f.getName()+'/'); | ||||||
|  |                         // Setting this bit explicitly is needed by some unzipping applications (see HUDSON-3294). | ||||||
|  |                         dirZipEntry.setExternalAttributes(BITMASK_IS_DIRECTORY); | ||||||
|  |                         zip.putNextEntry(dirZipEntry); | ||||||
|  |                         zip.closeEntry(); | ||||||
|  |                         for( File child : f.listFiles() ) | ||||||
|  |                             scan(child,zip,path+f.getName()+'/'); | ||||||
|  |                     } else { | ||||||
|  |                         zip.putNextEntry(new ZipEntry(path+f.getName())); | ||||||
|  |                         FileInputStream in = new FileInputStream(f); | ||||||
|  |                         int len; | ||||||
|  |                         while((len=in.read(buf))>0) | ||||||
|  |                             zip.write(buf,0,len); | ||||||
|  |                         in.close(); | ||||||
|  |                         zip.closeEntry(); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |              | ||||||
|             private static final long serialVersionUID = 1L; |             private static final long serialVersionUID = 1L; | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  | @ -294,12 +306,24 @@ public final class FilePath implements Serializable { | ||||||
|         final OutputStream out = (channel!=null)?new RemoteOutputStream(os):os; |         final OutputStream out = (channel!=null)?new RemoteOutputStream(os):os; | ||||||
|         act(new FileCallable<Void>() { |         act(new FileCallable<Void>() { | ||||||
|             public Void invoke(File dir, VirtualChannel channel) throws IOException { |             public Void invoke(File dir, VirtualChannel channel) throws IOException { | ||||||
|                 ZipWriter zw = new ZipWriter(out); |                 byte[] buf = new byte[8192]; | ||||||
|                 try { | 
 | ||||||
|                     accept(dir,glob,null,zw); |                 ZipOutputStream zip = new ZipOutputStream(out); | ||||||
|                 } finally { |                 zip.setEncoding(System.getProperty("file.encoding")); | ||||||
|                     zw.close(); |                 for( String entry : glob(dir,glob) ) { | ||||||
|  |                     File file = new File(dir,entry); | ||||||
|  |                     if (file.canRead()) { | ||||||
|  |                         zip.putNextEntry(new ZipEntry(dir.getName()+'/'+entry)); | ||||||
|  |                         FileInputStream in = new FileInputStream(file); | ||||||
|  |                         int len; | ||||||
|  |                         while((len=in.read(buf))>0) | ||||||
|  |                             zip.write(buf,0,len); | ||||||
|  |                         in.close(); | ||||||
|  |                         zip.closeEntry(); | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|  | 
 | ||||||
|  |                 zip.close(); | ||||||
|                 return null; |                 return null; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | @ -1351,69 +1375,39 @@ public final class FilePath implements Serializable { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Visits files in a directory recursively. |      * Writes to a tar stream and stores obtained files to the base dir. | ||||||
|      * Primarily used for building an archive with various filtering. |      * | ||||||
|  |      * @return | ||||||
|  |      *      number of files/directories that are written. | ||||||
|      */ |      */ | ||||||
|     private static abstract class FileVisitor { |     private Integer writeToTar(File baseDir, String fileMask, String excludes, OutputStream out) throws IOException { | ||||||
|         abstract void visit(File f, String relativePath) throws IOException; |         FileSet fs = Util.createFileSet(baseDir,fileMask,excludes); | ||||||
| 
 | 
 | ||||||
|         /** |         byte[] buf = new byte[8192]; | ||||||
|          * Decorates by a given filter. |  | ||||||
|          */ |  | ||||||
|         FileVisitor with(FileFilter f) { |  | ||||||
|             if(f==null) return this; |  | ||||||
|             return new FilterFileVisitor(f,this); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     private static final class FilterFileVisitor extends FileVisitor implements Serializable { |         TarOutputStream tar = new TarOutputStream(new BufferedOutputStream(out) { | ||||||
|         private final FileFilter filter; |             // TarOutputStream uses TarBuffer internally, | ||||||
|         private final FileVisitor visitor; |             // which flushes the stream for each block. this creates unnecessary | ||||||
| 
 |             // data stream fragmentation, and flush request to a remote, which slows things down. | ||||||
|         private FilterFileVisitor(FileFilter filter, FileVisitor visitor) { |             public void flush() throws IOException { | ||||||
|             this.filter = filter!=null ? filter : PASS_THROUGH; |                 // so don't do anything in flush | ||||||
|             this.visitor = visitor; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public void visit(File f, String relativePath) throws IOException { |  | ||||||
|             if(f.isDirectory() || filter.accept(f)) |  | ||||||
|                 visitor.visit(f,relativePath); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private static final FileFilter PASS_THROUGH = new FileFilter() { |  | ||||||
|             public boolean accept(File pathname) { |  | ||||||
|                 return true; |  | ||||||
|             } |             } | ||||||
|         }; |         }); | ||||||
| 
 |         tar.setLongFileMode(TarOutputStream.LONGFILE_GNU); | ||||||
|         private static final long serialVersionUID = 1L; |         String[] files; | ||||||
|     } |         if(baseDir.exists()) { | ||||||
| 
 |             DirectoryScanner ds = fs.getDirectoryScanner(new org.apache.tools.ant.Project()); | ||||||
|     /** |             files = ds.getIncludedFiles(); | ||||||
|      * {@link FileVisitor} that creates a tar archive. |         } else { | ||||||
|      */ |             files = new String[0]; | ||||||
|     private static final class TarWriter extends FileVisitor implements Closeable { |  | ||||||
|         private final byte[] buf = new byte[8192]; |  | ||||||
|         private final TarOutputStream tar; |  | ||||||
|         int filesWritten=0; |  | ||||||
| 
 |  | ||||||
|         private TarWriter(OutputStream out) { |  | ||||||
|             tar = new TarOutputStream(new BufferedOutputStream(out) { |  | ||||||
|                 // TarOutputStream uses TarBuffer internally, |  | ||||||
|                 // which flushes the stream for each block. this creates unnecessary |  | ||||||
|                 // data stream fragmentation, and flush request to a remote, which slows things down. |  | ||||||
|                 public void flush() throws IOException { |  | ||||||
|                     // so don't do anything in flush |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|             tar.setLongFileMode(TarOutputStream.LONGFILE_GNU); |  | ||||||
|         } |         } | ||||||
| 
 |         for( String f : files) { | ||||||
|         public void visit(File file, String relativePath) throws IOException { |  | ||||||
|             if(Functions.isWindows()) |             if(Functions.isWindows()) | ||||||
|                 relativePath = relativePath.replace('\\','/'); |                 f = f.replace('\\','/'); | ||||||
| 
 | 
 | ||||||
|             TarEntry te = new TarEntry(relativePath); |             File file = new File(baseDir, f); | ||||||
|  | 
 | ||||||
|  |             TarEntry te = new TarEntry(f); | ||||||
|             te.setModTime(file.lastModified()); |             te.setModTime(file.lastModified()); | ||||||
|             if(!file.isDirectory()) |             if(!file.isDirectory()) | ||||||
|                 te.setSize(file.length()); |                 te.setSize(file.length()); | ||||||
|  | @ -1429,129 +1423,11 @@ public final class FilePath implements Serializable { | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             tar.closeEntry(); |             tar.closeEntry(); | ||||||
|             filesWritten++; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public void close() throws IOException { |         tar.close(); | ||||||
|             tar.close(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     /** |         return files.length; | ||||||
|      * {@link FileVisitor} that creates a zip archive. |  | ||||||
|      */ |  | ||||||
|     private static final class ZipWriter extends FileVisitor implements Closeable { |  | ||||||
|         private final byte[] buf = new byte[8192]; |  | ||||||
|         private final ZipOutputStream zip; |  | ||||||
| 
 |  | ||||||
|         private ZipWriter(OutputStream out) { |  | ||||||
|             zip = new ZipOutputStream(out); |  | ||||||
|             zip.setEncoding(System.getProperty("file.encoding")); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public void visit(File f, String relativePath) throws IOException { |  | ||||||
|             if(f.isDirectory()) { |  | ||||||
|                 ZipEntry dirZipEntry = new ZipEntry(relativePath+'/'); |  | ||||||
|                 // Setting this bit explicitly is needed by some unzipping applications (see HUDSON-3294). |  | ||||||
|                 dirZipEntry.setExternalAttributes(BITMASK_IS_DIRECTORY); |  | ||||||
|                 zip.putNextEntry(dirZipEntry); |  | ||||||
|                 zip.closeEntry(); |  | ||||||
|             } else { |  | ||||||
|                 zip.putNextEntry(new ZipEntry(relativePath)); |  | ||||||
|                 FileInputStream in = new FileInputStream(f); |  | ||||||
|                 int len; |  | ||||||
|                 while((len=in.read(buf))>0) |  | ||||||
|                     zip.write(buf,0,len); |  | ||||||
|                 in.close(); |  | ||||||
|                 zip.closeEntry(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public void close() throws IOException { |  | ||||||
|             zip.close(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Bitmask indicating directories in 'external attributes' of a ZIP archive entry. |  | ||||||
|         private static final long BITMASK_IS_DIRECTORY = 1<<4; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Scans the given base directory with a GLOB and exclusion mask, and calls visitor. |  | ||||||
|      */ |  | ||||||
|     private void accept(File baseDir, String fileMask, String excludes, FileVisitor visitor) throws IOException { |  | ||||||
|         if(fileMask==null || excludes==null) { |  | ||||||
|             // optimization |  | ||||||
|             accept(baseDir,visitor); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         FileSet fs = Util.createFileSet(baseDir,fileMask,excludes); |  | ||||||
| 
 |  | ||||||
|         if(baseDir.exists()) { |  | ||||||
|             DirectoryScanner ds = fs.getDirectoryScanner(new org.apache.tools.ant.Project()); |  | ||||||
|             for( String f : ds.getIncludedFiles()) { |  | ||||||
|                 File file = new File(baseDir, f); |  | ||||||
|                 visitor.visit(file,f); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Scans the given directory tree recursively and calls visitor. |  | ||||||
|      */ |  | ||||||
|     private void accept(final File baseDir, final FileVisitor visitor) throws IOException { |  | ||||||
|         class Scanner { |  | ||||||
|             public void run() throws IOException { |  | ||||||
|                 scan(baseDir,""); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             private void scan(File f, String path) throws IOException { |  | ||||||
|                 if (f.canRead()) { |  | ||||||
|                     visitor.visit(f,path+f.getName()); |  | ||||||
|                     if(f.isDirectory()) { |  | ||||||
|                         for( File child : f.listFiles() ) |  | ||||||
|                             scan(child,path+f.getName()+'/'); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         new Scanner().run(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Writes files in 'this' directory to a tar stream. |  | ||||||
|      * |  | ||||||
|      * @param glob |  | ||||||
|      *      Ant file pattern mask, like "**/*.java". |  | ||||||
|      */ |  | ||||||
|     public int tar(OutputStream out, final String glob) throws IOException, InterruptedException { |  | ||||||
|         final OutputStream o = new RemoteOutputStream(out); |  | ||||||
|         try { |  | ||||||
|             return act(new FileCallable<Integer>() { |  | ||||||
|                 public Integer invoke(File f, VirtualChannel channel) throws IOException { |  | ||||||
|                     return writeToTar(f,glob,null,o); |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|         } finally { |  | ||||||
|             out.close(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Writes to a tar stream and stores obtained files to the base dir. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *      number of files/directories that are written. |  | ||||||
|      */ |  | ||||||
|     private Integer writeToTar(File baseDir, String fileMask, String excludes, OutputStream out) throws IOException { |  | ||||||
|         TarWriter tw = new TarWriter(out); |  | ||||||
|         try { |  | ||||||
|             accept(baseDir,fileMask,excludes,tw); |  | ||||||
|         } finally { |  | ||||||
|             tw.close(); |  | ||||||
|         } |  | ||||||
|         return tw.filesWritten; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  |  | ||||||
|  | @ -49,6 +49,7 @@ import hudson.util.ArgumentListBuilder; | ||||||
| import hudson.util.ForkOutputStream; | import hudson.util.ForkOutputStream; | ||||||
| import hudson.util.IOException2; | import hudson.util.IOException2; | ||||||
| import hudson.util.FormValidation; | import hudson.util.FormValidation; | ||||||
|  | import hudson.util.AtomicFileWriter; | ||||||
| import org.apache.commons.io.FileUtils; | import org.apache.commons.io.FileUtils; | ||||||
| import org.apache.commons.io.IOUtils; | import org.apache.commons.io.IOUtils; | ||||||
| import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||||
|  | @ -1010,6 +1011,13 @@ public class CVSSCM extends SCM implements Serializable { | ||||||
| 
 | 
 | ||||||
|             if(modified) { |             if(modified) { | ||||||
|                 // write it back |                 // write it back | ||||||
|  |                 AtomicFileWriter w = new AtomicFileWriter(entries); | ||||||
|  |                 try { | ||||||
|  |                     w.write(newContents.toString()); | ||||||
|  |                     w.commit(); | ||||||
|  |                 } finally { | ||||||
|  |                     w.abort(); | ||||||
|  |                 } | ||||||
|                 File tmp = new File(f, "CVS/Entries.tmp"); |                 File tmp = new File(f, "CVS/Entries.tmp"); | ||||||
|                 FileUtils.writeStringToFile(tmp,newContents.toString()); |                 FileUtils.writeStringToFile(tmp,newContents.toString()); | ||||||
|                 entries.delete(); |                 entries.delete(); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue