diff options
author | Pascal Rapicault | 2012-04-25 13:40:46 +0000 |
---|---|---|
committer | Pascal Rapicault | 2012-04-28 01:17:38 +0000 |
commit | 85f365d1c3e178bde1ae62dd343bf782edcd7264 (patch) | |
tree | 53b808c1e6f7fcd57fd5270309616feba6db357c /bundles | |
parent | 48addd2f57b4cb4299e7353d6d8061fc97c13585 (diff) | |
download | rt.equinox.p2-85f365d1c3e178bde1ae62dd343bf782edcd7264.tar.gz rt.equinox.p2-85f365d1c3e178bde1ae62dd343bf782edcd7264.tar.xz rt.equinox.p2-85f365d1c3e178bde1ae62dd343bf782edcd7264.zip |
Bug 307580 - [native] Add support for include/exclude patterns in unzip
action
Diffstat (limited to 'bundles')
7 files changed, 297 insertions, 22 deletions
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/touchpoint/natives/UnzipActionTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/touchpoint/natives/UnzipActionTest.java index cc63961f5..9c8fd12ed 100644 --- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/touchpoint/natives/UnzipActionTest.java +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/touchpoint/natives/UnzipActionTest.java @@ -189,4 +189,167 @@ public class UnzipActionTest extends AbstractProvisioningTest { backup.discard(); } + + /** + * Test that when a path is used only files from that path down are unzipped to target as well as undo works. + */ + public void testPath() { + String a = "a.txt"; + String b = "foo/b.txt"; + String c = "foo/bar/car/c.txt"; + String b1 = "b.txt"; + String c1 = "bar/car/c.txt"; + String c2 = "car/c.txt"; + + { + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put(ActionConstants.PARM_PATH, "foo"); + testUnzip(parameters, getTempFolder(), new String[] {b1, c1}, new String[] {a, b, c}); + } + { + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put(ActionConstants.PARM_PATH, "foo/"); + testUnzip(parameters, getTempFolder(), new String[] {b1, c1}, new String[] {a, b, c}); + } + { + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put(ActionConstants.PARM_PATH, "**/bar"); + testUnzip(parameters, getTempFolder(), new String[] {c2}, new String[] {a, b, c, b1}); + } + } + + /** + * Tests that only the files specified by inclusion path are unzipped as well as undo works. + */ + public void testInclusion() { + String a = "a.txt"; + String b = "foo/b.txt"; + String c = "foo/bar/car/c.txt"; + + // full path + { + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put(ActionConstants.PARM_INCLUDE, "foo/b.txt"); + testUnzip(parameters, getTempFolder(), new String[] {b}, new String[] {a, c}); + } + // wildcarded path + { + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put(ActionConstants.PARM_INCLUDE, "*/b.txt"); + testUnzip(parameters, getTempFolder(), new String[] {b}, new String[] {a, c}); + } + // subdir wildcarded path + { + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put(ActionConstants.PARM_INCLUDE, "**/c.txt"); + testUnzip(parameters, getTempFolder(), new String[] {c}, new String[] {a, b}); + } + } + + /** + * Tests that only the files specified by exclusion path are not unzipped as well as undo works. + */ + public void testExclusion() { + String a = "a.txt"; + String b = "foo/b.txt"; + String c = "foo/bar/car/c.txt"; + + // full path + { + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put(ActionConstants.PARM_EXCLUDE, "foo/b.txt"); + testUnzip(parameters, getTempFolder(), new String[] {a, c}, new String[] {b}); + } + // wildcarded path + { + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put(ActionConstants.PARM_EXCLUDE, "*/b.txt"); + testUnzip(parameters, getTempFolder(), new String[] {a, c}, new String[] {b}); + } + // subdir wildcarded path + { + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put(ActionConstants.PARM_EXCLUDE, "**/c.txt"); + testUnzip(parameters, getTempFolder(), new String[] {a, b}, new String[] {c}); + } + } + + /** + * Tests that only the files specified by inclusion path and not in exclusion path are unzipped as well as undo works. + */ + public void testInclusionAndExclusion() { + String a = "a.txt"; + String b = "foo/b.txt"; + String c = "foo/bar/car/c.txt"; + + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put(ActionConstants.PARM_INCLUDE, "*.txt"); + parameters.put(ActionConstants.PARM_EXCLUDE, "**/c.txt"); + testUnzip(parameters, getTempFolder(), new String[] {a, b}, new String[] {c}); + } + + private void testUnzip(Map<String, String> params, File installFolder, String[] shoudlExistNames, String[] shoudlNotExistNames) { + + ArrayList<File> shoudlExist = new ArrayList<File>(); + ArrayList<File> shoudlNotExist = new ArrayList<File>(); + + // first check that are no files in install folder + for (String fileName : shoudlExistNames) { + File file = new File(installFolder, fileName); + shoudlExist.add(file); + assertFalse("File " + file.getPath() + " should not exist", file.exists()); + } + for (String fileName : shoudlNotExistNames) { + File file = new File(installFolder, fileName); + shoudlNotExist.add(file); + assertFalse("File " + file.getPath() + " should not exist", file.exists()); + } + + Properties profileProperties = new Properties(); + profileProperties.setProperty(IProfile.PROP_INSTALL_FOLDER, installFolder.toString()); + IProfile profile = createProfile("test", profileProperties); + + File zipSource = getTestData("1.0", "/testData/nativeTouchpoint/a.dir.zip"); + File zipTarget = new File(installFolder, "a.dir.zip"); + copy("2.0", zipSource, zipTarget); + + InstallableUnitDescription iuDesc = new MetadataFactory.InstallableUnitDescription(); + iuDesc.setId("test"); + iuDesc.setVersion(DEFAULT_VERSION); + IArtifactKey key = PublisherHelper.createBinaryArtifactKey("test", DEFAULT_VERSION); + iuDesc.setArtifacts(new IArtifactKey[] {key}); + iuDesc.setTouchpointType(PublisherHelper.TOUCHPOINT_NATIVE); + IInstallableUnit iu = MetadataFactory.createInstallableUnit(iuDesc); + + Map parameters = new HashMap(); + parameters.put(ActionConstants.PARM_PROFILE, profile); + parameters.put("iu", iu); + parameters.put(ActionConstants.PARM_PROFILE, profile); + NativeTouchpoint touchpoint = new NativeTouchpoint(); + touchpoint.initializePhase(null, profile, "test", parameters); + + parameters.put(ActionConstants.PARM_SOURCE, zipTarget.getAbsolutePath()); + parameters.put(ActionConstants.PARM_TARGET, installFolder.getAbsolutePath()); + parameters.putAll(params); + parameters = Collections.unmodifiableMap(parameters); + + UnzipAction action = new UnzipAction(); + action.execute(parameters); + for (File file : shoudlExist) { + assertTrue("File " + file.getPath() + " should exist", file.exists()); + } + for (File file : shoudlNotExist) { + assertFalse("File " + file.getPath() + " should not exist", file.exists()); + } + + // does nothing so should not alter parameters + action.undo(parameters); + // check that undo removed all files + for (File file : shoudlExist) { + assertFalse("File " + file.getPath() + " should not exist", file.exists()); + } + for (File file : shoudlNotExist) { + assertFalse("File " + file.getPath() + " should not exist", file.exists()); + } + } }
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/nativeTouchpoint/dirFolder/a.txt b/bundles/org.eclipse.equinox.p2.tests/testData/nativeTouchpoint/dirFolder/a.txt new file mode 100644 index 000000000..c78a316ea --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests/testData/nativeTouchpoint/dirFolder/a.txt @@ -0,0 +1,2 @@ +A +// This a.txt should have the first line being a single A diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/nativeTouchpoint/dirFolder/foo/b.txt b/bundles/org.eclipse.equinox.p2.tests/testData/nativeTouchpoint/dirFolder/foo/b.txt new file mode 100644 index 000000000..11e42f95a --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests/testData/nativeTouchpoint/dirFolder/foo/b.txt @@ -0,0 +1,2 @@ +B +// This b.txt should have the first line being a single B diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/nativeTouchpoint/dirFolder/foo/bar/car/c.txt b/bundles/org.eclipse.equinox.p2.tests/testData/nativeTouchpoint/dirFolder/foo/bar/car/c.txt new file mode 100644 index 000000000..afdfac685 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests/testData/nativeTouchpoint/dirFolder/foo/bar/car/c.txt @@ -0,0 +1,2 @@ +C +// This c.txt should have the first line being a single C diff --git a/bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/p2/touchpoint/natives/Util.java b/bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/p2/touchpoint/natives/Util.java index 432dad556..3696bc15c 100644 --- a/bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/p2/touchpoint/natives/Util.java +++ b/bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/p2/touchpoint/natives/Util.java @@ -13,6 +13,8 @@ package org.eclipse.equinox.internal.p2.touchpoint.natives; import java.io.*; import java.net.URI; import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.eclipse.core.runtime.*; @@ -81,9 +83,19 @@ public class Util { * monitor and backup store may be null. */ public static File[] unzipFile(File zipFile, File outputDir, IBackupStore store, String taskName, IProgressMonitor monitor) throws IOException { + return unzipFile(zipFile, outputDir, null /*path*/, null /*includes*/, null /*excludes*/, store, taskName, monitor); + } + + /** + * Unzip from a File to an output directory, with progress indication and backup. + * monitor and backup store may be null. + * It takes in count exclude/exclude pattern (that can be null, case when everything is unzipped). + * If a path is specified, the path is consider as entry point in zip, as when the to directory in zip would have been the specified path. + */ + public static File[] unzipFile(File zipFile, File outputDir, String path, String[] includePatterns, String[] excludePatterns, IBackupStore store, String taskName, IProgressMonitor monitor) throws IOException { InputStream in = new FileInputStream(zipFile); try { - return unzipStream(in, zipFile.length(), outputDir, store, taskName, monitor); + return unzipStream(in, zipFile.length(), outputDir, path, includePatterns, excludePatterns, store, taskName, monitor); } catch (IOException e) { // add the file name to the message throw new IOException(NLS.bind(Messages.Util_Error_Unzipping, zipFile, e.getMessage())); @@ -97,6 +109,16 @@ public class Util { * if backup store is not null. */ public static File[] unzipStream(InputStream stream, long size, File outputDir, IBackupStore store, String taskName, IProgressMonitor monitor) throws IOException { + return unzipStream(stream, size, outputDir, null /*path*/, null /*includes*/, null /*excludes*/, store, taskName, monitor); + } + + /** + * Unzip from an InputStream to an output directory using backup of overwritten files + * if backup store is not null. + * It takes in count exclude/exclude pattern (that can be null, case when everything is unzipped). + * If a path is specified, the path is consider as entry point in zip, as when the to directory in zip would have been the specified path. + */ + public static File[] unzipStream(InputStream stream, long size, File outputDir, String path, String[] includePatterns, String[] excludePatterns, IBackupStore store, String taskName, IProgressMonitor monitor) throws IOException { InputStream is = monitor == null ? stream : stream; // new ProgressMonitorInputStream(stream, size, size, taskName, monitor); TODO Commented code ZipInputStream in = new ZipInputStream(new BufferedInputStream(is)); ZipEntry ze = in.getNextEntry(); @@ -106,28 +128,76 @@ public class Util { in.close(); throw new IOException(Messages.Util_Invalid_Zip_File_Format); } + + if (path != null && path.trim().length() == 0) + path = null; + Pattern pathRegex = path == null ? null : createAntStylePattern("(" + path + ")(*)"); //$NON-NLS-1$ //$NON-NLS-2$ + + Collection<Pattern> includeRegexp = new ArrayList<Pattern>(); + Collection<Pattern> excludeRegexp = new ArrayList<Pattern>(); + if (includePatterns != null) { + for (String pattern : includePatterns) { + if (pattern != null) { + includeRegexp.add(createAntStylePattern(pattern)); + } + } + } + if (excludePatterns != null) { + for (String pattern : excludePatterns) { + if (pattern != null) { + excludeRegexp.add(createAntStylePattern(pattern)); + } + } + } ArrayList<File> unzippedFiles = new ArrayList<File>(); do { - File outFile = new File(outputDir, ze.getName()); - unzippedFiles.add(outFile); - if (ze.isDirectory()) { - outFile.mkdirs(); - } else { - if (outFile.exists()) { - if (store != null) - store.backup(outFile); - else - outFile.delete(); - } else { - outFile.getParentFile().mkdirs(); + String name = ze.getName(); + if (pathRegex == null || pathRegex.matcher(name).matches()) { + boolean unzip = includeRegexp.isEmpty(); + for (Pattern pattern : includeRegexp) { + unzip = pattern.matcher(name).matches(); + if (unzip) + break; + } + if (unzip && !excludeRegexp.isEmpty()) { + for (Pattern pattern : excludeRegexp) { + if (pattern.matcher(name).matches()) { + unzip = false; + break; + } + } } - try { - copyStream(in, false, new FileOutputStream(outFile), true); - } catch (FileNotFoundException e) { - // TEMP: ignore this for now in case we're trying to replace - // a running eclipse.exe + if (unzip) { + if (pathRegex != null) { + Matcher matcher = pathRegex.matcher(name); + if (matcher.matches()) { + name = matcher.group(2); + if (name.startsWith("/")) //$NON-NLS-1$ + name = name.substring(1); + } + } + File outFile = new File(outputDir, name); + unzippedFiles.add(outFile); + if (ze.isDirectory()) { + outFile.mkdirs(); + } else { + if (outFile.exists()) { + if (store != null) + store.backup(outFile); + else + outFile.delete(); + } else { + outFile.getParentFile().mkdirs(); + } + try { + copyStream(in, false, new FileOutputStream(outFile), true); + } catch (FileNotFoundException e) { + // TEMP: ignore this for now in case we're trying to replace + // a running eclipse.exe + } + outFile.setLastModified(ze.getTime()); + } } - outFile.setLastModified(ze.getTime()); } in.closeEntry(); } while ((ze = in.getNextEntry()) != null); @@ -163,4 +233,31 @@ public class Util { } } } + + private static Pattern createAntStylePattern(String pattern) { + StringBuffer sb = new StringBuffer(); + for (int c = 0; c < pattern.length(); c++) { + switch (pattern.charAt(c)) { + case '.' : + sb.append("\\."); //$NON-NLS-1$ + break; + case '*' : + sb.append(".*"); //$NON-NLS-1$ + break; + case '?' : + sb.append(".?"); //$NON-NLS-1$ + break; + default : + sb.append(pattern.charAt(c)); + break; + } + } + String string = sb.toString(); + if (string.endsWith("\\..*")) { //$NON-NLS-1$ + sb.append("|"); //$NON-NLS-1$ + sb.append(string.substring(0, string.length() - 4)); + } + return Pattern.compile(sb.toString()); + } + } diff --git a/bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/p2/touchpoint/natives/actions/ActionConstants.java b/bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/p2/touchpoint/natives/actions/ActionConstants.java index 0818a1ec3..daa448bd6 100644 --- a/bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/p2/touchpoint/natives/actions/ActionConstants.java +++ b/bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/p2/touchpoint/natives/actions/ActionConstants.java @@ -19,6 +19,8 @@ public class ActionConstants { public static final String PARM_TARGET_DIR = "targetDir"; //$NON-NLS-1$ public static final String PARM_TARGET = "target"; //$NON-NLS-1$ public static final String PARM_SOURCE = "source"; //$NON-NLS-1$ + public static final String PARM_INCLUDE = "include"; //$NON-NLS-1$ + public static final String PARM_EXCLUDE = "exclude"; //$NON-NLS-1$ public static final String PARM_IU = "iu"; //$NON-NLS-1$ public static final String PIPE = "|"; //$NON-NLS-1$ public static final String PARM_AT_ARTIFACT = "@artifact"; //$NON-NLS-1$ diff --git a/bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/p2/touchpoint/natives/actions/UnzipAction.java b/bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/p2/touchpoint/natives/actions/UnzipAction.java index c2a9150e1..0d87a5718 100644 --- a/bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/p2/touchpoint/natives/actions/UnzipAction.java +++ b/bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/p2/touchpoint/natives/actions/UnzipAction.java @@ -62,7 +62,12 @@ public class UnzipAction extends ProvisioningAction { source = artifactLocation; } IBackupStore store = restoreable ? (IBackupStore) parameters.get(NativeTouchpoint.PARM_BACKUP) : null; - File[] unzippedFiles = unzip(source, target, store); + + String path = (String) parameters.get(ActionConstants.PARM_PATH); + String includePattern = (String) parameters.get(ActionConstants.PARM_INCLUDE); + String excludePattern = (String) parameters.get(ActionConstants.PARM_EXCLUDE); + + File[] unzippedFiles = unzip(source, target, path, includePattern, excludePattern, store); StringBuffer unzippedFileNameBuffer = new StringBuffer(); for (int i = 0; i < unzippedFiles.length; i++) unzippedFileNameBuffer.append(unzippedFiles[i].getAbsolutePath()).append(ActionConstants.PIPE); @@ -76,14 +81,16 @@ public class UnzipAction extends ProvisioningAction { * Unzips a source zip into the given destination. Any existing contents in the destination * are backed up in the provided backup store. */ - private static File[] unzip(String source, String destination, IBackupStore store) { + private static File[] unzip(String source, String destination, String path, String includePattern, String excludePattern, IBackupStore store) { File zipFile = new File(source); if (zipFile == null || !zipFile.exists()) { Util.log(UnzipAction.class.getName() + " the files to be unzipped is not here"); //$NON-NLS-1$ } try { String taskName = NLS.bind(Messages.unzipping, source); - return Util.unzipFile(zipFile, new File(destination), store, taskName, new NullProgressMonitor()); + String[] includes = includePattern == null ? null : includePattern.split("\\s+"); //$NON-NLS-1$ + String[] excludes = excludePattern == null ? null : excludePattern.split("\\s+"); //$NON-NLS-1$ + return Util.unzipFile(zipFile, new File(destination), path, includes, excludes, store, taskName, new NullProgressMonitor()); } catch (IOException e) { Util.log(UnzipAction.class.getName() + " error unzipping zipfile: " + zipFile.getAbsolutePath() + "destination: " + destination); //$NON-NLS-1$ //$NON-NLS-2$ } |