]> source.dussan.org Git - jgit.git/commitdiff
archive: Record executable and symlink bits 08/9008/3
authorJonathan Nieder <jrn@google.com>
Mon, 3 Dec 2012 18:41:25 +0000 (10:41 -0800)
committerJonathan Nieder <jrn@google.com>
Tue, 4 Dec 2012 23:34:07 +0000 (15:34 -0800)
Setting the mode for a zip entry is now as simple as
"entry.setUnixMode(mode)", so do that.

The test checks using the system's "zipinfo" command (from InfoZIP)
that the mode has been recorded correctly on systems that happen to
have a "zipinfo" command, using org.junit.Assume to distinguish them.

Change-Id: I4236c102fd76f18d01b2dc926eeb9b9fa11a61b7

org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java

index 583beefede36f312716e04002e70f4ca79003a81..cad379774e9c098add05d61f84350c4dc79bf8a5 100644 (file)
 package org.eclipse.jgit.pgm;
 
 import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeNoException;
 
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
 import java.io.InputStreamReader;
 import java.io.IOException;
+import java.io.OutputStream;
 
 import java.lang.String;
 import java.util.ArrayList;
@@ -57,7 +62,9 @@ import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
 import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.dircache.DirCache;
 import org.eclipse.jgit.lib.CLIRepositoryTestCase;
+import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.pgm.CLIGitCommand;
 import org.junit.Before;
 import org.junit.Ignore;
@@ -125,6 +132,32 @@ public class ArchiveTest extends CLIRepositoryTestCase {
                assertArrayEquals(expect, actual);
        }
 
+       @Test
+       public void testArchivePreservesMode() throws Exception {
+               writeTrashFile("plain", "a file with content");
+               writeTrashFile("executable", "an executable file");
+               writeTrashFile("symlink", "plain");
+               git.add().addFilepattern("plain").call();
+               git.add().addFilepattern("executable").call();
+               git.add().addFilepattern("symlink").call();
+
+               DirCache cache = db.lockDirCache();
+               cache.getEntry("executable").setFileMode(FileMode.EXECUTABLE_FILE);
+               cache.getEntry("symlink").setFileMode(FileMode.SYMLINK);
+               cache.write();
+               cache.commit();
+               cache.unlock();
+
+               git.commit().setMessage("three files with different modes").call();
+
+               final byte[] zipData = CLIGitCommand.rawExecute( //
+                               "git archive master", db);
+               writeRaw("zip-with-modes.zip", zipData);
+               assertContainsEntryWithMode("zip-with-modes.zip", "-rw-", "plain");
+               assertContainsEntryWithMode("zip-with-modes.zip", "-rwx", "executable");
+               assertContainsEntryWithMode("zip-with-modes.zip", "l", "symlink");
+       }
+
        @Test
        public void testArchivePreservesContent() throws Exception {
                final String payload = "“The quick brown fox jumps over the lazy dog!”";
@@ -138,6 +171,47 @@ public class ArchiveTest extends CLIRepositoryTestCase {
                                zipEntryContent(result, "xyzzy"));
        }
 
+       private void assertContainsEntryWithMode(String zipFilename, String mode, String name) //
+                       throws Exception {
+               final File cwd = db.getWorkTree();
+               final ProcessBuilder procBuilder = new ProcessBuilder("zipinfo", zipFilename) //
+                               .directory(cwd) //
+                               .redirectErrorStream(true);
+               Process proc = null;
+               try {
+                       proc = procBuilder.start();
+               } catch (IOException e) {
+                       // On machines without a "zipinfo" command, let the test pass.
+                       assumeNoException(e);
+               }
+
+               proc.getOutputStream().close();
+               final BufferedReader reader = new BufferedReader( //
+                               new InputStreamReader(proc.getInputStream(), "UTF-8"));
+               try {
+                       String line;
+                       while ((line = reader.readLine()) != null)
+                               if (line.startsWith(mode) && line.endsWith(name))
+                                       // found it!
+                                       return;
+                       fail("expected entry " + name + " with mode " + mode + " but found none");
+               } finally {
+                       proc.getOutputStream().close();
+                       proc.destroy();
+               }
+       }
+
+       private void writeRaw(String filename, byte[] data) //
+                       throws IOException {
+               final File path = new File(db.getWorkTree(), filename);
+               final OutputStream out = new FileOutputStream(path);
+               try {
+                       out.write(data);
+               } finally {
+                       out.close();
+               }
+       }
+
        private static String[] listZipEntries(byte[] zipData) throws IOException {
                final List<String> l = new ArrayList<String>();
                final ZipInputStream in = new ZipInputStream( //
index ec937a3cc33d7dc46bfbed1027bb4b719ab98b94..cc2f287b2ad7d038ea49d8fc25c85da6426002a3 100644 (file)
@@ -90,14 +90,20 @@ class Archive extends TextBuiltin {
                        final ZipArchiveEntry entry = new ZipArchiveEntry(name);
                        final ObjectLoader loader = reader.open(idBuf);
                        entry.setSize(loader.getSize());
-                       out.putArchiveEntry(entry);
-                       loader.copyTo(out);
-                       out.closeArchiveEntry();
 
-                       if (mode != FileMode.REGULAR_FILE)
+                       if (mode == FileMode.REGULAR_FILE)
+                               ; // ok
+                       else if (mode == FileMode.EXECUTABLE_FILE ||
+                                mode == FileMode.SYMLINK)
+                               entry.setUnixMode(mode.getBits());
+                       else
                                System.err.println(MessageFormat.format( //
                                                CLIText.get().archiveEntryModeIgnored, //
                                                name));
+
+                       out.putArchiveEntry(entry);
+                       loader.copyTo(out);
+                       out.closeArchiveEntry();
                }
 
                out.close();