Skip to content

Commit

Permalink
check for loaded packages during console installs
Browse files Browse the repository at this point in the history
  • Loading branch information
jjallaire committed Dec 10, 2012
1 parent 234a50f commit 1019922
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 28 deletions.
3 changes: 3 additions & 0 deletions src/cpp/session/SessionClientEvent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ const int kDeferredInitCompleted = 67;
const int kPlotsZoomSizeChanged = 68;
const int kSourceCppStarted = 69;
const int kSourceCppCompleted = 70;
const int kLoadedPackageUpdates = 71;
}

void ClientEvent::init(int type, const json::Value& data)
Expand Down Expand Up @@ -242,6 +243,8 @@ std::string ClientEvent::typeName() const
return "source_cpp_started";
case client_events::kSourceCppCompleted:
return "source_cpp_completed";
case client_events::kLoadedPackageUpdates:
return "loaded_package_updates";
default:
LOG_WARNING_MESSAGE("unexpected event type: " +
safe_convert::numberToString(type_));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ extern const int kDeferredInitCompleted;
extern const int kPlotsZoomSizeChanged;
extern const int kSourceCppStarted;
extern const int kSourceCppCompleted;
extern const int kLoadedPackageUpdates;
}

class ClientEvent
Expand Down
23 changes: 18 additions & 5 deletions src/cpp/session/modules/SessionPackages.R
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,20 @@
})

if (.rs.loadedPackageUpdates(pkgs)) {
stop(paste("One or more of the packages you are",
"installing (or their dependencies) are",
"currently loaded. In order to assure a",
"correct installation you should restart",
"R and then complete the installation."))

# attempt to determine the install command
if (length(sys.calls()) > 7) {
installCall <- sys.call(-7)
installCmd <- format(installCall)
} else {
installCmd <- NULL
}

# call back into rsession to send an event to the client
.rs.enqueLoadedPackageUpdates(installCmd)

# throw error
stop("Updating loaded packages")
}

# call original
Expand Down Expand Up @@ -337,6 +346,10 @@
}
})

.rs.addFunction("enqueLoadedPackageUpdates", function(installCmd)
{
.Call("rs_enqueLoadedPackageUpdates", installCmd)
})

