blob: ae782ba19288de6ec69914691a443c9dfe5958d6 [file] [log] [blame]
/*=============================================================================#
# 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 ));
}
}
}