/*
* SVNCommandHandler.java
*
* Copyright (C) 2009-12 by RStudio, Inc.
*
* Unless you have received this program directly from RStudio pursuant
* to the terms of a commercial license agreement with RStudio, then
* 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.vcs.svn;
import java.util.ArrayList;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.rstudio.core.client.command.CommandBinder;
import org.rstudio.core.client.command.Handler;
import org.rstudio.core.client.files.FileSystemItem;
import org.rstudio.core.client.widget.MessageDialog;
import org.rstudio.core.client.widget.Operation;
import org.rstudio.core.client.widget.OperationWithInput;
import org.rstudio.studio.client.RStudioGinjector;
import org.rstudio.studio.client.common.GlobalDisplay;
import org.rstudio.studio.client.common.SimpleRequestCallback;
import org.rstudio.studio.client.common.console.ConsoleProcess;
import org.rstudio.studio.client.common.vcs.ProcessResult;
import org.rstudio.studio.client.common.vcs.SVNServerOperations;
import org.rstudio.studio.client.common.vcs.StatusAndPath;
import org.rstudio.studio.client.common.vcs.ignore.Ignore;
import org.rstudio.studio.client.common.vcs.ignore.IgnoreList;
import org.rstudio.studio.client.server.ServerRequestCallback;
import org.rstudio.studio.client.workbench.commands.Commands;
import org.rstudio.studio.client.workbench.views.vcs.common.ConsoleProgressDialog;
import org.rstudio.studio.client.workbench.views.vcs.common.ProcessCallback;
import org.rstudio.studio.client.workbench.views.vcs.common.VCSFileOpener;
import org.rstudio.studio.client.workbench.views.vcs.svn.commit.SVNCommitDialog;
import org.rstudio.studio.client.workbench.views.vcs.svn.model.SVNState;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Command;
public class SVNCommandHandler
{
public interface Binder extends CommandBinder<Commands, SVNCommandHandler>
{
}
public SVNCommandHandler(SVNPresenterDisplay display,
GlobalDisplay globalDisplay,
Commands commands,
SVNServerOperations server,
SVNState svnState,
VCSFileOpener vcsFileOpener)
{
display_ = display;
globalDisplay_ = globalDisplay;
commands_ = commands;
server_ = server;
svnState_ = svnState;
vcsFileOpener_ = vcsFileOpener;
GWT.<Binder>create(Binder.class).bind(commands, this);
RStudioGinjector.INSTANCE.injectMembers(this);
}
@Inject
void initialize(Provider<SVNCommitDialog> pCommitDialog,
Provider<Ignore> pIgnore)
{
pCommitDialog_ = pCommitDialog;
pIgnore_ = pIgnore;
}
public void setFilesCommandsEnabled(boolean enabled)
{
commands_.vcsAddFiles().setEnabled(enabled);
commands_.vcsRemoveFiles().setEnabled(enabled);
commands_.vcsRevert().setEnabled(enabled);
commands_.vcsIgnore().setEnabled(enabled);
commands_.vcsResolve().setEnabled(enabled);
}
// onVcsPull and onVcsCommit and not direct command handlers because they
// are handled globally in the main frame (by BaseVcsPresenter or the
// satellite frame)
public void onVcsPull()
{
server_.svnUpdate(new SimpleRequestCallback<ConsoleProcess>()
{
@Override
public void onResponseReceived(ConsoleProcess response)
{
new ConsoleProgressDialog(response, server_).showModal();
}
});
}
public void onVcsCommit()
{
pCommitDialog_.get().showModal();
}
public void onVcsIgnore()
{
// special case for a single directory with property changes
ArrayList<StatusAndPath> items = display_.getSelectedItems();
if (items.size() == 1)
{
StatusAndPath item = items.get(0);
if (item.isDirectory() && item.getStatus().equals("M"))
{
String path = item.getPath();
if (path.equals("."))
path = "";
IgnoreList ignoreList = new IgnoreList(path,
new ArrayList<String>());
pIgnore_.get().showDialog(ignoreList, ignoreStrategy_);
return;
}
}
// standard case
ArrayList<String> paths = getPathArray();
pIgnore_.get().showDialog(paths, ignoreStrategy_);
}
private final Ignore.Strategy ignoreStrategy_ = new Ignore.Strategy() {
@Override
public String getDialogCaption()
{
return "SVN Ignore";
}
@Override
public String getIgnoresCaption()
{
return "svn:ignore";
}
@Override
public String getHelpLinkName()
{
return "svn_ignore_help";
}
@Override
public Filter getFilter()
{
return null;
}
@Override
public void getIgnores(String path,
ServerRequestCallback<ProcessResult> requestCallback)
{
server_.svnGetIgnores(path, requestCallback);
}
@Override
public void setIgnores(String path, String ignores,
ServerRequestCallback<ProcessResult> requestCallback)
{
server_.svnSetIgnores(path, ignores, requestCallback);
}
};
@Handler
void onVcsOpen()
{
vcsFileOpener_.openFiles(display_.getSelectedItems());
}
@Handler
void onVcsRefresh()
{
display_.getChangelistTable().showProgress();
svnState_.refresh(true);
}
@Handler
void onVcsRefreshNoError()
{
display_.getChangelistTable().showProgress();
svnState_.refresh(false);
}
@Handler
void onVcsAddFiles()
{
ArrayList<String> paths = getPathArray();
if (paths.size() > 0)
server_.svnAdd(paths, new ProcessCallback("SVN Add"));
}
@Handler
void onVcsRemoveFiles()
{
ArrayList<String> paths = getPathArray();
if (paths.size() > 0)
server_.svnDelete(paths, new ProcessCallback("SVN Delete"));
}
@Handler
void onVcsRevert()
{
final ArrayList<String> paths = getPathArray();
if (paths.size() == 0)
return;
doRevert(paths, new Command() {
@Override
public void execute()
{
display_.getChangelistTable().selectNextUnselectedItem();
display_.getChangelistTable().focus();
}
});
}
@Handler
void onVcsResolve()
{
ArrayList<StatusAndPath> items = display_.getSelectedItems();
if (items.size() == 0)
return;
final ArrayList<String> paths = new ArrayList<String>();
boolean conflict = false;
for (StatusAndPath item : items)
{
paths.add(item.getPath());
if ("C".equals(item.getStatus()))
conflict = true;
else if (item.isDirectory())
conflict = true;
}
Operation resolveOperation = new Operation()
{
@Override
public void execute()
{
new SVNResolveDialog(
paths.size(),
"Resolve",
new OperationWithInput<String>()
{
@Override
public void execute(String input)
{
server_.svnResolve(
input, paths,
new ProcessCallback("SVN Resolve"));
}
}).showModal();
}
};
if (conflict)
{
resolveOperation.execute();
}
else
{
String message =
(paths.size() > 1 ?
"None of the selected paths appear to have conflicts." :
"The selected path does not appear to have conflicts.") +
"\n\nDo you want to resolve anyway?";
globalDisplay_.showYesNoMessage(GlobalDisplay.MSG_WARNING,
"No Conflicts Detected",
message,
resolveOperation,
true);
}
}
public void revertFile(FileSystemItem file)
{
// build an ArrayList<String> so we can call the core helper
ArrayList<String> revertList = new ArrayList<String>();
for (StatusAndPath item : svnState_.getStatus())
{
if (item.getRawPath().equals(file.getPath()))
{
revertList.add(item.getPath());
break;
}
}
if (revertList.size() > 0)
{
doRevert(revertList, null);
}
else
{
globalDisplay_.showMessage(MessageDialog.INFO,
"No Changes to Revert",
"There are no changes to the file \"" +
file.getName() + "\" to revert.");
}
}
private void doRevert(final ArrayList<String> revertList,
final Command onRevertConfirmed)
{
String noun = revertList.size() == 1 ? "file" : "files";
globalDisplay_.showYesNoMessage(
GlobalDisplay.MSG_WARNING,
"Revert Changes",
"Changes to the selected " + noun + " will be reverted.\n\n" +
"Are you sure you want to continue?",
new Operation()
{
@Override
public void execute()
{
if (onRevertConfirmed != null)
onRevertConfirmed.execute();
server_.svnRevert(revertList,
new ProcessCallback("SVN Revert"));
}
},
false);
}
private ArrayList<String> getPathArray()
{
ArrayList<StatusAndPath> items = display_.getSelectedItems();
ArrayList<String> paths = new ArrayList<String>();
for (StatusAndPath item : items)
paths.add(item.getPath());
return paths;
}
private final SVNPresenterDisplay display_;
private final GlobalDisplay globalDisplay_;
private final Commands commands_;
private final SVNServerOperations server_;
private final SVNState svnState_;
private final VCSFileOpener vcsFileOpener_;
private Provider<SVNCommitDialog> pCommitDialog_;
private Provider<Ignore> pIgnore_;
}