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