SVN: svnkit.1.2.x; mergeinfo support (preliminary, commented out)
[fedora-idea.git] / plugins / svn4idea / src / org / jetbrains / idea / svn / SvnUtil.java
blobccfa388cc68d0052780ea2ee9a3b218446782792
1 /*
2 * Copyright 2000-2005 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org.jetbrains.idea.svn;
18 import com.intellij.openapi.application.ApplicationManager;
19 import com.intellij.openapi.progress.ProcessCanceledException;
20 import com.intellij.openapi.progress.ProgressIndicator;
21 import com.intellij.openapi.progress.ProgressManager;
22 import com.intellij.openapi.project.Project;
23 import com.intellij.openapi.util.Computable;
24 import com.intellij.openapi.vcs.AbstractVcsHelper;
25 import com.intellij.openapi.vcs.VcsException;
26 import com.intellij.openapi.vfs.VfsUtil;
27 import com.intellij.openapi.vfs.VirtualFile;
28 import com.intellij.openapi.vfs.VirtualFileManager;
29 import com.intellij.openapi.wm.WindowManager;
30 import org.jetbrains.annotations.NonNls;
31 import org.jetbrains.annotations.Nullable;
32 import org.jetbrains.idea.svn.dialogs.LockDialog;
33 import org.tmatesoft.svn.core.SVNException;
34 import org.tmatesoft.svn.core.SVNURL;
35 import org.tmatesoft.svn.core.wc.*;
37 import java.io.File;
38 import java.util.*;
40 public class SvnUtil {
41 @NonNls public static final String SVN_ADMIN_DIR_NAME = ".svn";
42 @NonNls public static final String ENTRIES_FILE_NAME = "entries";
43 @NonNls public static final String PATH_TO_LOCK_FILE = ".svn/lock";
44 @NonNls public static final String LOCK_FILE_NAME = "lock";
46 private SvnUtil() {
49 public static Collection<File> crawlWCRoots(File path, SvnWCRootCrawler callback, ProgressIndicator progress) {
50 final Collection<File> result = new HashSet<File>();
51 File parent = path.isFile() || !path.exists() ? path.getParentFile() : path;
52 if (SVNWCUtil.isVersionedDirectory(parent)) {
53 if (progress != null && progress.isCanceled()) {
54 throw new ProcessCanceledException();
56 final Collection<File> pending = callback.handleWorkingCopyRoot(path, progress);
57 if (progress != null && progress.isCanceled()) {
58 throw new ProcessCanceledException();
60 for (final File aPending : pending) {
61 result.addAll(crawlWCRoots(aPending, callback, progress));
63 result.add(path);
65 else if (path.isDirectory()) {
66 if (progress != null && progress.isCanceled()) {
67 throw new ProcessCanceledException();
69 File[] children = path.listFiles();
70 for (int i = 0; children != null && i < children.length; i++) {
71 if (progress != null && progress.isCanceled()) {
72 throw new ProcessCanceledException();
74 File child = children[i];
75 if (child.isDirectory()) {
76 result.addAll(crawlWCRoots(child, callback, progress));
80 return result;
83 public static String[] getLocationsForModule(final SvnVcs vcs, File path, ProgressIndicator progress) {
84 LocationsCrawler crawler = new LocationsCrawler(vcs);
85 crawlWCRoots(path, crawler, progress);
86 return crawler.getLocations();
89 public static Map<String, File> getLocationInfoForModule(final SvnVcs vcs, File path, ProgressIndicator progress) {
90 final LocationsCrawler crawler = new LocationsCrawler(vcs);
91 crawlWCRoots(path, crawler, progress);
92 return crawler.getLocationInfos();
95 public static void doLockFiles(Project project, final SvnVcs activeVcs, final File[] ioFiles) throws VcsException {
96 final String lockMessage;
97 final boolean force;
98 // TODO[yole]: check for shift pressed
99 if (activeVcs.getCheckoutOptions().getValue()) {
100 LockDialog dialog = new LockDialog(project, true, ioFiles != null && ioFiles.length > 1);
101 dialog.show();
102 if (!dialog.isOK()) {
103 return;
105 lockMessage = dialog.getComment();
106 force = dialog.isForce();
108 else {
109 lockMessage = "";
110 force = false;
113 final SVNException[] exception = new SVNException[1];
114 final Collection<String> failedLocks = new ArrayList<String>();
115 final int[] count = new int[]{ioFiles.length};
116 final ISVNEventHandler eventHandler = new ISVNEventHandler() {
117 public void handleEvent(SVNEvent event, double progress) {
118 if (event.getAction() == SVNEventAction.LOCK_FAILED) {
119 failedLocks.add(event.getErrorMessage() != null ?
120 event.getErrorMessage().getFullMessage() :
121 event.getFile().getAbsolutePath());
122 count[0]--;
126 public void checkCancelled() {
130 Runnable command = new Runnable() {
131 public void run() {
132 ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
133 SVNWCClient wcClient;
135 try {
136 wcClient = activeVcs.createWCClient();
137 wcClient.setEventHandler(eventHandler);
138 if (progress != null) {
139 progress.setText(SvnBundle.message("progress.text.locking.files"));
141 for (File ioFile : ioFiles) {
142 if (progress != null) {
143 progress.checkCanceled();
145 File file = ioFile;
146 if (progress != null) {
147 progress.setText2(SvnBundle.message("progress.text2.processing.file", file.getName()));
149 wcClient.doLock(new File[]{file}, force, lockMessage);
152 catch (SVNException e) {
153 exception[0] = e;
158 ProgressManager.getInstance().runProcessWithProgressSynchronously(command, SvnBundle.message("progress.title.lock.files"), false, project);
159 if (!failedLocks.isEmpty()) {
160 String[] failedFiles = failedLocks.toArray(new String[failedLocks.size()]);
161 List<VcsException> exceptions = new ArrayList<VcsException>();
163 for (String file : failedFiles) {
164 exceptions.add(new VcsException(SvnBundle.message("exception.text.locking.file.failed", file)));
166 AbstractVcsHelper.getInstance(project).showErrors(exceptions, SvnBundle.message("message.title.lock.failures"));
169 WindowManager.getInstance().getStatusBar(project).setInfo(SvnBundle.message("message.text.files.locked", count[0]));
170 if (exception[0] != null) {
171 throw new VcsException(exception[0]);
175 public static void doUnlockFiles(Project project, final SvnVcs activeVcs, final File[] ioFiles) throws VcsException {
176 final boolean force = true;
177 final SVNException[] exception = new SVNException[1];
178 final Collection<String> failedUnlocks = new ArrayList<String>();
179 final int[] count = new int[]{ioFiles.length};
180 final ISVNEventHandler eventHandler = new ISVNEventHandler() {
181 public void handleEvent(SVNEvent event, double progress) {
182 if (event.getAction() == SVNEventAction.UNLOCK_FAILED) {
183 failedUnlocks.add(event.getErrorMessage() != null ?
184 event.getErrorMessage().getFullMessage() :
185 event.getFile().getAbsolutePath());
186 count[0]--;
190 public void checkCancelled() {
194 Runnable command = new Runnable() {
195 public void run() {
196 ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
197 SVNWCClient wcClient;
199 try {
200 wcClient = activeVcs.createWCClient();
201 wcClient.setEventHandler(eventHandler);
202 if (progress != null) {
203 progress.setText(SvnBundle.message("progress.text.unlocking.files"));
205 for (File ioFile : ioFiles) {
206 if (progress != null) {
207 progress.checkCanceled();
209 File file = ioFile;
210 if (progress != null) {
211 progress.setText2(SvnBundle.message("progress.text2.processing.file", file.getName()));
213 wcClient.doUnlock(new File[]{file}, force);
216 catch (SVNException e) {
217 exception[0] = e;
222 ProgressManager.getInstance().runProcessWithProgressSynchronously(command, SvnBundle.message("progress.title.unlock.files"), false, project);
223 if (!failedUnlocks.isEmpty()) {
224 String[] failedFiles = failedUnlocks.toArray(new String[failedUnlocks.size()]);
225 List<VcsException> exceptions = new ArrayList<VcsException>();
227 for (String file : failedFiles) {
228 exceptions.add(new VcsException(SvnBundle.message("exception.text.failed.to.unlock.file", file)));
230 AbstractVcsHelper.getInstance(project).showErrors(exceptions, SvnBundle.message("message.title.unlock.failures"));
233 WindowManager.getInstance().getStatusBar(project).setInfo(SvnBundle.message("message.text.files.unlocked", count[0]));
234 if (exception[0] != null) {
235 throw new VcsException(exception[0]);
239 private static class LocationsCrawler implements SvnWCRootCrawler {
240 private SvnVcs myVcs;
241 private Map<String, File> myLocations;
243 public LocationsCrawler(SvnVcs vcs) {
244 myVcs = vcs;
245 myLocations = new HashMap<String, File>();
248 public String[] getLocations() {
249 final Set<String> set = myLocations.keySet();
250 return set.toArray(new String[set.size()]);
253 public Map<String, File> getLocationInfos() {
254 return Collections.unmodifiableMap(myLocations);
257 public Collection<File> handleWorkingCopyRoot(File root, ProgressIndicator progress) {
258 final Collection<File> result = new HashSet<File>();
259 if (progress != null) {
260 progress.setText(SvnBundle.message("progress.text.discovering.location", root.getAbsolutePath()));
262 try {
263 SVNWCClient wcClient = myVcs.createWCClient();
264 SVNInfo info = wcClient.doInfo(root, SVNRevision.WORKING);
265 if (info != null && info.getURL() != null) {
266 myLocations.put(info.getURL().toString(), info.getFile());
269 catch (SVNException e) {
272 return result;
276 @Nullable
277 public static String getRepositoryUUID(final SvnVcs vcs, final File file) {
278 final SVNWCClient client = vcs.createWCClient();
279 try {
280 final SVNInfo info = client.doInfo(file, SVNRevision.WORKING);
281 return (info == null) ? null : info.getRepositoryUUID();
282 } catch (SVNException e) {
283 return null;
287 @Nullable
288 public static String getRepositoryUUID(final SvnVcs vcs, final SVNURL url) {
289 final SVNWCClient client = vcs.createWCClient();
290 try {
291 final SVNInfo info = client.doInfo(url, SVNRevision.WORKING, SVNRevision.WORKING);
292 return (info == null) ? null : info.getRepositoryUUID();
293 } catch (SVNException e) {
294 return null;
298 @Nullable
299 public static SVNURL getRepositoryRoot(final SvnVcs vcs, final File file) {
300 final SVNWCClient client = vcs.createWCClient();
301 try {
302 final SVNInfo info = client.doInfo(file, SVNRevision.WORKING);
303 return (info == null) ? null : info.getRepositoryRootURL();
304 } catch (SVNException e) {
305 return null;
309 public static boolean isWorkingCopyRoot(final File file) {
310 try {
311 return SVNWCUtil.isWorkingCopyRoot(file);
312 } catch (SVNException e) {
313 return false;
317 @Nullable
318 public static File getWorkingCopyRoot(final File inFile) {
319 File file = inFile;
320 while ((file != null) && (file.isFile() || (! file.exists()))) {
321 file = file.getParentFile();
324 if (file == null) {
325 return null;
328 try {
329 return SVNWCUtil.getWorkingCopyRoot(file, true);
330 } catch (SVNException e) {
331 return null;
335 @Nullable
336 public static SVNURL getWorkingCopyUrl(final SvnVcs vcs, final File file) {
337 try {
338 if(SVNWCUtil.isWorkingCopyRoot(file)) {
339 final SVNWCClient client = vcs.createWCClient();
340 final SVNInfo info = client.doInfo(file, SVNRevision.WORKING);
341 return info.getURL();
343 } catch (SVNException e) {
346 return null;
349 public static File fileFromUrl(final File baseDir, final String baseUrl, final String fullUrl) throws SVNException {
350 assert fullUrl.startsWith(baseUrl);
352 final String part = fullUrl.substring(baseUrl.length()).replace('/', File.separatorChar).replace('\\', File.separatorChar);
353 return new File(baseDir, part);
356 public static VirtualFile getVirtualFile(final String filePath) {
357 @NonNls final String path = VfsUtil.pathToUrl(filePath.replace(File.separatorChar, '/'));
358 return ApplicationManager.getApplication().runReadAction(new Computable<VirtualFile>() {
359 @Nullable
360 public VirtualFile compute() {
361 return VirtualFileManager.getInstance().findFileByUrl(path);
366 @Nullable
367 public static SVNURL getBranchForUrl(final SvnVcs vcs, final VirtualFile vcsRoot, final String urlPath) {
368 final SvnBranchConfiguration configuration;
369 try {
370 final SVNURL url = SVNURL.parseURIEncoded(urlPath);
371 configuration = SvnBranchConfigurationManager.getInstance(vcs.getProject()).get(vcsRoot);
372 return configuration.getWorkingBranch(vcs.getProject(), url);
374 catch (SVNException e) {
375 return null;
376 } catch (VcsException e1) {
377 return null;
381 @Nullable
382 public static String getPathForProgress(final SVNEvent event) {
383 if (event.getFile() != null) {
384 return event.getFile().getName();
386 if (event.getURL() != null) {
387 return event.getURL().toString();
389 return null;