Merge pull request #1027 from eclipse/ade-mergable-manifest-xtend

#1018 Maintain existing formatting.
This commit is contained in:
Arne Deutsch 2019-02-12 09:46:32 +01:00 committed by GitHub
commit 86f6342354
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 189 additions and 38 deletions

View file

@ -134,10 +134,10 @@ public class MergeableManifest2Test {
}
@Test
public void manifest_LineWith513Chars_separatedOnTwoLines() throws Exception {
public void manifest_LineWith513Chars_separatedOnTwoLinesStaySeperated() throws Exception {
MergeableManifest2 manifest = newManifest("test: " + repeat("a", 506) + NL + " " + repeat("a", 7) + NL);
assertEquals(repeat("a", 513), getMainAttributeValue(manifest, "test"));
assertEquals(repeat("a", 506) + NL + " " + repeat("a", 7), getMainAttributeValue(manifest, "test"));
}
@Test(expected = IOException.class)
@ -201,21 +201,21 @@ public class MergeableManifest2Test {
public void manifest_oneMainEntry_continuesOnSecondLine() throws Exception {
MergeableManifest2 manifest = newManifest("test: 123\n 456\n");
assertEquals("123456", getMainAttributeValue(manifest, "test"));
assertEquals("123" + NL + " 456", getMainAttributeValue(manifest, "test"));
}
@Test
public void manifest_oneMainEntry_continuesOnSecondLine_windowsStyle() throws Exception {
MergeableManifest2 manifest = newManifest("test: 123\r\n 456\r\n");
assertEquals("123456", getMainAttributeValue(manifest, "test"));
assertEquals("123" + NL + " 456", getMainAttributeValue(manifest, "test"));
}
@Test
public void manifest_oneMainEntry_continuesOnSecondAndThirdLine() throws Exception {
MergeableManifest2 manifest = newManifest("test: 123\n 456\n 789\n");
assertEquals("123456789", getMainAttributeValue(manifest, "test"));
assertEquals("123" + NL + " 456" + NL + " 789", getMainAttributeValue(manifest, "test"));
}
@Test
@ -229,7 +229,7 @@ public class MergeableManifest2Test {
public void manifest_duplicateMainEntry_onTwoLines() throws Exception {
MergeableManifest2 manifest = newManifest("test: 1\n 2\ntest: 2\n 3\n");
assertEquals("23", getMainAttributeValue(manifest, "test"));
assertEquals("2" + NL + " 3", getMainAttributeValue(manifest, "test"));
}
@Test
@ -649,7 +649,7 @@ public class MergeableManifest2Test {
MergeableManifest2 manifest = newManifest("Manifest-Version: 1.0" + NL);
manifest.addRequiredBundles("\"a,b");
assertEquals("Manifest-Version: 1.0" + NL + "Require-Bundle: \"a," + NL + " b" + NL, write(manifest));
assertEquals("Manifest-Version: 1.0" + NL + "Require-Bundle: \"a,b" + NL, write(manifest));
}
@Test
@ -1160,6 +1160,149 @@ public class MergeableManifest2Test {
assertEquals(content, write(manifest));
}
@Test
public void readWrite_addRequiredBundles_realisticManifest_regression_multipleBundlesOnOneLine() throws Exception {
// @formatter:off
String content =
"Manifest-Version: 1.0" + NL +
"Bundle-ManifestVersion: 2" + NL +
"Bundle-Name: Xtext Homeautomation Example - Runtime" + NL +
"Bundle-Vendor: Eclipse Xtext" + NL +
"Bundle-Version: 2.16.0.qualifier" + NL +
"Bundle-SymbolicName: org.eclipse.xtext.example.homeautomation; singleton:=true" + NL +
"Bundle-ActivationPolicy: lazy" + NL +
"Require-Bundle: org.eclipse.xtext,org.eclipse.xtext.xbase,org.eclipse.equinox.common;bundle-version=\"3.5.0\"" + NL +
"Bundle-RequiredExecutionEnvironment: JavaSE-1.8" + NL +
"Export-Package: org.eclipse.xtext.example.homeautomation.ruleEngine.util,org.eclipse.xtext.example.homeautomation.formatting2" + NL +
"Import-Package: org.apache.log4j" + NL +
"Automatic-Module-Name: org.eclipse.xtext.example.homeautomation" + NL;
String expectedContent =
"Manifest-Version: 1.0" + NL +
"Bundle-ManifestVersion: 2" + NL +
"Bundle-Name: Xtext Homeautomation Example - Runtime" + NL +
"Bundle-Vendor: Eclipse Xtext" + NL +
"Bundle-Version: 2.16.0.qualifier" + NL +
"Bundle-SymbolicName: org.eclipse.xtext.example.homeautomation; singleton:=true" + NL +
"Bundle-ActivationPolicy: lazy" + NL +
"Require-Bundle: org.eclipse.xtext,org.eclipse.xtext.xbase,org.eclipse.equinox.common;bundle-version=\"3.5.0\"," + NL +
" org.eclipse.xtext.common.types" + NL +
"Bundle-RequiredExecutionEnvironment: JavaSE-1.8" + NL +
"Export-Package: org.eclipse.xtext.example.homeautomation.ruleEngine.util,org.eclipse.xtext.example.homeautomation.formatting2" + NL +
"Import-Package: org.apache.log4j" + NL +
"Automatic-Module-Name: org.eclipse.xtext.example.homeautomation" + NL;
// @formatter:on
MergeableManifest2 manifest = newManifest(content);
manifest.addRequiredBundles("org.eclipse.xtext.common.types");
assertEquals(expectedContent, write(manifest));
}
@Test
public void readWrite_realisticManifest_regression_xtend() throws Exception {
// @formatter:off
String content =
"Manifest-Version: 1.0" + NL +
"Bundle-ManifestVersion: 2" + NL +
"Bundle-Name: %pluginName" + NL +
"Bundle-SymbolicName: org.eclipse.xtend.core;singleton:=true" + NL +
"Bundle-Version: 2.17.0.qualifier" + NL +
"Bundle-ClassPath: ." + NL +
"Bundle-Vendor: %providerName" + NL +
"Bundle-Localization: plugin" + NL +
"Bundle-RequiredExecutionEnvironment: JavaSE-1.8" + NL +
"Export-Package: org.eclipse.xtend.core;x-friends:=\"org.eclipse.xtend.ide.common," + NL +
" org.eclipse.xtend.caliper.tests," + NL +
" org.eclipse.xtend.ide.tests\"," + NL +
" org.eclipse.xtend.core.compiler;x-friends:=\"org.eclipse.xtend.m2e," + NL +
" org.eclipse.xtend.ide.tests\"," + NL +
" org.eclipse.xtend.core.compiler.batch," + NL +
" org.eclipse.xtend.core.conversion;x-friends:=\"org.eclipse.xtend.ide," + NL +
" org.eclipse.xtend.caliper.tests," + NL +
" org.eclipse.xtend.ide.common\"," + NL +
" org.eclipse.xtend.core.documentation;x-internal:=true," + NL +
" org.eclipse.xtend.core.findReferences;x-internal:=true," + NL +
" org.eclipse.xtend.core.formatting2;x-friends:=\"org.eclipse.xtend.ide,\"" + NL +
" org.eclipse.xtend.ide.common," + NL +
" org.eclipse.xtend.core.imports;x-internal:=true," + NL +
" org.eclipse.xtend.core.javaconverter;x-friends:=\"org.eclipse.xtend.ide,\"" + NL +
" org.eclipse.xtend.ide.common," + NL +
" org.eclipse.xtend.core.jvmmodel;x-friends:=\"org.eclipse.xtend.ide," + NL +
" org.eclipse.xtend.caliper.tests," + NL +
" org.eclipse.xtend.ide.tests," + NL +
" org.eclipse.xtend.ide.common\"" + NL +
"Require-Bundle: org.eclipse.core.runtime;bundle-version=\"3.13.0\"," + NL +
" org.eclipse.emf.ecore;bundle-version=\"2.10.2\";visibility:=reexport" + NL +
"Bundle-ActivationPolicy: lazy" + NL +
"Import-Package: org.apache.log4j;version=\"1.2.15\"" + NL;
// @formatter:on
assertEquals(content, write(newManifest(content)));
}
@Test
public void readWrite_addExportedPackage_realisticManifest_regression_xtend() throws Exception {
// @formatter:off
String content =
"Manifest-Version: 1.0" + NL +
"Bundle-ManifestVersion: 2" + NL +
"Bundle-Name: %pluginName" + NL +
"Export-Package: org.eclipse.xtend.core;x-friends:=\"org.eclipse.xtend.ide.common," + NL +
" org.eclipse.xtend.caliper.tests," + NL +
" org.eclipse.xtend.ide.tests\"," + NL +
" org.eclipse.xtend.core.compiler;x-friends:=\"org.eclipse.xtend.m2e," + NL +
" org.eclipse.xtend.ide.tests\"," + NL +
" org.eclipse.xtend.core.compiler.batch," + NL +
" org.eclipse.xtend.core.conversion;x-friends:=\"org.eclipse.xtend.ide," + NL +
" org.eclipse.xtend.caliper.tests," + NL +
" org.eclipse.xtend.ide.common\"," + NL +
" org.eclipse.xtend.core.documentation;x-internal:=true," + NL +
" org.eclipse.xtend.core.findReferences;x-internal:=true," + NL +
" org.eclipse.xtend.core.formatting2;x-friends:=\"org.eclipse.xtend.ide,\"" + NL +
" org.eclipse.xtend.ide.common," + NL +
" org.eclipse.xtend.core.imports;x-internal:=true," + NL +
" org.eclipse.xtend.core.javaconverter;x-friends:=\"org.eclipse.xtend.ide,\"" + NL +
" org.eclipse.xtend.ide.common," + NL +
" org.eclipse.xtend.core.jvmmodel;x-friends:=\"org.eclipse.xtend.ide," + NL +
" org.eclipse.xtend.caliper.tests," + NL +
" org.eclipse.xtend.ide.tests," + NL +
" org.eclipse.xtend.ide.common\"" + NL +
"Require-Bundle: org.eclipse.core.runtime;bundle-version=\"3.13.0\"," + NL +
" org.eclipse.emf.ecore;bundle-version=\"2.10.2\";visibility:=reexport" + NL +
"Bundle-ActivationPolicy: lazy" + NL +
"Import-Package: org.apache.log4j;version=\"1.2.15\"" + NL;
String expectedNewContent =
"Manifest-Version: 1.0" + NL +
"Bundle-ManifestVersion: 2" + NL +
"Bundle-Name: %pluginName" + NL +
"Export-Package: org.eclipse.xtend.core;x-friends:=\"org.eclipse.xtend.ide.common," + NL +
" org.eclipse.xtend.caliper.tests," + NL +
" org.eclipse.xtend.ide.tests\"," + NL +
" org.eclipse.xtend.core.compiler;x-friends:=\"org.eclipse.xtend.m2e," + NL +
" org.eclipse.xtend.ide.tests\"," + NL +
" org.eclipse.xtend.core.compiler.batch," + NL +
" org.eclipse.xtend.core.conversion;x-friends:=\"org.eclipse.xtend.ide," + NL +
" org.eclipse.xtend.caliper.tests," + NL +
" org.eclipse.xtend.ide.common\"," + NL +
" org.eclipse.xtend.core.documentation;x-internal:=true," + NL +
" org.eclipse.xtend.core.findReferences;x-internal:=true," + NL +
" org.eclipse.xtend.core.formatting2;x-friends:=\"org.eclipse.xtend.ide,\"" + NL +
" org.eclipse.xtend.ide.common," + NL +
" org.eclipse.xtend.core.imports;x-internal:=true," + NL +
" org.eclipse.xtend.core.javaconverter;x-friends:=\"org.eclipse.xtend.ide,\"" + NL +
" org.eclipse.xtend.ide.common," + NL +
" org.eclipse.xtend.core.jvmmodel;x-friends:=\"org.eclipse.xtend.ide," + NL +
" org.eclipse.xtend.caliper.tests," + NL +
" org.eclipse.xtend.ide.tests," + NL +
" org.eclipse.xtend.ide.common\"," + NL +
" test" + NL +
"Require-Bundle: org.eclipse.core.runtime;bundle-version=\"3.13.0\"," + NL +
" org.eclipse.emf.ecore;bundle-version=\"2.10.2\";visibility:=reexport" + NL +
"Bundle-ActivationPolicy: lazy" + NL +
"Import-Package: org.apache.log4j;version=\"1.2.15\"" + NL;
// @formatter:on
MergeableManifest2 newManifest = newManifest(content);
newManifest.addExportedPackages("test");
assertEquals(expectedNewContent, write(newManifest));
}
/**
* In this final test we read all "META-INF/MANIFEST.MF" files from
* classpath. We the:

View file

@ -113,7 +113,7 @@ public class MergeableManifest2 implements Cloneable {
}
lineIndex++;
while (lineIndex < lines.size() && lines.get(lineIndex).startsWith(" ")) {
line += lines.get(lineIndex).substring(1);
line += newline + lines.get(lineIndex);
lineIndex++;
}
if (line.isEmpty()) {
@ -250,7 +250,8 @@ public class MergeableManifest2 implements Cloneable {
String oldBundles = mainAttributes.get(REQUIRE_BUNDLE);
if (oldBundles == null)
oldBundles = "";
BundleList resultList = BundleList.fromInput(oldBundles);
BundleList oldResultList = BundleList.fromInput(oldBundles, newline);
BundleList resultList = BundleList.fromInput(oldBundles, newline);
for (String bundle : requiredBundles) {
Bundle newBundle = Bundle.fromInput(bundle);
if (name != null && name.equals(newBundle.getName()))
@ -258,8 +259,9 @@ public class MergeableManifest2 implements Cloneable {
resultList.mergeInto(newBundle);
}
String result = resultList.toString();
modified |= !oldBundles.equals(result);
if (!oldBundles.equals(result))
boolean changed = !oldResultList.toString().equals(result);
modified |= changed;
if (changed)
mainAttributes.put(REQUIRE_BUNDLE, result);
}
@ -281,12 +283,14 @@ public class MergeableManifest2 implements Cloneable {
String oldBundles = mainAttributes.get(IMPORT_PACKAGE);
if (oldBundles == null)
oldBundles = "";
BundleList resultList = BundleList.fromInput(oldBundles);
BundleList oldResultList = BundleList.fromInput(oldBundles, newline);
BundleList resultList = BundleList.fromInput(oldBundles, newline);
for (String bundle : importedPackages)
resultList.mergeInto(Bundle.fromInput(bundle));
String result = resultList.toString();
modified |= !oldBundles.equals(result);
if (!oldBundles.equals(result))
boolean changed = !oldResultList.toString().equals(result);
modified |= changed;
if (changed)
mainAttributes.put(IMPORT_PACKAGE, result);
}
@ -308,12 +312,14 @@ public class MergeableManifest2 implements Cloneable {
String oldBundles = mainAttributes.get(EXPORT_PACKAGE);
if (oldBundles == null)
oldBundles = "";
BundleList resultList = BundleList.fromInput(oldBundles);
BundleList oldResultList = BundleList.fromInput(oldBundles, newline);
BundleList resultList = BundleList.fromInput(oldBundles, newline);
for (String bundle : exportedPackages)
resultList.mergeInto(Bundle.fromInput(bundle));
String result = resultList.toString();
modified |= !oldBundles.equals(result);
if (!oldBundles.equals(result))
boolean changed = !oldResultList.toString().equals(result);
modified |= changed;
if (changed)
mainAttributes.put(EXPORT_PACKAGE, result);
}
@ -400,8 +406,8 @@ public class MergeableManifest2 implements Cloneable {
String key = entry.getKey();
if (key.equals(MANIFEST_VERSION) || key.equals(SIGNATURE_VERSION))
continue;
String value = entry.getValue();
writer.append(make512Safe(new StringBuffer(key + ": " + separateCommas(value)), newline));
String value = mainAttributes.get(entry.getKey());
writer.append(make512Safe(new StringBuffer(key + ": " + value), newline));
}
}
@ -414,21 +420,11 @@ public class MergeableManifest2 implements Cloneable {
String value = child.getValue();
if (value.isEmpty())
continue;
writer.append(make512Safe(new StringBuffer(key + ": " + separateCommas(value)), newline));
writer.append(make512Safe(new StringBuffer(key + ": " + value), newline));
}
}
}
private String separateCommas(String value) {
String result = "";
String separator = "";
for (String part : splitAtCharHonorQuoting(value, ',')) {
result += separator + part;
separator = "," + newline + " ";
}
return result;
}
private static List<String> splitAtCharHonorQuoting(String value, char c) {
if (value.indexOf(c) == -1)
return Collections.singletonList(value);
@ -648,16 +644,18 @@ public class MergeableManifest2 implements Cloneable {
private static class BundleList {
private final List<Bundle> list;
private final String newline;
public BundleList(List<Bundle> list) {
public BundleList(List<Bundle> list, String newline) {
this.list = list;
this.newline = newline;
}
private static BundleList fromInput(String input) {
private static BundleList fromInput(String input, String newline) {
if (input.isEmpty())
return new BundleList(new ArrayList<>());
return new BundleList(new ArrayList<>(), newline);
return new BundleList(splitAtCharHonorQuoting(input, ',').stream().map(s -> Bundle.fromInput(s))
.collect(Collectors.toList()));
.collect(Collectors.toList()), newline);
}
public void mergeInto(Bundle newBundle) {
@ -688,8 +686,10 @@ public class MergeableManifest2 implements Cloneable {
}
}
}
// in case we add a new bundle and there are already other bundles
// we write it on a new line for better readability
if (!merged)
list.add(newBundle);
list.add(Bundle.fromBundleWithNewName(newBundle, newline + " " + newBundle.getName()));
}
// Output is used by algorithm ... do not change for debugging purposes!
@ -714,6 +714,12 @@ public class MergeableManifest2 implements Cloneable {
return new Bundle(input);
}
public static Bundle fromBundleWithNewName(Bundle bundle, String newName) {
if (bundle.getSuffix() == null)
return new Bundle(newName);
return new Bundle(newName + ";" + bundle.getSuffix());
}
public static Bundle fromNameVersion(String name, String version) {
return new Bundle(name + ";bundle-version=\"" + version + "\"");
}
@ -731,11 +737,13 @@ public class MergeableManifest2 implements Cloneable {
}
public boolean hasSameName(Bundle other) {
return Objects.equals(getName(), other.getName());
// trim because prefix (such as newline) is encoded in the name
return Objects.equals(getName().trim(), other.getName().trim());
}
public String getName() {
return split.get(0);
// trim because prefix (such as newline) is encoded in the name
return split.get(0).trim();
}
public String getSuffix() {
@ -761,7 +769,7 @@ public class MergeableManifest2 implements Cloneable {
// Output is used by algorithm ... do not change for debugging purposes!
@Override
public String toString() {
String bundleName = getName();
String bundleName = split.get(0); // Do not trim to not lose prefix
String bundleVersion = getVersion();
String bundleSuffix = getSuffix();
if (bundleVersion == null && bundleSuffix == null)