Merge branch 'master' of git.labs.intellij.net:idea/community
[idea/community.git] / plugins / svn4idea / src / org / jetbrains / idea / svn / actions / ShareProjectAction.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.jetbrains.idea.svn.actions;
17
18 import com.intellij.openapi.actionSystem.AnActionEvent;
19 import com.intellij.openapi.actionSystem.DataContext;
20 import com.intellij.openapi.actionSystem.PlatformDataKeys;
21 import com.intellij.openapi.actionSystem.Presentation;
22 import com.intellij.openapi.application.ApplicationNamesInfo;
23 import com.intellij.openapi.progress.ProgressIndicator;
24 import com.intellij.openapi.progress.ProgressManager;
25 import com.intellij.openapi.project.Project;
26 import com.intellij.openapi.ui.Messages;
27 import com.intellij.openapi.util.Ref;
28 import com.intellij.openapi.vcs.AbstractVcs;
29 import com.intellij.openapi.vcs.ProjectLevelVcsManager;
30 import com.intellij.openapi.vcs.VcsException;
31 import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
32 import com.intellij.openapi.vfs.VirtualFile;
33 import org.jetbrains.idea.svn.SvnBundle;
34 import org.jetbrains.idea.svn.SvnStatusUtil;
35 import org.jetbrains.idea.svn.SvnVcs;
36 import org.jetbrains.idea.svn.SvnWorkingCopyFormatHolder;
37 import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider;
38 import org.jetbrains.idea.svn.dialogs.ShareDialog;
39 import org.tmatesoft.svn.core.SVNCommitInfo;
40 import org.tmatesoft.svn.core.SVNDepth;
41 import org.tmatesoft.svn.core.SVNException;
42 import org.tmatesoft.svn.core.SVNURL;
43 import org.tmatesoft.svn.core.wc.SVNRevision;
44 import org.tmatesoft.svn.core.wc.SVNWCClient;
45
46 import java.io.File;
47
48 public class ShareProjectAction extends BasicAction {
49
50   protected String getActionName(AbstractVcs vcs) {
51     return SvnBundle.message("share.directory.action");
52   }
53
54   public void update(AnActionEvent e) {
55     Presentation presentation = e.getPresentation();
56     final DataContext dataContext = e.getDataContext();
57
58     Project project = PlatformDataKeys.PROJECT.getData(dataContext);
59     if ((project == null) || (ProjectLevelVcsManager.getInstance(project).isBackgroundVcsOperationRunning())) {
60       presentation.setEnabled(false);
61       presentation.setVisible(false);
62       return;
63     }
64
65     VirtualFile[] files = PlatformDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext);
66     if (files == null || files.length == 0) {
67       presentation.setEnabled(false);
68       presentation.setVisible(false);
69       return;
70     }
71     boolean enabled = false;
72     boolean visible = false;
73     if (files.length == 1 && files [0].isDirectory()) {
74       visible = true;
75       if (! SvnStatusUtil.isUnderControl(project, files[0])) {
76         enabled = true;
77       }
78     }
79     presentation.setEnabled(enabled);
80     presentation.setVisible(visible);
81   }
82
83   protected boolean isEnabled(Project project, SvnVcs vcs, VirtualFile file) {
84     return false;
85   }
86
87   protected boolean needsFiles() {
88     return true;
89   }
90
91   public static boolean share(final Project project, final VirtualFile file) throws VcsException {
92     return performImpl(project, SvnVcs.getInstance(project), file);
93   }
94
95   protected void perform(final Project project, final SvnVcs activeVcs, final VirtualFile file, DataContext context) throws VcsException {
96     performImpl(project, activeVcs, file);
97   }
98
99   private static boolean performImpl(final Project project, final SvnVcs activeVcs, final VirtualFile file) throws
100                                                                                                                               VcsException {
101     ShareDialog shareDialog = new ShareDialog(project);
102     shareDialog.show();
103
104     final String parent = shareDialog.getSelectedURL();
105     if (shareDialog.isOK() && parent != null) {
106       final Ref<Boolean> actionStarted = new Ref<Boolean>(Boolean.TRUE);
107       final SVNException[] error = new SVNException[1];
108
109       ExclusiveBackgroundVcsAction.run(project, new Runnable() {
110         public void run() {
111           ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
112             public void run() {
113               try {
114                 final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
115
116                 final File path = new File(file.getPath());
117                 if (! SvnCheckoutProvider.promptForWCFormatAndSelect(path, project)) {
118                   // action cancelled
119                   actionStarted.set(Boolean.FALSE);
120                   return;
121                 }
122                 SVNURL url = SVNURL.parseURIEncoded(parent).appendPath(file.getName(), false);
123                 final String urlText = url.toString();
124                 if (indicator != null) {
125                   indicator.checkCanceled();
126                   indicator.setText(SvnBundle.message("share.directory.create.dir.progress.text", urlText));
127                 }
128                 SVNCommitInfo info = activeVcs.createCommitClient().doMkDir(new SVNURL[] {url},
129                                                                             SvnBundle.message("share.directory.commit.message", file.getName(),
130                                                                                               ApplicationNamesInfo.getInstance().getFullProductName()));
131                 SVNRevision revision = SVNRevision.create(info.getNewRevision());
132
133                 if (indicator != null) {
134                   indicator.checkCanceled();
135                   indicator.setText(SvnBundle.message("share.directory.checkout.back.progress.text", urlText));
136                 }
137                 activeVcs.createUpdateClient().doCheckout(url, path, SVNRevision.UNDEFINED, revision, true);
138                 SvnWorkingCopyFormatHolder.setPresetFormat(null);
139
140                 addRecursively(activeVcs, file);
141               } catch (SVNException e) {
142                 error[0] = e;
143               } finally {
144                 activeVcs.invokeRefreshSvnRoots(true);
145                 SvnWorkingCopyFormatHolder.setPresetFormat(null);
146               }
147             }
148           }, SvnBundle.message("share.directory.title"), true, project);
149         }
150       });
151
152       if (Boolean.TRUE.equals(actionStarted.get())) {
153         if (error[0] != null) {
154           throw new VcsException(error[0].getMessage());
155         }
156         Messages.showInfoMessage(project, SvnBundle.message("share.directory.info.message", file.getName()),
157                                  SvnBundle.message("share.directory.title"));
158       }
159       return true;
160     }
161     return false;
162   }
163
164   @Override
165   protected void doVcsRefresh(final Project project, final VirtualFile file) {
166     VcsDirtyScopeManager.getInstance(project).dirDirtyRecursively(file);
167   }
168
169   private static void addRecursively(final SvnVcs activeVcs, final VirtualFile file) throws SVNException {
170     final SVNWCClient wcClient = activeVcs.createWCClient();
171     final SvnExcludingIgnoredOperation operation = new SvnExcludingIgnoredOperation(activeVcs.getProject(), new SvnExcludingIgnoredOperation.Operation() {
172       public void doOperation(final VirtualFile virtualFile) throws SVNException {
173         final File ioFile = new File(virtualFile.getPath());
174         final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
175         if (indicator != null) {
176           indicator.checkCanceled();
177           indicator.setText(SvnBundle.message("share.or.import.add.progress.text", virtualFile.getPath()));
178         }
179         wcClient.doAdd(ioFile, true, false, false, SVNDepth.EMPTY, false, false);
180       }
181     }, SVNDepth.INFINITY);
182
183     operation.execute(file);
184   }
185
186   protected void batchPerform(Project project, final SvnVcs activeVcs, VirtualFile[] file, DataContext context) throws VcsException {
187   }
188
189   protected boolean isBatchAction() {
190     return false;
191   }
192 }