Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java7
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/QueryUtil.java25
-rw-r--r--bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/RequestFlexer.java38
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/actions/RootIUAction.java2
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/AllAnyVersionTests.java3
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerProduct.java117
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerSharedInstall.java92
7 files changed, 279 insertions, 5 deletions
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java
index 12a45a2a0..fe741767f 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java
@@ -62,6 +62,13 @@ public final class MetadataFactory {
*/
public static final String PROP_TYPE_CATEGORY = "org.eclipse.equinox.p2.type.category"; //$NON-NLS-1$
+ /**
+ * A property key (value <code>"org.eclipse.equinox.p2.type.product"</code>) for a
+ * boolean property indicating that an installable unit is the root IU of a product.
+ *
+ */
+ public static final String PROP_TYPE_PRODUCT = "org.eclipse.equinox.p2.type.product"; //$NON-NLS-1$
+
public InstallableUnitDescription() {
super();
}
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/QueryUtil.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/QueryUtil.java
index 5b4c54c12..44f7c995c 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/QueryUtil.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/QueryUtil.java
@@ -13,8 +13,7 @@ package org.eclipse.equinox.p2.query;
import java.util.ArrayList;
import java.util.Collection;
import org.eclipse.equinox.internal.p2.metadata.InstallableUnit;
-import org.eclipse.equinox.internal.p2.metadata.expression.ContextExpression;
-import org.eclipse.equinox.internal.p2.metadata.expression.ExpressionFactory;
+import org.eclipse.equinox.internal.p2.metadata.expression.*;
import org.eclipse.equinox.internal.p2.metadata.expression.Expression.VariableFinder;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.expression.*;
@@ -35,6 +34,8 @@ public class QueryUtil {
public static final String PROP_TYPE_GROUP = "org.eclipse.equinox.p2.type.group"; //$NON-NLS-1$
+ public static final String PROP_TYPE_PRODUCT = "org.eclipse.equinox.p2.type.product"; //$NON-NLS-1$
+
public static final String PROP_TYPE_PATCH = "org.eclipse.equinox.p2.type.patch"; //$NON-NLS-1$
private static final IExpression matchesRequirementsExpression = ExpressionUtil.parse("$0.exists(r | this ~= r)"); //$NON-NLS-1$
@@ -210,6 +211,14 @@ public class QueryUtil {
}
/**
+ * Creates an {@link IInstallableUnit} that will match all products.
+ * @return The created query
+ */
+ public static IQuery<IInstallableUnit> createIUProductQuery() {
+ return createIUPropertyQuery(QueryUtil.PROP_TYPE_PRODUCT, Boolean.TRUE.toString());
+ }
+
+ /**
* Creates a query that searches for {@link IInstallableUnit} instances that have
* a property whose value matches the provided value. If no property name is
* specified, then all {@link IInstallableUnit} instances are accepted.
@@ -498,6 +507,18 @@ public class QueryUtil {
}
/**
+ * Test if the {@link IInstallableUnit} is a product.
+ * @param iu the element being tested.
+ * @return <tt>true</tt> if the parameter is a group.
+ */
+ public static boolean isProduct(IInstallableUnit iu) {
+ String value = iu.getProperty(PROP_TYPE_PRODUCT);
+ if (value != null && (value.equals(Boolean.TRUE.toString())))
+ return true;
+ return false;
+ }
+
+ /**
* Test if the {@link IInstallableUnit} is a patch.
* @param iu the element being tested.
* @return <tt>true</tt> if the parameter is a patch.
diff --git a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/RequestFlexer.java b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/RequestFlexer.java
index 25b764807..fc03057cc 100644
--- a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/RequestFlexer.java
+++ b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/RequestFlexer.java
@@ -17,6 +17,7 @@ import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
import org.eclipse.equinox.p2.engine.*;
import org.eclipse.equinox.p2.engine.query.IUProfilePropertyQuery;
+import org.eclipse.equinox.p2.engine.query.UserVisibleRootQuery;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.expression.ExpressionUtil;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
@@ -35,6 +36,10 @@ public class RequestFlexer {
private boolean allowInstalledRemoval = false;
private boolean allowDifferentVersion = false;
private boolean allowPartialInstall = false;
+
+ private boolean ensureProductPresence = true;
+ private boolean honorSharedSettings = true;
+
private ProvisioningContext provisioningContext;
Set<IRequirement> requirementsForElementsBeingInstalled = new HashSet<IRequirement>();
@@ -72,6 +77,10 @@ public class RequestFlexer {
provisioningContext = context;
}
+ public void setEnsureProduct(boolean productPresent) {
+ ensureProductPresence = productPresent;
+ }
+
public IProfileChangeRequest getChangeRequest(IProfileChangeRequest request, IProfile prof, IProgressMonitor monitor) {
this.profile = prof;
IProfileChangeRequest loosenedRequest = computeLooseRequest(request);
@@ -84,6 +93,9 @@ public class RequestFlexer {
if (intermediaryPlan.getAdditions().query(QueryUtil.ALL_UNITS, new NullProgressMonitor()).isEmpty() && intermediaryPlan.getRemovals().query(QueryUtil.ALL_UNITS, new NullProgressMonitor()).isEmpty())
//No changes, we can't return anything
return null;
+ if (!productContainmentOK(intermediaryPlan)) {
+ return null;
+ }
IProfileChangeRequest effectiveRequest = computeEffectiveChangeRequest(intermediaryPlan, loosenedRequest, request);
if (effectiveRequest.getAdditions().isEmpty() && effectiveRequest.getRemovals().isEmpty())
return null;
@@ -92,7 +104,7 @@ public class RequestFlexer {
private boolean canShortCircuit(IProfileChangeRequest originalRequest) {
//Case where the user is asking to install only some of the requested IUs but there is only one IU to install.
- if (allowPartialInstall)
+ if (allowPartialInstall && !allowInstalledUpdate && !allowDifferentVersion && !allowInstalledRemoval)
if (originalRequest.getAdditions().size() == 1 && originalRequest.getRemovals().isEmpty())
return true;
@@ -300,7 +312,7 @@ public class RequestFlexer {
//Loosen up the IUs that are already part of the profile
//Given how we are creating our request, this needs to take into account the removal from the original request as well as the change in inclusion
private IProfileChangeRequest loosenUpInstalledSoftware(IProfileChangeRequest request, IProfileChangeRequest originalRequest) {
- IQueryResult<IInstallableUnit> allRoots = profile.query(new IUProfilePropertyQuery(INCLUSION_RULES, IUProfilePropertyQuery.ANY), null);
+ Set<IInstallableUnit> allRoots = getRoots();
for (IInstallableUnit existingIU : allRoots) {
Collection<IInstallableUnit> potentialUpdates = allowInstalledUpdate ? findUpdates(existingIU) : new HashSet<IInstallableUnit>();
@@ -319,6 +331,15 @@ public class RequestFlexer {
return request;
}
+ private Set<IInstallableUnit> getRoots() {
+ Set<IInstallableUnit> allRoots = profile.query(new IUProfilePropertyQuery(INCLUSION_RULES, IUProfilePropertyQuery.ANY), null).toSet();
+ if (!honorSharedSettings)
+ return allRoots;
+ IQueryResult<IInstallableUnit> baseRoots = profile.query(new IUProfilePropertyQuery("org.eclipse.equinox.p2.base", Boolean.TRUE.toString()), null);
+ allRoots.removeAll(baseRoots.toUnmodifiableSet());
+ return allRoots;
+ }
+
//This return whether or not the given IU is installed optionally or not.
//This also take into account the future state
private boolean isOptionallyInstalled(IInstallableUnit existingIU, IProfileChangeRequest request) {
@@ -353,6 +374,19 @@ public class RequestFlexer {
}
}
return futureOptionalIUs;
+ }
+ private boolean productContainmentOK(IProvisioningPlan intermediaryPlan) {
+ if (!ensureProductPresence)
+ return true;
+ if (!hasProduct())
+ return true;
+ //At this point we know we had a product installed and we want to make sure there is one in the resulting solution
+ return !intermediaryPlan.getFutureState().query(QueryUtil.createIUProductQuery(), new NullProgressMonitor()).isEmpty();
}
+
+ private boolean hasProduct() {
+ return !profile.available(new UserVisibleRootQuery(), new NullProgressMonitor()).query(QueryUtil.createIUPropertyQuery(QueryUtil.PROP_TYPE_PRODUCT, Boolean.TRUE.toString()), new NullProgressMonitor()).isEmpty();
+ }
+
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/actions/RootIUAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/actions/RootIUAction.java
index 4c87ddccb..5f02f79da 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/actions/RootIUAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/actions/RootIUAction.java
@@ -157,7 +157,7 @@ public class RootIUAction extends AbstractPublisherAction {
root.setRequirements(requiredCapabilities.toArray(new IRequirement[requiredCapabilities.size()]));
root.setArtifacts(new IArtifactKey[0]);
- root.setProperty("lineUp", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+ root.setProperty(InstallableUnitDescription.PROP_TYPE_PRODUCT, Boolean.TRUE.toString());
root.setUpdateDescriptor(MetadataFactory.createUpdateDescriptor(id, VersionRange.emptyRange, IUpdateDescriptor.NORMAL, null));
root.setProperty(InstallableUnitDescription.PROP_TYPE_GROUP, Boolean.TRUE.toString());
root.setCapabilities(new IProvidedCapability[] {createSelfCapability(id, version)});
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/AllAnyVersionTests.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/AllAnyVersionTests.java
index cf742e742..b3c31750d 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/AllAnyVersionTests.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/AllAnyVersionTests.java
@@ -20,8 +20,11 @@ public class AllAnyVersionTests extends TestCase {
suite.addTestSuite(TestRequestFlexerOneInstalledOneBeingInstalled.class);
suite.addTestSuite(TestRequestFlexerOneInstalledReplacingIt.class);
suite.addTestSuite(TestRequestFlexerOneInstalledTwoBeingInstalled.class);
+ // suite.addTestSuite(TestRequestFlexerProduct.class);
suite.addTestSuite(TestRequestFlexerRequestWithOptionalInstall.class);
suite.addTestSuite(TestRequestFlexerRequestWithRemoval.class);
+ suite.addTestSuite(TestRequestFlexerSharedInstall.class);
return suite;
+
}
}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerProduct.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerProduct.java
new file mode 100644
index 000000000..a1ab3607d
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerProduct.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, Inc. and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.planner;
+
+import java.util.Properties;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.equinox.internal.p2.operations.RequestFlexer;
+import org.eclipse.equinox.p2.engine.*;
+import org.eclipse.equinox.p2.metadata.*;
+import org.eclipse.equinox.p2.planner.*;
+import org.eclipse.equinox.p2.tests.*;
+
+public class TestRequestFlexerProduct extends AbstractProvisioningTest {
+ public IInstallableUnit sdk1;
+
+ @IUDescription(content = "package: platform \n" + "singleton: true\n" + "version: 1 \n")
+ public IInstallableUnit platform1;
+
+ public IInstallableUnit sdk2;
+
+ @IUDescription(content = "package: platform \n" + "singleton: true\n" + "version: 2 \n")
+ public IInstallableUnit platform2;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 1 \n" + "depends: platform = 1")
+ public IInstallableUnit egit1;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit egit2;
+
+ @IUDescription(content = "package: svn1 \n" + "singleton: true\n" + "version: 1 \n" + "depends: platform = 1")
+ public IInstallableUnit svn1;
+
+ @IUDescription(content = "package: svn2 \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit svn2;
+
+ IProfile profile;
+
+ private IPlanner planner;
+
+ private IEngine engine;
+
+ private IProfileChangeRequest originalRequest;
+
+ private ProvisioningContext context;
+
+ private void setupSDK1() {
+ IRequirement[] reqPlatform1 = new IRequirement[1];
+ reqPlatform1[0] = MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "platform", new VersionRange("[1.0.0,1.0.0]"), null, true, false, true);
+ sdk1 = createIU("SDK", Version.create("1.0.0"), null, reqPlatform1, new IProvidedCapability[0], new Properties(), null, null, true);
+ }
+
+ private void setupSDK2() {
+ IRequirement[] reqPlatform1 = new IRequirement[1];
+ reqPlatform1[0] = MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "platform", new VersionRange("[2.0.0,2.0.0]"), null, true, false, true);
+ sdk2 = createIU("SDK", Version.create("2.0.0"), null, reqPlatform1, new IProvidedCapability[0], new Properties(), null, null, true);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ profile = createProfile("TestProfile." + getName());
+ IULoader.loadIUs(this);
+ setupSDK1();
+ setupSDK2();
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1, sdk2, platform2, egit1, egit2});
+ planner = createPlanner();
+ engine = createEngine();
+ assertOK(installAsRoots(profile, new IInstallableUnit[] {sdk1}, true, planner, engine));
+
+ originalRequest = planner.createChangeRequest(profile);
+ originalRequest.add(egit2);
+ originalRequest.setInstallableUnitInclusionRules(egit2, ProfileInclusionRules.createStrictInclusionRule(egit2));
+ assertNotOK(planner.getProvisioningPlan(originalRequest, context, null).getStatus());
+
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ getProfileRegistry().removeProfile(profile.getProfileId());
+ }
+
+ public void testProductRemovalIsDetected() {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowPartialInstall(false);
+ av.setAllowDifferentVersion(false);
+ av.setAllowInstalledElementRemoval(true);
+ av.setAllowInstalledElementChange(false);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+
+ //There is no solution because with the given criteria, it would remove the product
+ assertNull(realRequest);
+ }
+
+ public void testProductNewProduct() {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowPartialInstall(false);
+ av.setAllowDifferentVersion(false);
+ av.setAllowInstalledElementRemoval(true);
+ av.setAllowInstalledElementChange(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+
+ //In this case we can update the base, so we will find sdk2
+ assertTrue(realRequest.getAdditions().contains(egit2));
+ assertTrue(realRequest.getAdditions().contains(sdk2));
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerSharedInstall.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerSharedInstall.java
new file mode 100644
index 000000000..11a715bd1
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerSharedInstall.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, Inc. and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.planner;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.equinox.internal.p2.operations.RequestFlexer;
+import org.eclipse.equinox.p2.engine.*;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.planner.*;
+import org.eclipse.equinox.p2.tests.*;
+
+public class TestRequestFlexerSharedInstall extends AbstractProvisioningTest {
+ @IUDescription(content = "package: sdk \n" + "singleton: true\n" + "version: 1 \n" + "depends: platform = 1")
+ public IInstallableUnit sdk1;
+
+ @IUDescription(content = "package: platform \n" + "singleton: true\n" + "version: 1 \n")
+ public IInstallableUnit platform1;
+
+ @IUDescription(content = "package: sdk \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit sdk2;
+
+ @IUDescription(content = "package: platform \n" + "singleton: true\n" + "version: 2 \n")
+ public IInstallableUnit platform2;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 1 \n" + "depends: platform = 1")
+ public IInstallableUnit egit1;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit egit2;
+
+ @IUDescription(content = "package: svn1 \n" + "singleton: true\n" + "version: 1 \n" + "depends: platform = 1")
+ public IInstallableUnit svn1;
+
+ @IUDescription(content = "package: svn2 \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit svn2;
+
+ IProfile profile;
+
+ private IPlanner planner;
+
+ private IEngine engine;
+
+ private IProfileChangeRequest originalRequest;
+
+ private ProvisioningContext context;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ profile = createProfile("TestProfile." + getName());
+ IULoader.loadIUs(this);
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1, sdk2, platform2, egit1, egit2});
+ planner = createPlanner();
+ engine = createEngine();
+ assertOK(installAsRootsAndFlaggedAsBase(profile, new IInstallableUnit[] {sdk1}, true, planner, engine));
+
+ originalRequest = planner.createChangeRequest(profile);
+ originalRequest.add(egit2);
+ originalRequest.setInstallableUnitInclusionRules(egit2, ProfileInclusionRules.createStrictInclusionRule(egit2));
+ assertNotOK(planner.getProvisioningPlan(originalRequest, context, null).getStatus());
+
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ getProfileRegistry().removeProfile(profile.getProfileId());
+ }
+
+ public void testBaseBlocked() {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowPartialInstall(false);
+ av.setAllowDifferentVersion(false);
+ av.setAllowInstalledElementRemoval(true);
+ av.setAllowInstalledElementChange(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+
+ //Even though we allow for the base to change (removal and change), there is no solution because it is a shared install
+ //and thus the roots from the base are immutable
+ assertNull(realRequest);
+ }
+
+}

Back to the top