svn: Refactored "ShareProjectAction" - code simplified, @NotNull

This commit is contained in:
Konstantin Kolosovsky
2017-02-09 15:29:29 +03:00
parent 47d9ae218c
commit 9b2cee87ca
3 changed files with 95 additions and 137 deletions
@@ -594,9 +594,9 @@ public class SvnUtil {
return info == null ? null : info.getURL();
}
public static boolean remoteFolderIsEmpty(final SvnVcs vcs, final String url) throws VcsException {
public static boolean remoteFolderIsEmpty(@NotNull SvnVcs vcs, @NotNull String url) throws VcsException {
SvnTarget target = SvnTarget.fromURL(createUrl(url));
final Ref<Boolean> result = new Ref<>(true);
Ref<Boolean> result = new Ref<>(true);
DirectoryEntryConsumer handler = new DirectoryEntryConsumer() {
@Override
@@ -18,13 +18,9 @@ package org.jetbrains.idea.svn.actions;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsException;
@@ -36,51 +32,38 @@ import org.jetbrains.idea.svn.api.ClientFactory;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider;
import org.jetbrains.idea.svn.dialogs.ShareDialog;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
import static com.intellij.openapi.progress.ProgressManager.progress;
import static com.intellij.openapi.ui.Messages.*;
import static com.intellij.openapi.vfs.VfsUtilCore.virtualToIoFile;
import static com.intellij.util.ArrayUtil.isEmpty;
import static org.jetbrains.idea.svn.SvnBundle.message;
import static org.jetbrains.idea.svn.SvnUtil.append;
import static org.jetbrains.idea.svn.SvnUtil.createUrl;
public class ShareProjectAction extends BasicAction {
@NotNull
@Override
protected String getActionName() {
return SvnBundle.message("share.directory.action");
return message("share.directory.action");
}
@Override
public void update(@NotNull AnActionEvent e) {
Presentation presentation = e.getPresentation();
DataContext dataContext = e.getDataContext();
VirtualFile[] files = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY);
Project project = e.getProject();
boolean visible = project != null &&
!ProjectLevelVcsManager.getInstance(project).isBackgroundVcsOperationRunning() &&
!isEmpty(files) &&
files.length == 1 &&
files[0].isDirectory();
Project project = CommonDataKeys.PROJECT.getData(dataContext);
if ((project == null) || (ProjectLevelVcsManager.getInstance(project).isBackgroundVcsOperationRunning())) {
presentation.setEnabled(false);
presentation.setVisible(false);
return;
}
VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext);
if (files == null || files.length == 0) {
presentation.setEnabled(false);
presentation.setVisible(false);
return;
}
boolean enabled = false;
boolean visible = false;
if (files.length == 1 && files [0].isDirectory()) {
visible = true;
if (! SvnStatusUtil.isUnderControl(project, files[0])) {
enabled = true;
}
}
presentation.setEnabled(enabled);
presentation.setVisible(visible);
e.getPresentation().setVisible(visible);
e.getPresentation().setEnabled(visible && !SvnStatusUtil.isUnderControl(project, files[0]));
}
@Override
@@ -88,17 +71,17 @@ public class ShareProjectAction extends BasicAction {
return false;
}
public static boolean share(@NotNull Project project, VirtualFile file) throws VcsException {
return performImpl(project, SvnVcs.getInstance(project), file);
public static boolean share(@NotNull Project project, @NotNull VirtualFile file) throws VcsException {
return performImpl(SvnVcs.getInstance(project), file);
}
@Override
protected void perform(@NotNull SvnVcs vcs, @NotNull VirtualFile file, @NotNull DataContext context) throws VcsException {
performImpl(vcs.getProject(), vcs, file);
performImpl(vcs, file);
}
private static boolean performImpl(Project project, SvnVcs activeVcs, VirtualFile file) throws VcsException {
ShareDialog shareDialog = new ShareDialog(project, file.getName());
private static boolean performImpl(@NotNull SvnVcs vcs, @NotNull VirtualFile file) throws VcsException {
ShareDialog shareDialog = new ShareDialog(vcs.getProject(), file.getName());
shareDialog.show();
String parent = shareDialog.getSelectedURL();
@@ -106,127 +89,103 @@ public class ShareProjectAction extends BasicAction {
Ref<Boolean> actionStarted = new Ref<>(Boolean.TRUE);
Exception[] error = new Exception[1];
ShareDialog.ShareTarget shareTarget = shareDialog.getShareTarget();
ProgressManager progressManager = ProgressManager.getInstance();
if (ShareDialog.ShareTarget.useSelected.equals(shareTarget)) {
boolean folderEmpty = checkRemoteFolder(project, activeVcs, parent, progressManager);
if (!folderEmpty) {
int promptAnswer =
Messages.showYesNoDialog(project, "Remote folder \"" + parent + "\" is not empty.\nDo you want to continue sharing?",
"Share directory", Messages.getWarningIcon());
if (Messages.YES != promptAnswer) return false;
}
if (ShareDialog.ShareTarget.useSelected.equals(shareTarget) &&
!isFolderEmpty(vcs, parent) &&
YES !=
showYesNoDialog(vcs.getProject(), "Remote folder \"" + parent + "\" is not empty.\nDo you want to continue sharing?",
"Share Directory", getWarningIcon())) {
return false;
}
WorkingCopyFormat format = SvnCheckoutProvider.promptForWCopyFormat(virtualToIoFile(file), project);
WorkingCopyFormat format = SvnCheckoutProvider.promptForWCopyFormat(virtualToIoFile(file), vcs.getProject());
actionStarted.set(format != WorkingCopyFormat.UNKNOWN);
// means operation cancelled
if (format == WorkingCopyFormat.UNKNOWN) {
return true;
}
ExclusiveBackgroundVcsAction.run(project, () -> progressManager.runProcessWithProgressSynchronously(() -> {
try {
ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
File path = virtualToIoFile(file);
ExclusiveBackgroundVcsAction.run(vcs.getProject(), () ->
ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> {
try {
SvnWorkingCopyFormatHolder.setPresetFormat(format);
SvnWorkingCopyFormatHolder.setPresetFormat(format);
SvnTarget checkoutTarget =
createFolderStructure(vcs, file, shareTarget, shareDialog.createStandardStructure(), createUrl(parent),
shareDialog.getCommitText());
SVNURL parenUrl = SVNURL.parseURIEncoded(parent);
SVNURL checkoutUrl;
SVNRevision revision;
String commitText = shareDialog.getCommitText();
if (ShareDialog.ShareTarget.useSelected.equals(shareTarget)) {
checkoutUrl = parenUrl;
revision = SVNRevision.HEAD;
progress(message("share.directory.checkout.back.progress.text", checkoutTarget.getPathOrUrlString()));
ClientFactory factory = SvnCheckoutProvider.getFactory(vcs, format);
factory.createCheckoutClient()
.checkout(SvnTarget.fromURL(checkoutTarget.getURL()), virtualToIoFile(file), checkoutTarget.getPegRevision(), Depth.INFINITY,
false, false, format, null);
addRecursively(vcs, factory, file);
}
else if (ShareDialog.ShareTarget.useProjectName.equals(shareTarget)) {
Pair<SVNRevision, SVNURL> pair = createRemoteFolder(activeVcs, parenUrl, file.getName(), commitText);
revision = pair.getFirst();
checkoutUrl = pair.getSecond();
catch (VcsException e) {
error[0] = e;
}
else {
Pair<SVNRevision, SVNURL> pair = createRemoteFolder(activeVcs, parenUrl, file.getName(), commitText);
Pair<SVNRevision, SVNURL> trunkPair = createRemoteFolder(activeVcs, pair.getSecond(), "trunk", commitText);
checkoutUrl = trunkPair.getSecond();
revision = trunkPair.getFirst();
if (shareDialog.createStandardStructure()) {
createRemoteFolder(activeVcs, pair.getSecond(), "branches", commitText);
createRemoteFolder(activeVcs, pair.getSecond(), "tags", commitText);
}
finally {
vcs.invokeRefreshSvnRoots();
SvnWorkingCopyFormatHolder.setPresetFormat(null);
}
if (indicator != null) {
indicator.checkCanceled();
indicator.setText(SvnBundle.message("share.directory.checkout.back.progress.text", checkoutUrl.toString()));
}
ClientFactory factory = SvnCheckoutProvider.getFactory(activeVcs, format);
factory.createCheckoutClient()
.checkout(SvnTarget.fromURL(checkoutUrl), path, revision, Depth.INFINITY, false, false, format, null);
addRecursively(activeVcs, factory, file);
}
catch (SVNException | VcsException e) {
error[0] = e;
}
finally {
activeVcs.invokeRefreshSvnRoots();
SvnWorkingCopyFormatHolder.setPresetFormat(null);
}
}, SvnBundle.message("share.directory.title"), true, project));
}, message("share.directory.title"), true, vcs.getProject()));
if (Boolean.TRUE.equals(actionStarted.get())) {
if (error[0] != null) {
throw new VcsException(error[0].getMessage());
}
Messages.showInfoMessage(project, SvnBundle.message("share.directory.info.message", file.getName()),
SvnBundle.message("share.directory.title"));
showInfoMessage(vcs.getProject(), message("share.directory.info.message", file.getName()), message("share.directory.title"));
}
return true;
}
return false;
}
private static boolean checkRemoteFolder(Project project, SvnVcs activeVcs, String parent, ProgressManager progressManager)
throws VcsException {
VcsException[] exc = new VcsException[1];
boolean[] folderEmpty = new boolean[1];
@NotNull
private static SvnTarget createFolderStructure(@NotNull SvnVcs vcs,
@NotNull VirtualFile file,
@NotNull ShareDialog.ShareTarget shareTarget,
boolean createStandardStructure,
@NotNull SVNURL parentUrl,
@NotNull String commitText) throws VcsException {
switch (shareTarget) {
case useSelected:
return SvnTarget.fromURL(parentUrl, SVNRevision.HEAD);
case useProjectName:
return createRemoteFolder(vcs, parentUrl, file.getName(), commitText);
default:
SvnTarget projectRoot = createRemoteFolder(vcs, parentUrl, file.getName(), commitText);
SvnTarget trunk = createRemoteFolder(vcs, projectRoot.getURL(), "trunk", commitText);
progressManager.runProcessWithProgressSynchronously(() -> {
try {
folderEmpty[0] = SvnUtil.remoteFolderIsEmpty(activeVcs, parent);
}
catch (VcsException e) {
exc[0] = e;
}
}, "Check remote folder contents", false, project);
if (exc[0] != null) {
throw exc[0];
if (createStandardStructure) {
createRemoteFolder(vcs, projectRoot.getURL(), "branches", commitText);
createRemoteFolder(vcs, projectRoot.getURL(), "tags", commitText);
}
return trunk;
}
return folderEmpty[0];
}
private static boolean isFolderEmpty(@NotNull SvnVcs vcs, @NotNull String folderUrl) throws VcsException {
return ProgressManager.getInstance().runProcessWithProgressSynchronously(
() -> SvnUtil.remoteFolderIsEmpty(vcs, folderUrl), "Check Remote Folder Contents", false, vcs.getProject());
}
@NotNull
private static Pair<SVNRevision, SVNURL> createRemoteFolder(@NotNull SvnVcs vcs,
@NotNull SVNURL parent,
String folderName,
String commitText) throws VcsException, SVNException {
SVNURL url = parent.appendPath(folderName, false);
ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
if (indicator != null) {
indicator.checkCanceled();
indicator.setText(SvnBundle.message("share.directory.create.dir.progress.text", url.toString()));
}
private static SvnTarget createRemoteFolder(@NotNull SvnVcs vcs,
@NotNull SVNURL parent,
@NotNull String folderName,
@NotNull String commitText) throws VcsException {
SVNURL url = append(parent, folderName);
String message =
SvnBundle.message("share.directory.commit.message", folderName, ApplicationNamesInfo.getInstance().getFullProductName(), commitText);
message("share.directory.commit.message", folderName, ApplicationNamesInfo.getInstance().getFullProductName(), commitText);
SvnTarget target = SvnTarget.fromURL(url);
long revision = vcs.getFactoryFromSettings().createBrowseClient().createDirectory(target, message, false);
return Pair.create(SVNRevision.create(revision), url);
progress(message("share.directory.create.dir.progress.text", url.toString()));
long revision = vcs.getFactoryFromSettings().createBrowseClient().createDirectory(target, message, false);
return SvnTarget.fromURL(url, SVNRevision.create(revision));
}
@Override
@@ -234,17 +193,15 @@ public class ShareProjectAction extends BasicAction {
VcsDirtyScopeManager.getInstance(vcs.getProject()).dirDirtyRecursively(file);
}
private static void addRecursively(@NotNull SvnVcs vcs, @NotNull ClientFactory factory, @NotNull VirtualFile file) throws VcsException {
SvnExcludingIgnoredOperation operation = new SvnExcludingIgnoredOperation(vcs.getProject(), virtualFile -> {
ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
if (indicator != null) {
indicator.checkCanceled();
indicator.setText(SvnBundle.message("share.or.import.add.progress.text", virtualFile.getPath()));
}
factory.createAddClient().add(virtualToIoFile(virtualFile), Depth.EMPTY, false, false, true, null);
private static void addRecursively(@NotNull SvnVcs vcs, @NotNull ClientFactory factory, @NotNull VirtualFile rootFile)
throws VcsException {
SvnExcludingIgnoredOperation operation = new SvnExcludingIgnoredOperation(vcs.getProject(), file -> {
progress(message("share.or.import.add.progress.text", file.getPath()));
factory.createAddClient().add(virtualToIoFile(file), Depth.EMPTY, false, false, true, null);
}, Depth.INFINITY);
operation.execute(file);
operation.execute(rootFile);
}
@Override
@@ -162,6 +162,7 @@ public class ShareDialog extends RepositoryBrowserDialog {
return wrapper;
}
@NotNull
public ShareTarget getShareTarget() {
if (myExisting.isSelected()) {
return ShareTarget.useSelected;