| /*=============================================================================# |
| # Copyright (c) 2012, 2021 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.rj.renv.runtime; |
| |
| import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullElse; |
| |
| import static org.eclipse.statet.internal.rj.renv.core.REnvCoreInternals.BUNDLE_ID; |
| |
| import org.eclipse.statet.jcommons.lang.NonNullByDefault; |
| 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.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.BasicRPkgBuilt; |
| import org.eclipse.statet.rj.renv.core.BasicRPkgCompilation; |
| import org.eclipse.statet.rj.renv.core.BasicRPkgList; |
| import org.eclipse.statet.rj.renv.core.RLibLocation; |
| import org.eclipse.statet.rj.renv.core.RNumVersion; |
| import org.eclipse.statet.rj.renv.core.RPkgBuilt; |
| import org.eclipse.statet.rj.renv.core.RPkgCompilation; |
| import org.eclipse.statet.rj.renv.core.RPkgList; |
| import org.eclipse.statet.rj.services.FunctionCall; |
| import org.eclipse.statet.rj.services.RService; |
| |
| |
| @NonNullByDefault |
| public class RuntimeRPkgInfoLoader { |
| |
| |
| 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; |
| |
| |
| public RuntimeRPkgInfoLoader() { |
| } |
| |
| |
| public RPkgCompilation<RPkgBuilt> loadInstalled(final RuntimeRLibPaths rLibPaths, |
| final boolean @Nullable [] update, final @Nullable RPkgCompilation<RPkgBuilt> prevInstalled, |
| // final Change event, |
| final RService r, final ProgressMonitor m) throws StatusException { |
| m.beginSubTask("Updating installed R packages..."); |
| try { |
| final BasicRPkgCompilation<RPkgBuilt> newInstalled= new BasicRPkgCompilation<>( |
| rLibPaths.getRLibLocations().size() ); |
| // 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<RPkgBuilt> oldList= (prevInstalled != null) ? |
| prevInstalled.getBySource(libLocation.getDirectory()) : null; |
| final BasicRPkgList<RPkgBuilt> newList= new BasicRPkgList<>(nPkgs); |
| 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(); |
| final String built= nonNullElse( |
| store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkg, INST_LIST_IDX1_BUILT)), |
| "" ); //$NON-NLS-1$ |
| final RPkgBuilt oldPkg= (oldList != null) ? oldList.get(name) : null; |
| final RPkgBuilt newPkg; |
| if (oldPkg != null |
| && oldPkg.getVersion().toString().equals(version) |
| && oldPkg.getBuilt().equals(built) ) { |
| newPkg= oldPkg; |
| } |
| else { |
| final String title= nonNullElse( |
| store.getChar(RDataUtils.getDataIdx(nPkgs, idxPkg, INST_LIST_IDX1_TITLE)), |
| "" ); //$NON-NLS-1$ |
| newPkg= new BasicRPkgBuilt(name, |
| RNumVersion.create(version), built, |
| title, libLocation ); |
| |
| // 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 RPkgBuilt 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<RPkgBuilt> prevList= prevInstalled.getBySource(libLocation.getDirectory()); |
| if (prevList != null) { |
| newInstalled.add(libLocation.getDirectory(), prevList); |
| } |
| else { |
| // error/warning? |
| } |
| } |
| } |
| |
| return newInstalled; |
| } |
| catch (final UnexpectedRDataException | StatusException e) { |
| throw new StatusException(new ErrorStatus(BUNDLE_ID, |
| "An error occurred when loading list of installed R packages.", |
| e )); |
| } |
| } |
| |
| } |