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