diff options
author | Pascal Rapicault (Ericsson) | 2013-02-14 21:18:26 +0000 |
---|---|---|
committer | Pascal Rapicault | 2013-02-14 21:18:26 +0000 |
commit | 9e096dc6c118e0af8ac81ae8a0e9398397557368 (patch) | |
tree | 7428fdd732761ddc51aa5e5263ac6da8fdec7b84 | |
parent | 4d94af97f0fbf679496a68be657684c297994aa3 (diff) | |
download | rt.equinox.p2-9e096dc6c118e0af8ac81ae8a0e9398397557368.tar.gz rt.equinox.p2-9e096dc6c118e0af8ac81ae8a0e9398397557368.tar.xz rt.equinox.p2-9e096dc6c118e0af8ac81ae8a0e9398397557368.zip |
Improve logic to detect whether migration is needed
3 files changed, 153 insertions, 9 deletions
diff --git a/bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF index bfd8881e6..224ab0911 100644 --- a/bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF @@ -53,7 +53,8 @@ Require-Bundle: org.eclipse.equinox.frameworkadmin, org.apache.ant;bundle-version="1.7.1", org.eclipse.equinox.p2.transport.ecf;bundle-version="1.0.0", org.eclipse.equinox.p2.publisher.eclipse;bundle-version="1.0.0", - org.eclipse.equinox.p2.operations;bundle-version="2.1.0" + org.eclipse.equinox.p2.operations;bundle-version="2.1.0", + org.eclipse.equinox.p2.ui.sdk.scheduler Eclipse-RegisterBuddy: org.eclipse.equinox.p2.artifact.repository Bundle-RequiredExecutionEnvironment: J2SE-1.5, J2SE-1.4 diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/sharedinstall/NeedsMigration.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/sharedinstall/NeedsMigration.java new file mode 100644 index 000000000..cf9859fb9 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/sharedinstall/NeedsMigration.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * Copyright (c) 2013 Ericsson AB 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: + * Ericsson AB - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.p2.tests.sharedinstall; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.AutomaticUpdateScheduler; +import org.eclipse.equinox.p2.engine.IEngine; +import org.eclipse.equinox.p2.engine.IProfile; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.planner.IPlanner; +import org.eclipse.equinox.p2.tests.*; + +public class NeedsMigration extends AbstractProvisioningTest { + @IUDescription(content = "package: sdk \n" + "singleton: true\n" + "version: 1 \n") + public IInstallableUnit sdk1; + + @IUDescription(content = "package: sdk \n" + "singleton: true\n" + "version: 2 \n") + public IInstallableUnit sdk2; + + @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 1 \n") + public IInstallableUnit egit1; + + @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 2 \n") + public IInstallableUnit egit2; + + @IUDescription(content = "package: cdt \n" + "singleton: true\n" + "version: 1 \n") + public IInstallableUnit cdt1; + + @IUDescription(content = "package: eppPackage \n" + "singleton: true\n" + "version: 1 \n" + "depends: sdk = 1, egit =1") + public IInstallableUnit eppPackage; + + private IPlanner planner; + private IEngine engine; + private AutomaticUpdateScheduler scheduler; + private Method needsMigrationMethod; + + @Override + protected void setUp() throws Exception { + IULoader.loadIUs(this); + planner = createPlanner(); + engine = createEngine(); + scheduler = new AutomaticUpdateScheduler(); + createTestMetdataRepository(new IInstallableUnit[] {sdk1, sdk2, egit1, egit2, cdt1, eppPackage}); + needsMigrationMethod = scheduler.getClass().getDeclaredMethod("needsMigration", IProfile.class, IProfile.class); + needsMigrationMethod.setAccessible(true); + } + + public void testEmptyUserProfile() { + IProfile previousUserProfile = createProfile("previous" + getName()); + IProfile currentBaseProfile = createProfile("current" + getName()); + assertOK(install(currentBaseProfile, new IInstallableUnit[] {sdk1}, true, planner, engine)); + + //The user version and the base version are the same + assertFalse(needsMigration(previousUserProfile, currentBaseProfile)); + } + + public void testSameVersions() { + IProfile previousUserProfile = createProfile("previous" + getName()); + IProfile currentBaseProfile = createProfile("current" + getName()); + assertOK(install(previousUserProfile, new IInstallableUnit[] {sdk1}, true, planner, engine)); + assertOK(install(currentBaseProfile, new IInstallableUnit[] {sdk1}, true, planner, engine)); + + //The user version and the base version are the same + assertFalse(needsMigration(previousUserProfile, currentBaseProfile)); + } + + public void testDifferentVersions() { + IProfile previousUserProfile = createProfile("previous" + getName()); + IProfile currentBaseProfile = createProfile("current" + getName()); + assertOK(installAsRoots(previousUserProfile, new IInstallableUnit[] {sdk1}, true, planner, engine)); + assertOK(installAsRoots(currentBaseProfile, new IInstallableUnit[] {sdk2}, true, planner, engine)); + + //The user version is older than the base version + assertFalse(needsMigration(previousUserProfile, currentBaseProfile)); + } + + public void testUserProfileNewerThanBaseVersion() { + IProfile previousUserProfile = createProfile("previous" + getName()); + IProfile currentBaseProfile = createProfile("current" + getName()); + assertOK(installAsRoots(previousUserProfile, new IInstallableUnit[] {sdk2, egit2}, true, planner, engine)); + assertOK(installAsRoots(currentBaseProfile, new IInstallableUnit[] {sdk2, egit1}, true, planner, engine)); + + //The user version is higher than what the base has + assertTrue(needsMigration(previousUserProfile, currentBaseProfile)); + } + + public void testBaseEncompassWhatUserHas() { + IProfile previousUserProfile = createProfile("previous" + getName()); + IProfile currentBaseProfile = createProfile("current" + getName()); + assertOK(installAsRoots(previousUserProfile, new IInstallableUnit[] {sdk1, egit1}, true, planner, engine)); + assertOK(installAsRoots(currentBaseProfile, new IInstallableUnit[] {eppPackage}, true, planner, engine)); + + //All the elements that are in the user profile are included in the base + assertFalse(needsMigration(previousUserProfile, currentBaseProfile)); + } + + public void testBaseEncompassSomePartsOfWhatUserHas() { + IProfile previousUserProfile = createProfile("previous" + getName()); + IProfile currentBaseProfile = createProfile("current" + getName()); + assertOK(installAsRoots(previousUserProfile, new IInstallableUnit[] {sdk1, egit1, cdt1}, true, planner, engine)); + assertOK(installAsRoots(currentBaseProfile, new IInstallableUnit[] {eppPackage}, true, planner, engine)); + + //Not all the elements that are in the user profile are included in the base + assertTrue(needsMigration(previousUserProfile, currentBaseProfile)); + } + + private boolean needsMigration(IProfile previousUserProfile, IProfile currentBaseProfile) { + try { + return (Boolean) needsMigrationMethod.invoke(scheduler, previousUserProfile, currentBaseProfile); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } +} diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk.scheduler/src/org/eclipse/equinox/internal/p2/ui/sdk/scheduler/AutomaticUpdateScheduler.java b/bundles/org.eclipse.equinox.p2.ui.sdk.scheduler/src/org/eclipse/equinox/internal/p2/ui/sdk/scheduler/AutomaticUpdateScheduler.java index 2183d5b06..9bdc28207 100644 --- a/bundles/org.eclipse.equinox.p2.ui.sdk.scheduler/src/org/eclipse/equinox/internal/p2/ui/sdk/scheduler/AutomaticUpdateScheduler.java +++ b/bundles/org.eclipse.equinox.p2.ui.sdk.scheduler/src/org/eclipse/equinox/internal/p2/ui/sdk/scheduler/AutomaticUpdateScheduler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2011 IBM Corporation and others. + * Copyright (c) 2008, 2013 IBM Corporation 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 @@ -12,17 +12,18 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.ui.sdk.scheduler; -import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.migration.AbstractPage_c; -import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.migration.ImportFromInstallationWizard_c; - import com.ibm.icu.util.Calendar; import com.ibm.icu.util.ULocale; +import java.util.Iterator; import java.util.Set; import org.eclipse.core.runtime.*; import org.eclipse.core.runtime.preferences.ConfigurationScope; import org.eclipse.core.runtime.preferences.IScopeContext; import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper; import org.eclipse.equinox.internal.p2.garbagecollector.GarbageCollector; +import org.eclipse.equinox.internal.p2.metadata.query.UpdateQuery; +import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.migration.AbstractPage_c; +import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.migration.ImportFromInstallationWizard_c; import org.eclipse.equinox.internal.provisional.p2.updatechecker.*; import org.eclipse.equinox.p2.core.IProvisioningAgent; import org.eclipse.equinox.p2.engine.IProfile; @@ -31,6 +32,7 @@ import org.eclipse.equinox.p2.engine.query.IUProfilePropertyQuery; import org.eclipse.equinox.p2.engine.query.UserVisibleRootQuery; import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.equinox.p2.query.IQuery; +import org.eclipse.equinox.p2.query.QueryUtil; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.widgets.Display; @@ -119,7 +121,7 @@ public class AutomaticUpdateScheduler implements IStartup { final IProfile previousProfile = findProfileBeforeReset(registry, currentProfile); if (previousProfile != null && currentProfile != null) { - if (isCurrentProfileLacksUnitsFromPrevious(previousProfile, currentProfile)) { + if (needsMigration(previousProfile, currentProfile)) { if (remindMeLater) { openMigrationWizard(previousProfile); } @@ -133,13 +135,27 @@ public class AutomaticUpdateScheduler implements IStartup { * @param currentProfile is the current profile used by eclipse. * @return true if set difference between previousProfile units and currentProfile units not empty, otherwise false */ - private boolean isCurrentProfileLacksUnitsFromPrevious(IProfile previousProfile, IProfile currentProfile) { - + private boolean needsMigration(IProfile previousProfile, IProfile currentProfile) { + //First, try the case of inclusion Set<IInstallableUnit> previousProfileUnits = previousProfile.query(new UserVisibleRootQuery(), null).toSet(); Set<IInstallableUnit> currentProfileUnits = currentProfile.available(new UserVisibleRootQuery(), null).toSet(); previousProfileUnits.removeAll(currentProfileUnits); - return !previousProfileUnits.isEmpty(); + //For the IUs left in the previous profile, look for those that could be in the base but not as roots + Iterator<IInstallableUnit> previousProfileIterator = previousProfileUnits.iterator(); + while (previousProfileIterator.hasNext()) { + if (!currentProfile.available(QueryUtil.createIUQuery(previousProfileIterator.next()), null).isEmpty()) + previousProfileIterator.remove(); + } + + //For the IUs left in the previous profile, look for those that could be available in the root but as higher versions (they could be root or not) + previousProfileIterator = previousProfileUnits.iterator(); + while (previousProfileIterator.hasNext()) { + if (!currentProfile.available(new UpdateQuery(previousProfileIterator.next()), null).isEmpty()) + previousProfileIterator.remove(); + } + + return !previousProfileUnits.isEmpty(); } private void openMigrationWizard(final IProfile inputProfile) { |