# HG changeset patch # User Artem Tikhomirov # Date 1407082140 -7200 # Node ID 661e77dc88ba26c39512fcb90da8d5c05fb2de59 # Parent a864fb309e4b9bfb57dc9302bc9a90842ee6d905 Mac support: respect Mac alternatives of command-line arguments for common unix tools diff -r a864fb309e4b -r 661e77dc88ba src/org/tmatesoft/hg/internal/FileSystemHelper.java --- a/src/org/tmatesoft/hg/internal/FileSystemHelper.java Sun Aug 03 18:04:13 2014 +0200 +++ b/src/org/tmatesoft/hg/internal/FileSystemHelper.java Sun Aug 03 18:09:00 2014 +0200 @@ -46,6 +46,10 @@ linkCmd = Arrays.asList("mklink", "%1", "%2"); chmodCmd = Collections.emptyList(); statCmd = Collections.emptyList(); + } else if (Internals.runningOnMac()) { + linkCmd = Arrays.asList("/bin/ln", "-s", "%2", "%1"); + chmodCmd = Arrays.asList("/bin/chmod", "+x", "%1"); + statCmd = Arrays.asList("stat", "-f", "%p", "%1"); } else { linkCmd = Arrays.asList("/bin/ln", "-s", "%2", "%1"); chmodCmd = Arrays.asList("/bin/chmod", "+x", "%1"); diff -r a864fb309e4b -r 661e77dc88ba src/org/tmatesoft/hg/internal/Internals.java --- a/src/org/tmatesoft/hg/internal/Internals.java Sun Aug 03 18:04:13 2014 +0200 +++ b/src/org/tmatesoft/hg/internal/Internals.java Sun Aug 03 18:09:00 2014 +0200 @@ -306,6 +306,9 @@ public static boolean runningOnWindows() { return System.getProperty("os.name").indexOf("Windows") != -1; } + public static boolean runningOnMac() { + return System.getProperty("os.name").indexOf("Mac") != -1; + } /** * @param fsHint optional hint pointing to filesystem of interest (generally, it's possible to mount diff -r a864fb309e4b -r 661e77dc88ba src/org/tmatesoft/hg/util/RegularFileStats.java --- a/src/org/tmatesoft/hg/util/RegularFileStats.java Sun Aug 03 18:04:13 2014 +0200 +++ b/src/org/tmatesoft/hg/util/RegularFileStats.java Sun Aug 03 18:09:00 2014 +0200 @@ -68,6 +68,7 @@ RegularFileStats(SessionContext ctx) { sessionContext = ctx; + final Pattern pLink, pExec; if (Internals.runningOnWindows()) { // XXX this implementation is not yet tested against any Windows repository, // only against sample dir listings. As long as Mercurial doesn't handle Windows @@ -75,21 +76,27 @@ command = Arrays.asList("cmd", "/c", "dir"); // Windows patterns need to work against full directory listing (I didn't find a way // to list single file with its attributes like SYMLINK) - Pattern pLink = Pattern.compile("^\\S+.*\\s+\\s+(\\S.*)\\s+\\[(.+)\\]$", Pattern.MULTILINE); - Pattern pExec = Pattern.compile("^\\S+.*\\s+\\d+\\s+(\\S.*\\.exe)$", Pattern.MULTILINE); - linkMatcher = pLink.matcher(""); - execMatcher = pExec.matcher(""); + pLink = Pattern.compile("^\\S+.*\\s+\\s+(\\S.*)\\s+\\[(.+)\\]$", Pattern.MULTILINE); + pExec = Pattern.compile("^\\S+.*\\s+\\d+\\s+(\\S.*\\.exe)$", Pattern.MULTILINE); + } else if (Internals.runningOnMac()) { + command = Arrays.asList("/bin/ls", "-lnoT"); + // -n to present userid and group as digits + // -o don't need group + // -T complete time in standard format (used as boundary in the pattern) + // Perhaps, shall use -B for octal non-printable characters. Shall implement unescapeFilename, below, then. + pLink = Pattern.compile("^lrwxr.xr.x\\s.*\\s\\d\\d:\\d\\d:\\d\\d \\d\\d\\d\\d (.+) -> (.+)$", Pattern.MULTILINE); + pExec = Pattern.compile("^-..[sx]..[sx]..[sx]\\s.*\\s\\d\\d:\\d\\d:\\d\\d \\d\\d\\d\\d (.+)$", Pattern.MULTILINE); } else { command = Arrays.asList("/bin/ls", "-l", "-Q"); // -Q is essential to get quoted name - the only way to // tell exact file name (which may start or end with spaces. - Pattern pLink = Pattern.compile("^lrwxrwxrwx\\s.*\\s\"(.*)\"\\s+->\\s+\"(.*)\"$", Pattern.MULTILINE); + pLink = Pattern.compile("^lrwxrwxrwx\\s.*\\s\"(.*)\"\\s+->\\s+\"(.*)\"$", Pattern.MULTILINE); // 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) // group(2) is link target - Pattern pExec = Pattern.compile("^-..[sx]..[sx]..[sx]\\s.*\\s\"(.+)\"$", Pattern.MULTILINE); + pExec = Pattern.compile("^-..[sx]..[sx]..[sx]\\s.*\\s\"(.+)\"$", Pattern.MULTILINE); // pExec: group(1) is name of executable file - linkMatcher = pLink.matcher(""); - execMatcher = pExec.matcher(""); } + linkMatcher = pLink.matcher(""); + execMatcher = pExec.matcher(""); execHelper = new ProcessExecHelper(); } @@ -119,7 +126,7 @@ if (execMatcher.reset(result).find()) { execs = new HashSet(); do { - execs.add(execMatcher.group(1)); + execs.add(unescapeFilename(execMatcher.group(1))); } while (execMatcher.find()); } else { execs = Collections.emptySet(); // indicate we tried and found nothing @@ -127,7 +134,7 @@ if (linkMatcher.reset(result).find()) { links = new HashMap(); do { - links.put(linkMatcher.group(1), linkMatcher.group(2)); + links.put(unescapeFilename(linkMatcher.group(1)), unescapeFilename(linkMatcher.group(2))); } while (linkMatcher.find()); } else { links = Collections.emptyMap(); @@ -150,7 +157,7 @@ sessionContext.getLog().dump(getClass(), Warn, ex, String.format("Failed to detect flags for %s", f)); // IGNORE, keep isExec and isSymlink false } -} + } public boolean isExecutable() { return isExec; @@ -166,4 +173,9 @@ } throw new UnsupportedOperationException(); } + + // FIXME nop at the moment, but need to implement if use escape code for non-printable characters + private static String unescapeFilename(String cs) { + return cs; + } }