Mercurial > hg4j
comparison src/org/tmatesoft/hg/util/RegularFileStats.java @ 713:661e77dc88ba tip
Mac support: respect Mac alternatives of command-line arguments for common unix tools
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Sun, 03 Aug 2014 18:09:00 +0200 |
parents | c02b5710d9ac |
children |
comparison
equal
deleted
inserted
replaced
712:a864fb309e4b | 713:661e77dc88ba |
---|---|
66 private Map<String, Set<String>> dir2execs = new TreeMap<String, Set<String>>(); | 66 private Map<String, Set<String>> dir2execs = new TreeMap<String, Set<String>>(); |
67 | 67 |
68 | 68 |
69 RegularFileStats(SessionContext ctx) { | 69 RegularFileStats(SessionContext ctx) { |
70 sessionContext = ctx; | 70 sessionContext = ctx; |
71 final Pattern pLink, pExec; | |
71 if (Internals.runningOnWindows()) { | 72 if (Internals.runningOnWindows()) { |
72 // XXX this implementation is not yet tested against any Windows repository, | 73 // XXX this implementation is not yet tested against any Windows repository, |
73 // only against sample dir listings. As long as Mercurial doesn't handle Windows | 74 // only against sample dir listings. As long as Mercurial doesn't handle Windows |
74 // links, we don't really need this | 75 // links, we don't really need this |
75 command = Arrays.asList("cmd", "/c", "dir"); | 76 command = Arrays.asList("cmd", "/c", "dir"); |
76 // Windows patterns need to work against full directory listing (I didn't find a way | 77 // Windows patterns need to work against full directory listing (I didn't find a way |
77 // to list single file with its attributes like SYMLINK) | 78 // to list single file with its attributes like SYMLINK) |
78 Pattern pLink = Pattern.compile("^\\S+.*\\s+<SYMLINK>\\s+(\\S.*)\\s+\\[(.+)\\]$", Pattern.MULTILINE); | 79 pLink = Pattern.compile("^\\S+.*\\s+<SYMLINK>\\s+(\\S.*)\\s+\\[(.+)\\]$", Pattern.MULTILINE); |
79 Pattern pExec = Pattern.compile("^\\S+.*\\s+\\d+\\s+(\\S.*\\.exe)$", Pattern.MULTILINE); | 80 pExec = Pattern.compile("^\\S+.*\\s+\\d+\\s+(\\S.*\\.exe)$", Pattern.MULTILINE); |
80 linkMatcher = pLink.matcher(""); | 81 } else if (Internals.runningOnMac()) { |
81 execMatcher = pExec.matcher(""); | 82 command = Arrays.asList("/bin/ls", "-lnoT"); |
83 // -n to present userid and group as digits | |
84 // -o don't need group | |
85 // -T complete time in standard format (used as boundary in the pattern) | |
86 // Perhaps, shall use -B for octal non-printable characters. Shall implement unescapeFilename, below, then. | |
87 pLink = Pattern.compile("^lrwxr.xr.x\\s.*\\s\\d\\d:\\d\\d:\\d\\d \\d\\d\\d\\d (.+) -> (.+)$", Pattern.MULTILINE); | |
88 pExec = Pattern.compile("^-..[sx]..[sx]..[sx]\\s.*\\s\\d\\d:\\d\\d:\\d\\d \\d\\d\\d\\d (.+)$", Pattern.MULTILINE); | |
82 } else { | 89 } else { |
83 command = Arrays.asList("/bin/ls", "-l", "-Q"); // -Q is essential to get quoted name - the only way to | 90 command = Arrays.asList("/bin/ls", "-l", "-Q"); // -Q is essential to get quoted name - the only way to |
84 // tell exact file name (which may start or end with spaces. | 91 // tell exact file name (which may start or end with spaces. |
85 Pattern pLink = Pattern.compile("^lrwxrwxrwx\\s.*\\s\"(.*)\"\\s+->\\s+\"(.*)\"$", Pattern.MULTILINE); | 92 pLink = Pattern.compile("^lrwxrwxrwx\\s.*\\s\"(.*)\"\\s+->\\s+\"(.*)\"$", Pattern.MULTILINE); |
86 // pLink: group(1) is full name if single file listing (ls -l /usr/bin/java) and short name if directory listing (ls -l /usr/bin) | 93 // pLink: group(1) is full name if single file listing (ls -l /usr/bin/java) and short name if directory listing (ls -l /usr/bin) |
87 // group(2) is link target | 94 // group(2) is link target |
88 Pattern pExec = Pattern.compile("^-..[sx]..[sx]..[sx]\\s.*\\s\"(.+)\"$", Pattern.MULTILINE); | 95 pExec = Pattern.compile("^-..[sx]..[sx]..[sx]\\s.*\\s\"(.+)\"$", Pattern.MULTILINE); |
89 // pExec: group(1) is name of executable file | 96 // pExec: group(1) is name of executable file |
90 linkMatcher = pLink.matcher(""); | |
91 execMatcher = pExec.matcher(""); | |
92 } | 97 } |
98 linkMatcher = pLink.matcher(""); | |
99 execMatcher = pExec.matcher(""); | |
93 execHelper = new ProcessExecHelper(); | 100 execHelper = new ProcessExecHelper(); |
94 } | 101 } |
95 | 102 |
96 /** | 103 /** |
97 * Fails silently indicating false for both x and l in case interaction with file system failed | 104 * Fails silently indicating false for both x and l in case interaction with file system failed |
117 CharSequence result = execHelper.exec(cmd); | 124 CharSequence result = execHelper.exec(cmd); |
118 | 125 |
119 if (execMatcher.reset(result).find()) { | 126 if (execMatcher.reset(result).find()) { |
120 execs = new HashSet<String>(); | 127 execs = new HashSet<String>(); |
121 do { | 128 do { |
122 execs.add(execMatcher.group(1)); | 129 execs.add(unescapeFilename(execMatcher.group(1))); |
123 } while (execMatcher.find()); | 130 } while (execMatcher.find()); |
124 } else { | 131 } else { |
125 execs = Collections.emptySet(); // indicate we tried and found nothing | 132 execs = Collections.emptySet(); // indicate we tried and found nothing |
126 } | 133 } |
127 if (linkMatcher.reset(result).find()) { | 134 if (linkMatcher.reset(result).find()) { |
128 links = new HashMap<String, String>(); | 135 links = new HashMap<String, String>(); |
129 do { | 136 do { |
130 links.put(linkMatcher.group(1), linkMatcher.group(2)); | 137 links.put(unescapeFilename(linkMatcher.group(1)), unescapeFilename(linkMatcher.group(2))); |
131 } while (linkMatcher.find()); | 138 } while (linkMatcher.find()); |
132 } else { | 139 } else { |
133 links = Collections.emptyMap(); | 140 links = Collections.emptyMap(); |
134 } | 141 } |
135 dir2links.put(dirName, links); | 142 dir2links.put(dirName, links); |
148 // IGNORE, keep isExec and isSymlink false | 155 // IGNORE, keep isExec and isSymlink false |
149 } catch (IOException ex) { | 156 } catch (IOException ex) { |
150 sessionContext.getLog().dump(getClass(), Warn, ex, String.format("Failed to detect flags for %s", f)); | 157 sessionContext.getLog().dump(getClass(), Warn, ex, String.format("Failed to detect flags for %s", f)); |
151 // IGNORE, keep isExec and isSymlink false | 158 // IGNORE, keep isExec and isSymlink false |
152 } | 159 } |
153 } | 160 } |
154 | 161 |
155 public boolean isExecutable() { | 162 public boolean isExecutable() { |
156 return isExec; | 163 return isExec; |
157 } | 164 } |
158 | 165 |
164 if (isSymlink) { | 171 if (isSymlink) { |
165 return symlinkValue; | 172 return symlinkValue; |
166 } | 173 } |
167 throw new UnsupportedOperationException(); | 174 throw new UnsupportedOperationException(); |
168 } | 175 } |
176 | |
177 // FIXME nop at the moment, but need to implement if use escape code for non-printable characters | |
178 private static String unescapeFilename(String cs) { | |
179 return cs; | |
180 } | |
169 } | 181 } |