KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > subversion > util > SvnUtils


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.subversion.util;
21
22 import org.netbeans.modules.subversion.client.SvnClient;
23 import org.openide.*;
24 import org.openide.cookies.EditorCookie;
25 import org.openide.nodes.Node;
26 import org.openide.windows.TopComponent;
27 import org.openide.util.Lookup;
28 import org.openide.filesystems.FileUtil;
29 import org.openide.filesystems.FileObject;
30 import org.openide.loaders.DataObject;
31 import org.openide.loaders.DataShadow;
32 import org.openide.loaders.DataObjectNotFoundException;
33 import org.netbeans.api.project.*;
34 import org.netbeans.api.fileinfo.NonRecursiveFolder;
35 import org.netbeans.modules.subversion.FileStatusCache;
36 import org.netbeans.modules.subversion.Subversion;
37 import org.netbeans.modules.subversion.FileInformation;
38 import org.netbeans.modules.subversion.SvnFileNode;
39
40 import java.io.*;
41 import java.lang.Character JavaDoc;
42 import java.util.*;
43 import java.text.ParseException JavaDoc;
44 import java.util.regex.Matcher JavaDoc;
45 import java.util.regex.Pattern JavaDoc;
46 import java.util.regex.PatternSyntaxException JavaDoc;
47 import org.netbeans.modules.subversion.SvnModuleConfig;
48 import org.netbeans.modules.subversion.client.ExceptionHandler;
49 import org.netbeans.modules.subversion.options.AnnotationExpression;
50 import org.netbeans.modules.versioning.util.FlatFolder;
51 import org.tigris.subversion.svnclientadapter.*;
52 import org.tigris.subversion.svnclientadapter.utils.SVNUrlUtils;
53
54 /**
55  * Subversion-specific utilities.
56  * TODO: PETR Move generic methods to versioncontrol module
57  *
58  * @author Maros Sandor
59  */

