# HG changeset patch # User Artem Tikhomirov # Date 1315959379 -7200 # Node ID a415fe296a50687967f768fba43a78ed8775cef8 # Parent 1483e57541ef1d8db899b70e6d70fa69202d21b3 Refactor PathRewrite to accept any char sequence, not only string diff -r 1483e57541ef -r a415fe296a50 src/org/tmatesoft/hg/core/HgCloneCommand.java --- a/src/org/tmatesoft/hg/core/HgCloneCommand.java Wed Sep 14 02:12:47 2011 +0200 +++ b/src/org/tmatesoft/hg/core/HgCloneCommand.java Wed Sep 14 02:16:19 2011 +0200 @@ -209,7 +209,7 @@ revisionSequence.clear(); fncacheFiles.add("data/" + name + ".i"); // FIXME this is pure guess, // need to investigate more how filenames are kept in fncache - File file = new File(hgDir, filename = storagePathHelper.rewrite(name)); + File file = new File(hgDir, filename = storagePathHelper.rewrite(name).toString()); file.getParentFile().mkdirs(); indexFile = new FileOutputStream(file); } catch (IOException ex) { diff -r 1483e57541ef -r a415fe296a50 src/org/tmatesoft/hg/internal/Internals.java --- a/src/org/tmatesoft/hg/internal/Internals.java Wed Sep 14 02:12:47 2011 +0200 +++ b/src/org/tmatesoft/hg/internal/Internals.java Wed Sep 14 02:16:19 2011 +0200 @@ -54,17 +54,12 @@ public PathRewrite buildRepositoryFilesHelper() { if ((requiresFlags & STORE) != 0) { return new PathRewrite() { - public String rewrite(String path) { + public CharSequence rewrite(CharSequence path) { return "store/" + path; } }; } else { - return new PathRewrite() { - public String rewrite(String path) { - //no-op - return path; - } - }; + return new PathRewrite.Empty(); } } @@ -108,4 +103,8 @@ new File(hgDir, "store").mkdir(); // with that, hg verify says ok. } + public static boolean runningOnWindows() { + return System.getProperty("os.name").indexOf("Windows") != -1; + } + } diff -r 1483e57541ef -r a415fe296a50 src/org/tmatesoft/hg/internal/RelativePathRewrite.java --- a/src/org/tmatesoft/hg/internal/RelativePathRewrite.java Wed Sep 14 02:12:47 2011 +0200 +++ b/src/org/tmatesoft/hg/internal/RelativePathRewrite.java Wed Sep 14 02:16:19 2011 +0200 @@ -37,7 +37,8 @@ this.rootPath = rootPath; } - public String rewrite(String path) { + public CharSequence rewrite(CharSequence p) { + String path = p == null ? null : p.toString(); if (path != null && path.startsWith(rootPath)) { if (path.length() == rootPath.length()) { return ""; diff -r 1483e57541ef -r a415fe296a50 src/org/tmatesoft/hg/internal/StoragePathHelper.java --- a/src/org/tmatesoft/hg/internal/StoragePathHelper.java Wed Sep 14 02:12:47 2011 +0200 +++ b/src/org/tmatesoft/hg/internal/StoragePathHelper.java Wed Sep 14 02:16:19 2011 +0200 @@ -43,13 +43,14 @@ // FIXME document what path argument is, whether it includes .i or .d, and whether it's 'normalized' (slashes) or not. // since .hg/store keeps both .i files and files without extension (e.g. fncache), guees, for data == false // we shall assume path has extension - public String rewrite(String path) { + public CharSequence rewrite(CharSequence p) { final String STR_STORE = "store/"; final String STR_DATA = "data/"; final String STR_DH = "dh/"; final String reservedChars = "\\:*?\"<>|"; char[] hexByte = new char[2]; + String path = p.toString(); path = path.replace(".hg/", ".hg.hg/").replace(".i/", ".i.hg/").replace(".d/", ".d.hg/"); StringBuilder sb = new StringBuilder(path.length() << 1); if (store || fncache) { diff -r 1483e57541ef -r a415fe296a50 src/org/tmatesoft/hg/repo/HgRepository.java --- a/src/org/tmatesoft/hg/repo/HgRepository.java Wed Sep 14 02:12:47 2011 +0200 +++ b/src/org/tmatesoft/hg/repo/HgRepository.java Wed Sep 14 02:16:19 2011 +0200 @@ -32,6 +32,7 @@ import org.tmatesoft.hg.internal.DataAccessProvider; import org.tmatesoft.hg.internal.Experimental; import org.tmatesoft.hg.internal.Filter; +import org.tmatesoft.hg.internal.Internals; import org.tmatesoft.hg.internal.RequiresFile; import org.tmatesoft.hg.internal.RevlogStream; import org.tmatesoft.hg.internal.SubrepoManager; @@ -71,6 +72,7 @@ private final PathRewrite normalizePath; private final PathRewrite dataPathHelper; private final PathRewrite repoPathHelper; + private final boolean isCaseSensitiveFileSystem; private HgChangelog changelog; private HgManifest manifest; @@ -93,6 +95,7 @@ dataAccess = null; dataPathHelper = repoPathHelper = null; normalizePath = null; + isCaseSensitiveFileSystem = !Internals.runningOnWindows(); } HgRepository(String repositoryPath, File repositoryRoot) { @@ -106,12 +109,14 @@ } repoLocation = repositoryPath; dataAccess = new DataAccessProvider(); - final boolean runningOnWindows = System.getProperty("os.name").indexOf("Windows") != -1; + final boolean runningOnWindows = Internals.runningOnWindows(); + isCaseSensitiveFileSystem = !runningOnWindows; if (runningOnWindows) { normalizePath = new PathRewrite() { - public String rewrite(String path) { + public CharSequence rewrite(CharSequence p) { // TODO handle . and .. (although unlikely to face them from GUI client) + String path = p.toString(); path = path.replace('\\', '/').replace("//", "/"); if (path.startsWith("/")) { path = path.substring(1); @@ -142,7 +147,7 @@ public HgChangelog getChangelog() { if (this.changelog == null) { - String storagePath = repoPathHelper.rewrite("00changelog.i"); + CharSequence storagePath = repoPathHelper.rewrite("00changelog.i"); RevlogStream content = resolve(Path.create(storagePath), true); this.changelog = new HgChangelog(this, content); } @@ -207,8 +212,8 @@ } public HgDataFile getFileNode(String path) { - String nPath = normalizePath.rewrite(path); - String storagePath = dataPathHelper.rewrite(nPath); + CharSequence nPath = normalizePath.rewrite(path); + CharSequence storagePath = dataPathHelper.rewrite(nPath); RevlogStream content = resolve(Path.create(storagePath), false); Path p = Path.create(nPath); if (content == null) { @@ -218,7 +223,7 @@ } public HgDataFile getFileNode(Path path) { - String storagePath = dataPathHelper.rewrite(path.toString()); + CharSequence storagePath = dataPathHelper.rewrite(path.toString()); RevlogStream content = resolve(Path.create(storagePath), false); // XXX no content when no file? or HgDataFile.exists() to detect that? if (content == null) { @@ -273,7 +278,16 @@ // XXX package-local, unless there are cases when required from outside (guess, working dir/revision walkers may hide dirstate access and no public visibility needed) // XXX consider passing Path pool or factory to produce (shared) Path instead of Strings /*package-local*/ final HgDirstate loadDirstate(PathPool pathPool) { - return new HgDirstate(this, new File(repoDir, "dirstate"), pathPool); + PathRewrite canonicalPath = null; + if (!isCaseSensitiveFileSystem) { + canonicalPath = new PathRewrite() { + + public CharSequence rewrite(CharSequence path) { + return path.toString().toLowerCase(); + } + }; + } + return new HgDirstate(this, new File(repoDir, "dirstate"), pathPool, canonicalPath); } /** diff -r 1483e57541ef -r a415fe296a50 src/org/tmatesoft/hg/util/Path.java --- a/src/org/tmatesoft/hg/util/Path.java Wed Sep 14 02:12:47 2011 +0200 +++ b/src/org/tmatesoft/hg/util/Path.java Wed Sep 14 02:16:19 2011 +0200 @@ -101,14 +101,19 @@ return CompareResult.Unrelated; } - public static Path create(String path) { + public static Path create(CharSequence path) { if (path == null) { throw new IllegalArgumentException(); } - if (path.indexOf('\\') != -1) { + if (path instanceof Path) { + Path o = (Path) path; + return o; + } + String p = path.toString(); + if (p.indexOf('\\') != -1) { throw new IllegalArgumentException(); } - Path rv = new Path(path); + Path rv = new Path(p); return rv; } diff -r 1483e57541ef -r a415fe296a50 src/org/tmatesoft/hg/util/PathPool.java --- a/src/org/tmatesoft/hg/util/PathPool.java Wed Sep 14 02:12:47 2011 +0200 +++ b/src/org/tmatesoft/hg/util/PathPool.java Wed Sep 14 02:16:19 2011 +0200 @@ -36,14 +36,14 @@ } public Path path(String p) { - p = pathRewrite.rewrite(p); + p = pathRewrite.rewrite(p).toString(); return get(p, true); } // pipes path object through cache to reuse instance, if possible // TODO unify with Pool public Path path(Path p) { - String s = pathRewrite.rewrite(p.toString()); + String s = pathRewrite.rewrite(p).toString(); Path cached = get(s, false); if (cached == null) { cache.put(s, new SoftReference(cached = p)); diff -r 1483e57541ef -r a415fe296a50 src/org/tmatesoft/hg/util/PathRewrite.java --- a/src/org/tmatesoft/hg/util/PathRewrite.java Wed Sep 14 02:12:47 2011 +0200 +++ b/src/org/tmatesoft/hg/util/PathRewrite.java Wed Sep 14 02:16:19 2011 +0200 @@ -27,11 +27,10 @@ */ public interface PathRewrite { - // XXX think over CharSequence use instead of String - public String rewrite(String path); + public CharSequence rewrite(CharSequence path); public static class Empty implements PathRewrite { - public String rewrite(String path) { + public CharSequence rewrite(CharSequence path) { return path; } } @@ -51,7 +50,7 @@ return this; } - public String rewrite(String path) { + public CharSequence rewrite(CharSequence path) { for (PathRewrite pr : chain) { path = pr.rewrite(path); } diff -r 1483e57541ef -r a415fe296a50 test/org/tmatesoft/hg/test/StatusOutputParser.java --- a/test/org/tmatesoft/hg/test/StatusOutputParser.java Wed Sep 14 02:12:47 2011 +0200 +++ b/test/org/tmatesoft/hg/test/StatusOutputParser.java Wed Sep 14 02:16:19 2011 +0200 @@ -48,10 +48,10 @@ private final boolean winPathSeparator = File.separatorChar == '\\'; - public String rewrite(String s) { + public CharSequence rewrite(CharSequence s) { if (winPathSeparator) { // Java impl always give slashed path, while Hg uses local, os-specific convention - s = s.replace('\\', '/'); + s = s.toString().replace('\\', '/'); } return s; } diff -r 1483e57541ef -r a415fe296a50 test/org/tmatesoft/hg/test/TestStorePath.java --- a/test/org/tmatesoft/hg/test/TestStorePath.java Wed Sep 14 02:12:47 2011 +0200 +++ b/test/org/tmatesoft/hg/test/TestStorePath.java Wed Sep 14 02:16:19 2011 +0200 @@ -16,9 +16,9 @@ */ package org.tmatesoft.hg.test; -import static org.hamcrest.CoreMatchers.equalTo; import junit.framework.Assert; +import org.hamcrest.CoreMatchers; import org.junit.Rule; import org.junit.Test; import org.tmatesoft.hg.internal.Internals; @@ -66,8 +66,8 @@ String n3 = "AUX.THE-QUICK-BROWN-FOX-JU:MPS-OVER-THE-LAZY-DOG-THE-QUICK-BROWN-FOX-JUMPS-OVER-THE-LAZY-DOG.TXT"; String r3 = "store/dh/au~78.the-quick-brown-fox-ju~3amps-over-the-lazy-dog-the-quick-brown-fox-jud4dcadd033000ab2b26eb66bae1906bcb15d4a70.i"; // TODO segment[8] == [. ], segment[8] in the middle of windows reserved name or character (to see if ~xx is broken) - errorCollector.checkThat(storePathHelper.rewrite(n1), equalTo(r1)); - errorCollector.checkThat(storePathHelper.rewrite(n2), equalTo(r2)); - errorCollector.checkThat(storePathHelper.rewrite(n3), equalTo(r3)); + errorCollector.checkThat(storePathHelper.rewrite(n1), CoreMatchers.equalTo(r1)); + errorCollector.checkThat(storePathHelper.rewrite(n2), CoreMatchers.equalTo(r2)); + errorCollector.checkThat(storePathHelper.rewrite(n3), CoreMatchers.equalTo(r3)); } }