ExcludedFileIndex -> FileIndexFacade; use it in PsiClassImplUtil
[idea/community.git] / plugins / svn4idea / src / org / jetbrains / idea / svn / checkout / SvnCheckoutProvider.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.checkout;
17
18 import com.intellij.lifecycle.PeriodicalTasksCloser;
19 import com.intellij.openapi.progress.ProgressIndicator;
20 import com.intellij.openapi.progress.ProgressManager;
21 import com.intellij.openapi.progress.Task;
22 import com.intellij.openapi.project.Project;
23 import com.intellij.openapi.roots.FileIndexFacade;
24 import com.intellij.openapi.ui.Messages;
25 import com.intellij.openapi.util.Ref;
26 import com.intellij.openapi.util.io.FileUtil;
27 import com.intellij.openapi.vcs.CheckoutProvider;
28 import com.intellij.openapi.vcs.VcsConfiguration;
29 import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx;
30 import com.intellij.openapi.vcs.update.RefreshVFsSynchronously;
31 import com.intellij.openapi.vfs.LocalFileSystem;
32 import com.intellij.openapi.vfs.VirtualFile;
33 import org.jetbrains.annotations.NotNull;
34 import org.jetbrains.annotations.Nullable;
35 import org.jetbrains.idea.svn.*;
36 import org.jetbrains.idea.svn.actions.ExclusiveBackgroundVcsAction;
37 import org.jetbrains.idea.svn.actions.SvnExcludingIgnoredOperation;
38 import org.jetbrains.idea.svn.dialogs.CheckoutDialog;
39 import org.tmatesoft.svn.core.SVNCancelException;
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.*;
44
45 import javax.swing.*;
46 import java.io.File;
47
48 public class SvnCheckoutProvider implements CheckoutProvider {
49
50   public void doCheckout(@NotNull final Project project, Listener listener) {
51     CheckoutDialog dialog = new CheckoutDialog(project, listener);
52     dialog.show();
53   }
54
55   public static void doCheckout(final Project project, final File target, final String url, final SVNRevision revision,
56                                 final SVNDepth depth, final boolean ignoreExternals, @Nullable final Listener listener) {
57     if (! target.exists()) {
58       target.mkdirs();
59     }
60
61     final String selectedFormat = promptForWCopyFormat(target, project);
62     if (selectedFormat == null) {
63       // cancelled
64       return;
65     }
66
67     checkout(project, target, url, revision, depth, ignoreExternals, listener, WorkingCopyFormat.getInstance(selectedFormat));
68   }
69
70   public static void checkout(final Project project,
71                                final File target,
72                                final String url,
73                                final SVNRevision revision,
74                                final SVNDepth depth,
75                                final boolean ignoreExternals,
76                                final Listener listener, final WorkingCopyFormat selectedFormat) {
77     final Ref<Boolean> checkoutSuccessful = new Ref<Boolean>();
78     final SVNException[] exception = new SVNException[1];
79     final Task.Backgroundable checkoutBackgroundTask = new Task.Backgroundable(project,
80                      SvnBundle.message("message.title.check.out"), true, VcsConfiguration.getInstance(project).getCheckoutOption()) {
81       public void run(@NotNull final ProgressIndicator indicator) {
82         SvnWorkingCopyFormatHolder.setPresetFormat(selectedFormat);
83
84         final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
85         final SVNUpdateClient client = SvnVcs.getInstance(project).createUpdateClient();
86         client.setEventHandler(new CheckoutEventHandler(SvnVcs.getInstance(project), false, progressIndicator));
87         client.setIgnoreExternals(ignoreExternals);
88         try {
89           progressIndicator.setText(SvnBundle.message("progress.text.checking.out", target.getAbsolutePath()));
90           client.doCheckout(SVNURL.parseURIEncoded(url), target, SVNRevision.UNDEFINED, revision, depth, true);
91           progressIndicator.checkCanceled();
92           checkoutSuccessful.set(Boolean.TRUE);
93         }
94         catch (SVNCancelException ignore) {
95         }
96         catch (SVNException e) {
97           exception[0] = e;
98         }
99         finally {
100           client.setIgnoreExternals(false);
101           client.setEventHandler(null);
102           SvnWorkingCopyFormatHolder.setPresetFormat(null);
103         }
104       }
105
106       public void onCancel() {
107         onSuccess();
108       }
109
110       public void onSuccess() {
111         if (exception[0] != null) {
112           Messages.showErrorDialog(SvnBundle.message("message.text.cannot.checkout", exception[0].getMessage()), SvnBundle.message("message.title.check.out"));
113         }
114
115         final VirtualFile vf = RefreshVFsSynchronously.findCreatedFile(target);
116         if (vf != null) {
117           vf.refresh(true, true, new Runnable() {
118             public void run() {
119               SwingUtilities.invokeLater(new Runnable() {
120                 @Override
121                 public void run() {
122                   notifyListener();
123                 }
124               });
125             }
126           });
127         }
128         else {
129           notifyListener();
130         }
131       }
132
133       private void notifyListener() {
134         notifyRootManagerIfUnderProject(project, target);
135         if (listener != null) {
136           if (!checkoutSuccessful.isNull()) {
137             listener.directoryCheckedOut(target);
138           }
139           listener.checkoutCompleted();
140         }
141       }
142     };
143     ProgressManager.getInstance().run(checkoutBackgroundTask);
144   }
145
146   private static void notifyRootManagerIfUnderProject(final Project project, final File directory) {
147     if (project.isDefault()) return;
148     final ProjectLevelVcsManagerEx plVcsManager = ProjectLevelVcsManagerEx.getInstanceEx(project);
149     final SvnVcs vcs = (SvnVcs) plVcsManager.findVcsByName(SvnVcs.VCS_NAME);
150
151     final VirtualFile[] files = vcs.getSvnFileUrlMapping().getNotFilteredRoots();
152     for (VirtualFile file : files) {
153       if (FileUtil.isAncestor(new File(file.getPath()), directory, false)) {
154         // todo: should be done like auto detection
155         plVcsManager.fireDirectoryMappingsChanged();
156         return;
157       }
158     }
159   }
160
161   public static boolean promptForWCFormatAndSelect(final File target, final Project project) {
162     final String result = promptForWCopyFormat(target, project);
163     if (result != null) {
164       SvnWorkingCopyFormatHolder.setPresetFormat(WorkingCopyFormat.getInstance(result));
165     }
166     return result != null;
167   }
168
169   @Nullable
170   private static String promptForWCopyFormat(final File target, final Project project) {
171     String formatMode = null;
172     final Ref<Boolean> wasOk = new Ref<Boolean>();
173     while ((formatMode == null) && (! Boolean.FALSE.equals(wasOk.get()))) {
174       formatMode = SvnFormatSelector.showUpgradeDialog(target, project, true, SvnConfiguration.UPGRADE_AUTO_16, wasOk);
175     }
176     return Boolean.TRUE.equals(wasOk.get()) ? formatMode : null;
177   }
178
179   public static void doExport(final Project project, final File target, final String url, final SVNDepth depth,
180                               final boolean ignoreExternals, final boolean force, final String eolStyle) {
181     try {
182       final SVNException[] exception = new SVNException[1];
183       final SVNUpdateClient client = SvnVcs.getInstance(project).createUpdateClient();
184
185       ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
186         public void run() {
187           ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
188           client.setEventHandler(new CheckoutEventHandler(SvnVcs.getInstance(project), true, progressIndicator));
189           client.setIgnoreExternals(ignoreExternals);
190           try {
191             progressIndicator.setText(SvnBundle.message("progress.text.export", target.getAbsolutePath()));
192             client.doExport(SVNURL.parseURIEncoded(url), target, SVNRevision.UNDEFINED, SVNRevision.HEAD, eolStyle, force, depth);
193           }
194           catch (SVNException e) {
195             exception[0] = e;
196           }
197           finally {
198             client.setIgnoreExternals(false);
199             client.setEventHandler(null);
200           }
201         }
202       }, SvnBundle.message("message.title.export"), true, project);
203       if (exception[0] != null) {
204         throw exception[0];
205       }
206     }
207     catch (SVNException e1) {
208       Messages.showErrorDialog(SvnBundle.message("message.text.cannot.export", e1.getMessage()), SvnBundle.message("message.title.export"));
209     }
210   }
211
212   public static void doImport(final Project project, final File target, final SVNURL url, final SVNDepth depth,
213                               final boolean includeIgnored, final String message) {
214     final Ref<String> errorMessage = new Ref<String>();
215     final SVNCommitClient client = SvnVcs.getInstance(project).createCommitClient();
216     final String targetPath = FileUtil.toSystemIndependentName(target.getAbsolutePath());
217
218     ExclusiveBackgroundVcsAction.run(project, new Runnable() {
219       public void run() {
220         ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
221           public void run() {
222             ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
223             client.setEventHandler(new CheckoutEventHandler(SvnVcs.getInstance(project), true, progressIndicator));
224             try {
225               progressIndicator.setText(SvnBundle.message("progress.text.import", target.getAbsolutePath()));
226
227               final VirtualFile targetVf = SvnUtil.getVirtualFile(targetPath);
228               if (targetVf == null) {
229                 errorMessage.set("Can not find file: " + targetPath);
230               } else if (project.isDefault() || !PeriodicalTasksCloser.getInstance().safeGetService(project, FileIndexFacade.class)
231                 .isInContent(targetVf)) {
232                 // do not pay attention to ignored/excluded settings
233                 client.doImport(target, url, message, null, !includeIgnored, false, depth);
234               } else {
235                 client.setCommitHandler(new MyFilter(LocalFileSystem.getInstance(), new SvnExcludingIgnoredOperation.Filter(project)));
236                 client.doImport(target, url, message, null, !includeIgnored, false, depth);
237               }
238             }
239             catch (SVNException e) {
240               errorMessage.set(e.getMessage());
241             }
242             finally {
243               client.setIgnoreExternals(false);
244               client.setEventHandler(null);
245             }
246           }
247         }, SvnBundle.message("message.title.import"), true, project);
248       }
249     });
250     
251     if (! errorMessage.isNull()) {
252       Messages.showErrorDialog(SvnBundle.message("message.text.cannot.import", errorMessage.get()), SvnBundle.message("message.title.import"));
253     }
254   }
255
256   private static class MyFilter extends DefaultSVNCommitHandler implements ISVNFileFilter {
257     private final LocalFileSystem myLfs;
258     private final SvnExcludingIgnoredOperation.Filter myFilter;
259
260     private MyFilter(LocalFileSystem lfs, SvnExcludingIgnoredOperation.Filter filter) {
261       myLfs = lfs;
262       myFilter = filter;
263     }
264
265     public boolean accept(final File file) throws SVNException {
266       final VirtualFile vf = myLfs.findFileByIoFile(file);
267       return vf != null && myFilter.accept(vf);
268     }
269   }
270
271   public String getVcsName() {
272     return "_Subversion";
273   }
274
275 }
276
277