60 public class SvnUtils {
61     
62     private static final Pattern JavaDoc metadataPattern = Pattern.compile(".*\\" + File.separatorChar + "(\\.|_)svn(\\" + File.separatorChar + ".*|$)");
63     
64     private static Node [] contextNodesCached;
65     private static Context contextCached;
66     
67     /**
68      * Semantics is similar to {@link org.openide.windows.TopComponent#getActivatedNodes()} except that this
69      * method returns File objects instead od Nodes. Every node is examined for Files it represents. File and Folder
70      * nodes represent their underlying files or folders. Project nodes are represented by their source groups. Other
71      * logical nodes must provide FileObjects in their Lookup.
72      *
73      * @return File [] array of activated files
74      * @param nodes or null (then taken from windowsystem, it may be wrong on editor tabs #66700).
75      */

76     public static Context getCurrentContext(Node[] nodes) {
77         if (nodes == null) {
78             nodes = TopComponent.getRegistry().getActivatedNodes();
79         }
80         if (Arrays.equals(contextNodesCached, nodes)) return contextCached;
81         List<File> files = new ArrayList<File>(nodes.length);
82         List<File> rootFiles = new ArrayList<File>(nodes.length);
83         List<File> rootFileExclusions = new ArrayList<File>(5);
84         for (int i = 0; i < nodes.length; i++) {
85             Node node = nodes[i];
86             SvnFileNode svnNode = (SvnFileNode) node.getLookup().lookup(SvnFileNode.class);
87             if (svnNode != null) {
88                 files.add(svnNode.getFile());
89                 rootFiles.add(svnNode.getFile());
90                 continue;
91             }
92             Project project = (Project) node.getLookup().lookup(Project.class);
93             if (project != null) {
94                 addProjectFiles(files, rootFiles, rootFileExclusions, project);
95                 continue;
96             }
97             addFileObjects(node, files, rootFiles);
98         }
99         
100         contextCached = new Context(files, rootFiles, rootFileExclusions);
101         contextNodesCached = nodes;
102         return contextCached;
103     }
104     
105     
106     /**
107      * Semantics is similar to {@link org.openide.windows.TopComponent#getActivatedNodes()} except that this
108      * method returns File objects instead od Nodes. Every node is examined for Files it represents. File and Folder
109      * nodes represent their underlying files or folders. Project nodes are represented by their source groups. Other
110      * logical nodes must provide FileObjects in their Lookup.
111      *
112      * @param nodes null (then taken from windowsystem, it may be wrong on editor tabs #66700).
113      * @param includingFileStatus if any activated file does not have this CVS status, an empty array is returned
114      * @param includingFolderStatus if any activated folder does not have this CVS status, an empty array is returned
115      * @return File [] array of activated files, or an empty array if any of examined files/folders does not have given status
116      */

117     public static Context getCurrentContext(Node[] nodes, int includingFileStatus, int includingFolderStatus) {
118         Context context = getCurrentContext(nodes);
119         FileStatusCache cache = Subversion.getInstance().getStatusCache();
120         File [] files = context.getRootFiles();
121         for (int i = 0; i < files.length; i++) {
122             File file = files[i];
123             FileInformation fi = cache.getStatus(file);
124             if (file.isDirectory()) {
125                 if ((fi.getStatus() & includingFolderStatus) == 0) return Context.Empty;
126             } else {
127                 if ((fi.getStatus() & includingFileStatus) == 0) return Context.Empty;
128             }
129         }
130         return context;
131     }
132     
133     /**
134      * @return <code>true</code> if
135      * <ul>
136      * <li> the node contains a project in its lookup and
137      * <li> the project contains at least one CVS versioned source group
138      * </ul>
139      * otherwise <code>false</code>.
140      */

141     public static boolean isVersionedProject(Node node) {
142         Lookup lookup = node.getLookup();
143         Project project = (Project) lookup.lookup(Project.class);
144         return isVersionedProject(project);
145     }
146     
147     /**
148      * @return <code>true</code> if
149      * <ul>
150      * <li> the project != null and
151      * <li> the project contains at least one CVS versioned source group
152      * </ul>
153      * otherwise <code>false</code>.
154      */

155     public static boolean isVersionedProject(Project project) {
156         if (project != null) {
157             FileStatusCache cache = Subversion.getInstance().getStatusCache();
158             Sources sources = ProjectUtils.getSources(project);
159             SourceGroup [] sourceGroups = sources.getSourceGroups(Sources.TYPE_GENERIC);
160             for (int j = 0; j < sourceGroups.length; j++) {
161                 SourceGroup sourceGroup = sourceGroups[j];
162                 File f = FileUtil.toFile(sourceGroup.getRootFolder());
163                 //if (f != null) { XXX fallback if experimntal should not work
164
// File probe = new File (f, ".svn");
165
// File probe2 = new File (f, "_svn");
166
// if (probe.isDirectory() || probe2.isDirectory()) {
167
// return true;
168
// }
169
// }
170
if ((cache.getStatus(f).getStatus() & FileInformation.STATUS_MANAGED) != 0) return true; // XXX experimental
171
}
172         }
173         return false;
174     }
175     
176     private static void addFileObjects(Node node, List<File> files, List<File> rootFiles) {
177         Collection<? extends NonRecursiveFolder> folders = node.getLookup().lookup(new Lookup.Template<NonRecursiveFolder>(NonRecursiveFolder.class)).allInstances();
178         List<File> nodeFiles = new ArrayList<File>();
179         if (folders.size() > 0) {
180             for (NonRecursiveFolder j : folders) {
181                 nodeFiles.add(new FlatFolder(FileUtil.toFile(j.getFolder()).getAbsolutePath()));
182             }
183         } else {
184             Collection<? extends FileObject> fileObjects = node.getLookup().lookup(new Lookup.Template<FileObject>(FileObject.class)).allInstances();
185             if (fileObjects.size() > 0) {
186                 nodeFiles.addAll(toFileCollection(fileObjects));
187             } else {
188                 DataObject dataObject = node.getCookie(DataObject.class);
189                 if (dataObject instanceof DataShadow) {
190                     dataObject = ((DataShadow) dataObject).getOriginal();
191                 }
192                 if (dataObject != null) {
193                     Collection<File> doFiles = toFileCollection(dataObject.files());
194                     nodeFiles.addAll(doFiles);
195                 }
196             }
197         }
198         files.addAll(nodeFiles);
199         rootFiles.addAll(nodeFiles);
200     }
201     
202     /**
203      * Determines all files and folders that belong to a given project and adds them to the supplied Collection.
204      *
205      * @param filteredFiles destination collection of Files
206      * @param project project to examine
207      */

208     public static void addProjectFiles(Collection<File> filteredFiles, Collection<File> rootFiles, Collection<File> rootFilesExclusions, Project project) {
209         FileStatusCache cache = Subversion.getInstance().getStatusCache();
210         Sources sources = ProjectUtils.getSources(project);
211         SourceGroup [] sourceGroups = sources.getSourceGroups(Sources.TYPE_GENERIC);
212         for (int j = 0; j < sourceGroups.length; j++) {
213             SourceGroup sourceGroup = sourceGroups[j];
214             FileObject srcRootFo = sourceGroup.getRootFolder();
215             File rootFile = FileUtil.toFile(srcRootFo);
216             if ((cache.getStatus(rootFile).getStatus() & FileInformation.STATUS_MANAGED) == 0) continue;
217             rootFiles.add(rootFile);
218             boolean containsSubprojects = false;
219             FileObject [] rootChildren = srcRootFo.getChildren();
220             Set<File> projectFiles = new HashSet<File>(rootChildren.length);
221             for (int i = 0; i < rootChildren.length; i++) {
222                 FileObject rootChildFo = rootChildren[i];
223                 if (Subversion.getInstance().isAdministrative(rootChildFo.getNameExt())) continue;
224                 File child = FileUtil.toFile(rootChildFo);
225                 if (sourceGroup.contains(rootChildFo)) {
226                     // TODO: #60516 deep scan is required here but not performed due to performace reasons
227
projectFiles.add(child);
228                 } else {
229                     int status = cache.getStatus(child).getStatus();
230                     if (status != FileInformation.STATUS_NOTVERSIONED_EXCLUDED) {
231                         rootFilesExclusions.add(child);
232                         containsSubprojects = true;
233                     }
234                 }
235             }
236             if (containsSubprojects) {
237                 filteredFiles.addAll(projectFiles);
238             } else {
239                 filteredFiles.add(rootFile);
240             }
241         }
242     }
243     
244     /**
245      * May take a long time for many projects, consider making the call from worker threads.
246      *
247      * @param projects projects to examine
248      * @return Context context that defines list of supplied projects
249      */

250     public static Context getProjectsContext(Project [] projects) {
251         List<File> filtered = new ArrayList<File>();
252         List<File> roots = new ArrayList<File>();
253         List<File> exclusions = new ArrayList<File>();
254         for (int i = 0; i < projects.length; i++) {
255             addProjectFiles(filtered, roots, exclusions, projects[i]);
256         }
257         return new Context(filtered, roots, exclusions);
258     }
259     
260     private static Collection<File> toFileCollection(Collection<? extends FileObject> fileObjects) {
261         Set<File> files = new HashSet<File>(fileObjects.size()*4/3+1);
262         for (FileObject f: fileObjects) {
263             files.add(FileUtil.toFile(f));
264         }
265         files.remove(null);
266         return files;
267     }
268     
269     public static File [] toFileArray(Collection<FileObject> fileObjects) {
270         Set<File> files = new HashSet<File>(fileObjects.size()*4/3+1);
271         for (Iterator<FileObject> i = fileObjects.iterator(); i.hasNext();) {
272             files.add(FileUtil.toFile(i.next()));
273         }
274         files.remove(null);
275         return files.toArray(new File[files.size()]);
276     }
277     
278     /**
279      * Tests parent/child relationship of files.
280      *
281      * @param parent file to be parent of the second parameter
282      * @param file file to be a child of the first parameter
283      * @return true if the second parameter represents the same file as the first parameter OR is its descendant (child)
284      */

285     public static boolean isParentOrEqual(File parent, File file) {
286         for (; file != null; file = file.getParentFile()) {
287             if (file.equals(parent)) return true;
288         }
289         return false;
290     }
291     
292     /**
293      * Computes previous revision or <code>null</code>
294      * for initial.
295      *
296      * @param revision num.dot revision or <code>null</code>
297      */

298     public static String JavaDoc previousRevision(String JavaDoc revision) {
299         return revision == null ? null : Long.toString(Long.parseLong(revision) - 1);
300     }
301     
302     /**
303      * Compute relative path to repository root.
304      * For not yet versioned files guess the URL
305      * from parent context.
306      *
307      * <p>I/O intensive avoid calling it frnm AWT.
308      *
309      * @return the repository url or null for unknown
310      */

311     public static String JavaDoc getRelativePath(File file) {
312         String JavaDoc repositoryPath = null;
313         SvnClient client = Subversion.getInstance().getClient(false);
314         
315         List<String JavaDoc> path = new ArrayList<String JavaDoc>();
316         SVNUrl repositoryURL = null;
317         while (Subversion.getInstance().isManaged(file)) {
318             
319             ISVNInfo info = null;
320             try {
321                 info = client.getInfoFromWorkingCopy(file);
322             } catch (SVNClientException ex) {
323                 if (ExceptionHandler.isUnversionedResource(ex.getMessage()) == false) {
324                     ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
325                 }
326             }
327             
328             if (info != null && info.getUrl() != null) {
329                 SVNUrl fileURL = decode(info.getUrl());
330                 repositoryURL = info.getRepository();
331                 
332                 if (fileURL != null && repositoryURL != null) {
333                     String JavaDoc fileLink = fileURL.toString();
334                     String JavaDoc repositoryLink = repositoryURL.toString();
335                     repositoryPath = fileLink.substring(repositoryLink.length());
336                     
337                     Iterator it = path.iterator();
338                     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
339                     while (it.hasNext()) {
340                         String JavaDoc segment = (String JavaDoc) it.next();
341                         sb.append("/"); // NOI18N
342
sb.append(segment);
343                     }
344                     repositoryPath += sb.toString();
345                     break;
346                 }
347             }
348             
349             path.add(0, file.getName());
350             file = file.getParentFile();
351             
352         }
353         
354         return repositoryPath;
355     }
356     
357     /**
358      * Compute relative path to repository root.
359      * For not yet versioned files guess the URL
360      * from parent context.
361      *
362      * <p>I/O intensive avoid calling it frnm AWT.
363      *
364      * @return the repository url or null for unknown
365      * XXX we need this until we get a local implementation for client.getInfoFromWorkingCopy(file);
366      */

367     public static String JavaDoc getRelativePath(SVNUrl repositoryURL, File file) {
368         String JavaDoc repositoryPath = null;
369         SvnClient client = Subversion.getInstance().getClient(false);
370         
371         List<String JavaDoc> path = new ArrayList<String JavaDoc>();
372         while (Subversion.getInstance().isManaged(file)) {
373             
374             ISVNStatus status = null;
375             try {
376                 status = client.getSingleStatus(file);
377             } catch (SVNClientException ex) {
378                 if (ExceptionHandler.isUnversionedResource(ex.getMessage()) == false) {
379                     ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
380                 }
381             }
382             
383             if (status != null && status.getUrl() != null) {
384                 SVNUrl fileURL = status.getUrl();
385                 
386                 if (fileURL != null && repositoryURL != null) {
387                     fileURL = decode(fileURL);
388                     String JavaDoc fileLink = fileURL.toString();
389                     String JavaDoc repositoryLink = repositoryURL.toString();
390                     repositoryPath = fileLink.substring(repositoryLink.length());
391                     
392                     Iterator it = path.iterator();
393                     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
394                     while (it.hasNext()) {
395                         String JavaDoc segment = (String JavaDoc) it.next();
396                         sb.append("/"); // NOI18N
397
sb.append(segment);
398                     }
399                     repositoryPath += sb.toString();
400                     break;
401                 }
402             }
403             
404             path.add(0, file.getName());
405             file = file.getParentFile();
406             
407         }
408         
409         return repositoryPath;
410     }
411     
412     /**
413      * Returns the repository root for the given file.
414      * For not yet versioned files guess the URL
415      * from parent context.
416      *
417      * <p>I/O intensive avoid calling it frnm AWT.
418      *
419      * @return the repository url or null for unknown
420      */

421     public static SVNUrl getRepositoryRootUrl(File file) {
422         SvnClient client = Subversion.getInstance().getClient(false);
423         
424         SVNUrl repositoryURL = null;
425         while (Subversion.getInstance().isManaged(file)) {
426             ISVNInfo info = null;
427             try {
428                 info = client.getInfoFromWorkingCopy(file);
429             } catch (SVNClientException ex) {
430                 if (ExceptionHandler.isUnversionedResource(ex.getMessage()) == false) {
431                     ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
432                 }
433             }
434             
435             if (info != null && info.getUrl() != null) {
436                 repositoryURL = info.getRepository();
437                 if (repositoryURL != null) {
438                     break;
439                 }
440             }
441             
442             // path.add(0, file.getName());
443
file = file.getParentFile();
444             
445         }
446         return repositoryURL;
447     }
448     
449     /**
450      * Returns the repository URL for the given file.
451      * For not yet versioned files guess the URL
452      * from parent context.
453      *
454      * <p>I/O intensive avoid calling it frnm AWT.
455      *
456      * @return the repository url or null for unknown
457      */

458     public static SVNUrl getRepositoryUrl(File file) {
459         SvnClient client = Subversion.getInstance().getClient(false);
460         
461         StringBuffer JavaDoc path = new StringBuffer JavaDoc();
462         SVNUrl fileURL = null;
463         while (Subversion.getInstance().isManaged(file)) {
464             
465             try {
466                 // it works with 1.3 workdirs and our .svn parser
467
ISVNStatus status = getSingleStatus(client, file);
468                 if (status != null) {
469                     fileURL = decode(status.getUrl());
470                     if (fileURL != null) {
471                         break;
472                     }
473                 }
474             } catch (SVNClientException ex) {
475                 if (ExceptionHandler.isUnversionedResource(ex.getMessage()) == false) {
476                     ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
477                 }
478             }
479             
480             // slower fallback
481

482             ISVNInfo info = null;
483             try {
484                 info = client.getInfoFromWorkingCopy(file);
485             } catch (SVNClientException ex) {
486                 if (ExceptionHandler.isUnversionedResource(ex.getMessage()) == false) {
487                     ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
488                 }
489             }
490             
491             if (info != null) {
492                 fileURL = decode(info.getUrl());
493                 
494                 if (fileURL != null ) {
495                     break;
496                 }
497             }
498             
499             path.insert(0, file.getName()).insert(0, "/");
500             file = file.getParentFile();
501             
502         }
503         if (path.length() > 0) fileURL = fileURL.appendPath(path.toString());
504         return fileURL;
505     }
506     
507     private static ISVNStatus getSingleStatus(SvnClient client, File file) throws SVNClientException{
508         return client.getSingleStatus(file);
509     }
510     
511     /**
512      * Decodes svn URI by decoding %XX escape sequences.
513      *
514      * @param url url to decode
515      * @return decoded url
516      */

517     private static SVNUrl decode(SVNUrl url) {
518         if (url == null) return null;
519         String JavaDoc s = url.toString();
520         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(s.length());
521
522         boolean inQuery = false;
523         for (int i = 0; i < s.length(); i++) {
524             char c = s.charAt(i);
525             if (c == '?') {
526                 inQuery = true;
527             } else if (c == '+' && inQuery) {
528                 c = ' ';
529             } else if (c == '%' && i + 2 < s.length() && isHexDigit(s.charAt(i + 1)) && isHexDigit(s.charAt(i + 2))) {
530                 c = (char) Integer.parseInt(s.substring(i + 1, i + 3), 16);
531                 i += 2;
532             }
533             sb.append(c);
534         }
535         try {
536             return new SVNUrl(sb.toString());
537         } catch (java.net.MalformedURLException JavaDoc e) {
538             throw new RuntimeException JavaDoc(e);
539         }
540     }
541
542     private static boolean isHexDigit(char c) {
543         return c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f';
544     }
545     
546     /*
547      * Determines a versioned file's repository path
548      *
549      * @param file versioned file
550      * @return file's path in repository
551      */

552     public static String JavaDoc getRepositoryPath(File file) {
553         SVNUrl url = getRepositoryUrl(file);
554         SVNUrl rootUrl = getRepositoryRootUrl(file);
555         return SVNUrlUtils.getRelativePath(rootUrl, url, true);
556     }
557     
558     /**
559      * Checks if the file is binary.
560      *
561      * @param file file to check
562      * @return true if the file cannot be edited in NetBeans text editor, false otherwise
563      */

564     public static boolean isFileContentBinary(File file) {
565         FileObject fo = FileUtil.toFileObject(file);
566         if (fo == null) return false;
567         try {
568             DataObject dao = DataObject.find(fo);
569             return dao.getCookie(EditorCookie.class) == null;
570         } catch (DataObjectNotFoundException e) {
571             // not found, continue
572
}
573         return false;
574     }
575     
576     /**
577      * @return true if the buffer is almost certainly binary.
578      * Note: Non-ASCII based encoding encoded text is binary,
579      * newlines cannot be reliably detected.
580      */

581     public static boolean isBinary(byte[] buffer) {
582         for (int i = 0; i<buffer.length; i++) {
583             int ch = buffer[i];
584             if (ch < 32 && ch != '\t' && ch != '\n' && ch != '\r') {
585                 return true;
586             }
587         }
588         return false;
589     }
590     
591     /**
592      * Compares two {@link FileInformation} objects by importance of statuses they represent.
593      */

594     public static class ByImportanceComparator<T> implements Comparator<FileInformation> {
595         public int compare(FileInformation i1, FileInformation i2) {
596             return getComparableStatus(i1.getStatus()) - getComparableStatus(i2.getStatus());
597         }
598     }
599     
600     
601     /**
602      * Normalize flat files, Subversion treats folder as normal file
603      * so it's necessary explicitly list direct descendants to
604      * get classical flat behaviour.
605      *
606      * <p> E.g. revert on package node means:
607      * <ul>
608      * <li>revert package folder properties AND
609      * <li>revert all modified (including deleted) files in the folder
610      * </ul>
611      *
612      * @return files with given status and direct descendants with given status.
613      */

614     public static File[] flatten(File[] files, int status) {
615         LinkedList<File> ret = new LinkedList<File>();
616         
617         FileStatusCache cache = Subversion.getInstance().getStatusCache();
618         for (int i = 0; i<files.length; i++) {
619             File dir = files[i];
620             FileInformation info = cache.getStatus(dir);
621             if ((status & info.getStatus()) != 0) {
622                 ret.add(dir);
623             }
624             File[] entries = cache.listFiles(dir); // comparing to dir.listFiles() lists already deleted too
625
for (int e = 0; e<entries.length; e++) {
626                 File entry = entries[e];
627                 info = cache.getStatus(entry);
628                 if ((status & info.getStatus()) != 0) {
629                     ret.add(entry);
630                 }
631             }
632         }
633         
634         return ret.toArray(new File[ret.size()]);
635     }
636     
637     /**
638      * Utility method that returns all non-excluded modified files that are
639      * under given roots (folders) and have one of specified statuses.
640      *
641      * @param context context to search
642      * @param includeStatus bit mask of file statuses to include in result
643      * @return File [] array of Files having specified status
644      */

645     public static File [] getModifiedFiles(Context context, int includeStatus) {
646         File[] all = Subversion.getInstance().getStatusCache().listFiles(context, includeStatus);
647         List<File> files = new ArrayList<File>();
648         for (int i = 0; i < all.length; i++) {
649             File file = all[i];
650             String JavaDoc path = file.getAbsolutePath();
651             if (SvnModuleConfig.getDefault().isExcludedFromCommit(path) == false) {
652                 files.add(file);
653             }
654         }
655         
656         // ensure that command roots (files that were explicitly selected by user) are included in Diff
657
FileStatusCache cache = Subversion.getInstance().getStatusCache();
658         File [] rootFiles = context.getRootFiles();
659         for (int i = 0; i < rootFiles.length; i++) {
660             File file = rootFiles[i];
661             if (file.isFile() && (cache.getStatus(file).getStatus() & includeStatus) != 0 && !files.contains(file)) {
662                 files.add(file);
663             }
664         }
665         return files.toArray(new File[files.size()]);
666     }
667     
668     
669     /**
670      * Checks file location.
671      *
672      * @param file file to check
673      * @return true if the file or folder is a part of subverion metadata, false otherwise
674      */

675     public static boolean isPartOfSubversionMetadata(File file) {
676         return metadataPattern.matcher(file.getAbsolutePath()).matches();
677     }
678     
679     /**
680      * Gets integer status that can be used in comparators. The more important the status is for the user,
681      * the lower value it has. Conflict is 0, unknown status is 100.
682      *
683      * @return status constant suitable for 'by importance' comparators
684      */

685     public static int getComparableStatus(int status) {
686         if (0 != (status & FileInformation.STATUS_VERSIONED_CONFLICT)) {
687             return 0;
688         } else if (0 != (status & FileInformation.STATUS_VERSIONED_MERGE)) {
689             return 1;
690         } else if (0 != (status & FileInformation.STATUS_VERSIONED_DELETEDLOCALLY)) {
691             return 10;
692         } else if (0 != (status & FileInformation.STATUS_VERSIONED_REMOVEDLOCALLY)) {
693             return 11;
694         } else if (0 != (status & FileInformation.STATUS_NOTVERSIONED_NEWLOCALLY)) {
695             return 12;
696         } else if (0 != (status & FileInformation.STATUS_VERSIONED_ADDEDLOCALLY)) {
697             return 13;
698         } else if (0 != (status & FileInformation.STATUS_VERSIONED_MODIFIEDLOCALLY)) {
699             return 14;
700         } else if (0 != (status & FileInformation.STATUS_VERSIONED_REMOVEDINREPOSITORY)) {
701             return 30;
702         } else if (0 != (status & FileInformation.STATUS_VERSIONED_NEWINREPOSITORY)) {
703             return 31;
704         } else if (0 != (status & FileInformation.STATUS_VERSIONED_MODIFIEDINREPOSITORY)) {
705             return 32;
706         } else if (0 != (status & FileInformation.STATUS_VERSIONED_UPTODATE)) {
707             return 50;
708         } else if (0 != (status & FileInformation.STATUS_NOTVERSIONED_EXCLUDED)) {
709             return 100;
710         } else if (0 != (status & FileInformation.STATUS_NOTVERSIONED_NOTMANAGED)) {
711             return 101;
712         } else if (status == FileInformation.STATUS_UNKNOWN) {
713             return 102;
714         } else {
715             throw new IllegalArgumentException JavaDoc("Uncomparable status: " + status); // NOI18N
716
}
717     }
718     
719     //static final Pattern branchTagPattern = Pattern.compile(".*/(branches|tags)/(.+?)/.*"); // NOI18N
720
// static final Pattern branchPattern = Pattern.compile(".*/(branches)/(.+?)/.*"); // NOI18N
721
// static final Pattern tagPattern = Pattern.compile(".*/(tags)/(.+?)/.*"); // NOI18N
722

723     public static String JavaDoc getCopy(File file) {
724         return getCopy(file, SvnModuleConfig.getDefault().getAnnotationExpresions());
725     }
726
727     /**
728      * Returns copy branch or tag name if lives
729      * in typical location (branches, tags).
730      *
731      * @return name or null
732      */

733     public static String JavaDoc getCopy(File file, List<AnnotationExpression> annotationExpressions) {
734         SVNUrl url = getRepositoryUrl(file);
735         return getCopy(url, annotationExpressions);
736     }
737     
738     public static String JavaDoc getCopy(SVNUrl url) {
739         return getCopy(url, SvnModuleConfig.getDefault().getAnnotationExpresions());
740     }
741     
742     public static String JavaDoc getCopy(SVNUrl url, List<AnnotationExpression> annotationExpressions) {
743         if (url != null) {
744             for (Iterator<AnnotationExpression> it = annotationExpressions.iterator(); it.hasNext();) {
745                 AnnotationExpression annotationExpression = it.next();
746                 
747                 Matcher JavaDoc m = annotationExpression.getUrlPatern().matcher(url.toString());
748                 if (m.matches()) {
749                     String JavaDoc ae = annotationExpression.getAnnotationExp();
750                     
751                     StringBuffer JavaDoc copyName = new StringBuffer JavaDoc();
752                     StringBuffer JavaDoc groupStr = new StringBuffer JavaDoc();
753                     boolean inGroup = false;
754                     
755                     for (int i = 0; i < ae.length(); i++) {
756                         char c = ae.charAt(i);
757                         if(c == '\\') {
758                             inGroup = true;
759                             continue;
760                         } else if(inGroup) {
761                             if(Character.isDigit(c)) {
762                                 groupStr.append(c);
763                             } else {
764                                 if(groupStr.length() > 0) {
765                                     int group = Integer.valueOf(groupStr.toString()).intValue();
766                                     copyName.append(m.group(group));
767                                     groupStr = new StringBuffer JavaDoc();
768                                 } else {
769                                     copyName.append('\\');
770                                     copyName.append(c);
771                                 }
772                                 inGroup = false;
773                             }
774                             continue;
775                         }
776                         copyName.append(c);
777                     }
778                     if(groupStr.length() > 0) {
779                         int group = Integer.valueOf(groupStr.toString()).intValue();
780                         copyName.append(m.group(group));
781                     }
782                     return copyName.toString();
783                 }
784             }
785         }
786         return null;
787     }
788     
789 // /**
790
// * Returns branch name if the file is inside 'branches' folder.
791
// *
792
// * @return branch name or null
793
// */
794
// public static String getBranch(File file, List<AnnotationExpression> annotationExpressions) {
795
// SVNUrl url = getRepositoryUrl(file);
796
// if (url != null) {
797
// Matcher m = branchPattern.matcher(url.toString());
798
// if (m.matches()) {
799
// return m.group(2);
800
// }
801
// }
802
// return null;
803
// }
804

805 // /**
806
// * Returns tag name if the file is inside 'tags' folder.
807
// *
808
// * @return branch name or null
809
// */
810
// public static String getTag(File file) {
811
// SVNUrl url = getRepositoryUrl(file);
812
// if (url != null) {
813
// Matcher m = tagPattern.matcher(url.toString());
814
// if (m.matches()) {
815
// return m.group(2);
816
// }
817
// }
818
// return null;
819
// }
820

821     /**
822      * Refreshes statuses of this folder and all its parent folders up to filesystem root.
823      *
824      * @param folder folder to refresh
825      */

826     public static void refreshRecursively(File folder) {
827         if (folder == null) return;
828         refreshRecursively(folder.getParentFile());
829         Subversion.getInstance().getStatusCache().refresh(folder, FileStatusCache.REPOSITORY_STATUS_UNKNOWN);
830     }
831     
832     public static String JavaDoc ripUserFromHost(String JavaDoc host) {
833         int idx = host.indexOf('@');
834         if(idx < 0) {
835             return host;
836         } else {
837             return host.substring(idx + 1);
838         }
839     }
840     
841     public static SVNRevision getSVNRevision(String JavaDoc revisionString) {
842         try {
843             // HEAD, PREV, BASE, COMMITED, ...
844
return SVNRevision.getRevision(revisionString);
845         } catch (ParseException JavaDoc ex) {
846             return new SVNRevision.Number(Long.parseLong(revisionString));
847         }
848     }
849     
850     /*
851      * Returns the first pattern from the list which matches with the given value.
852      * The patterns are interpreted as shell paterns.
853      *
854      * @param patterns
855      * @param value
856      * @return the first pattern matching with the given value
857      */

858     public static List<String JavaDoc> getMatchinIgnoreParterns(List<String JavaDoc> patterns, String JavaDoc value, boolean onlyFirstMatch) {
859         List<String JavaDoc> ret = new ArrayList<String JavaDoc>();
860         for (Iterator<String JavaDoc> i = patterns.iterator(); i.hasNext();) {
861             try {
862                 // may contain shell patterns (almost identical to RegExp)
863
String JavaDoc patternString = i.next();
864                 String JavaDoc shellPatternString = regExpToFilePatterns(patternString);
865                 Pattern JavaDoc pattern = Pattern.compile(shellPatternString);
866                 if (pattern.matcher(value).matches()) {
867                     ret.add(patternString);
868                     if(onlyFirstMatch) {
869                         return ret;
870                     }
871                 }
872             } catch (PatternSyntaxException JavaDoc e) {
873                 // it's difference between shell and regexp
874
// or user error (set invalid property), rethrow?
875
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
876             }
877         }
878         return ret;
879     }
880     
881     private static String JavaDoc regExpToFilePatterns(String JavaDoc exp) {
882         exp = exp.replaceAll("\\.", "\\\\."); // NOI18N
883
exp = exp.replaceAll("\\*", ".*"); // NOI18N
884
exp = exp.replaceAll("\\?", "."); // NOI18N
885

886         exp = exp.replaceAll("\\$", "\\\\\\$"); // NOI18N
887
exp = exp.replaceAll("\\^", "\\\\^"); // NOI18N
888
exp = exp.replaceAll("\\<", "\\\\<"); // NOI18N
889
exp = exp.replaceAll("\\>", "\\\\>"); // NOI18N
890
exp = exp.replaceAll("\\[", "\\\\["); // NOI18N
891
exp = exp.replaceAll("\\]", "\\\\]"); // NOI18N
892
exp = exp.replaceAll("\\{", "\\\\{"); // NOI18N
893
exp = exp.replaceAll("\\}", "\\\\}"); // NOI18N
894
exp = exp.replaceAll("\\(", "\\\\("); // NOI18N
895
exp = exp.replaceAll("\\)", "\\\\)"); // NOI18N
896
exp = exp.replaceAll("\\+", "\\\\+"); // NOI18N
897
exp = exp.replaceAll("\\|", "\\\\|"); // NOI18N
898

899         return exp;
900     }
901 }
902
Popular Tags