Mercurial > jhg
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 } |
