| /*=============================================================================# |
| # Copyright (c) 2012, 2019 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.internal.r.core.pkgmanager; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.concurrent.locks.Lock; |
| import java.util.concurrent.locks.ReentrantReadWriteLock; |
| |
| import org.osgi.service.prefs.BackingStoreException; |
| |
| import org.eclipse.core.filesystem.EFS; |
| import org.eclipse.core.filesystem.IFileStore; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.preferences.IEclipsePreferences; |
| import org.eclipse.core.runtime.preferences.IScopeContext; |
| import org.eclipse.core.runtime.preferences.InstanceScope; |
| import org.eclipse.osgi.util.NLS; |
| |
| import org.eclipse.statet.jcommons.collections.ImCollections; |
| import org.eclipse.statet.jcommons.collections.ImIdentitySet; |
| import org.eclipse.statet.jcommons.collections.ImList; |
| import org.eclipse.statet.jcommons.lang.Nullable; |
| import org.eclipse.statet.jcommons.status.ErrorStatus; |
| import org.eclipse.statet.jcommons.status.ProgressMonitor; |
| import org.eclipse.statet.jcommons.status.Status; |
| import org.eclipse.statet.jcommons.status.StatusException; |
| import org.eclipse.statet.jcommons.status.Statuses; |
| import org.eclipse.statet.jcommons.ts.core.Tool; |
| |
| import org.eclipse.statet.ecommons.collections.FastList; |
| import org.eclipse.statet.ecommons.preferences.core.Preference.NullableStringPref; |
| import org.eclipse.statet.ecommons.preferences.core.PreferenceAccess; |
| import org.eclipse.statet.ecommons.preferences.core.PreferenceSetService; |
| import org.eclipse.statet.ecommons.preferences.core.PreferenceSetService.ChangeEvent; |
| import org.eclipse.statet.ecommons.preferences.core.util.PreferenceUtils; |
| import org.eclipse.statet.ecommons.runtime.core.util.StatusUtils; |
| |
| import org.eclipse.statet.internal.r.core.RCorePlugin; |
| import org.eclipse.statet.internal.r.core.renv.REnvConfigurationImpl; |
| import org.eclipse.statet.r.core.RCore; |
| import org.eclipse.statet.r.core.pkgmanager.IRPkgData; |
| import org.eclipse.statet.r.core.pkgmanager.IRPkgInfoAndData; |
| import org.eclipse.statet.r.core.pkgmanager.IRPkgManager; |
| import org.eclipse.statet.r.core.pkgmanager.IRPkgSet; |
| import org.eclipse.statet.r.core.pkgmanager.IRView; |
| import org.eclipse.statet.r.core.pkgmanager.ISelectedRepos; |
| import org.eclipse.statet.r.core.pkgmanager.RPkgAction; |
| import org.eclipse.statet.r.core.pkgmanager.RPkgUtils; |
| import org.eclipse.statet.r.core.pkgmanager.RRepo; |
| import org.eclipse.statet.r.core.pkgmanager.RRepoMirror; |
| import org.eclipse.statet.r.core.pkgmanager.SelectedRepos; |
| import org.eclipse.statet.r.core.renv.IREnvConfiguration; |
| import org.eclipse.statet.r.core.tool.AbstractStatetRRunnable; |
| import org.eclipse.statet.r.core.tool.IRConsoleService; |
| import org.eclipse.statet.rj.data.RCharacterStore; |
| import org.eclipse.statet.rj.data.RDataFrame; |
| import org.eclipse.statet.rj.data.RDataUtils; |
| import org.eclipse.statet.rj.data.RLogicalStore; |
| import org.eclipse.statet.rj.data.RNumericStore; |
| import org.eclipse.statet.rj.data.RObject; |
| import org.eclipse.statet.rj.data.RStore; |
| import org.eclipse.statet.rj.data.RVector; |
| import org.eclipse.statet.rj.data.UnexpectedRDataException; |
| import org.eclipse.statet.rj.data.impl.RCharacter32Store; |
| import org.eclipse.statet.rj.data.impl.RVectorImpl; |
| import org.eclipse.statet.rj.renv.core.BasicRPkgCompilation; |
| import org.eclipse.statet.rj.renv.core.REnv; |
| import org.eclipse.statet.rj.renv.core.REnvConfiguration; |
| import org.eclipse.statet.rj.renv.core.RNumVersion; |
| import org.eclipse.statet.rj.renv.core.RPkg; |
| import org.eclipse.statet.rj.renv.core.RPkgCompilation; |
| import org.eclipse.statet.rj.renv.core.RPkgType; |
| import org.eclipse.statet.rj.renv.runtime.RPkgManager; |
| import org.eclipse.statet.rj.renv.runtime.RPkgManagerDataset; |
| import org.eclipse.statet.rj.renv.runtime.RuntimeRLibPaths; |
| import org.eclipse.statet.rj.renv.runtime.RuntimeRLibPathsLoader; |
| import org.eclipse.statet.rj.server.util.ServerUtils; |
| import org.eclipse.statet.rj.services.FunctionCall; |
| import org.eclipse.statet.rj.services.RPlatform; |
| import org.eclipse.statet.rj.services.RService; |
| import org.eclipse.statet.rj.ts.core.AbstractRToolRunnable; |
| import org.eclipse.statet.rj.ts.core.RToolService; |
| |
| |
| public class RPkgManagerImpl implements IRPkgManager.Ext, PreferenceSetService.ChangeListener { |
| |
| |
| private static final int REQUIRE_CRAN= 0x0_1000_0000; |
| private static final int REQUIRE_BIOC= 0x0_2000_0000; |
| private static final int REQUIRE_REPOS= 0x0_8000_0000; |
| |
| private static final int REQUIRE_REPO_PKGS= 0x0_0100_0000; |
| private static final int REQUIRE_INST_PKGS= 0x0_0800_0000; |
| |
| private static final ImIdentitySet<String> PREF_QUALIFIERS= ImCollections.newIdentitySet( |
| PREF_QUALIFIER ); |
| |
| private static final RRepoPref LAST_CRAN_PREF= new RRepoPref(PREF_QUALIFIER, "LastCRAN.repo"); //$NON-NLS-1$ |
| private static final RRepoPref LAST_BIOC_PREF= new RRepoPref(PREF_QUALIFIER, "LastBioC.repo"); //$NON-NLS-1$ |
| |
| private static final int MIRROR_CHECK= 1000 * 60 * 60 * 6; |
| private static final int PKG_CHECK= 1000 * 60 * 60 * 3; |
| |
| |
| private final REnv rEnv; |
| private RPlatform rPlatform; |
| |
| private final PreferenceAccess prefAccess; |
| |
| private final IFileStore rEnvDirectory; |
| |
| private boolean firstTime; |
| |
| private String bioCVersion; |
| private final NullableStringPref bioCVersionPref; |
| |
| private List<RRepo> customRepos; |
| private final List<RRepo> addRepos; |
| private List<RRepo> rRepos; |
| private List<RRepo> allRepos; |
| private List<RRepo> selectedReposInR; |
| private final RRepoListPref selectedReposPref; |
| |
| private List<RRepo> customCRAN; |
| private List<RRepoMirror> rCRANMirrors; |
| private ImList<RRepo> allCRAN; |
| private String selectedCRANInR; |
| private final RRepoPref selectedCRANPref; |
| |
| private List<RRepo> customBioC; |
| private List<RRepoMirror> rBioCMirrors; |
| private ImList<RRepo> allBioC; |
| private String selectedBioCInR; |
| private final RRepoPref selectedBioCPref; |
| private long mirrorsStamp; |
| |
| private SelectedRepos selectedRepos; |
| |
| private RVector<RNumericStore> libs= null; |
| private RuntimeRLibPathsLoader rLibGroups; |
| private RuntimeRLibPaths rLibPaths; |
| |
| private RPkgSet dataset; |
| private FullRPkgSet datasetExt; |
| private long pkgsStamp; |
| final RPkgScanner pkgScanner= new RPkgScanner(); |
| |
| private int requested; |
| private volatile int requireLoad; |
| private volatile int requireConfirm; |
| |
| private final FastList<Listener> listeners= new FastList<>(Listener.class); |
| |
| private final ReentrantReadWriteLock lock= new ReentrantReadWriteLock(); |
| |
| private List<RView> rViews; |
| private RNumVersion rViewsVersion; |
| // private List<RView> bioCViews; |
| // private String bioCViewsVersion; |
| // private long bioCViewsStamp; |
| |
| private Tool rProcess; |
| private int rTask; |
| private Change rTaskEvent; |
| |
| private final DB db; |
| private final Cache cache; |
| |
| |
| public RPkgManagerImpl(final IREnvConfiguration config) { |
| this.rEnv= config.getREnv(); |
| this.rEnvDirectory= EFS.getLocalFileSystem().getStore(REnvConfigurationImpl.getStateLocation(this.rEnv)); |
| final String qualifier= config.getPrefNodeQualifier(); |
| this.selectedReposPref= new RRepoListPref(qualifier, "RPkg.Repos.repos"); //$NON-NLS-1$ |
| this.selectedCRANPref= new RRepoPref(qualifier, "RPkg.CRANMirror.repo"); //$NON-NLS-1$ |
| this.bioCVersionPref= new NullableStringPref(qualifier, "RPkg.BioCVersion.ver"); //$NON-NLS-1$ |
| this.selectedBioCPref= new RRepoPref(qualifier, "RPkg.BioCMirror.repo"); //$NON-NLS-1$ |
| |
| this.prefAccess= PreferenceUtils.getInstancePrefs(); |
| this.addRepos= new ArrayList<>(); |
| if (config.getType() == IREnvConfiguration.USER_LOCAL_TYPE) { |
| final String rjVersion= "" + ServerUtils.RJ_VERSION[0] + '.' + ServerUtils.RJ_VERSION[1]; //$NON-NLS-1$ |
| this.addRepos.add(new RRepo(RRepo.SPECIAL_PREFIX + "rj", "RJ", "http://download.walware.de/rj-" + rjVersion, null)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| this.selectedRepos= new SelectedRepos( |
| this.prefAccess.getPreferenceValue(this.selectedReposPref), |
| this.prefAccess.getPreferenceValue(this.selectedCRANPref), |
| this.prefAccess.getPreferenceValue(this.bioCVersionPref), |
| this.prefAccess.getPreferenceValue(this.selectedBioCPref) ); |
| |
| this.db= DB.create(this.rEnv, this.rEnvDirectory); |
| this.cache= new Cache(this.rEnvDirectory); |
| resetPkgs(config); |
| |
| this.firstTime= true; |
| this.mirrorsStamp= this.pkgsStamp= System.currentTimeMillis(); |
| this.requireLoad |= (REQUIRE_CRAN | REQUIRE_BIOC | REQUIRE_REPOS); |
| this.requireLoad |= (REQUIRE_REPO_PKGS | REQUIRE_INST_PKGS); |
| |
| this.prefAccess.addPreferenceSetListener(this, PREF_QUALIFIERS); |
| |
| getWriteLock().lock(); |
| try { |
| loadPrefs(true); |
| } |
| finally { |
| getWriteLock().unlock(); |
| } |
| } |
| |
| private void resetPkgs(final REnvConfiguration rEnvConfig) { |
| this.datasetExt= null; |
| if (this.db != null && rEnvConfig != null) { |
| this.dataset= new RPkgSet(this.rEnv, rEnvConfig, |
| this.db.loadInstalled(rEnvConfig.getRLibGroups()) ); |
| } |
| else { |
| this.dataset= null; |
| } |
| } |
| |
| |
| @Override |
| public REnv getREnv() { |
| return this.rEnv; |
| } |
| |
| Cache getCache() { |
| return this.cache; |
| } |
| |
| @Override |
| public RPlatform getRPlatform() { |
| return this.rPlatform; |
| } |
| |
| @Override |
| public Lock getReadLock() { |
| return this.lock.readLock(); |
| } |
| |
| @Override |
| public Lock getWriteLock() { |
| return this.lock.writeLock(); |
| } |
| |
| |
| @Override |
| public void preferenceChanged(final ChangeEvent event) { |
| if (event.contains(PREF_QUALIFIER) |
| && (event.contains(CUSTOM_REPO_PREF) |
| || event.contains(CUSTOM_CRAN_MIRROR_PREF) |
| || event.contains(CUSTOM_BIOC_MIRROR_PREF) )) { |
| loadPrefs(true); |
| } |
| } |
| |
| public void dispose() { |
| this.prefAccess.removePreferenceSetListener(this); |
| } |
| |
| |
| @Override |
| public void check(final int flags, |
| final RService r, final ProgressMonitor m) throws StatusException { |
| checkInit(flags, r, m); |
| check(r, m); |
| } |
| |
| protected int checkRequest(int request) { |
| request= RPkgManager.expandFlags(request); |
| request= checkAutoRefresh(request); |
| return request; |
| } |
| |
| private int checkAutoRefresh(int request) { |
| final long stamp= System.currentTimeMillis(); |
| if ((request & AVAILABLE_REPOS) != 0 |
| && Math.abs(this.mirrorsStamp - stamp) > MIRROR_CHECK) { |
| request |= REFRESH_AVAILABLE_REPOS; |
| } |
| if ((request & AVAILABLE_PKGS) != 0 |
| && Math.abs(this.pkgsStamp - stamp) > PKG_CHECK) { |
| request |= REFRESH_AVAILABLE_PKGS; |
| } |
| return request; |
| } |
| |
| @Override |
| public int request(int request) { |
| request= checkRequest(request); |
| getWriteLock().lock(); |
| try { |
| this.requested |= request; |
| } |
| finally { |
| getWriteLock().unlock(); |
| } |
| |
| final RPkgManagerDataset dataset= getDataset(); |
| if (dataset != null && (dataset.getProviding() & request) == request) { |
| return OK; |
| } |
| if ((request & (AVAILABLE_PKGS | REFRESH_AVAILABLE_REPOS)) == AVAILABLE_PKGS |
| && dataset != null && (dataset.getProviding() & AVAILABLE_REPOS) != 0) { |
| final Status status= getReposStatus(null); |
| if (status.getSeverity() > Status.INFO) { |
| return REQUIRES_CONFIG; |
| } |
| } |
| return REQUIRES_UPDATE; |
| } |
| |
| private void checkInit(final int flags, |
| final RService r, final ProgressMonitor m) throws StatusException { |
| if ((flags & INITIAL) == INITIAL || this.rPlatform == null) { |
| checkRVersion(r.getPlatform()); |
| |
| final REnvConfiguration rEnvConfig= this.rEnv.get(REnvConfiguration.class); |
| if (rEnvConfig != null && rEnvConfig.isRemote()) { |
| this.rLibGroups= REnvLibGroups.loadFromR(r, m); |
| } |
| } |
| } |
| |
| private void check( |
| final RService r, final ProgressMonitor m) throws StatusException { |
| if (!beginRTaskSilent((RToolService) r, m)) { |
| return; |
| } |
| try { |
| checkInstalled(false, null, r, m); |
| |
| if (this.rTaskEvent != null) { |
| fireUpdate(this.rTaskEvent); |
| } |
| } |
| catch (final Exception e) { |
| throw new StatusException(new ErrorStatus(RCore.BUNDLE_ID, |
| "An error occurred when checking for new and updated R packages.", |
| e )); |
| } |
| finally { |
| this.rTaskEvent= null; |
| endRTask(); |
| } |
| } |
| |
| private void checkRVersion(final RPlatform rPlatform) { |
| if (this.rPlatform != null && !this.rPlatform.getRVersion().equals(rPlatform.getRVersion())) { |
| getWriteLock().lock(); |
| try { |
| this.requireLoad |= (REQUIRE_REPOS | REQUIRE_CRAN | REQUIRE_BIOC); |
| this.requireLoad |= (REQUIRE_REPO_PKGS | REQUIRE_INST_PKGS); |
| } |
| finally { |
| getWriteLock().unlock(); |
| } |
| } |
| this.rPlatform= rPlatform; |
| } |
| |
| private void updateRequireLoad() { |
| getWriteLock().lock(); |
| try { |
| final int requested= checkAutoRefresh(this.requested); |
| |
| if ((requested & RESET) != 0) { |
| this.selectedRepos= new SelectedRepos(Collections.<RRepo> emptyList(), |
| null, null, null); |
| savePrefs(this.selectedRepos); |
| |
| this.requireLoad |= (REQUIRE_REPOS | REQUIRE_CRAN | REQUIRE_BIOC); |
| |
| final Change change= new Change(this.rEnv); |
| change.repos= 1; |
| checkRepos(change); |
| |
| this.requireLoad |= (REQUIRE_REPO_PKGS | REQUIRE_INST_PKGS); |
| |
| final REnvConfiguration rEnvConfig= this.rEnv.get(REnvConfiguration.class); |
| resetPkgs(rEnvConfig); |
| this.firstTime= true; |
| } |
| else { |
| if ((requested & REFRESH_INSTALLED_PKGS) != 0) { |
| this.requireLoad= (REQUIRE_INST_PKGS); |
| } |
| if ((requested & REFRESH_AVAILABLE_REPOS) != 0) { |
| this.requireLoad |= (REQUIRE_CRAN | REQUIRE_BIOC); |
| } |
| if ((requested & REFRESH_AVAILABLE_PKGS) != 0) { |
| this.requireLoad |= (REQUIRE_REPO_PKGS); |
| } |
| } |
| |
| this.requested &= INSTALLED | AVAILABLE; |
| } |
| finally { |
| getWriteLock().unlock(); |
| } |
| } |
| |
| |
| @Override |
| public Status getReposStatus(final ISelectedRepos repos) { |
| final ISelectedRepos current= this.selectedRepos; |
| final int confirm= this.requireConfirm; |
| return getReposStatus((repos != null) ? repos : current, current, confirm); |
| } |
| |
| private Status getReposStatus(final ISelectedRepos repos, final ISelectedRepos current, final int confirm) { |
| if (repos.getRepos().isEmpty()) { |
| return createStatus(Status.ERROR, "No repository is selected. Select the repositories where to install R packages from."); |
| } |
| |
| final boolean requireCRAN= RVarRepo.requireCRANMirror(repos.getRepos()); |
| if (requireCRAN && repos.getCRANMirror() == null) { |
| return createStatus(Status.ERROR, "No CRAN mirror is selected. Selected a mirror for CRAN."); |
| } |
| final boolean requireBioC= RVarRepo.requireBioCMirror(repos.getRepos()); |
| if (requireBioC && repos.getBioCMirror() == null) { |
| return createStatus(Status.ERROR, "No BioC mirror is selected. Selected a mirror for Bioconductor."); |
| } |
| |
| if ((requireCRAN && (confirm & REQUIRE_CRAN) != 0) |
| || (requireBioC && (confirm & REQUIRE_BIOC) != 0) |
| || (repos != current && !repos.equals(current) )) { |
| return createStatus(Status.INFO, "Check the repository settings and confirm with 'Apply' to show the available R packages."); |
| } |
| |
| return Statuses.OK_STATUS; |
| } |
| |
| private static Status createStatus(final int severity, final String message) { |
| return Statuses.newStatus(severity, RCore.BUNDLE_ID, message); |
| } |
| |
| @Override |
| public void update(final RService r, final ProgressMonitor m) throws StatusException { |
| beginRTask((RToolService) r, m); |
| try { |
| checkInit(0, r, m); |
| |
| this.rTaskEvent= new Change(this.rEnv); |
| |
| final ISelectedRepos settings= runLoadRepos(r, m); |
| if (settings != null) { |
| runApplyRepo(settings, r, m); |
| } |
| runLoadPkgs(settings, r, m); |
| fireUpdate(this.rTaskEvent); |
| } |
| finally { |
| this.rTaskEvent= null; |
| endRTask(); |
| } |
| } |
| |
| |
| private void checkMirrors(final Change event) { |
| if ((this.requireLoad & (REQUIRE_CRAN | REQUIRE_BIOC)) != 0) { |
| return; |
| } |
| |
| SelectedRepos selected= this.selectedRepos; |
| this.allCRAN= ImCollections.concatList(this.customCRAN, this.rCRANMirrors); |
| |
| RRepo selectedCRAN= selected.getCRANMirror(); |
| if (selected.getCRANMirror() != null) { |
| selectedCRAN= Util.findRepo(this.allCRAN, selectedCRAN); |
| } |
| else if (this.firstTime && this.selectedCRANInR != null) { |
| selectedCRAN= Util.getRepoByURL(this.allCRAN, this.selectedCRANInR); |
| } |
| if (selectedCRAN == null) { |
| this.requireConfirm |= REQUIRE_CRAN; |
| selectedCRAN= this.prefAccess.getPreferenceValue(LAST_CRAN_PREF); |
| if (selectedCRAN != null) { |
| selectedCRAN= Util.findRepo(this.allCRAN, selectedCRAN); |
| } |
| if (!this.customCRAN.isEmpty() |
| && (selectedCRAN == null || !selectedCRAN.getId().startsWith(RRepo.CUSTOM_PREFIX)) ) { |
| selectedCRAN= this.customCRAN.get(0); |
| } |
| if (this.firstTime && selectedCRAN == null && !this.rCRANMirrors.isEmpty()) { |
| selectedCRAN= getRegionMirror(this.rCRANMirrors); |
| } |
| } |
| |
| |
| RRepo selectedBioC= selected.getBioCMirror(); |
| this.allBioC= ImCollections.concatList(this.customBioC, this.rBioCMirrors); |
| if (selectedBioC != null) { |
| selectedBioC= Util.findRepo(this.allBioC, selectedBioC); |
| } |
| else if (this.firstTime && this.selectedBioCInR != null) { |
| selectedBioC= RPkgUtils.getRepoByURL(this.allBioC, this.selectedBioCInR); |
| } |
| if (selectedBioC == null) { |
| this.requireConfirm |= REQUIRE_BIOC; |
| selectedBioC= this.prefAccess.getPreferenceValue(LAST_BIOC_PREF); |
| if (!this.customBioC.isEmpty() |
| && (selectedBioC == null || !selectedBioC.getId().startsWith(RRepo.CUSTOM_PREFIX)) ) { |
| selectedBioC= this.customBioC.get(0); |
| } |
| if (this.firstTime && selectedBioC == null && !this.rBioCMirrors.isEmpty()) { |
| selectedBioC= getRegionMirror(this.rBioCMirrors); |
| if (selectedBioC == null) { |
| selectedBioC= this.rBioCMirrors.get(0); |
| } |
| } |
| } |
| |
| selected= new SelectedRepos( |
| selected.getRepos(), |
| selectedCRAN, |
| this.bioCVersion, |
| selectedBioC ); |
| if ((this.requireLoad & (REQUIRE_REPOS)) == 0) { |
| for (final RRepo repo : this.allRepos) { |
| if (repo instanceof RVarRepo) { |
| ((RVarRepo) repo).updateURL(selected); |
| } |
| } |
| } |
| this.selectedRepos= selected; |
| |
| event.pkgs= 1; |
| } |
| |
| private void checkRepos(final Change event) { |
| if ((this.requireLoad & (REQUIRE_CRAN | REQUIRE_BIOC | REQUIRE_REPOS)) != 0) { |
| return; |
| } |
| |
| SelectedRepos selected= this.selectedRepos; |
| |
| this.allRepos= new ArrayList<>(this.customRepos.size() + this.addRepos.size() + this.rRepos.size()); |
| this.allRepos.addAll(this.customRepos); |
| this.allRepos.addAll(this.addRepos); |
| for (final RRepo repo : this.allRepos) { |
| if (repo instanceof RVarRepo) { |
| ((RVarRepo) repo).updateURL(selected); |
| } |
| } |
| for (final RRepo repo : this.rRepos) { |
| if (repo instanceof RVarRepo) { |
| ((RVarRepo) repo).updateURL(selected); |
| } |
| } |
| for (final RRepo repo : this.rRepos) { |
| if (!repo.getId().isEmpty()) { |
| if (RPkgUtils.getRepoById(this.allRepos, repo.getId()) == null) { |
| this.allRepos.add(repo); |
| } |
| } |
| else { |
| if (Util.getRepoByURL(this.allRepos, repo) == null) { |
| this.allRepos.add(RVarRepo.create(RRepo.R_PREFIX + repo.getURL(), repo.getName(), |
| repo.getURL(), null )); |
| } |
| } |
| } |
| |
| { final Collection<RRepo> selectedRepos= selected.getRepos(); |
| final Collection<RRepo> previous= (this.firstTime && selectedRepos.isEmpty()) ? |
| this.selectedReposInR : selectedRepos; |
| final List<RRepo> repos= new ArrayList<>(previous.size()); |
| for (RRepo repo : previous) { |
| repo= Util.findRepo(this.allRepos, repo); |
| if (repo != null) { |
| repos.add(repo); |
| } |
| } |
| selected= new SelectedRepos( |
| repos, |
| selected.getCRANMirror(), |
| selected.getBioCVersion(), |
| selected.getBioCMirror() ); |
| this.selectedRepos= selected; |
| } |
| |
| this.requireLoad |= REQUIRE_REPO_PKGS; |
| |
| event.repos= 1; |
| } |
| |
| |
| private void loadPrefs(final boolean custom) { |
| final Change event= new Change(this.rEnv); |
| final PreferenceAccess prefs= PreferenceUtils.getInstancePrefs(); |
| getWriteLock().lock(); |
| try { |
| if (custom) { |
| this.customRepos= prefs.getPreferenceValue(CUSTOM_REPO_PREF); |
| this.customCRAN= prefs.getPreferenceValue(CUSTOM_CRAN_MIRROR_PREF); |
| this.customBioC= prefs.getPreferenceValue(CUSTOM_BIOC_MIRROR_PREF); |
| |
| checkRepos(event); |
| } |
| } |
| finally { |
| getWriteLock().unlock(); |
| } |
| fireUpdate(event); |
| } |
| |
| |
| @Override |
| public void addListener(final Listener listener) { |
| this.listeners.add(listener); |
| } |
| |
| @Override |
| public void removeListener(final Listener listener) { |
| this.listeners.remove(listener); |
| } |
| |
| private void fireUpdate(final Event event) { |
| // if (event.reposChanged() == 0 && event.pkgsChanged() == 0 && event.viewsChanged() == 0) { |
| // return; |
| // } |
| final Listener[] listeners= this.listeners.toArray(); |
| for (int i= 0; i < listeners.length; i++) { |
| listeners[i].handleChange(event); |
| } |
| } |
| |
| |
| @Override |
| public List<RRepo> getAvailableRepos() { |
| return this.allRepos; |
| } |
| |
| @Override |
| public ISelectedRepos getSelectedRepos() { |
| return this.selectedRepos; |
| } |
| |
| @Override |
| public void setSelectedRepos(final ISelectedRepos repos) { |
| List<RRepo> selectedRepos; |
| { final Collection<RRepo> selected= repos.getRepos(); |
| selectedRepos= new ArrayList<>(selected.size()); |
| for (final RRepo repo : this.allRepos) { |
| if (selected.contains(repo)) { |
| selectedRepos.add(repo); |
| } |
| } |
| } |
| RRepo selectedCRAN; |
| { final RRepo repo= repos.getCRANMirror(); |
| selectedCRAN= (repo != null) ? Util.findRepo(this.allCRAN, repo) : null; |
| this.requireConfirm &= ~REQUIRE_CRAN; |
| } |
| RRepo selectedBioC; |
| { final RRepo repo= repos.getBioCMirror(); |
| selectedBioC= (repo != null) ? Util.findRepo(this.allBioC, repo) : null; |
| this.requireConfirm &= ~REQUIRE_BIOC; |
| } |
| |
| final SelectedRepos previousSettings= this.selectedRepos; |
| final SelectedRepos newSettings= new SelectedRepos( |
| selectedRepos, |
| selectedCRAN, |
| previousSettings.getBioCVersion(), selectedBioC ); |
| for (final RRepo repo : this.allRepos) { |
| if (repo instanceof RVarRepo) { |
| ((RVarRepo) repo).updateURL(newSettings); |
| } |
| } |
| this.selectedRepos= newSettings; |
| savePrefs(newSettings); |
| |
| if (!newSettings.equals(previousSettings)) { |
| this.requireLoad |= (REQUIRE_REPO_PKGS); |
| |
| final Change event= new Change(this.rEnv); |
| event.repos= 1; |
| fireUpdate(event); |
| } |
| } |
| |
| @Override |
| public RRepo getRepo(final String repoId) { |
| if (repoId.isEmpty()) { |
| return null; |
| } |
| RRepo repo= this.selectedRepos.getRepo(repoId); |
| if (repo == null) { |
| repo= RPkgUtils.getRepoById(this.allRepos, repoId); |
| } |
| return repo; |
| } |
| |
| private void savePrefs(final SelectedRepos repos) { |
| if (this.rEnv.get(IREnvConfiguration.class) == null) { |
| return; |
| } |
| final IScopeContext prefs= InstanceScope.INSTANCE; |
| |
| final IEclipsePreferences globalNode= prefs.getNode(PREF_QUALIFIER); |
| final IEclipsePreferences envNode= prefs.getNode(this.selectedReposPref.getQualifier()); |
| |
| PreferenceUtils.setPrefValue(envNode, this.selectedReposPref, repos.getRepos()); |
| PreferenceUtils.setPrefValue(envNode, this.selectedCRANPref, repos.getCRANMirror()); |
| PreferenceUtils.setPrefValue(envNode, this.bioCVersionPref, repos.getBioCVersion()); |
| PreferenceUtils.setPrefValue(envNode, this.selectedBioCPref, repos.getBioCMirror()); |
| |
| if (repos.getCRANMirror() != null) { |
| PreferenceUtils.setPrefValue(globalNode, LAST_CRAN_PREF, repos.getCRANMirror()); |
| } |
| if (repos.getBioCMirror() != null) { |
| PreferenceUtils.setPrefValue(globalNode, LAST_BIOC_PREF, repos.getBioCMirror()); |
| } |
| |
| try { |
| globalNode.flush(); |
| envNode.flush(); |
| } |
| catch (final BackingStoreException e) { |
| RCorePlugin.logError("An error occurred when saving the R package manager preferences.", e); |
| } |
| } |
| |
| |
| @Override |
| public ImList<RRepo> getAvailableCRANMirrors() { |
| return this.allCRAN; |
| } |
| |
| @Override |
| public List<RRepo> getAvailableBioCMirrors() { |
| return this.allBioC; |
| } |
| |
| @Override |
| public RuntimeRLibPaths getRLibPaths() { |
| return this.rLibPaths; |
| } |
| |
| private RuntimeRLibPathsLoader getRLibLoader() { |
| if (this.rLibGroups != null) { |
| return this.rLibGroups; |
| } |
| final IREnvConfiguration rEnvConfig= this.rEnv.get(IREnvConfiguration.class); |
| if (rEnvConfig != null) { |
| return new RuntimeRLibPathsLoader(rEnvConfig); |
| } |
| return null; |
| } |
| |
| @Override |
| public @Nullable IRPkgSet getDataset() { |
| return (this.datasetExt != null) ? this.datasetExt : this.dataset; |
| } |
| |
| @Override |
| public IRPkgSet.Ext getExtRPkgSet() { |
| return this.datasetExt; |
| } |
| |
| @Override |
| public List<? extends IRView> getRViews() { |
| return this.rViews; |
| } |
| |
| // @Override |
| // public List<? extends IRView> getBioCViews() { |
| // return biocViews; |
| // } |
| |
| |
| @Override |
| public void apply(final Tool process) { |
| process.getQueue().add(new AbstractRToolRunnable("r/renv/rpkg.apply", //$NON-NLS-1$ |
| "Perform Package Manager Operations") { |
| @Override |
| protected void run(final RToolService r, final ProgressMonitor m) throws StatusException { |
| runApply(r, m); |
| } |
| }); |
| } |
| |
| |
| private boolean beginRTaskSilent(final RToolService r, final ProgressMonitor m) { |
| synchronized (this) { |
| if (this.rProcess != null) { |
| return false; |
| } |
| this.rProcess= r.getTool(); |
| this.rTask= 1; |
| return true; |
| } |
| } |
| |
| private void beginRTask(final RToolService r, final ProgressMonitor m) throws StatusException { |
| synchronized (this) { |
| while (this.rProcess != null) { |
| if (this.rTask == 1) { |
| m.beginSubTask("Waiting for package check..."); |
| try { |
| wait(); |
| } |
| catch (final InterruptedException e) { |
| if (m.isCanceled()) { |
| throw new StatusException(Statuses.CANCEL_STATUS); |
| } |
| } |
| } |
| else { |
| final Status status= new ErrorStatus(RCore.BUNDLE_ID, |
| NLS.bind("Another package manager task for ''{0}'' is already running in ''{0}''", |
| this.rEnv.getName(), this.rProcess.getLabel(Tool.DEFAULT_LABEL) )); |
| // r.handleStatus(status, monitor); |
| throw new StatusException(status); |
| } |
| } |
| this.rProcess= r.getTool(); |
| this.rTask= 2; |
| } |
| } |
| |
| private void endRTask() { |
| synchronized (this) { |
| this.rProcess= null; |
| this.rTask= 0; |
| notifyAll(); |
| } |
| } |
| |
| protected void runApply(final RService r, final ProgressMonitor m) throws StatusException { |
| beginRTask((RToolService) r, m); |
| try { |
| final ISelectedRepos selectedRepos; |
| getReadLock().lock(); |
| try { |
| selectedRepos= this.selectedRepos; |
| } |
| finally { |
| getReadLock().unlock(); |
| } |
| |
| if (getReposStatus(selectedRepos).getSeverity() != Status.ERROR) { |
| updateRequireLoad(); |
| |
| this.rTaskEvent= new Change(this.rEnv); |
| |
| runApplyRepo(selectedRepos, r, m); |
| runLoadPkgs(selectedRepos, r, m); |
| |
| fireUpdate(this.rTaskEvent); |
| } |
| } |
| finally { |
| this.rTaskEvent= null; |
| endRTask(); |
| } |
| } |
| |
| private ISelectedRepos runLoadRepos(final RService r, final ProgressMonitor m) throws StatusException { |
| try { |
| String bioCVersion= null; |
| try { |
| final RObject data= r.evalData("as.character(rj:::renv.getBioCVersion())", m); |
| bioCVersion= RDataUtils.checkSingleCharValue(data); |
| } |
| catch (final StatusException e) { |
| try { |
| final RObject data= r.evalData("as.character(tools:::.BioC_version_associated_with_R_version)", m); |
| bioCVersion= RDataUtils.checkSingleCharValue(data); |
| } |
| catch (final StatusException ignore) { |
| RCorePlugin.logError("Failed to get the version of BioC.", e); |
| } |
| } |
| |
| final boolean loadRMirrors= ((this.requireLoad & (REQUIRE_CRAN | REQUIRE_BIOC)) != 0); |
| final boolean loadRRepos= ((this.requireLoad & (REQUIRE_REPOS)) != 0); |
| |
| List<RRepoMirror> rCRANMirrors= null; |
| List<RRepoMirror> rBioCMirrors= null; |
| String selectedCRAN= null; |
| String selectedBioC= null; |
| if (loadRMirrors) { |
| m.beginSubTask("Fetching available mirrors..."); |
| final String mirrorArgs= "all= FALSE, local.only= FALSE"; //$NON-NLS-1$ |
| |
| rCRANMirrors= fetchMirrors("getCRANmirrors(" + mirrorArgs + ')', r, m); //$NON-NLS-1$ |
| |
| try { |
| rBioCMirrors= fetchMirrors("utils:::.getMirrors('https://bioconductor.org/BioC_mirrors.csv', file.path(R.home('doc'), 'BioC_mirrors.csv'), " + mirrorArgs + ')', r, m); //$NON-NLS-1$ |
| } |
| catch (final Exception e) { |
| } |
| if (rBioCMirrors == null || rBioCMirrors.isEmpty()) { |
| final String[][] s= new String[][] { |
| { "United States (Seattle)", "http://www.bioconductor.org", "us" }, |
| { "United States (Rockville)", "http://watson.nci.nih.gov/bioc_mirror", "us" }, |
| { "Germany (Dortmund)", "http://bioconductor.statistik.tu-dortmund.de", "de" }, |
| { "China (Anhui)", "http://mirrors.ustc.edu.cn/bioc/", "cn" }, |
| { "United Kingdom (Hinxton)", "http://mirrors.ebi.ac.uk/bioconductor/", "uk" }, |
| { "Riken, Kobe (Japan)", "http://bioconductor.jp/", "jp" }, |
| { "Australia (Sydney)", "http://mirror.aarnet.edu.au/pub/bioconductor/", "au" }, |
| { "Brazil (Ribeirão Preto)", "http://bioconductor.fmrp.usp.br/", "br" }, |
| }; |
| rBioCMirrors= new ArrayList<>(s.length); |
| for (int i= 0; i < s.length; i++) { |
| final String url= Util.checkURL(s[i][1]); |
| if (!url.isEmpty()) { |
| rBioCMirrors.add(new RRepoMirror(RRepo.R_PREFIX + url, s[i][0], url, s[i][2])); |
| } |
| } |
| } |
| } |
| |
| List<RRepo> rrepos= null; |
| List<RRepo> selected= null; |
| if (loadRRepos) { |
| m.beginSubTask("Fetching available repositories..."); |
| { final RObject data= r.evalData("options('repos')[[1L]]", m); //$NON-NLS-1$ |
| if (data.getRObjectType() != RObject.TYPE_NULL) { |
| final RCharacterStore urls= RDataUtils.checkRCharVector(data).getData(); |
| final RStore<?> ids= ((RVector<?>) data).getNames(); |
| |
| final int l= RDataUtils.checkIntLength(urls); |
| selected= new ArrayList<>(l); |
| for (int i= 0; i < l; i++) { |
| final String id= (ids != null) ? ids.getChar(i) : null; |
| final String url= urls.getChar(i); |
| |
| final RRepo repo= Util.createRepoFromR(id, null, url); |
| if (repo != null) { |
| selected.add(repo); |
| } |
| } |
| } |
| else { |
| selected= new ArrayList<>(4); |
| } |
| } |
| |
| final RObject data= r.evalData("local({" + //$NON-NLS-1$ |
| "p <- file.path(Sys.getenv('HOME'), '.R', 'repositories')\n" + //$NON-NLS-1$ |
| "if (!file.exists(p)) p <- file.path(R.home('etc'), 'repositories')\n" + //$NON-NLS-1$ |
| "r <- utils::read.delim(p, header= TRUE, comment.char= '#', colClasses= c(rep.int('character', 3L), rep.int('logical', 4L)))\n" + //$NON-NLS-1$ |
| "r[c(names(r)[1L], 'URL', 'default')]\n" + //$NON-NLS-1$ |
| "})", m); //$NON-NLS-1$ |
| final RDataFrame df= RDataUtils.checkRDataFrame(data); |
| final RStore<?> ids= df.getRowNames(); |
| final RCharacterStore labels= RDataUtils.checkRCharVector(df.get(0)).getData(); |
| final RCharacterStore urls= RDataUtils.checkRCharVector(df.get("URL")).getData(); //$NON-NLS-1$ |
| final RLogicalStore isDefault= (selected.isEmpty()) ? |
| RDataUtils.checkRLogiVector(df.get("default")).getData() : null; //$NON-NLS-1$ |
| |
| { final int l= RDataUtils.checkIntLength(labels); |
| rrepos= new ArrayList<>(l + 4); |
| for (int i= 0; i < l; i++) { |
| final String id= (ids != null) ? ids.getChar(i) : null; |
| final String url= urls.getChar(i); |
| |
| final RRepo repo= Util.createRepoFromR(id, labels.getChar(i), url); |
| if (repo != null) { |
| rrepos.add(repo); |
| if (isDefault != null && isDefault.getLogi(i)) { |
| selected.add(repo); |
| } |
| } |
| } |
| } |
| |
| for (int i= 0; i < selected.size(); i++) { |
| final RRepo repo= selected.get(i); |
| RRepo rrepo= null; |
| if (!repo.getURL().isEmpty()) { |
| rrepo= RPkgUtils.getRepoByURL(rrepos, repo.getURL()); |
| } |
| if (rrepo != null) { |
| selected.set(i, rrepo); |
| continue; |
| } |
| if (!repo.getId().isEmpty()) { |
| final int j= rrepos.indexOf(repo); // by id |
| if (j >= 0) { |
| rrepo= rrepos.get(j); |
| if (!RVarRepo.hasVars(rrepo.getURL())) { |
| rrepo.setURL(repo.getURL()); |
| } |
| selected.set(i, rrepo); |
| continue; |
| } |
| } |
| repo.setName(RRepo.hintName(repo)); |
| continue; |
| } |
| } |
| |
| if (loadRMirrors) { |
| if (loadRRepos) { |
| final RRepo repo= RPkgUtils.getRepoById(rrepos, RRepo.CRAN_ID); |
| if (repo != null && !repo.getURL().isEmpty() |
| && !RVarRepo.hasVars(repo.getURL()) ) { |
| selectedCRAN= repo.getURL(); |
| } |
| } |
| else { |
| final RObject data= r.evalData("options('repos')[[1L]]['CRAN']", m); //$NON-NLS-1$ |
| if (data.getRObjectType() != RObject.TYPE_NULL) { |
| final String url= Util.checkURL(RDataUtils.checkSingleChar(data)); |
| if (!url.isEmpty() && !RVarRepo.hasVars(url)) { |
| selectedCRAN= url; |
| } |
| } |
| } |
| { final RObject data= r.evalData("options('BioC_mirror')[[1L]]", m); //$NON-NLS-1$ |
| if (data.getRObjectType() != RObject.TYPE_NULL) { |
| selectedBioC= RDataUtils.checkSingleChar(data); |
| } |
| } |
| } |
| |
| getWriteLock().lock(); |
| try { |
| this.bioCVersion= bioCVersion; |
| |
| if (loadRMirrors) { |
| this.requireLoad &= ~(REQUIRE_CRAN | REQUIRE_BIOC); |
| this.rCRANMirrors= rCRANMirrors; |
| this.selectedCRANInR= selectedCRAN; |
| this.rBioCMirrors= rBioCMirrors; |
| this.selectedBioCInR= selectedBioC; |
| this.mirrorsStamp= this.rTaskEvent.stamp; |
| |
| checkMirrors(this.rTaskEvent); |
| } |
| if (loadRRepos) { |
| this.requireLoad &= ~(REQUIRE_REPOS); |
| this.rRepos= rrepos; |
| this.selectedReposInR= selected; |
| |
| checkRepos(this.rTaskEvent); |
| } |
| this.firstTime= false; |
| |
| if (getReposStatus(this.selectedRepos, this.selectedRepos, this.requireConfirm) |
| .getSeverity() == Status.OK ) { |
| return this.selectedRepos; |
| } |
| return null; |
| } |
| finally { |
| getWriteLock().unlock(); |
| } |
| } |
| catch (final Exception e) { |
| throw new StatusException(new ErrorStatus(RCore.BUNDLE_ID, 0, |
| "An error occurred when loading data for package manager.", e) ); |
| } |
| } |
| |
| private List<RRepoMirror> fetchMirrors(final String rExpr, final RService r, |
| final ProgressMonitor m) throws StatusException, UnexpectedRDataException { |
| final RObject data= r.evalData(rExpr + "[c('Name', 'URL', 'CountryCode')]", m); //$NON-NLS-1$ |
| final RDataFrame df= RDataUtils.checkRDataFrame(data); |
| final RCharacterStore names= RDataUtils.checkRCharVector(df.get("Name")).getData(); //$NON-NLS-1$ |
| final RCharacterStore urls= RDataUtils.checkRCharVector(df.get("URL")).getData(); //$NON-NLS-1$ |
| final RCharacterStore countryCodes= RDataUtils.checkRCharVector(df.get("CountryCode")).getData(); //$NON-NLS-1$ |
| |
| final int l= RDataUtils.checkIntLength(names); |
| final List<RRepoMirror> mirrors= new ArrayList<>(l); |
| for (int i= 0; i < l; i++) { |
| final String url= Util.checkURL(urls.getChar(i)); |
| if (!url.isEmpty()) { |
| mirrors.add(new RRepoMirror(RRepo.R_PREFIX + url, names.getChar(i), url, |
| countryCodes.getChar(i) )); |
| } |
| } |
| return mirrors; |
| } |
| |
| private RRepoMirror getRegionMirror(final List<RRepoMirror> mirrors) { |
| final String countryCode= Locale.getDefault().getCountry().toLowerCase(); |
| RRepoMirror http= null; |
| for (final RRepoMirror repo : mirrors) { |
| if (countryCode.equals(repo.getCountryCode())) { |
| if (repo.getURL().startsWith("https:")) { //$NON-NLS-1$ |
| return repo; |
| } |
| else if (http == null) { |
| http= repo; |
| } |
| } |
| } |
| return http; |
| } |
| |
| private void runApplyRepo(final ISelectedRepos repos, |
| final RService r, final ProgressMonitor m) throws StatusException { |
| m.beginSubTask("Setting repository configuration..."); |
| try { |
| if (repos.getBioCMirror() != null) { |
| final FunctionCall call= r.createFunctionCall("options"); |
| call.addChar("BioC_mirror", repos.getBioCMirror().getURL()); |
| call.evalVoid(m); |
| } |
| { final List<RRepo> selectedRepos= (List<RRepo>) repos.getRepos(); |
| final String[] ids= new String[selectedRepos.size()]; |
| final String[] urls= new String[selectedRepos.size()]; |
| for (int i= 0; i < urls.length; i++) { |
| final RRepo repo= selectedRepos.get(i); |
| ids[i]= repo.getId(); |
| urls[i]= repo.getURL(); |
| } |
| final RVector<RCharacterStore> data= new RVectorImpl<>( |
| new RCharacter32Store(urls), RObject.CLASSNAME_CHARACTER, ids); |
| |
| final FunctionCall call= r.createFunctionCall("options"); |
| call.add("repos", data); |
| call.evalVoid(m); |
| } |
| } |
| catch (final StatusException e) { |
| throw new StatusException(new ErrorStatus(RCore.BUNDLE_ID, |
| "An error occurred when setting repository configuration in R.", |
| e )); |
| } |
| } |
| |
| private void runLoadPkgs(final ISelectedRepos repoSettings, |
| final RService r, final ProgressMonitor m) throws StatusException { |
| final boolean loadRepoPkgs= ((this.requireLoad & (REQUIRE_REPO_PKGS)) != 0 |
| && getReposStatus(repoSettings).getSeverity() == Status.OK ); |
| boolean loadInstPkgs= ((this.requireLoad & (REQUIRE_INST_PKGS)) != 0); |
| |
| RPkgCompilation<IRPkgData> available= null; |
| if (loadRepoPkgs) { |
| available= this.pkgScanner.loadAvailable(this.rEnv, repoSettings, r, m); |
| loadInstPkgs= true; // to combine in package |
| } |
| |
| if (loadInstPkgs) { |
| checkInstalled(true, available, r, m); |
| } |
| |
| if (loadRepoPkgs || loadInstPkgs) { |
| getWriteLock().lock(); |
| try { |
| setPkgs(); |
| |
| if (loadRepoPkgs) { |
| this.requireLoad &= ~REQUIRE_REPO_PKGS; |
| this.pkgsStamp= this.rTaskEvent.stamp; |
| this.rTaskEvent.pkgs |= AVAILABLE_PKGS; |
| } |
| if (loadInstPkgs) { |
| this.requireLoad &= ~REQUIRE_INST_PKGS; |
| } |
| |
| if (this.datasetExt != null) { |
| checkRViews(this.datasetExt, r, m); |
| } |
| } |
| finally { |
| getWriteLock().unlock(); |
| } |
| } |
| } |
| |
| |
| private void checkInstalled(final boolean fullUpdate, @Nullable RPkgCompilation<IRPkgData> newAvailable, |
| final RService r, final ProgressMonitor m) throws StatusException { |
| RVector<RNumericStore> libs= null; |
| boolean[] update= null; |
| |
| final RuntimeRLibPathsLoader rLibLoader= getRLibLoader(); |
| try { |
| libs= rLibLoader.loadLibStamps(r, m); |
| |
| final int l= RDataUtils.checkIntLength(libs.getData()); |
| ITER_LIBS: for (int idxLib= 0; idxLib < l; idxLib++) { |
| final String libPath= libs.getNames().getChar(idxLib); |
| if (this.libs != null) { |
| final int idx= (int) this.libs.getNames().indexOf(libPath); |
| if (idx >= 0) { |
| if (this.libs.getData().getNum(idx) == libs.getData().getNum(idxLib)) { |
| continue ITER_LIBS; |
| } |
| } |
| } |
| if (update == null) { |
| update= new boolean[l]; |
| } |
| update[idxLib]= true; |
| } |
| |
| this.libs= libs; |
| } |
| catch (final UnexpectedRDataException | StatusException e) { |
| throw new StatusException(new ErrorStatus(RCore.BUNDLE_ID, |
| "An error occurred when checking for changed R libraries.", |
| e )); |
| } |
| |
| if (update != null || fullUpdate) { |
| if (this.rTaskEvent == null) { |
| this.rTaskEvent= new Change(this.rEnv); |
| } |
| if (this.rTaskEvent.oldPkgs == null) { |
| this.rTaskEvent.oldPkgs= getDataset(); |
| } |
| if (this.datasetExt != null || fullUpdate) { |
| this.rLibPaths= rLibLoader.load(libs, RuntimeRLibPathsLoader.FULL_CHECK, r, m); |
| if (newAvailable == null) { |
| newAvailable= (this.datasetExt != null) ? |
| this.datasetExt.getAvailable() : |
| new BasicRPkgCompilation<>(0); |
| } |
| final FullRPkgSet newPkgs= new FullRPkgSet(this.rEnv, this.rLibPaths, newAvailable); |
| this.pkgScanner.updateInstFull(this.rLibPaths, update, newPkgs, this.rTaskEvent, r, m); |
| this.rTaskEvent.newPkgs= newPkgs; |
| } |
| else { |
| this.rLibPaths= rLibLoader.load(libs, 0, r, m); |
| this.rTaskEvent.newPkgs= new RPkgSet(this.rEnv, this.rLibPaths, |
| this.pkgScanner.loadInstalled(this.rLibPaths, update, this.rTaskEvent, r, m) ); |
| } |
| |
| if (this.rTaskEvent.installedPkgs != null && this.rTaskEvent.installedPkgs.names.isEmpty()) { |
| this.rTaskEvent.installedPkgs= null; |
| } |
| if (!fullUpdate) { |
| setPkgs(); |
| } |
| if (this.rTaskEvent.installedPkgs != null && this.db != null) { |
| this.db.updatePkgs(this.rTaskEvent); |
| } |
| |
| if (!fullUpdate && this.datasetExt != null) { |
| checkRViews(this.datasetExt, r, m); |
| } |
| } |
| } |
| |
| private void setPkgs() { |
| final Change event= this.rTaskEvent; |
| if (event.newPkgs instanceof FullRPkgSet) { |
| this.datasetExt= (FullRPkgSet) event.newPkgs; |
| this.dataset= null; |
| } |
| else if (event.newPkgs instanceof RPkgSet) { |
| this.datasetExt= null; |
| this.dataset= (RPkgSet) event.newPkgs; |
| } |
| if (event.installedPkgs != null) { |
| event.pkgs |= INSTALLED; |
| } |
| } |
| |
| private void checkRViews(final FullRPkgSet pkgs, |
| final RService r, final ProgressMonitor m) { |
| final RPkgInfoAndData pkg= pkgs.getInstalled().getFirst("ctv"); //$NON-NLS-1$ |
| if (pkg == null || pkg.getVersion().equals(this.rViewsVersion)) { |
| return; |
| } |
| final List<RView> rViews= RViewTasks.loadRViews(r, m); |
| if (rViews != null) { |
| this.rViews= rViews; |
| this.rViewsVersion= pkg.getVersion(); |
| this.rTaskEvent.views= 1; |
| } |
| } |
| |
| |
| @Override |
| public IRPkgData addToCache(final IFileStore store, final IProgressMonitor monitor) throws CoreException { |
| try { |
| final RPkg pkg= RPkgUtils.checkPkgFileName(store.getName()); |
| final RPkgType type= RPkgUtils.checkPkgType(store.getName(), this.rPlatform); |
| this.cache.add(pkg.getName(), type, store, monitor); |
| return new RPkgData(pkg.getName(), RNumVersion.NONE, RRepo.WS_CACHE_PREFIX + type.name().toLowerCase()); |
| } |
| catch (final StatusException e) { |
| throw StatusUtils.convert(e); |
| } |
| } |
| |
| |
| @Override |
| public void perform(final Tool rTool, final List<? extends RPkgAction> actions) { |
| if (actions.isEmpty()) { |
| return; |
| } |
| final String label= (actions.get(0).getAction() == RPkgAction.UNINSTALL) ? |
| "Uninstall R Packages" : "Install/Update R Packages"; |
| final RPkgOperator op= new RPkgOperator(this); |
| rTool.getQueue().add(new AbstractStatetRRunnable("r/renv/pkgs.inst", label) { //$NON-NLS-1$ |
| @Override |
| protected void run(final IRConsoleService r, final ProgressMonitor m) throws StatusException { |
| beginRTask(r, m); |
| try { |
| checkNewCommand(r, m); |
| r.briefAboutToChange(); |
| op.runActions(actions, r, m); |
| } |
| catch (final UnexpectedRDataException | StatusException e) { |
| throw new StatusException(new ErrorStatus(RCore.BUNDLE_ID, |
| "An error occurred when installing and updating R packages.", |
| e )); |
| } |
| finally { |
| endRTask(); |
| |
| r.briefChanged(IRConsoleService.PACKAGE_CHANGE); |
| } |
| } |
| }); |
| } |
| |
| @Override |
| public void loadPkgs(final Tool rTool, final List<? extends IRPkgInfoAndData> pkgs, |
| final boolean expliciteLocation) { |
| final RPkgOperator op= new RPkgOperator(this); |
| rTool.getQueue().add(new AbstractStatetRRunnable("r/renv/pkgs.load", //$NON-NLS-1$ |
| "Load R Packages") { |
| @Override |
| protected void run(final IRConsoleService r, final ProgressMonitor m) throws StatusException { |
| checkNewCommand(r, m); |
| op.loadPkgs(pkgs, expliciteLocation, r, m); |
| } |
| }); |
| } |
| |
| } |