2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
package org.netbeans.modules.mercurial.util;
44
import java.io.BufferedWriter;
45
import java.io.BufferedReader;
46
import java.io.FileReader;
48
import java.io.FileOutputStream;
49
import java.io.IOException;
50
import java.io.OutputStreamWriter;
51
import java.io.PrintWriter;
53
import java.util.List;
54
import java.util.Arrays;
55
import java.util.ArrayList;
56
import java.util.LinkedList;
57
import java.util.Collection;
60
import java.util.HashSet;
61
import java.util.Comparator;
62
import java.util.Iterator;
63
import java.util.regex.Pattern;
64
import org.netbeans.modules.mercurial.FileInformation;
65
import org.netbeans.modules.mercurial.FileStatusCache;
66
import org.netbeans.modules.mercurial.Mercurial;
67
import org.netbeans.modules.mercurial.HgModuleConfig;
68
import org.netbeans.modules.mercurial.HgException;
69
import org.netbeans.modules.mercurial.ui.status.SyncFileNode;
70
import org.openide.util.NbBundle;
72
import org.openide.loaders.DataObject;
73
import org.openide.filesystems.FileObject;
74
import org.openide.nodes.Node;
75
import org.openide.windows.OutputEvent;
76
import org.openide.windows.TopComponent;
77
import org.netbeans.modules.versioning.spi.VCSContext;
78
import org.openide.windows.IOProvider;
79
import org.openide.windows.InputOutput;
80
import org.openide.windows.OutputWriter;
81
import java.util.Calendar;
82
import java.util.HashMap;
83
import java.util.logging.Level;
84
import javax.swing.JOptionPane;
85
import org.openide.cookies.EditorCookie;
86
import org.openide.filesystems.FileUtil;
87
import org.openide.filesystems.FileLock;
88
import org.openide.loaders.DataObjectNotFoundException;
89
import org.netbeans.api.project.Project;
90
import org.netbeans.api.project.ProjectUtils;
91
import org.netbeans.api.project.Sources;
92
import org.netbeans.api.project.SourceGroup;
93
import org.netbeans.api.queries.SharabilityQuery;
94
import org.openide.awt.HtmlBrowser;
95
import org.openide.util.Utilities;
96
import org.openide.windows.OutputListener;
102
public class HgUtils {
103
private static final Pattern metadataPattern = Pattern.compile(".*\\" + File.separatorChar + "(\\.)hg(\\" + File.separatorChar + ".*|$)"); // NOI18N
105
// IGNORE SUPPORT HG: following file patterns are added to {Hg repos}/.hgignore and Hg will ignore any files
106
// that match these patterns, reporting "I"status for them // NOI18N
107
private static final String [] HG_IGNORE_FILES = { "\\.orig$", "\\.rej$"}; // NOI18N
109
private static final String FILENAME_HGIGNORE = ".hgignore"; // NOI18N
111
private static final int MAX_LINES_TO_PRINT = 500;
113
private static final String MSG_TOO_MANY_LINES = "The number of output lines is greater than 500; see message log for complete output";
117
* isSolaris - check you are running onthe Solaris OS
119
* @return boolean true - on Solaris, false - not on Solaris
121
public static boolean isSolaris(){
122
return System.getProperty("os.name").equals("SunOS"); // NOI18N
126
* isInUserPath - check if passed in name is on the Users PATH environment setting
128
* @param name to check
129
* @return boolean true - on PATH, false - not on PATH
131
public static boolean isInUserPath(String name) {
132
String pathEnv = System.getenv().get("PATH");// NOI18N
133
// Work around issues on Windows fetching PATH
134
if(pathEnv == null) pathEnv = System.getenv().get("Path");// NOI18N
135
if(pathEnv == null) pathEnv = System.getenv().get("path");// NOI18N
136
String pathSeparator = System.getProperty("path.separator");// NOI18N
137
if (pathEnv == null || pathSeparator == null) return false;
139
String[] paths = pathEnv.split(pathSeparator);
140
for (String path : paths) {
141
File f = new File(path, name);
142
// On Windows isFile will fail on hgk.cmd use !isDirectory
143
if (f.exists() && !f.isDirectory()) {
151
* confirmDialog - display a confirmation dialog
153
* @param bundleLocation location of string resources to display
154
* @param title of dialog to display
155
* @param query ask user
156
* @return boolean true - answered Yes, false - answered No
158
public static boolean confirmDialog(Class bundleLocation, String title, String query) {
159
int response = JOptionPane.showOptionDialog(null, NbBundle.getMessage(bundleLocation, query), NbBundle.getMessage(bundleLocation, title), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
161
if (response == JOptionPane.YES_OPTION) {
169
* warningDialog - display a warning dialog
171
* @param bundleLocation location of string resources to display
172
* @param title of dialog to display
173
* @param warning to display to the user
175
public static void warningDialog(Class bundleLocation, String title, String warning) {
176
JOptionPane.showMessageDialog(null,
177
NbBundle.getMessage(bundleLocation,warning),
178
NbBundle.getMessage(bundleLocation,title),
179
JOptionPane.WARNING_MESSAGE);
184
* stripDoubleSlash - converts '\\' to '\' in path on Windows
186
* @param String path to convert
187
* @return String converted path
189
public static String stripDoubleSlash(String path){
190
if(Utilities.isWindows()){
191
return path.replace("\\\\", "\\");
196
* isLocallyAdded - checks to see if this file has been Locally Added to Hg
198
* @param file to check
199
* @return boolean true - ignore, false - not ignored
201
public static boolean isLocallyAdded(File file){
202
if (file == null) return false;
203
Mercurial hg = Mercurial.getInstance();
205
if ((hg.getFileStatusCache().getStatus(file).getStatus() & FileInformation.STATUS_VERSIONED_ADDEDLOCALLY) !=0)
212
* isIgnored - checks to see if this is a file Hg should ignore
214
* @param File file to check
215
* @return boolean true - ignore, false - not ignored
217
public static boolean isIgnored(File file){
218
if (file == null) return true;
219
String name = file.getName();
221
Set<Pattern> patterns = new HashSet<Pattern>(5);
222
addIgnorePatterns(patterns, Mercurial.getInstance().getTopmostManagedParent(file));
224
for (Iterator i = patterns.iterator(); i.hasNext();) {
225
Pattern pattern = (Pattern) i.next();
226
if (pattern.matcher(name).matches()) {
231
if (FILENAME_HGIGNORE.equals(name)) return false;
232
int sharability = SharabilityQuery.getSharability(file);
233
if (sharability == SharabilityQuery.NOT_SHARABLE) return true;
238
* createIgnored - creates .hgignore file in the repository in which
239
* the given file belongs. This .hgignore file ensures Hg will ignore
240
* the files specified in HG_IGNORE_FILES list
242
* @param path to repository to place .hgignore file
244
public static void createIgnored(File path){
245
if( path == null) return;
246
BufferedWriter fileWriter = null;
247
Mercurial hg = Mercurial.getInstance();
248
File root = hg.getTopmostManagedParent(path);
249
if( root == null) return;
250
File ignore = new File(root, FILENAME_HGIGNORE);
251
if (ignore.exists()) return;
254
fileWriter = new BufferedWriter(
255
new OutputStreamWriter(new FileOutputStream(ignore)));
256
for (String name : HG_IGNORE_FILES) {
257
fileWriter.write(name + "\n"); // NOI18N
259
} catch (IOException ex) {
260
Mercurial.LOG.log(Level.FINE, "createIgnored(): File {0} - {1}", // NOI18N
261
new Object[] {ignore.getAbsolutePath(), ex.toString()});
265
hg.getFileStatusCache().refresh(ignore, FileStatusCache.REPOSITORY_STATUS_UNKNOWN);
266
} catch (IOException ex) {
267
Mercurial.LOG.log(Level.FINE, "createIgnored(): File {0} - {1}", // NOI18N
268
new Object[] {ignore.getAbsolutePath(), ex.toString()});
273
private static void addIgnorePatterns(Set<Pattern> patterns, File file) {
274
Set<String> shPatterns;
276
shPatterns = readIgnoreEntries(file);
277
} catch (IOException e) {
278
// ignore invalid entries
281
for (Iterator i = shPatterns.iterator(); i.hasNext();) {
282
String shPattern = (String) i.next();
283
if ("!".equals(shPattern)) { // NOI18N
287
patterns.add(Pattern.compile(shPattern));
288
} catch (Exception e) {
289
// unsupported pattern
295
private static Set<String> readIgnoreEntries(File directory) throws IOException {
296
File hgIgnore = new File(directory, FILENAME_HGIGNORE);
298
Set<String> entries = new HashSet<String>(5);
299
if (!hgIgnore.canRead()) return entries;
302
BufferedReader r = null;
304
r = new BufferedReader(new FileReader(hgIgnore));
305
while ((s = r.readLine()) != null) {
306
entries.addAll(Arrays.asList(s.trim().split(" ")));
309
if (r != null) try { r.close(); } catch (IOException e) {}
314
private static String computePatternToIgnore(File directory, File file) {
315
String name = file.getAbsolutePath().substring(directory.getAbsolutePath().length()+1);
316
return name.replace(' ', '?').replace(File.separatorChar, '/');
319
private static void writeIgnoreEntries(File directory, Set entries) throws IOException {
320
File hgIgnore = new File(directory, FILENAME_HGIGNORE);
321
FileObject fo = FileUtil.toFileObject(hgIgnore);
323
if (entries.size() == 0) {
324
if (fo != null) fo.delete();
328
if (fo == null || !fo.isValid()) {
329
fo = FileUtil.toFileObject(directory);
330
fo = fo.createData(FILENAME_HGIGNORE);
332
FileLock lock = fo.lock();
333
PrintWriter w = null;
335
w = new PrintWriter(fo.getOutputStream(lock));
336
for (Iterator i = entries.iterator(); i.hasNext();) {
341
if (w != null) w.close();
346
* addIgnored - Add the specified files to the .hgignore file in the
347
* specified repository.
349
* @param directory for repository for .hgignore file
350
* @param files an array of Files to be added
352
public static void addIgnored(File directory, File[] files) throws IOException {
353
Set<String> entries = readIgnoreEntries(directory);
354
for (File file: files) {
355
String patterntoIgnore = computePatternToIgnore(directory, file);
356
entries.add(patterntoIgnore);
358
writeIgnoreEntries(directory, entries);
362
* removeIgnored - Remove the specified files from the .hgignore file in
363
* the specified repository.
365
* @param directory for repository for .hgignore file
366
* @param files an array of Files to be removed
368
public static void removeIgnored(File directory, File[] files) throws IOException {
369
Set entries = readIgnoreEntries(directory);
370
for (File file: files) {
371
String patterntoIgnore = computePatternToIgnore(directory, file);
372
entries.remove(patterntoIgnore);
374
writeIgnoreEntries(directory, entries);
378
* Returns a Map keyed by Directory, containing a single File/FileInformation Map for each Directories file contents.
380
* @param Map of <File, FileInformation> interestingFiles to be processed and divided up into Files in Directory
381
* @param Collection of <File> files to be processed against the interestingFiles
382
* @return Map of Dirs containing Map of files and status for all files in each directory
383
* @throws org.netbeans.modules.mercurial.HgException
385
public static Map<File, Map<File, FileInformation>> getInterestingDirs(Map<File, FileInformation> interestingFiles, Collection<File> files) {
386
Map<File, Map<File, FileInformation>> interestingDirs = new HashMap<File, Map<File, FileInformation>>();
388
Calendar start = Calendar.getInstance();
389
for (File file : files) {
390
if (file.isDirectory()) {
391
if (interestingDirs.get(file) == null) {
392
interestingDirs.put(file, new HashMap<File, FileInformation>());
395
File par = file.getParentFile();
397
if (interestingDirs.get(par) == null) {
398
interestingDirs.put(par, new HashMap<File, FileInformation>());
400
FileInformation fi = interestingFiles.get(file);
401
interestingDirs.get(par).put(file, fi);
405
Calendar end = Calendar.getInstance();
406
Mercurial.LOG.log(Level.FINE, "getInterestingDirs: process interesting Dirs took {0} millisecs", // NOI18N
407
end.getTimeInMillis() - start.getTimeInMillis());
408
return interestingDirs;
412
* Semantics is similar to {@link org.openide.windows.TopComponent#getActivatedNodes()} except that this
413
* method returns File objects instead of Nodes. Every node is examined for Files it represents. File and Folder
414
* nodes represent their underlying files or folders. Project nodes are represented by their source groups. Other
415
* logical nodes must provide FileObjects in their Lookup.
417
* @param nodes null (then taken from windowsystem, it may be wrong on editor tabs #66700).
418
* @param includingFileStatus if any activated file does not have this CVS status, an empty array is returned
419
* @param includingFolderStatus if any activated folder does not have this CVS status, an empty array is returned
420
* @return File [] array of activated files, or an empty array if any of examined files/folders does not have given status
422
public static VCSContext getCurrentContext(Node[] nodes, int includingFileStatus, int includingFolderStatus) {
423
VCSContext context = getCurrentContext(nodes);
424
FileStatusCache cache = Mercurial.getInstance().getFileStatusCache();
425
for (File file : context.getRootFiles()) {
426
FileInformation fi = cache.getStatus(file);
427
if (file.isDirectory()) {
428
if ((fi.getStatus() & includingFolderStatus) == 0) return VCSContext.EMPTY;
430
if ((fi.getStatus() & includingFileStatus) == 0) return VCSContext.EMPTY;
437
* Semantics is similar to {@link org.openide.windows.TopComponent#getActiva
438
tedNodes()} except that this
439
* method returns File objects instead of Nodes. Every node is examined for
440
Files it represents. File and Folder
441
* nodes represent their underlying files or folders. Project nodes are repr
442
esented by their source groups. Other
443
* logical nodes must provide FileObjects in their Lookup.
445
* @return File [] array of activated files
446
* @param nodes or null (then taken from windowsystem, it may be wrong on ed
450
public static VCSContext getCurrentContext(Node[] nodes) {
452
nodes = TopComponent.getRegistry().getActivatedNodes();
454
return VCSContext.forNodes(nodes);
458
* Returns path to repository root or null if not managed
461
* @return String of repository root path
463
public static String getRootPath(VCSContext context){
464
File root = getRootFile(context);
465
return (root == null) ? null: root.getAbsolutePath();
469
* Returns path to repository root or null if not managed
472
* @return String of repository root path
474
public static File getRootFile(VCSContext context){
475
if (context == null) return null;
476
Mercurial hg = Mercurial.getInstance();
477
File [] files = context.getRootFiles().toArray(new File[context.getRootFiles().size()]);
478
if (files == null || files.length == 0) return null;
480
File root = hg.getTopmostManagedParent(files[0]);
485
* Returns File object for Project Directory
488
* @return File object of Project Directory
490
public static File getProjectFile(VCSContext context){
491
return getProjectFile(getProject(context));
494
public static Project getProject(VCSContext context){
495
if (context == null) return null;
496
Node [] nodes = context.getElements().lookupAll(Node.class).toArray(new Node[0]);
497
for (Node node : nodes) {
500
Project project = (Project) tmpNode.getLookup().lookup(Project.class);
501
while (project == null) {
502
tmpNode = tmpNode.getParentNode();
503
if (tmpNode == null) {
504
Mercurial.LOG.log(Level.FINE, "HgUtils.getProjectFile(): No project for {0}", // NOI18N
508
project = (Project) tmpNode.getLookup().lookup(Project.class);
510
if (project != null) {
517
public static File getProjectFile(Project project){
518
if (project == null) return null;
520
FileObject fo = project.getProjectDirectory();
521
return FileUtil.toFile(fo);
524
public static File[] getProjectRootFiles(Project project){
525
if (project == null) return null;
526
Set<File> set = new HashSet<File>();
528
Sources sources = ProjectUtils.getSources(project);
529
SourceGroup [] sourceGroups = sources.getSourceGroups(Sources.TYPE_GENERIC);
530
for (int j = 0; j < sourceGroups.length; j++) {
531
SourceGroup sourceGroup = sourceGroups[j];
532
FileObject srcRootFo = sourceGroup.getRootFolder();
533
File rootFile = FileUtil.toFile(srcRootFo);
536
return set.toArray(new File[set.size()]);
540
* Checks file location to see if it is part of mercurial metdata
542
* @param file file to check
543
* @return true if the file or folder is a part of mercurial metadata, false otherwise
545
public static boolean isPartOfMercurialMetadata(File file) {
546
return metadataPattern.matcher(file.getAbsolutePath()).matches();
551
* Forces refresh of Status for the given directory
553
* @param start file or dir to begin refresh from
556
public static void forceStatusRefresh(File file) {
557
if (Mercurial.getInstance().isAdministrative(file)) return;
560
FileStatusCache cache = Mercurial.getInstance().getFileStatusCache();
562
cache.refreshCached(file);
563
File repository = Mercurial.getInstance().getTopmostManagedParent(file);
564
if (repository == null) {
568
if (file.isDirectory()) {
569
Map<File, FileInformation> interestingFiles;
570
interestingFiles = HgCommand.getInterestingStatus(repository, file);
571
if (!interestingFiles.isEmpty()){
572
Collection<File> files = interestingFiles.keySet();
573
for (File aFile : files) {
574
FileInformation fi = interestingFiles.get(aFile);
575
cache.refreshFileStatus(aFile, fi, null);
580
} catch (HgException ex) {
585
* Forces refresh of Status for the specfied context.
587
* @param VCSContext context to be updated.
590
public static void forceStatusRefresh(VCSContext context) {
591
for (File root : context.getRootFiles()) {
592
forceStatusRefresh(root);
597
* Forces refresh of Status for the project of the specified context
599
* @param VCSContext ctx whose project is be updated.
602
public static void forceStatusRefreshProject(VCSContext context) {
603
Project project = getProject(context);
604
if (project == null) return;
605
File[] files = getProjectRootFiles(project);
606
for (int j = 0; j < files.length; j++) {
607
forceStatusRefresh(files[j]);
612
* Tests parent/child relationship of files.
614
* @param parent file to be parent of the second parameter
615
* @param file file to be a child of the first parameter
616
* @return true if the second parameter represents the same file as the first parameter OR is its descendant (child)
618
public static boolean isParentOrEqual(File parent, File file) {
619
for (; file != null; file = file.getParentFile()) {
620
if (file.equals(parent)) return true;
626
* Returns path of file relative to root repository or a warning message
627
* if the file is not under the repository root.
629
* @param File to get relative path from the repository root
630
* @return String of relative path of the file from teh repository root
632
public static String getRelativePath(File file) {
634
return NbBundle.getMessage(SyncFileNode.class, "LBL_Location_NotInRepository"); // NOI18N
636
String shortPath = file.getAbsolutePath();
637
if (shortPath == null){
638
return NbBundle.getMessage(SyncFileNode.class, "LBL_Location_NotInRepository"); // NOI18N
641
Mercurial mercurial = Mercurial.getInstance();
642
File rootManagedFolder = mercurial.getTopmostManagedParent(file);
643
if ( rootManagedFolder == null){
644
return NbBundle.getMessage(SyncFileNode.class, "LBL_Location_NotInRepository"); // NOI18N
647
String root = rootManagedFolder.getAbsolutePath();
648
if(shortPath.startsWith(root)) {
649
return shortPath.substring(root.length()+1);
651
return NbBundle.getMessage(SyncFileNode.class, "LBL_Location_NotInRepository"); // NOI18N
656
* Normalize flat files, Mercurial treats folder as normal file
657
* so it's necessary explicitly list direct descendants to
658
* get classical flat behaviour.
660
* <p> E.g. revert on package node means:
662
* <li>revert package folder properties AND
663
* <li>revert all modified (including deleted) files in the folder
666
* @return files with given status and direct descendants with given status.
669
public static File[] flatten(File[] files, int status) {
670
LinkedList<File> ret = new LinkedList<File>();
672
FileStatusCache cache = Mercurial.getInstance().getFileStatusCache();
673
for (int i = 0; i<files.length; i++) {
675
FileInformation info = cache.getStatus(dir);
676
if ((status & info.getStatus()) != 0) {
679
File[] entries = cache.listFiles(dir); // comparing to dir.listFiles() lists already deleted too
680
for (int e = 0; e<entries.length; e++) {
681
File entry = entries[e];
682
info = cache.getStatus(entry);
683
if ((status & info.getStatus()) != 0) {
689
return ret.toArray(new File[ret.size()]);
693
* Utility method that returns all non-excluded modified files that are
694
* under given roots (folders) and have one of specified statuses.
696
* @param context context to search
697
* @param includeStatus bit mask of file statuses to include in result
698
* @return File [] array of Files having specified status
700
public static File [] getModifiedFiles(VCSContext context, int includeStatus) {
701
File[] all = Mercurial.getInstance().getFileStatusCache().listFiles(context, includeStatus);
702
List<File> files = new ArrayList<File>();
703
for (int i = 0; i < all.length; i++) {
705
String path = file.getAbsolutePath();
706
if (HgModuleConfig.getDefault().isExcludedFromCommit(path) == false) {
711
// ensure that command roots (files that were explicitly selected by user) are included in Diff
712
FileStatusCache cache = Mercurial.getInstance().getFileStatusCache();
713
for (File file : context.getRootFiles()) {
714
if (file.isFile() && (cache.getStatus(file).getStatus() & includeStatus) != 0 && !files.contains(file)) {
718
return files.toArray(new File[files.size()]);
722
* Checks if the file is binary.
724
* @param file file to check
725
* @return true if the file cannot be edited in NetBeans text editor, false otherwise
727
public static boolean isFileContentBinary(File file) {
728
FileObject fo = FileUtil.toFileObject(file);
729
if (fo == null) return false;
731
DataObject dao = DataObject.find(fo);
732
return dao.getCookie(EditorCookie.class) == null;
733
} catch (DataObjectNotFoundException e) {
734
// not found, continue
740
* @return true if the buffer is almost certainly binary.
741
* Note: Non-ASCII based encoding encoded text is binary,
742
* newlines cannot be reliably detected.
744
public static boolean isBinary(byte[] buffer) {
745
for (int i = 0; i<buffer.length; i++) {
747
if (ch < 32 && ch != '\t' && ch != '\n' && ch != '\r') {
755
* Compares two {@link FileInformation} objects by importance of statuses they represent.
757
public static class ByImportanceComparator<T> implements Comparator<FileInformation> {
758
public int compare(FileInformation i1, FileInformation i2) {
759
return getComparableStatus(i1.getStatus()) - getComparableStatus(i2.getStatus());
764
* Gets integer status that can be used in comparators. The more important the status is for the user,
765
* the lower value it has. Conflict is 0, unknown status is 100.
767
* @return status constant suitable for 'by importance' comparators
769
public static int getComparableStatus(int status) {
770
if (0 != (status & FileInformation.STATUS_VERSIONED_CONFLICT)) {
772
} else if (0 != (status & FileInformation.STATUS_VERSIONED_MERGE)) {
774
} else if (0 != (status & FileInformation.STATUS_VERSIONED_DELETEDLOCALLY)) {
776
} else if (0 != (status & FileInformation.STATUS_VERSIONED_REMOVEDLOCALLY)) {
778
} else if (0 != (status & FileInformation.STATUS_NOTVERSIONED_NEWLOCALLY)) {
780
} else if (0 != (status & FileInformation.STATUS_VERSIONED_ADDEDLOCALLY)) {
782
} else if (0 != (status & FileInformation.STATUS_VERSIONED_MODIFIEDLOCALLY)) {
784
} else if (0 != (status & FileInformation.STATUS_VERSIONED_REMOVEDINREPOSITORY)) {
786
} else if (0 != (status & FileInformation.STATUS_VERSIONED_NEWINREPOSITORY)) {
788
} else if (0 != (status & FileInformation.STATUS_VERSIONED_MODIFIEDINREPOSITORY)) {
790
} else if (0 != (status & FileInformation.STATUS_VERSIONED_UPTODATE)) {
792
} else if (0 != (status & FileInformation.STATUS_NOTVERSIONED_EXCLUDED)){
794
} else if (0 != (status & FileInformation.STATUS_NOTVERSIONED_NOTMANAGED)) {
796
} else if (status == FileInformation.STATUS_UNKNOWN) {
799
throw new IllegalArgumentException("Uncomparable status: " + status); // NOI18N
803
protected static int getFileEnabledStatus() {
807
protected static int getDirectoryEnabledStatus() {
808
return FileInformation.STATUS_MANAGED & ~FileInformation.STATUS_NOTVERSIONED_EXCLUDED;
812
* Rips an eventual username off - e.g. user@svn.host.org
814
* @param host - hostname with a userneame
815
* @return host - hostname without the username
817
public static String ripUserFromHost(String host) {
818
int idx = host.indexOf('@');
822
return host.substring(idx + 1);
828
* Print contents of list to Mercurial Output Tab
830
* @param list to print out
833
public static void outputMercurialTab(List<String> list){
834
if( list.isEmpty()) return;
836
InputOutput io = IOProvider.getDefault().getIO(Mercurial.MERCURIAL_OUTPUT_TAB_TITLE, false);
838
OutputWriter out = io.getOut();
840
int lines = list.size();
841
if (lines > MAX_LINES_TO_PRINT) {
842
out.println(list.get(1));
843
out.println(list.get(2));
844
out.println(list.get(3));
846
out.println(list.get(list.size() -1));
847
out.println(MSG_TOO_MANY_LINES);
848
for (String s : list){
849
Mercurial.LOG.log(Level.WARNING, s);
852
for (String s : list){
861
* Print msg to Mercurial Output Tab
863
* @param String msg to print out
866
public static void outputMercurialTab(String msg){
867
if( msg == null) return;
869
InputOutput io = IOProvider.getDefault().getIO(Mercurial.MERCURIAL_OUTPUT_TAB_TITLE, false);
871
OutputWriter out = io.getOut();
878
* Print msg to Mercurial Output Tab in Red
880
* @param String msg to print out
883
public static void outputMercurialTabInRed(String msg){
884
if( msg == null) return;
886
InputOutput io = IOProvider.getDefault().getIO(Mercurial.MERCURIAL_OUTPUT_TAB_TITLE, false);
888
OutputWriter out = io.getErr();
895
* Print URL to Mercurial Output Tab as an active Hyperlink
897
* @param String sURL to print out
900
public static void outputMercurialTabLink(final String sURL){
901
if (sURL == null) return;
904
InputOutput io = IOProvider.getDefault().getIO(Mercurial.MERCURIAL_OUTPUT_TAB_TITLE, false);
906
OutputWriter out = io.getOut();
908
OutputListener listener = new OutputListener() {
909
public void outputLineAction(OutputEvent ev) {
911
HtmlBrowser.URLDisplayer.getDefault().showURL(new URL(sURL));
912
} catch (IOException ex) {
916
public void outputLineSelected(OutputEvent ev) {}
917
public void outputLineCleared(OutputEvent ev) {}
919
out.println(sURL, listener, true);
921
} catch (IOException ex) {
927
* Select and Clear Mercurial Output Tab
929
* @param list to print out
932
public static void clearOutputMercurialTab(){
933
InputOutput io = IOProvider.getDefault().getIO(
934
Mercurial.MERCURIAL_OUTPUT_TAB_TITLE, false);
937
OutputWriter out = io.getOut();
941
} catch (IOException ex) {
948
* This utility class should not be instantiated anywhere.