| /*=============================================================================# |
| # 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.Collections; |
| import java.util.List; |
| |
| import org.eclipse.osgi.util.NLS; |
| |
| 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.StatusException; |
| |
| import org.eclipse.statet.r.core.RCore; |
| import org.eclipse.statet.r.core.pkgmanager.IRPkgData; |
| import org.eclipse.statet.r.core.pkgmanager.IRPkgInfo; |
| import org.eclipse.statet.r.core.pkgmanager.ISelectedRepos; |
| import org.eclipse.statet.r.core.pkgmanager.RPkgInfo; |
| import org.eclipse.statet.r.core.pkgmanager.RPkgUtils; |
| import org.eclipse.statet.r.core.pkgmanager.RRepo; |
| import org.eclipse.statet.rj.data.RArray; |
| import org.eclipse.statet.rj.data.RCharacterStore; |
| import org.eclipse.statet.rj.data.RDataUtils; |
| import org.eclipse.statet.rj.data.UnexpectedRDataException; |
| import org.eclipse.statet.rj.renv.core.BasicRPkg; |
| import org.eclipse.statet.rj.renv.core.BasicRPkgCompilation; |
| import org.eclipse.statet.rj.renv.core.REnv; |
| import org.eclipse.statet.rj.renv.core.RLibLocation; |
| 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.RPkgList; |
| import org.eclipse.statet.rj.renv.runtime.RLibLocationInfo; |
| import org.eclipse.statet.rj.renv.runtime.RuntimeRLibPaths; |
| import org.eclipse.statet.rj.services.FunctionCall; |
| import org.eclipse.statet.rj.services.RService; |
| |
| |
| final class RPkgScanner { |
| |
| private static final String AVAIL_LIST_FNAME= "rj:::renv.getAvailPkgs"; //$NON-NLS-1$ |
| private static final int AVAIL_LIST_COUNT1= 9; |
| private static final int AVAIL_LIST_IDX1_NAME= 0; |
| private static final int AVAIL_LIST_IDX1_VERSION= 1; |
| private static final int AVAIL_LIST_IDX1_PRIORITY= 2; |
| private static final int AVAIL_LIST_IDX1_LICENSE= 3; |
| private static final int AVAIL_LIST_IDX1_DEPENDS= 4; |
| private static final int AVAIL_LIST_IDX1_IMPORTS= 5; |
| private static final int AVAIL_LIST_IDX1_LINKINGTO= 6; |
| private static final int AVAIL_LIST_IDX1_SUGGESTS= 7; |
| private static final int AVAIL_LIST_IDX1_ENHANCES= 8; |
| |
| private static final String INST_LIST_FNAME= "rj:::renv.getInstPkgs"; //$NON-NLS-1$ |
| private static final int INST_LIST_COUNT1= 4; |
| private static final int INST_LIST_IDX1_NAME= 0; |
| private static final int INST_LIST_IDX1_VERSION= 1; |
| private static final int INST_LIST_IDX1_TITLE= 2; |
| private static final int INST_LIST_IDX1_BUILT= 3; |
| |
| private static final String INST_DETAIL_FNAME= "rj:::renv.getInstPkgDetail"; //$NON-NLS-1$ |
| private static final int INST_DETAIL_LENGTH= 7; |
| private static final int INST_DETAIL_IDX_PRIORITY= 0; |
| private static final int INST_DETAIL_IDX_LICENSE= 1; |
| private static final int INST_DETAIL_IDX_DEPENDS= 2; |
| private static final int INST_DETAIL_IDX_IMPORTS= 3; |
| private static final int INST_DETAIL_IDX_LINKINGTO= 4; |
| private static final int INST_DETAIL_IDX_SUGGESTS= 5; |
| private static final int INST_DETAIL_IDX_ENHANCES= 6; |
| |
| private static @Nullable String decodeDescrField(final @Nullable String s) { |
| if (s == null) { |
| return null; |
| } |
| int mode= 0; // 1= single space, 2= chars to replace |
| int idxMode= 0; |
| int idxDone= 0; |
| StringBuilder sb= null; |
| for (int idx = 0; idx < s.length(); idx++) { |
| switch (s.charAt(idx)) { |
| case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: |
| case 0x08: case 0x09: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0E: case 0x0F: |
| case 0x7F: |
| switch (mode) { |
| case 0: |
| mode= 2; |
| idxMode= idx; |
| continue; |
| case 1: |
| mode= 2; |
| continue; |
| // case 2: |
| default: |
| continue; |
| } |
| case ' ': |
| switch (mode) { |
| case 0: |
| mode= 1; |
| idxMode= idx; |
| continue; |
| case 1: |
| mode= 2; |
| continue; |
| // case 2: |
| default: |
| continue; |
| } |
| default: |
| switch (mode) { |
| case 0: |
| continue; |
| case 1: |
| mode= 0; |
| continue; |
| // case 2: |
| default: |
| if (sb == null) { |
| sb= new StringBuilder(s.length()); |
| } |
| sb.append(s, idxDone, idxMode); |
| sb.append(' '); |
| idxDone= idx + 1; |
| mode= 0; |
| continue; |
| } |
| } |
| } |
| if (sb != null) { |
| sb.append(s, idxDone, (mode == 0) ? s.length() : idxMode); |
| return sb.toString(); |
| } |
| else { |
| return (mode == 0) ? s : s.substring(0, idxMode); |
| } |
| } |
| |
| |
| private static List<RPkg> parsePkgRefs(final String s) { |
| if (s == null || s.isEmpty()) { |
| return Collections.emptyList(); |
| } |
| final List<RPkg> list= new ArrayList<>(4); |
| String name= null; |
| String version= null; |
| boolean ws; |
| final StringBuilder sb= new StringBuilder(); |
| ITER_S: for (int i= 0; i <= s.length();) { |
| int c= (i < s.length()) ? s.charAt(i) : -1; |
| |
| if (c == -1 || c == ',') { |
| if (name != null) { |
| list.add(new BasicRPkg(name, RNumVersion.create(version))); |
| } |
| name= null; |
| version= null; |
| i++; |
| continue ITER_S; |
| } |
| if (Character.isLetterOrDigit(c)) { |
| if (name != null) { |
| // ? |
| } |
| name= null; |
| version= null; |
| int j= i + 1; |
| while (true) { |
| c= (j < s.length()) ? s.charAt(j) : -1; |
| if (c < 0 || Character.isWhitespace(c) || c == '(' || c == ',') { |
| name= s.substring(i, j).intern(); |
| i= j; |
| continue ITER_S; |
| } |
| j++; |
| } |
| } |
| if (c == '(') { |
| if (name == null || version != null) { |
| // ? |
| name= null; |
| version= null; |
| } |
| sb.setLength(0); |
| ws= false; |
| int j= ++i; |
| while (true) { |
| c= (j < s.length()) ? s.charAt(j) : -1; |
| if (c < 0 || c == ')') { |
| version= sb.toString(); |
| i= j + 1; |
| continue ITER_S; |
| } |
| if (Character.isWhitespace(c)) { |
| ws= true; |
| } |
| else { |
| if (ws) { |
| sb.append(' '); |
| ws= false; |
| } |
| sb.append((char) c); |
| } |
| j++; |
| } |
| } |
| |
| i++; |
| continue ITER_S; |
| } |
| return list; |
| } |
| |
| |
| private final BasicRPkgCompilation<IRPkgData> expectedPkgs= new BasicRPkgCompilation<IRPkgData>(4) { |
| @Override |
| protected RPkgList<IRPkgData> newPkgList() { |
| return new RPkgListImpl<>(4); |
| } |
| }; |
| |
| |
| public RPkgScanner() { |
| } |
| |
| |
| void addExpectedPkg(final RLibLocation location, final IRPkgData pkg) { |
| final String path= location.getDirectory(); |
| final RPkgListImpl<IRPkgData> list= (RPkgListImpl<IRPkgData>) this.expectedPkgs.getOrAdd(path); |
| list.set(pkg); |
| } |
| |
| private void clearExpected() { |
| final List<RPkgList<IRPkgData>> all= this.expectedPkgs.getAll(); |
| for (final RPkgList<IRPkgData> list : all) { |
| ((RPkgListImpl<IRPkgData>) list).clear(); |
| } |
| } |
| |
| |
| RPkgCompilation<IRPkgData> loadAvailable(final REnv rEnv, final ISelectedRepos repoSettings, |
| final RService r, final ProgressMonitor m) throws StatusException { |
| m.beginSubTask("Loading available R packages..."); |
| try { |
| final RCharacterStore repos= RDataUtils.checkRCharVector(r.evalData( |
| "options('repos')[[1L]]", m)).getData(); //$NON-NLS-1$ |
| final int l= RDataUtils.checkIntLength(repos); |
| |
| final BasicRPkgCompilation<IRPkgData> newAvailable= new BasicRPkgCompilation<>(l); |
| for (int idxRepos= 0; idxRepos < l; idxRepos++) { |
| final String repoURL= repos.getChar(idxRepos); |
| if (repoURL == null || repoURL.isEmpty()) { |
| continue; |
| } |
| final RRepo repo= Util.getRepoByURL(repoSettings.getRepos(), repoURL); |
| m.beginSubTask(NLS.bind("Loading available R packages from {0}...", repoURL)); |
| |
| RArray<RCharacterStore> data; |
| { final FunctionCall call= r.createFunctionCall(AVAIL_LIST_FNAME); |
| call.addChar("repo", repoURL); //$NON-NLS-1$ |
| if (repo.getPkgType() != null) { |
| final String key= RPkgUtils.getPkgTypeInstallKey(r.getPlatform(), repo.getPkgType()); |
| if (key == null) { |
| continue; |
| } |
| } |
| data= RDataUtils.checkRCharArray(call.evalData(m), 2); |
| RDataUtils.checkColumnCountEqual(data, AVAIL_LIST_COUNT1); |
| } |
| |
| final RCharacterStore store= data.getData(); |
| final int nPkgs= data.getDim().getInt(0); |
| final RPkgListImpl<IRPkgData> list= new RPkgListImpl<>(nPkgs); |
| newAvailable.add(repo.getId(), list); |
| |
| for (int idxPkgs= 0; idxPkgs < nPkgs; idxPkgs++) { |
| String name= store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkgs, AVAIL_LIST_IDX1_NAME)); |
| final String version= store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkgs, AVAIL_LIST_IDX1_VERSION)); |
| if (name != null && !name.isEmpty() && version != null) { |
| name= name.intern(); |
| final RPkgData pkg= new RPkgData(name, RNumVersion.create(version), repo.getId()); |
| |
| pkg.setLicense(store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkgs, AVAIL_LIST_IDX1_LICENSE))); |
| |
| pkg.setDepends(RPkgScanner.parsePkgRefs(store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkgs, AVAIL_LIST_IDX1_DEPENDS)))); |
| pkg.setImports(RPkgScanner.parsePkgRefs(store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkgs, AVAIL_LIST_IDX1_IMPORTS)))); |
| pkg.setLinkingTo(RPkgScanner.parsePkgRefs(store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkgs, AVAIL_LIST_IDX1_LINKINGTO)))); |
| pkg.setSuggests(RPkgScanner.parsePkgRefs(store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkgs, AVAIL_LIST_IDX1_SUGGESTS)))); |
| pkg.setEnhances(RPkgScanner.parsePkgRefs(store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkgs, AVAIL_LIST_IDX1_ENHANCES)))); |
| |
| pkg.setPriority(store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkgs, AVAIL_LIST_IDX1_PRIORITY))); |
| |
| list.add(pkg); |
| } |
| } |
| } |
| |
| return newAvailable; |
| } |
| catch (final UnexpectedRDataException | StatusException e) { |
| throw new StatusException(new ErrorStatus(RCore.BUNDLE_ID, |
| "An error occurred when loading list of available R packages.", |
| e )); |
| } |
| } |
| |
| RPkgCompilation<IRPkgInfo> loadInstalled(final RuntimeRLibPaths rLibPaths, final boolean[] update, |
| final Change event, |
| final RService r, final ProgressMonitor m) throws StatusException { |
| m.beginSubTask("Updating installed R packages..."); |
| try { |
| final BasicRPkgCompilation<IRPkgInfo> newInstalled= new BasicRPkgCompilation<>( |
| rLibPaths.getRLibLocations().size() ); |
| final RPkgCompilation<IRPkgInfo> prevInstalled= (RPkgCompilation<IRPkgInfo>) |
| ((event.oldPkgs != null) ? event.oldPkgs.getInstalled() : null); |
| final RPkgChangeSet changeSet= new RPkgChangeSet(); |
| event.installedPkgs= changeSet; |
| for (final RLibLocation libLocation : rLibPaths.getRLibLocations()) { |
| final RLibLocationInfo locationInfo= rLibPaths.getInfo(libLocation); |
| if (locationInfo == null || locationInfo.getLibPathsIndex() < 0) { |
| continue; |
| } |
| if (newInstalled.getBySource(libLocation.getDirectory()) != null) { |
| continue; |
| } |
| if (update == null || update[locationInfo.getLibPathsIndex()] || prevInstalled == null) { |
| final RArray<RCharacterStore> data; |
| { final FunctionCall call= r.createFunctionCall(INST_LIST_FNAME); |
| call.addChar("lib", locationInfo.getDirectoryRPath()); //$NON-NLS-1$ |
| data= RDataUtils.checkRCharArray(call.evalData(m), 2); |
| RDataUtils.checkColumnCountEqual(data, INST_LIST_COUNT1); |
| } |
| final RCharacterStore store= data.getData(); |
| final int nPkgs= data.getDim().getInt(0); |
| |
| final RPkgList<IRPkgInfo> oldList= (prevInstalled != null) ? |
| prevInstalled.getBySource(libLocation.getDirectory()) : null; |
| final RPkgListImpl<IRPkgInfo> newList= new RPkgListImpl<>(nPkgs); |
| final RPkgList<IRPkgData> expectedList= this.expectedPkgs.getBySource(libLocation.getDirectory()); |
| for (int idxPkg= 0; idxPkg < nPkgs; idxPkg++) { |
| String name= store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkg, INST_LIST_IDX1_NAME)); |
| final String version= store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkg, INST_LIST_IDX1_VERSION)); |
| if (name != null && !name.isEmpty() && version != null && !version.isEmpty()) { |
| name= name.intern(); |
| String built= store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkg, INST_LIST_IDX1_BUILT)); |
| if (built == null) { |
| built= ""; //$NON-NLS-1$ |
| } |
| final IRPkgInfo oldPkg= (oldList != null) ? oldList.get(name) : null; |
| final IRPkgInfo newPkg; |
| final boolean changed= (oldPkg == null |
| || !oldPkg.getVersion().toString().equals(version) |
| || !oldPkg.getBuilt().equals(built) ); |
| |
| if (!changed) { |
| newPkg= oldPkg; |
| } |
| else { |
| final IRPkgData expectedData = |
| (expectedList != null) ? expectedList.get(name) : null; |
| newPkg= new RPkgInfo(name, RNumVersion.create(version), built, |
| decodeDescrField( |
| store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkg, INST_LIST_IDX1_TITLE)) ), |
| libLocation, |
| 0, |
| event.stamp, |
| (expectedData != null) ? expectedData.getRepoId() : null ); |
| |
| changeSet.names.add(name); |
| if (oldPkg == null) { |
| changeSet.added.add(newPkg); |
| } |
| else { |
| changeSet.changed.add(oldPkg); |
| } |
| } |
| |
| newList.add(newPkg); |
| } |
| } |
| if (oldList != null) { |
| int i= 0, j= 0; |
| final int in= oldList.size(), jn= newList.size(); |
| while (i < in) { |
| final IRPkgInfo oldPkg= oldList.get(i++); |
| final String name= oldPkg.getName(); |
| if (j < jn) { |
| if (newList.get(j).getName() == name) { |
| j++; |
| continue; |
| } |
| final int idx= newList.indexOf(name, j + 1); |
| if (idx >= 0) { |
| j= idx + 1; |
| continue; |
| } |
| } |
| changeSet.names.add(name); |
| changeSet.deleted.add(oldPkg); |
| } |
| } |
| |
| newInstalled.add(libLocation.getDirectory(), newList); |
| } |
| else { |
| final RPkgList<IRPkgInfo> prevList= prevInstalled.getBySource(libLocation.getDirectory()); |
| if (prevList != null) { |
| newInstalled.add(libLocation.getDirectory(), prevList); |
| } |
| else { |
| // error/warning? |
| } |
| } |
| } |
| |
| clearExpected(); |
| |
| return newInstalled; |
| } |
| catch (final UnexpectedRDataException | StatusException e) { |
| throw new StatusException(new ErrorStatus(RCore.BUNDLE_ID, |
| "An error occurred when loading list of installed R packages.", |
| e )); |
| } |
| } |
| |
| void updateInstFull(final RuntimeRLibPaths rLibPaths, final boolean[] update, |
| final FullRPkgSet newPkgs, final Change event, |
| final RService r, final ProgressMonitor m) throws StatusException { |
| m.beginSubTask("Updating installed R packages..."); |
| try { |
| final FullRPkgSet oldFullPkgs= (event.oldPkgs instanceof FullRPkgSet) ? |
| (FullRPkgSet) event.oldPkgs : null; |
| final RPkgChangeSet changeSet= new RPkgChangeSet(); |
| event.installedPkgs= changeSet; |
| for (final RLibLocation location : rLibPaths.getRLibLocations()) { |
| final RLibLocationInfo locationInfo= rLibPaths.getInfo(location); |
| if (locationInfo == null || locationInfo.getLibPathsIndex() < 0) { |
| continue; |
| } |
| if (update == null || update[locationInfo.getLibPathsIndex()] || oldFullPkgs == null) { |
| final RArray<RCharacterStore> data; |
| { final FunctionCall call= r.createFunctionCall(INST_LIST_FNAME); |
| call.addChar("lib", locationInfo.getDirectoryRPath()); //$NON-NLS-1$ |
| data= RDataUtils.checkRCharArray(call.evalData(m), 2); |
| RDataUtils.checkColumnCountEqual(data, INST_LIST_COUNT1); |
| } |
| final RCharacterStore store= data.getData(); |
| final int nPkgs= data.getDim().getInt(0); |
| |
| final RPkgList<? extends IRPkgInfo> oldList= (event.oldPkgs != null) ? |
| event.oldPkgs.getInstalled().getBySource(location.getDirectory()) : null; |
| final RPkgListImpl<RPkgInfoAndData> newList= new RPkgListImpl<>(nPkgs); |
| final RPkgList<IRPkgData> expectedList= this.expectedPkgs.getBySource(location.getDirectory()); |
| for (int idxPkg= 0; idxPkg < nPkgs; idxPkg++) { |
| String name= store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkg, INST_LIST_IDX1_NAME)); |
| final String version= store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkg, INST_LIST_IDX1_VERSION)); |
| if (name != null && !name.isEmpty() && version != null && !version.isEmpty()) { |
| name= name.intern(); |
| String built= store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkg, INST_LIST_IDX1_BUILT)); |
| if (built == null) { |
| built= ""; //$NON-NLS-1$ |
| } |
| final IRPkgInfo oldPkg= (oldList != null) ? oldList.get(name) : null; |
| final RPkgInfoAndData newPkg; |
| final boolean changed= (oldPkg == null |
| || !oldPkg.getVersion().toString().equals(version) |
| || !oldPkg.getBuilt().equals(built) ); |
| |
| if (!changed && (oldPkg instanceof RPkgInfoAndData)) { |
| newPkg= (RPkgInfoAndData) oldPkg; |
| } |
| else { |
| final IRPkgData expectedData= (changed && expectedList != null) ? |
| expectedList.get(name) : null; |
| newPkg= new RPkgInfoAndData(name, |
| (!changed) ? oldPkg.getVersion() : RNumVersion.create(version), |
| built, |
| decodeDescrField( |
| store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkg, INST_LIST_IDX1_TITLE)) ), |
| location, |
| (!changed) ? oldPkg.getFlags() : 0, |
| (!changed) ? oldPkg.getInstallStamp() : event.stamp, |
| (!changed) ? oldPkg.getRepoId() : ((expectedData != null) ? expectedData.getRepoId() : null) ); |
| |
| RCharacterStore detail; |
| { final FunctionCall call= r.createFunctionCall(INST_DETAIL_FNAME); |
| call.addChar("lib", locationInfo.getDirectoryRPath()); //$NON-NLS-1$ |
| call.addChar("name", name); //$NON-NLS-1$ |
| detail= RDataUtils.checkRCharVector(call.evalData(m)).getData(); |
| RDataUtils.checkLengthEqual(detail, INST_DETAIL_LENGTH); |
| } |
| |
| newPkg.setPriority(detail.getChar(INST_DETAIL_IDX_PRIORITY)); |
| newPkg.setLicense(detail.getChar(INST_DETAIL_IDX_LICENSE)); |
| |
| newPkg.setDepends(RPkgScanner.parsePkgRefs(detail.getChar(INST_DETAIL_IDX_DEPENDS))); |
| newPkg.setImports(RPkgScanner.parsePkgRefs(detail.getChar(INST_DETAIL_IDX_IMPORTS))); |
| newPkg.setLinkingTo(RPkgScanner.parsePkgRefs(detail.getChar(INST_DETAIL_IDX_LINKINGTO))); |
| newPkg.setSuggests(RPkgScanner.parsePkgRefs(detail.getChar(INST_DETAIL_IDX_SUGGESTS))); |
| newPkg.setEnhances(RPkgScanner.parsePkgRefs(detail.getChar(INST_DETAIL_IDX_ENHANCES))); |
| |
| if (changed) { |
| changeSet.names.add(name); |
| if (oldPkg == null) { |
| changeSet.added.add(newPkg); |
| } |
| else { |
| changeSet.changed.add(oldPkg); |
| } |
| } |
| } |
| |
| newList.add(newPkg); |
| } |
| } |
| if (oldList != null) { |
| int i= 0, j= 0; |
| final int in= oldList.size(), jn= newList.size(); |
| while (i < in) { |
| final IRPkgInfo oldPkg= oldList.get(i++); |
| final String name= oldPkg.getName(); |
| if (j < jn) { |
| if (newList.get(j).getName() == name) { |
| j++; |
| continue; |
| } |
| final int idx= newList.indexOf(name, j + 1); |
| if (idx >= 0) { |
| j= idx + 1; |
| continue; |
| } |
| } |
| changeSet.names.add(name); |
| changeSet.deleted.add(oldPkg); |
| } |
| } |
| |
| newPkgs.getInstalled().add(location.getDirectory(), newList); |
| } |
| else { |
| newPkgs.getInstalled().add(location.getDirectory(), |
| oldFullPkgs.getInstalled().getBySource(location.getDirectory()) ); |
| } |
| } |
| return; |
| } |
| catch (final UnexpectedRDataException | StatusException e) { |
| throw new StatusException(new ErrorStatus(RCore.BUNDLE_ID, |
| "An error occurred when loading list of installed R packages.", |
| e )); |
| } |
| } |
| |
| } |