From 6ac40fbf59edf472da98d7dc1573e4be6d0b981b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Sat, 11 May 2024 08:22:00 +0200 Subject: [PATCH] Remember referenced repositories as system repositories instead of user Currently there is a quite surprising behavior, that if a user adds an updatesite that contains a referenced repository, that after an update-check additional repositories are visible. Even worse these are now used additionally to check for updates and if they contain other references these are also added and so on. This can result not only in a long list of sites the user never has added and has no clue where they are coming from but even pulling in unwanted or conflicting updates. This now distinguishes two cases: 1) A repository is discovered by the RepositoryAction it is handled as a user added repository and becomes visible 2) A repository is discovered by a reference in that case it is handled as a system repository and not becomes visible that way the list of user visible repositories stay clean from referenced repositories and unexpected side effects on update checks. --- .../repository/LocalMetadataRepository.java | 7 ++- .../helpers/AbstractRepositoryManager.java | 10 ++- .../p2/repository/RepositoryEvent.java | 61 +++++++++++++++---- .../eclipse/actions/RepositoryAction.java | 2 +- .../.settings/.api_filters | 40 ++++++++++++ .../internal/p2/ui/model/ElementUtils.java | 21 +++++-- 6 files changed, 116 insertions(+), 25 deletions(-) create mode 100644 bundles/org.eclipse.equinox.p2.ui/.settings/.api_filters diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/LocalMetadataRepository.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/LocalMetadataRepository.java index aff033c6e5..a8f67bc2fe 100644 --- a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/LocalMetadataRepository.java +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/LocalMetadataRepository.java @@ -185,14 +185,17 @@ public void initialize(RepositoryState state) { * Broadcast discovery events for all repositories referenced by this repository. */ public void publishRepositoryReferences() { - IProvisioningEventBus bus = getProvisioningAgent().getService(IProvisioningEventBus.class); + IProvisioningAgent agent = getProvisioningAgent(); + IProvisioningEventBus bus = agent.getService(IProvisioningEventBus.class); if (bus == null) { return; } List repositoriesSnapshot = createRepositoriesSnapshot(); + boolean referenceAsSystem = Boolean + .parseBoolean(agent.getProperty("p2.metadata.repository.reference.system", "true")); //$NON-NLS-1$ //$NON-NLS-2$ for (IRepositoryReference reference : repositoriesSnapshot) { RepositoryEvent event = RepositoryEvent.newDiscoveryEvent(reference.getLocation(), reference.getNickname(), - reference.getType(), reference.isEnabled()); + reference.getType(), reference.isEnabled(), referenceAsSystem); bus.publishEvent(event); } } diff --git a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/helpers/AbstractRepositoryManager.java b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/helpers/AbstractRepositoryManager.java index 310c14e149..7e6ee3167d 100644 --- a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/helpers/AbstractRepositoryManager.java +++ b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/helpers/AbstractRepositoryManager.java @@ -167,16 +167,19 @@ private boolean addRepository(RepositoryInfo info, boolean signalAdd) { boolean added = true; synchronized (repositoryLock) { - if (repositories == null) + if (repositories == null) { restoreRepositories(); - if (contains(info.location)) + } + if (contains(info.location)) { return false; + } added = repositories.put(getKey(info.location), info) == null; // save the given repository in the preferences. remember(info, true); } - if (added && signalAdd) + if (added && signalAdd) { broadcastChangeEvent(info.location, getRepositoryType(), RepositoryEvent.ADDED, info.isEnabled); + } return added; } @@ -847,6 +850,7 @@ public void notify(EventObject o) { info.location = event.getRepositoryLocation(); info.isEnabled = event.isRepositoryEnabled(); info.nickname = event.getRepositoryNickname(); + info.isSystem = event.isSystem(); addRepository(info, true); } } diff --git a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/provisional/p2/repository/RepositoryEvent.java b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/provisional/p2/repository/RepositoryEvent.java index 930a127b70..3305dcd941 100644 --- a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/provisional/p2/repository/RepositoryEvent.java +++ b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/provisional/p2/repository/RepositoryEvent.java @@ -7,7 +7,7 @@ * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 - * + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -21,7 +21,7 @@ /** * An event indicating a repository was added, removed, changed, * or discovered. - * + * * @see IProvisioningEventBus * @noextend This class is not intended to be subclassed by clients. */ @@ -29,19 +29,19 @@ public class RepositoryEvent extends EventObject { private static final long serialVersionUID = 3082402920617281765L; /** - * A change kind constant (value 0), indicating a repository was added to the + * A change kind constant (value 0), indicating a repository was added to the * list of repositories known to a repository manager. */ public static final int ADDED = 0; /** - * A change kind constant (value 1), indicating a repository was removed from + * A change kind constant (value 1), indicating a repository was removed from * the list of repositories known to a repository manager. */ public static final int REMOVED = 1; /** - * A change kind constant (value 2), indicating a repository known to a + * A change kind constant (value 2), indicating a repository known to a * repository manager was modified. */ public static final int CHANGED = 2; @@ -67,25 +67,48 @@ public class RepositoryEvent extends EventObject { private final int kind, type; private boolean isEnabled; private String nickname; + private boolean system; /** * Creates and returns a new repository discovery event. - * @param location the location of the repository that changed. - * @param nickname the repository nickname + * + * @param location the location of the repository that changed. + * @param nickname the repository nickname * @param repositoryType the type of repository that was changed - * @param enabled whether the repository is enabled + * @param enabled whether the repository is enabled + * @return A new repository discovery event + * @see IRepository#PROP_NICKNAME + */ + public static RepositoryEvent newDiscoveryEvent(URI location, String nickname, int repositoryType, + boolean enabled) { + RepositoryEvent event = new RepositoryEvent(location, repositoryType, DISCOVERED, enabled); + event.nickname = nickname; + return event; + } + + /** + * Creates and returns a new repository discovery event. + * + * @param location the location of the repository that changed. + * @param nickname the repository nickname + * @param repositoryType the type of repository that was changed + * @param enabled whether the repository is enabled + * @param system whether the repository is a system repository * @return A new repository discovery event * @see IRepository#PROP_NICKNAME + * @since 2.9 */ - public static RepositoryEvent newDiscoveryEvent(URI location, String nickname, int repositoryType, boolean enabled) { + public static RepositoryEvent newDiscoveryEvent(URI location, String nickname, int repositoryType, boolean enabled, + boolean system) { RepositoryEvent event = new RepositoryEvent(location, repositoryType, DISCOVERED, enabled); event.nickname = nickname; + event.system = system; return event; } /** * Creates a new repository event. - * + * * @param location the location of the repository that changed. * @param repositoryType the type of repository that was changed * @param kind the kind of change that occurred. @@ -121,9 +144,21 @@ public String getRepositoryNickname() { return nickname; } + /** + * Returns if the repository is a system type see + * {@link IRepository#PROP_SYSTEM}. This method is only applicable for the + * {@link #DISCOVERED} event type. For other event types this method returns + * false. + * + * @since 2.9 + */ + public boolean isSystem() { + return system; + } + /** * Returns the location of the repository associated with this event. - * + * * @return the location of the repository associated with this event. */ public URI getRepositoryLocation() { @@ -134,7 +169,7 @@ public URI getRepositoryLocation() { * Returns the type of repository associated with this event. Clients * should not assume that the set of possible repository types is closed; * clients should ignore events from repository types they don't know about. - * + * * @return the type of repository associated with this event. * ({@link IRepository#TYPE_METADATA} or {@link IRepository#TYPE_ARTIFACT}). */ @@ -144,7 +179,7 @@ public int getRepositoryType() { /** * Returns whether the affected repository is enabled. - * + * * @return true if the repository is enabled, * and false otherwise. */ diff --git a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/actions/RepositoryAction.java b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/actions/RepositoryAction.java index 793e782950..22a54d120c 100644 --- a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/actions/RepositoryAction.java +++ b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/actions/RepositoryAction.java @@ -149,7 +149,7 @@ protected RepositoryEvent createEvent(Map parameters) throws Cor // default is to be enabled String enablement = (String) parameters.get(ActionConstants.PARM_REPOSITORY_ENABLEMENT); boolean enabled = enablement == null ? true : Boolean.parseBoolean(enablement); - return RepositoryEvent.newDiscoveryEvent(location, name, type, enabled); + return RepositoryEvent.newDiscoveryEvent(location, name, type, enabled, false); } /** diff --git a/bundles/org.eclipse.equinox.p2.ui/.settings/.api_filters b/bundles/org.eclipse.equinox.p2.ui/.settings/.api_filters new file mode 100644 index 0000000000..b8cf94d164 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.ui/.settings/.api_filters @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/model/ElementUtils.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/model/ElementUtils.java index f43492a5fd..bc0ad49404 100644 --- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/model/ElementUtils.java +++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/model/ElementUtils.java @@ -35,14 +35,16 @@ */ public class ElementUtils { - public static void updateRepositoryUsingElements(final ProvisioningUI ui, final MetadataRepositoryElement[] elements) { + public static void updateRepositoryUsingElements(final ProvisioningUI ui, + final MetadataRepositoryElement[] elements) { ui.signalRepositoryOperationStart(); IMetadataRepositoryManager metaManager = ProvUI.getMetadataRepositoryManager(ui.getSession()); IArtifactRepositoryManager artManager = ProvUI.getArtifactRepositoryManager(ui.getSession()); try { int visibilityFlags = ui.getRepositoryTracker().getMetadataRepositoryFlags(); URI[] currentlyEnabled = metaManager.getKnownRepositories(visibilityFlags); - URI[] currentlyDisabled = metaManager.getKnownRepositories(IRepositoryManager.REPOSITORIES_DISABLED | visibilityFlags); + URI[] currentlyDisabled = metaManager + .getKnownRepositories(IRepositoryManager.REPOSITORIES_DISABLED | visibilityFlags); for (MetadataRepositoryElement element : elements) { URI location = element.getLocation(); if (element.isEnabled()) { @@ -50,16 +52,21 @@ public static void updateRepositoryUsingElements(final ProvisioningUI ui, final // It should be enabled and is not currently setColocatedRepositoryEnablement(ui, location, true); else if (!containsURI(currentlyEnabled, location)) { - // It is not known as enabled or disabled. Add it. + // It is not known as enabled or disabled. Add it. metaManager.addRepository(location); artManager.addRepository(location); + // even though it is not contained in the visible repositories, it could have + // been a system repository we mark it here explicitly as no longer being a + // system one + metaManager.setRepositoryProperty(location, IRepository.PROP_SYSTEM, "false"); //$NON-NLS-1$ + artManager.setRepositoryProperty(location, IRepository.PROP_SYSTEM, "false"); //$NON-NLS-1$ } } else { if (containsURI(currentlyEnabled, location)) // It should be disabled, and is currently enabled setColocatedRepositoryEnablement(ui, location, false); else if (!containsURI(currentlyDisabled, location)) { - // It is not known as enabled or disabled. Add it and then disable it. + // It is not known as enabled or disabled. Add it and then disable it. metaManager.addRepository(location); artManager.addRepository(location); setColocatedRepositoryEnablement(ui, location, false); @@ -71,7 +78,7 @@ else if (!containsURI(currentlyDisabled, location)) { artManager.setRepositoryProperty(location, IRepository.PROP_NICKNAME, name); } } - // Are there any elements that need to be deleted? Go over the original state + // Are there any elements that need to be deleted? Go over the original state // and remove any elements that weren't in the elements we were given Set nowKnown = new HashSet<>(); for (MetadataRepositoryElement element : elements) @@ -137,7 +144,9 @@ public static AvailableIUElement[] requestToElement(Remedy remedy, boolean insta if (iuDetail.getStatus() == RemedyIUDetail.STATUS_NOT_ADDED) continue; AvailableIUElement element = new AvailableIUElement(root, iuDetail.getIu(), ui.getProfileId(), true); - if (iuDetail.getBeingInstalledVersion() != null && iuDetail.getRequestedVersion() != null && iuDetail.getBeingInstalledVersion().compareTo(iuDetail.getRequestedVersion()) < 0 && !installMode) + if (iuDetail.getBeingInstalledVersion() != null && iuDetail.getRequestedVersion() != null + && iuDetail.getBeingInstalledVersion().compareTo(iuDetail.getRequestedVersion()) < 0 + && !installMode) element.setImageOverlayId(ProvUIImages.IMG_INFO); else if (iuDetail.getStatus() == RemedyIUDetail.STATUS_REMOVED) element.setImageId(ProvUIImages.IMG_REMOVED);