1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 package org.eclipse.jgit.pgm;
44
45 import static org.junit.Assert.assertArrayEquals;
46 import static org.junit.Assert.fail;
47 import static org.junit.Assume.assumeNoException;
48
49 import java.io.BufferedInputStream;
50 import java.io.BufferedReader;
51 import java.io.ByteArrayInputStream;
52 import java.io.File;
53 import java.io.FileInputStream;
54 import java.io.FileOutputStream;
55 import java.io.IOException;
56 import java.io.InputStreamReader;
57 import java.io.OutputStream;
58 import java.util.ArrayList;
59 import java.util.Arrays;
60 import java.util.List;
61 import java.util.concurrent.Callable;
62 import java.util.concurrent.ExecutorService;
63 import java.util.concurrent.Executors;
64 import java.util.concurrent.Future;
65 import java.util.zip.ZipEntry;
66 import java.util.zip.ZipInputStream;
67
68 import org.eclipse.jgit.api.Git;
69 import org.eclipse.jgit.dircache.DirCache;
70 import org.eclipse.jgit.lib.CLIRepositoryTestCase;
71 import org.eclipse.jgit.lib.FileMode;
72 import org.junit.Before;
73 import org.junit.Test;
74
75 public class ArchiveTest extends CLIRepositoryTestCase {
76 private Git git;
77 private String emptyTree;
78
79 @Override
80 @Before
81 public void setUp() throws Exception {
82 super.setUp();
83 git = new Git(db);
84 git.commit().setMessage("initial commit").call();
85 emptyTree = db.resolve("HEAD^{tree}").abbreviate(12).name();
86 }
87
88 @Test
89 public void testEmptyArchive() throws Exception {
90 byte[] result = CLIGitCommand.executeRaw(
91 "git archive --format=zip " + emptyTree, db).outBytes();
92 assertArrayEquals(new String[0], listZipEntries(result));
93 }
94
95 @Test
96 public void testEmptyTar() throws Exception {
97 byte[] result = CLIGitCommand.executeRaw(
98 "git archive --format=tar " + emptyTree, db).outBytes();
99 assertArrayEquals(new String[0], listTarEntries(result));
100 }
101
102 @Test
103 public void testUnrecognizedFormat() throws Exception {
104 String[] expect = new String[] {
105 "fatal: Unknown archive format 'nonsense'", "" };
106 String[] actual = executeUnchecked(
107 "git archive --format=nonsense " + emptyTree);
108 assertArrayEquals(expect, actual);
109 }
110
111 @Test
112 public void testArchiveWithFiles() throws Exception {
113 writeTrashFile("a", "a file with content!");
114 writeTrashFile("c", "");
115 writeTrashFile("unrelated", "another file, just for kicks");
116 git.add().addFilepattern("a").call();
117 git.add().addFilepattern("c").call();
118 git.commit().setMessage("populate toplevel").call();
119
120 byte[] result = CLIGitCommand.executeRaw(
121 "git archive --format=zip HEAD", db).outBytes();
122 assertArrayEquals(new String[] { "a", "c" },
123 listZipEntries(result));
124 }
125
126 private void commitGreeting() throws Exception {
127 writeTrashFile("greeting", "hello, world!");
128 git.add().addFilepattern("greeting").call();
129 git.commit().setMessage("a commit with a file").call();
130 }
131
132 @Test
133 public void testDefaultFormatIsTar() throws Exception {
134 commitGreeting();
135 byte[] result = CLIGitCommand.executeRaw(
136 "git archive HEAD", db).outBytes();
137 assertArrayEquals(new String[] { "greeting" },
138 listTarEntries(result));
139 }
140
141 private static String shellQuote(String s) {
142 return "'" + s.replace("'", "'\\''") + "'";
143 }
144
145 @Test
146 public void testFormatOverridesFilename() throws Exception {
147 File archive = new File(db.getWorkTree(), "format-overrides-name.tar");
148 String path = archive.getAbsolutePath();
149
150 commitGreeting();
151 assertArrayEquals(new String[] { "" },
152 execute("git archive " +
153 "--format=zip " +
154 shellQuote("--output=" + path) + " " +
155 "HEAD"));
156 assertContainsEntryWithMode(path, "", "greeting");
157 assertIsZip(archive);
158 }
159
160 @Test
161 public void testUnrecognizedExtensionMeansTar() throws Exception {
162 File archive = new File(db.getWorkTree(), "example.txt");
163 String path = archive.getAbsolutePath();
164
165 commitGreeting();
166 assertArrayEquals(new String[] { "" },
167 execute("git archive " +
168 shellQuote("--output=" + path) + " " +
169 "HEAD"));
170 assertTarContainsEntry(path, "", "greeting");
171 assertIsTar(archive);
172 }
173
174 @Test
175 public void testNoExtensionMeansTar() throws Exception {
176 File archive = new File(db.getWorkTree(), "example");
177 String path = archive.getAbsolutePath();
178
179 commitGreeting();
180 assertArrayEquals(new String[] { "" },
181 execute("git archive " +
182 shellQuote("--output=" + path) + " " +
183 "HEAD"));
184 assertIsTar(archive);
185 }
186
187 @Test
188 public void testExtensionMatchIsAnchored() throws Exception {
189 File archive = new File(db.getWorkTree(), "two-extensions.zip.bak");
190 String path = archive.getAbsolutePath();
191
192 commitGreeting();
193 assertArrayEquals(new String[] { "" },
194 execute("git archive " +
195 shellQuote("--output=" + path) + " " +
196 "HEAD"));
197 assertIsTar(archive);
198 }
199
200 @Test
201 public void testZipExtension() throws Exception {
202 File archiveWithDot = new File(db.getWorkTree(), "greeting.zip");
203 File archiveNoDot = new File(db.getWorkTree(), "greetingzip");
204
205 commitGreeting();
206 execute("git archive " +
207 shellQuote("--output=" + archiveWithDot.getAbsolutePath()) + " " +
208 "HEAD");
209 execute("git archive " +
210 shellQuote("--output=" + archiveNoDot.getAbsolutePath()) + " " +
211 "HEAD");
212 assertIsZip(archiveWithDot);
213 assertIsTar(archiveNoDot);
214 }
215
216 @Test
217 public void testTarExtension() throws Exception {
218 File archive = new File(db.getWorkTree(), "tarball.tar");
219 String path = archive.getAbsolutePath();
220
221 commitGreeting();
222 assertArrayEquals(new String[] { "" },
223 execute("git archive " +
224 shellQuote("--output=" + path) + " " +
225 "HEAD"));
226 assertIsTar(archive);
227 }
228
229 @Test
230 public void testTgzExtensions() throws Exception {
231 commitGreeting();
232
233 for (String ext : Arrays.asList("tar.gz", "tgz")) {
234 File archiveWithDot = new File(db.getWorkTree(), "tarball." + ext);
235 File archiveNoDot = new File(db.getWorkTree(), "tarball" + ext);
236
237 execute("git archive " +
238 shellQuote("--output=" + archiveWithDot.getAbsolutePath()) + " " +
239 "HEAD");
240 execute("git archive " +
241 shellQuote("--output=" + archiveNoDot.getAbsolutePath()) + " " +
242 "HEAD");
243 assertIsGzip(archiveWithDot);
244 assertIsTar(archiveNoDot);
245 }
246 }
247
248 @Test
249 public void testTbz2Extension() throws Exception {
250 commitGreeting();
251
252 for (String ext : Arrays.asList("tar.bz2", "tbz", "tbz2")) {
253 File archiveWithDot = new File(db.getWorkTree(), "tarball." + ext);
254 File archiveNoDot = new File(db.getWorkTree(), "tarball" + ext);
255
256 execute("git archive " +
257 shellQuote("--output=" + archiveWithDot.getAbsolutePath()) + " " +
258 "HEAD");
259 execute("git archive " +
260 shellQuote("--output=" + archiveNoDot.getAbsolutePath()) + " " +
261 "HEAD");
262 assertIsBzip2(archiveWithDot);
263 assertIsTar(archiveNoDot);
264 }
265 }
266
267 @Test
268 public void testTxzExtension() throws Exception {
269 commitGreeting();
270
271 for (String ext : Arrays.asList("tar.xz", "txz")) {
272 File archiveWithDot = new File(db.getWorkTree(), "tarball." + ext);
273 File archiveNoDot = new File(db.getWorkTree(), "tarball" + ext);
274
275 execute("git archive " +
276 shellQuote("--output=" + archiveWithDot.getAbsolutePath()) + " " +
277 "HEAD");
278 execute("git archive " +
279 shellQuote("--output=" + archiveNoDot.getAbsolutePath()) + " " +
280 "HEAD");
281 assertIsXz(archiveWithDot);
282 assertIsTar(archiveNoDot);
283 }
284 }
285
286 @Test
287 public void testArchiveWithSubdir() throws Exception {
288 writeTrashFile("a", "a file with content!");
289 writeTrashFile("b.c", "before subdir in git sort order");
290 writeTrashFile("b0c", "after subdir in git sort order");
291 writeTrashFile("c", "");
292 git.add().addFilepattern("a").call();
293 git.add().addFilepattern("b.c").call();
294 git.add().addFilepattern("b0c").call();
295 git.add().addFilepattern("c").call();
296 git.commit().setMessage("populate toplevel").call();
297 writeTrashFile("b/b", "file in subdirectory");
298 writeTrashFile("b/a", "another file in subdirectory");
299 git.add().addFilepattern("b").call();
300 git.commit().setMessage("add subdir").call();
301
302 byte[] result = CLIGitCommand.executeRaw(
303 "git archive --format=zip master", db).outBytes();
304 String[] expect = { "a", "b.c", "b0c", "b/", "b/a", "b/b", "c" };
305 String[] actual = listZipEntries(result);
306
307 Arrays.sort(expect);
308 Arrays.sort(actual);
309 assertArrayEquals(expect, actual);
310 }
311
312 @Test
313 public void testTarWithSubdir() throws Exception {
314 writeTrashFile("a", "a file with content!");
315 writeTrashFile("b.c", "before subdir in git sort order");
316 writeTrashFile("b0c", "after subdir in git sort order");
317 writeTrashFile("c", "");
318 git.add().addFilepattern("a").call();
319 git.add().addFilepattern("b.c").call();
320 git.add().addFilepattern("b0c").call();
321 git.add().addFilepattern("c").call();
322 git.commit().setMessage("populate toplevel").call();
323 writeTrashFile("b/b", "file in subdirectory");
324 writeTrashFile("b/a", "another file in subdirectory");
325 git.add().addFilepattern("b").call();
326 git.commit().setMessage("add subdir").call();
327
328 byte[] result = CLIGitCommand.executeRaw(
329 "git archive --format=tar master", db).outBytes();
330 String[] expect = { "a", "b.c", "b0c", "b/", "b/a", "b/b", "c" };
331 String[] actual = listTarEntries(result);
332
333 Arrays.sort(expect);
334 Arrays.sort(actual);
335 assertArrayEquals(expect, actual);
336 }
337
338 private void commitBazAndFooSlashBar() throws Exception {
339 writeTrashFile("baz", "a file");
340 writeTrashFile("foo/bar", "another file");
341 git.add().addFilepattern("baz").call();
342 git.add().addFilepattern("foo").call();
343 git.commit().setMessage("sample commit").call();
344 }
345
346 @Test
347 public void testArchivePrefixOption() throws Exception {
348 commitBazAndFooSlashBar();
349 byte[] result = CLIGitCommand.executeRaw(
350 "git archive --prefix=x/ --format=zip master", db).outBytes();
351 String[] expect = { "x/baz", "x/foo/", "x/foo/bar" };
352 String[] actual = listZipEntries(result);
353
354 Arrays.sort(expect);
355 Arrays.sort(actual);
356 assertArrayEquals(expect, actual);
357 }
358
359 @Test
360 public void testTarPrefixOption() throws Exception {
361 commitBazAndFooSlashBar();
362 byte[] result = CLIGitCommand.executeRaw(
363 "git archive --prefix=x/ --format=tar master", db).outBytes();
364 String[] expect = { "x/baz", "x/foo/", "x/foo/bar" };
365 String[] actual = listTarEntries(result);
366
367 Arrays.sort(expect);
368 Arrays.sort(actual);
369 assertArrayEquals(expect, actual);
370 }
371
372 private void commitFoo() throws Exception {
373 writeTrashFile("foo", "a file");
374 git.add().addFilepattern("foo").call();
375 git.commit().setMessage("boring commit").call();
376 }
377
378 @Test
379 public void testPrefixDoesNotNormalizeDoubleSlash() throws Exception {
380 commitFoo();
381 byte[] result = CLIGitCommand.executeRaw(
382 "git archive --prefix=x// --format=zip master", db).outBytes();
383 String[] expect = { "x//foo" };
384 assertArrayEquals(expect, listZipEntries(result));
385 }
386
387 @Test
388 public void testPrefixDoesNotNormalizeDoubleSlashInTar() throws Exception {
389 commitFoo();
390 byte[] result = CLIGitCommand.executeRaw(
391 "git archive --prefix=x// --format=tar master", db).outBytes();
392 String[] expect = { "x//foo" };
393 assertArrayEquals(expect, listTarEntries(result));
394 }
395
396
397
398
399
400
401
402
403
404
405 @Test
406 public void testPrefixWithoutTrailingSlash() throws Exception {
407 commitBazAndFooSlashBar();
408 byte[] result = CLIGitCommand.executeRaw(
409 "git archive --prefix=my- --format=zip master", db).outBytes();
410 String[] expect = { "my-baz", "my-foo/", "my-foo/bar" };
411 String[] actual = listZipEntries(result);
412
413 Arrays.sort(expect);
414 Arrays.sort(actual);
415 assertArrayEquals(expect, actual);
416 }
417
418 @Test
419 public void testTarPrefixWithoutTrailingSlash() throws Exception {
420 commitBazAndFooSlashBar();
421 byte[] result = CLIGitCommand.executeRaw(
422 "git archive --prefix=my- --format=tar master", db).outBytes();
423 String[] expect = { "my-baz", "my-foo/", "my-foo/bar" };
424 String[] actual = listTarEntries(result);
425
426 Arrays.sort(expect);
427 Arrays.sort(actual);
428 assertArrayEquals(expect, actual);
429 }
430
431 @Test
432 public void testArchiveIncludesSubmoduleDirectory() throws Exception {
433 writeTrashFile("a", "a file with content!");
434 writeTrashFile("c", "after submodule");
435 git.add().addFilepattern("a").call();
436 git.add().addFilepattern("c").call();
437 git.commit().setMessage("initial commit").call();
438 git.submoduleAdd().setURI("./.").setPath("b").call().close();
439 git.commit().setMessage("add submodule").call();
440
441 byte[] result = CLIGitCommand.executeRaw(
442 "git archive --format=zip master", db).outBytes();
443 String[] expect = { ".gitmodules", "a", "b/", "c" };
444 String[] actual = listZipEntries(result);
445
446 Arrays.sort(expect);
447 Arrays.sort(actual);
448 assertArrayEquals(expect, actual);
449 }
450
451 @Test
452 public void testTarIncludesSubmoduleDirectory() throws Exception {
453 writeTrashFile("a", "a file with content!");
454 writeTrashFile("c", "after submodule");
455 git.add().addFilepattern("a").call();
456 git.add().addFilepattern("c").call();
457 git.commit().setMessage("initial commit").call();
458 git.submoduleAdd().setURI("./.").setPath("b").call().close();
459 git.commit().setMessage("add submodule").call();
460
461 byte[] result = CLIGitCommand.executeRaw(
462 "git archive --format=tar master", db).outBytes();
463 String[] expect = { ".gitmodules", "a", "b/", "c" };
464 String[] actual = listTarEntries(result);
465
466 Arrays.sort(expect);
467 Arrays.sort(actual);
468 assertArrayEquals(expect, actual);
469 }
470
471 @Test
472 public void testArchivePreservesMode() throws Exception {
473 writeTrashFile("plain", "a file with content");
474 writeTrashFile("executable", "an executable file");
475 writeTrashFile("symlink", "plain");
476 writeTrashFile("dir/content", "clutter in a subdir");
477 git.add().addFilepattern("plain").call();
478 git.add().addFilepattern("executable").call();
479 git.add().addFilepattern("symlink").call();
480 git.add().addFilepattern("dir").call();
481
482 DirCache cache = db.lockDirCache();
483 cache.getEntry("executable").setFileMode(FileMode.EXECUTABLE_FILE);
484 cache.getEntry("symlink").setFileMode(FileMode.SYMLINK);
485 cache.write();
486 cache.commit();
487 cache.unlock();
488
489 git.commit().setMessage("three files with different modes").call();
490
491 byte[] zipData = CLIGitCommand.executeRaw(
492 "git archive --format=zip master", db).outBytes();
493 writeRaw("zip-with-modes.zip", zipData);
494 assertContainsEntryWithMode("zip-with-modes.zip", "-rw-", "plain");
495 assertContainsEntryWithMode("zip-with-modes.zip", "-rwx", "executable");
496 assertContainsEntryWithMode("zip-with-modes.zip", "l", "symlink");
497 assertContainsEntryWithMode("zip-with-modes.zip", "-rw-", "dir/");
498 }
499
500 @Test
501 public void testTarPreservesMode() throws Exception {
502 writeTrashFile("plain", "a file with content");
503 writeTrashFile("executable", "an executable file");
504 writeTrashFile("symlink", "plain");
505 writeTrashFile("dir/content", "clutter in a subdir");
506 git.add().addFilepattern("plain").call();
507 git.add().addFilepattern("executable").call();
508 git.add().addFilepattern("symlink").call();
509 git.add().addFilepattern("dir").call();
510
511 DirCache cache = db.lockDirCache();
512 cache.getEntry("executable").setFileMode(FileMode.EXECUTABLE_FILE);
513 cache.getEntry("symlink").setFileMode(FileMode.SYMLINK);
514 cache.write();
515 cache.commit();
516 cache.unlock();
517
518 git.commit().setMessage("three files with different modes").call();
519
520 byte[] archive = CLIGitCommand.executeRaw(
521 "git archive --format=tar master", db).outBytes();
522 writeRaw("with-modes.tar", archive);
523 assertTarContainsEntry("with-modes.tar", "-rw-r--r--", "plain");
524 assertTarContainsEntry("with-modes.tar", "-rwxr-xr-x", "executable");
525 assertTarContainsEntry("with-modes.tar", "l", "symlink -> plain");
526 assertTarContainsEntry("with-modes.tar", "drwxr-xr-x", "dir/");
527 }
528
529 @Test
530 public void testArchiveWithLongFilename() throws Exception {
531 String filename = "";
532 List<String> l = new ArrayList<String>();
533 for (int i = 0; i < 20; i++) {
534 filename = filename + "1234567890/";
535 l.add(filename);
536 }
537 filename = filename + "1234567890";
538 l.add(filename);
539 writeTrashFile(filename, "file with long path");
540 git.add().addFilepattern("1234567890").call();
541 git.commit().setMessage("file with long name").call();
542
543 byte[] result = CLIGitCommand.executeRaw(
544 "git archive --format=zip HEAD", db).outBytes();
545 assertArrayEquals(l.toArray(new String[l.size()]),
546 listZipEntries(result));
547 }
548
549 @Test
550 public void testTarWithLongFilename() throws Exception {
551 String filename = "";
552 List<String> l = new ArrayList<String>();
553 for (int i = 0; i < 20; i++) {
554 filename = filename + "1234567890/";
555 l.add(filename);
556 }
557 filename = filename + "1234567890";
558 l.add(filename);
559 writeTrashFile(filename, "file with long path");
560 git.add().addFilepattern("1234567890").call();
561 git.commit().setMessage("file with long name").call();
562
563 byte[] result = CLIGitCommand.executeRaw(
564 "git archive --format=tar HEAD", db).outBytes();
565 assertArrayEquals(l.toArray(new String[l.size()]),
566 listTarEntries(result));
567 }
568
569 @Test
570 public void testArchivePreservesContent() throws Exception {
571 String payload = "“The quick brown fox jumps over the lazy dog!”";
572 writeTrashFile("xyzzy", payload);
573 git.add().addFilepattern("xyzzy").call();
574 git.commit().setMessage("add file with content").call();
575
576 byte[] result = CLIGitCommand.executeRaw(
577 "git archive --format=zip HEAD", db).outBytes();
578 assertArrayEquals(new String[] { payload },
579 zipEntryContent(result, "xyzzy"));
580 }
581
582 @Test
583 public void testTarPreservesContent() throws Exception {
584 String payload = "“The quick brown fox jumps over the lazy dog!”";
585 writeTrashFile("xyzzy", payload);
586 git.add().addFilepattern("xyzzy").call();
587 git.commit().setMessage("add file with content").call();
588
589 byte[] result = CLIGitCommand.executeRaw(
590 "git archive --format=tar HEAD", db).outBytes();
591 assertArrayEquals(new String[] { payload },
592 tarEntryContent(result, "xyzzy"));
593 }
594
595 private Process spawnAssumingCommandPresent(String... cmdline) {
596 File cwd = db.getWorkTree();
597 ProcessBuilder procBuilder = new ProcessBuilder(cmdline)
598 .directory(cwd)
599 .redirectErrorStream(true);
600 Process proc = null;
601 try {
602 proc = procBuilder.start();
603 } catch (IOException e) {
604
605 assumeNoException(e);
606 }
607
608 return proc;
609 }
610
611 private BufferedReader readFromProcess(Process proc) throws Exception {
612 return new BufferedReader(
613 new InputStreamReader(proc.getInputStream(), "UTF-8"));
614 }
615
616 private void grepForEntry(String name, String mode, String... cmdline)
617 throws Exception {
618 Process proc = spawnAssumingCommandPresent(cmdline);
619 proc.getOutputStream().close();
620 BufferedReader reader = readFromProcess(proc);
621 try {
622 String line;
623 while ((line = reader.readLine()) != null)
624 if (line.startsWith(mode) && line.endsWith(name))
625
626 return;
627 fail("expected entry " + name + " with mode " + mode + " but found none");
628 } finally {
629 proc.getOutputStream().close();
630 proc.destroy();
631 }
632 }
633
634 private void assertMagic(long offset, byte[] magicBytes, File file) throws Exception {
635 BufferedInputStream in = new BufferedInputStream(
636 new FileInputStream(file));
637 try {
638 in.skip(offset);
639
640 byte[] actual = new byte[magicBytes.length];
641 in.read(actual);
642 assertArrayEquals(magicBytes, actual);
643 } finally {
644 in.close();
645 }
646 }
647
648 private void assertMagic(byte[] magicBytes, File file) throws Exception {
649 assertMagic(0, magicBytes, file);
650 }
651
652 private void assertIsTar(File file) throws Exception {
653 assertMagic(257, new byte[] { 'u', 's', 't', 'a', 'r', 0 }, file);
654 }
655
656 private void assertIsZip(File file) throws Exception {
657 assertMagic(new byte[] { 'P', 'K', 3, 4 }, file);
658 }
659
660 private void assertIsGzip(File file) throws Exception {
661 assertMagic(new byte[] { 037, (byte) 0213 }, file);
662 }
663
664 private void assertIsBzip2(File file) throws Exception {
665 assertMagic(new byte[] { 'B', 'Z', 'h' }, file);
666 }
667
668 private void assertIsXz(File file) throws Exception {
669 assertMagic(new byte[] { (byte) 0xfd, '7', 'z', 'X', 'Z', 0 }, file);
670 }
671
672 private void assertContainsEntryWithMode(String zipFilename, String mode, String name)
673 throws Exception {
674 grepForEntry(name, mode, "zipinfo", zipFilename);
675 }
676
677 private void assertTarContainsEntry(String tarfile, String mode, String name)
678 throws Exception {
679 grepForEntry(name, mode, "tar", "tvf", tarfile);
680 }
681
682 private void writeRaw(String filename, byte[] data)
683 throws IOException {
684 File path = new File(db.getWorkTree(), filename);
685 OutputStream out = new FileOutputStream(path);
686 try {
687 out.write(data);
688 } finally {
689 out.close();
690 }
691 }
692
693 private static String[] listZipEntries(byte[] zipData) throws IOException {
694 List<String> l = new ArrayList<String>();
695 ZipInputStream in = new ZipInputStream(
696 new ByteArrayInputStream(zipData));
697
698 ZipEntry e;
699 while ((e = in.getNextEntry()) != null)
700 l.add(e.getName());
701 in.close();
702 return l.toArray(new String[l.size()]);
703 }
704
705 private static Future<Object> writeAsync(final OutputStream stream, final byte[] data) {
706 ExecutorService executor = Executors.newSingleThreadExecutor();
707
708 return executor.submit(new Callable<Object>() {
709 public Object call() throws IOException {
710 try {
711 stream.write(data);
712 return null;
713 } finally {
714 stream.close();
715 }
716 }
717 });
718 }
719
720 private String[] listTarEntries(byte[] tarData) throws Exception {
721 List<String> l = new ArrayList<String>();
722 Process proc = spawnAssumingCommandPresent("tar", "tf", "-");
723 BufferedReader reader = readFromProcess(proc);
724 OutputStream out = proc.getOutputStream();
725
726
727 Future<?> writing = writeAsync(out, tarData);
728
729 try {
730 String line;
731 while ((line = reader.readLine()) != null)
732 l.add(line);
733
734 return l.toArray(new String[l.size()]);
735 } finally {
736 writing.get();
737 reader.close();
738 proc.destroy();
739 }
740 }
741
742 private static String[] zipEntryContent(byte[] zipData, String path)
743 throws IOException {
744 ZipInputStream in = new ZipInputStream(
745 new ByteArrayInputStream(zipData));
746 ZipEntry e;
747 while ((e = in.getNextEntry()) != null) {
748 if (!e.getName().equals(path))
749 continue;
750
751
752 List<String> l = new ArrayList<String>();
753 BufferedReader reader = new BufferedReader(
754 new InputStreamReader(in, "UTF-8"));
755 String line;
756 while ((line = reader.readLine()) != null)
757 l.add(line);
758 return l.toArray(new String[l.size()]);
759 }
760
761
762 return null;
763 }
764
765 private String[] tarEntryContent(byte[] tarData, String path)
766 throws Exception {
767 List<String> l = new ArrayList<String>();
768 Process proc = spawnAssumingCommandPresent("tar", "Oxf", "-", path);
769 BufferedReader reader = readFromProcess(proc);
770 OutputStream out = proc.getOutputStream();
771 Future<?> writing = writeAsync(out, tarData);
772
773 try {
774 String line;
775 while ((line = reader.readLine()) != null)
776 l.add(line);
777
778 return l.toArray(new String[l.size()]);
779 } finally {
780 writing.get();
781 reader.close();
782 proc.destroy();
783 }
784 }
785 }