.rs.addJsonRpcHandler("loaded_package_updates_required", function(pkgs)
{
Expand Down
21 changes: 21 additions & 0 deletions src/cpp/session/modules/SessionPackages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <r/RSexp.hpp>
#include <r/RExec.hpp>
#include <r/RFunctionHook.hpp>
#include <r/RRoutines.hpp>

#include <session/SessionModuleContext.hpp>

Expand Down Expand Up @@ -174,10 +175,30 @@ Error availablePackagesEnd(const core::json::JsonRpcRequest& request,
return Success();
}

SEXP rs_enqueLoadedPackageUpdates(SEXP installCmdSEXP)
{
std::string installCmd;
if (installCmdSEXP != R_NilValue)
installCmd = r::sexp::asString(installCmdSEXP);

ClientEvent event(client_events::kLoadedPackageUpdates, installCmd);
module_context::enqueClientEvent(event);

return R_NilValue;
}


} // anonymous namespace

Error initialize()
{
// register routines
R_CallMethodDef methodDef ;
methodDef.name = "rs_enqueLoadedPackageUpdates" ;
methodDef.fun = (DL_FUNC) rs_enqueLoadedPackageUpdates ;
methodDef.numArgs = 1;
r::routines::addCallMethod(methodDef);

using boost::bind;
using namespace module_context;
ExecBlock initBlock ;
Expand Down
5 changes: 3 additions & 2 deletions src/gwt/src/org/rstudio/core/client/MessageDisplay.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,16 @@ public void showMessage(int type,
.addButton("OK", dismissed)
.showModal();
}

public void showMessage(int type,
String caption,
String message,
Operation dismissed,
String okLabel,
boolean includeCancel)
{
DialogBuilder dialog = createDialog(type, caption, message)
.addButton("OK", dismissed);
.addButton(okLabel, dismissed);
if (includeCancel)
dialog.addButton("Cancel");
dialog.showModal();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import org.rstudio.core.client.Barrier;
import org.rstudio.core.client.Barrier.Token;
import org.rstudio.core.client.StringUtil;
import org.rstudio.core.client.command.CommandBinder;
import org.rstudio.core.client.command.Handler;
import org.rstudio.core.client.events.BarrierReleasedEvent;
Expand Down Expand Up @@ -405,7 +406,7 @@ protected void onSuccess()
pingDelivered_ = true;

// issue after restart command
if (afterRestartCommand != null)
if (!StringUtil.isNullOrEmpty(afterRestartCommand))
{
eventBus_.fireEvent(
new SendToConsoleEvent(afterRestartCommand,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class ClientEvent extends JavaScriptObject
public static final String PlotsZoomSizeChanged = "plots_zoom_size_changed";
public static final String SourceCppStarted = "source_cpp_started";
public static final String SourceCppCompleted = "source_cpp_completed";
public static final String LoadedPackageUpdates = "loaded_package_updates";


protected ClientEvent()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@
import org.rstudio.studio.client.workbench.views.help.events.ShowHelpEvent;
import org.rstudio.studio.client.workbench.views.history.events.HistoryEntriesAddedEvent;
import org.rstudio.studio.client.workbench.views.history.model.HistoryEntry;
import org.rstudio.studio.client.workbench.views.output.find.events.FindOperationEndedEvent;
import org.rstudio.studio.client.workbench.views.output.find.events.FindResultEvent;
import org.rstudio.studio.client.workbench.views.output.sourcecpp.events.SourceCppCompletedEvent;
import org.rstudio.studio.client.workbench.views.output.sourcecpp.events.SourceCppStartedEvent;
import org.rstudio.studio.client.workbench.views.output.sourcecpp.model.SourceCppState;
import org.rstudio.studio.client.workbench.views.packages.events.InstalledPackagesChangedEvent;
import org.rstudio.studio.client.workbench.views.packages.events.LoadedPackageUpdatesEvent;
import org.rstudio.studio.client.workbench.views.packages.events.PackageStatusChangedEvent;
import org.rstudio.studio.client.workbench.views.packages.model.PackageStatus;
import org.rstudio.studio.client.workbench.views.plots.events.LocatorEvent;
Expand Down Expand Up @@ -369,7 +369,7 @@ else if (type.equals(ClientEvent.FindResult))
else if (type.equals(ClientEvent.FindOperationEnded))
{
String data = event.getData();
eventBus_.fireEvent(new FindOperationEndedEvent(data));
eventBus_.fireEvent(new LoadedPackageUpdatesEvent(data));
}
else if (type.equals(ClientEvent.RPubsUploadStatus))
{
Expand Down Expand Up @@ -418,6 +418,11 @@ else if (type.equals(ClientEvent.SourceCppCompleted))
SourceCppState state = event.getData();
eventBus_.fireEvent(new SourceCppCompletedEvent(state));
}
else if (type.equals(ClientEvent.LoadedPackageUpdates))
{
String installCmd = event.getData();
eventBus_.fireEvent(new LoadedPackageUpdatesEvent(installCmd));
}
else if (type.equals(ClientEvent.ListChanged))
{
eventBus_.fireEvent(new ListChangedEvent(event.<JsObject>getData()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import org.rstudio.studio.client.workbench.views.help.events.ShowHelpEvent;
import org.rstudio.studio.client.workbench.views.packages.events.InstalledPackagesChangedEvent;
import org.rstudio.studio.client.workbench.views.packages.events.InstalledPackagesChangedHandler;
import org.rstudio.studio.client.workbench.views.packages.events.LoadedPackageUpdatesEvent;
import org.rstudio.studio.client.workbench.views.packages.events.PackageStatusChangedEvent;
import org.rstudio.studio.client.workbench.views.packages.events.PackageStatusChangedHandler;
import org.rstudio.studio.client.workbench.views.packages.model.PackageInfo;
Expand Down Expand Up @@ -703,6 +704,11 @@ public void onError(ServerError error)
});
}

public void onLoadedPackageUpdates(LoadedPackageUpdatesEvent event)
{
restartForInstallWithConfirmation(event.getInstallCmd());
}

private class InstallCommand
{
public InstallCommand(List<String> packages, String cmd)
Expand All @@ -729,23 +735,7 @@ public void onResponseReceived(Boolean required)
{
if (required)
{
globalDisplay_.showMessage(
MessageDialog.WARNING,
"Restart Required for Package Updates",
"One or more of the packages you are installing (or " +
"their dependencies) are currently loaded. In order " +
"to assure correct installation you need to " +
"restart R before proceeding.\n\n" +
"RStudio will restart R now. All current work and data " +
"will be preserved and package installation will "+
"continue automatically after the restart.\n",
new Operation() { public void execute()
{
events_.fireEvent(new SuspendAndRestartEvent(
SuspendOptions.createSaveAll(true), command.cmd));

}},
true);
restartForInstallWithConfirmation(command.cmd);
}
else
{
Expand All @@ -772,6 +762,34 @@ private void executePkgCommand(String cmd)
{
events_.fireEvent(new SendToConsoleEvent(cmd, true));
}

private void restartForInstallWithConfirmation(final String installCmd)
{
String msg = "One or more of the packages that will be updated by this " +
"installation are currently loaded. Restarting R prior " +
"to updating these packages is strongly recommended.\n\n" +
"RStudio will restart R now (all current work and data " +
"will be preserved during the restart). ";

if (installCmd.startsWith("install.packages"))
{
msg += "Installation of the selected packages will continue " +
"automatically after the restart.";
}

globalDisplay_.showMessage(
MessageDialog.WARNING,
"Updating Loaded Packages",
msg,
new Operation() { public void execute()
{
events_.fireEvent(new SuspendAndRestartEvent(
SuspendOptions.createSaveAll(true), installCmd));

}},
"Restart R",
true);
}


private final Display view_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,19 @@

import org.rstudio.core.client.command.CommandBinder;
import org.rstudio.core.client.command.Handler;
import org.rstudio.studio.client.application.events.EventBus;
import org.rstudio.studio.client.workbench.commands.Commands;
import org.rstudio.studio.client.workbench.ui.DelayLoadTabShim;
import org.rstudio.studio.client.workbench.ui.DelayLoadWorkbenchTab;
import org.rstudio.studio.client.workbench.views.packages.events.LoadedPackageUpdatesEvent;

public class PackagesTab extends DelayLoadWorkbenchTab<Packages>
{
public interface Binder extends CommandBinder<Commands, Shim> {}

public abstract static class Shim
extends DelayLoadTabShim<Packages, PackagesTab>
implements LoadedPackageUpdatesEvent.Handler
{
@Handler
public abstract void onInstallPackage();
Expand All @@ -34,9 +37,13 @@ public abstract static class Shim
}

@Inject
public PackagesTab(Shim shim, Binder binder, Commands commands)
public PackagesTab(Shim shim,
Binder binder,
EventBus events,
Commands commands)
{
super("Packages", shim);
binder.bind(commands, shim);
events.addHandler(LoadedPackageUpdatesEvent.TYPE, shim);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* LoadedPackageUpdatesEvent.java
*
* Copyright (C) 2009-12 by RStudio, Inc.
*
* This program is licensed to you under the terms of version 3 of the
* GNU Affero General Public License. This program is distributed WITHOUT
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
* AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
*
*/
package org.rstudio.studio.client.workbench.views.packages.events;

import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;

public class LoadedPackageUpdatesEvent extends GwtEvent<LoadedPackageUpdatesEvent.Handler>
{
public interface Handler extends EventHandler
{
void onLoadedPackageUpdates(LoadedPackageUpdatesEvent event);
}

public LoadedPackageUpdatesEvent(String installCmd)
{
installCmd_ = installCmd;
}

public String getInstallCmd()
{
return installCmd_;
}

@Override
public Type<Handler> getAssociatedType()
{
return TYPE;
}

@Override
protected void dispatch(Handler handler)
{
handler.onLoadedPackageUpdates(this);
}

private final String installCmd_;

public static final Type<Handler> TYPE = new Type<Handler>();
}

0 comments on commit 1019922

Please sign in to comment.