Mercurial > jhg
comparison src/org/tmatesoft/hg/internal/Internals.java @ 414:bb278ccf9866
Pull changes from smartgit3 branch
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Wed, 21 Mar 2012 20:51:12 +0100 |
| parents | 7f27122011c3 63c5a9d7ca3f |
| children | ee8264d80747 |
comparison
equal
deleted
inserted
replaced
| 413:7f27122011c3 | 414:bb278ccf9866 |
|---|---|
| 19 import static org.tmatesoft.hg.internal.RequiresFile.*; | 19 import static org.tmatesoft.hg.internal.RequiresFile.*; |
| 20 | 20 |
| 21 import java.io.File; | 21 import java.io.File; |
| 22 import java.io.FileOutputStream; | 22 import java.io.FileOutputStream; |
| 23 import java.io.IOException; | 23 import java.io.IOException; |
| 24 import java.nio.charset.Charset; | |
| 24 import java.util.ArrayList; | 25 import java.util.ArrayList; |
| 25 import java.util.Arrays; | 26 import java.util.Arrays; |
| 26 import java.util.Collections; | 27 import java.util.Collections; |
| 28 import java.util.Iterator; | |
| 27 import java.util.LinkedHashSet; | 29 import java.util.LinkedHashSet; |
| 28 import java.util.List; | 30 import java.util.List; |
| 29 import java.util.StringTokenizer; | 31 import java.util.StringTokenizer; |
| 30 | 32 |
| 31 import org.tmatesoft.hg.core.SessionContext; | 33 import org.tmatesoft.hg.core.SessionContext; |
| 53 * XXX perhaps, need to respect this property not only for data files, but for manifest and changelog as well? | 55 * XXX perhaps, need to respect this property not only for data files, but for manifest and changelog as well? |
| 54 * (@see HgRepository#getChangelog and #getManifest()) | 56 * (@see HgRepository#getChangelog and #getManifest()) |
| 55 */ | 57 */ |
| 56 public static final String CFG_PROPERTY_REVLOG_STREAM_CACHE = "hg4j.repo.disable_revlog_cache"; | 58 public static final String CFG_PROPERTY_REVLOG_STREAM_CACHE = "hg4j.repo.disable_revlog_cache"; |
| 57 | 59 |
| 60 /** | |
| 61 * Name of charset to use when translating Unicode filenames to Mercurial storage paths, string, | |
| 62 * to resolve with {@link Charset#forName(String)}. | |
| 63 * E.g. <code>"cp1251"</code> or <code>"Latin-1"</code>. | |
| 64 * | |
| 65 * <p>Mercurial uses system encoding when mangling storage paths. Default value | |
| 66 * based on 'file.encoding' Java system property is usually fine here, however | |
| 67 * in certain scenarios it may be desirable to force a different one, and this | |
| 68 * property is exactly for this purpose. | |
| 69 * | |
| 70 * <p>E.g. Eclipse defaults to project encoding (Launch config, Common page) when launching an application, | |
| 71 * and if your project happen to use anything but filesystem default (say, UTF8 on cp1251 system), | |
| 72 * native storage paths won't match | |
| 73 */ | |
| 74 public static final String CFG_PROPERTY_FS_FILENAME_ENCODING = "hg.fs.filename.encoding"; | |
| 75 | |
| 58 private int requiresFlags = 0; | 76 private int requiresFlags = 0; |
| 59 private List<Filter.Factory> filterFactories; | 77 private List<Filter.Factory> filterFactories; |
| 78 private final SessionContext sessionContext; | |
| 60 private final boolean isCaseSensitiveFileSystem; | 79 private final boolean isCaseSensitiveFileSystem; |
| 61 private final boolean shallCacheRevlogsInRepo; | 80 private final boolean shallCacheRevlogsInRepo; |
| 62 | |
| 63 | 81 |
| 64 public Internals(SessionContext ctx) { | 82 public Internals(SessionContext ctx) { |
| 83 this.sessionContext = ctx; | |
| 65 isCaseSensitiveFileSystem = !runningOnWindows(); | 84 isCaseSensitiveFileSystem = !runningOnWindows(); |
| 66 Object p = ctx.getProperty(CFG_PROPERTY_REVLOG_STREAM_CACHE, true); | 85 Object p = ctx.getProperty(CFG_PROPERTY_REVLOG_STREAM_CACHE, true); |
| 67 shallCacheRevlogsInRepo = p instanceof Boolean ? ((Boolean) p).booleanValue() : Boolean.parseBoolean(String.valueOf(p)); | 86 shallCacheRevlogsInRepo = p instanceof Boolean ? ((Boolean) p).booleanValue() : Boolean.parseBoolean(String.valueOf(p)); |
| 68 } | 87 } |
| 69 | 88 |
| 80 requiresFlags = flags; | 99 requiresFlags = flags; |
| 81 } | 100 } |
| 82 | 101 |
| 83 public PathRewrite buildNormalizePathRewrite() { | 102 public PathRewrite buildNormalizePathRewrite() { |
| 84 if (runningOnWindows()) { | 103 if (runningOnWindows()) { |
| 85 return new PathRewrite() { | 104 return new WinToNixPathRewrite(); |
| 86 | |
| 87 public CharSequence rewrite(CharSequence p) { | |
| 88 // TODO handle . and .. (although unlikely to face them from GUI client) | |
| 89 String path = p.toString(); | |
| 90 path = path.replace('\\', '/').replace("//", "/"); | |
| 91 if (path.startsWith("/")) { | |
| 92 path = path.substring(1); | |
| 93 } | |
| 94 return path; | |
| 95 } | |
| 96 }; | |
| 97 } else { | 105 } else { |
| 98 return new PathRewrite.Empty(); // or strip leading slash, perhaps? | 106 return new PathRewrite.Empty(); // or strip leading slash, perhaps? |
| 99 } | 107 } |
| 100 } | 108 } |
| 101 | 109 |
| 102 // XXX perhaps, should keep both fields right here, not in the HgRepository | 110 // XXX perhaps, should keep both fields right here, not in the HgRepository |
| 103 public PathRewrite buildDataFilesHelper() { | 111 public PathRewrite buildDataFilesHelper() { |
| 104 return new StoragePathHelper((requiresFlags & STORE) != 0, (requiresFlags & FNCACHE) != 0, (requiresFlags & DOTENCODE) != 0); | 112 // Note, tests in TestStorePath depend on the encoding not being cached |
| 113 Charset cs = getFileEncoding(); | |
| 114 // StoragePathHelper needs fine-grained control over char encoding, hence doesn't use EncodingHelper | |
| 115 return new StoragePathHelper((requiresFlags & STORE) != 0, (requiresFlags & FNCACHE) != 0, (requiresFlags & DOTENCODE) != 0, cs); | |
| 105 } | 116 } |
| 106 | 117 |
| 107 public PathRewrite buildRepositoryFilesHelper() { | 118 public PathRewrite buildRepositoryFilesHelper() { |
| 108 if ((requiresFlags & STORE) != 0) { | 119 if ((requiresFlags & STORE) != 0) { |
| 109 return new PathRewrite() { | 120 return new PathRewrite() { |
| 153 new File(hgDir, "store").mkdir(); // with that, hg verify says ok. | 164 new File(hgDir, "store").mkdir(); // with that, hg verify says ok. |
| 154 } | 165 } |
| 155 | 166 |
| 156 public boolean isCaseSensitiveFileSystem() { | 167 public boolean isCaseSensitiveFileSystem() { |
| 157 return isCaseSensitiveFileSystem; | 168 return isCaseSensitiveFileSystem; |
| 169 } | |
| 170 | |
| 171 public EncodingHelper buildFileNameEncodingHelper() { | |
| 172 return new EncodingHelper(getFileEncoding()); | |
| 173 } | |
| 174 | |
| 175 private Charset getFileEncoding() { | |
| 176 Object altEncoding = sessionContext.getProperty(CFG_PROPERTY_FS_FILENAME_ENCODING, null); | |
| 177 Charset cs; | |
| 178 if (altEncoding == null) { | |
| 179 cs = Charset.defaultCharset(); | |
| 180 } else { | |
| 181 try { | |
| 182 cs = Charset.forName(altEncoding.toString()); | |
| 183 } catch (IllegalArgumentException ex) { | |
| 184 // both IllegalCharsetNameException and UnsupportedCharsetException are subclasses of IAE, too | |
| 185 // not severe enough to throw an exception, imo. Just record the fact it's bad ad we ignore it | |
| 186 sessionContext.getLog().error(Internals.class, ex, String.format("Bad configuration value for filename encoding %s", altEncoding)); | |
| 187 cs = Charset.defaultCharset(); | |
| 188 } | |
| 189 } | |
| 190 return cs; | |
| 158 } | 191 } |
| 159 | 192 |
| 160 public static boolean runningOnWindows() { | 193 public static boolean runningOnWindows() { |
| 161 return System.getProperty("os.name").indexOf("Windows") != -1; | 194 return System.getProperty("os.name").indexOf("Windows") != -1; |
| 162 } | 195 } |
| 341 } | 374 } |
| 342 | 375 |
| 343 public boolean shallCacheRevlogs() { | 376 public boolean shallCacheRevlogs() { |
| 344 return shallCacheRevlogsInRepo; | 377 return shallCacheRevlogsInRepo; |
| 345 } | 378 } |
| 379 | |
| 380 public static <T> CharSequence join(Iterable<T> col, CharSequence separator) { | |
| 381 if (col == null) { | |
| 382 return String.valueOf(col); | |
| 383 } | |
| 384 Iterator<T> it = col.iterator(); | |
| 385 if (!it.hasNext()) { | |
| 386 return "[]"; | |
| 387 } | |
| 388 String v = String.valueOf(it.next()); | |
| 389 StringBuilder sb = new StringBuilder(v); | |
| 390 while (it.hasNext()) { | |
| 391 sb.append(separator); | |
| 392 v = String.valueOf(it.next()); | |
| 393 sb.append(v); | |
| 394 } | |
| 395 return sb; | |
| 396 } | |
| 346 } | 397 } |
