Mercurial > hg4j
comparison src/org/tmatesoft/hg/internal/Internals.java @ 493:ba36f66c32b4
Refactor to keep knowledge about repository control files and their location in respect to .hg/ in a single place (facilitate future adoption of shared repositories)
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> | 
|---|---|
| date | Thu, 18 Oct 2012 18:36:13 +0200 | 
| parents | b3c16d1aede0 | 
| children | d2f6ab541330 | 
   comparison
  equal
  deleted
  inserted
  replaced
| 492:e4eaa23e3442 | 493:ba36f66c32b4 | 
|---|---|
| 14 * the terms of a license other than GNU General Public License | 14 * the terms of a license other than GNU General Public License | 
| 15 * contact TMate Software at support@hg4j.com | 15 * contact TMate Software at support@hg4j.com | 
| 16 */ | 16 */ | 
| 17 package org.tmatesoft.hg.internal; | 17 package org.tmatesoft.hg.internal; | 
| 18 | 18 | 
| 19 import static org.tmatesoft.hg.internal.RequiresFile.*; | |
| 20 import static org.tmatesoft.hg.util.LogFacility.Severity.Error; | 19 import static org.tmatesoft.hg.util.LogFacility.Severity.Error; | 
| 21 | 20 | 
| 22 import java.io.File; | 21 import java.io.File; | 
| 23 import java.io.IOException; | 22 import java.io.IOException; | 
| 24 import java.nio.charset.Charset; | 23 import java.nio.charset.Charset; | 
| 29 import java.util.LinkedHashSet; | 28 import java.util.LinkedHashSet; | 
| 30 import java.util.List; | 29 import java.util.List; | 
| 31 import java.util.StringTokenizer; | 30 import java.util.StringTokenizer; | 
| 32 | 31 | 
| 33 import org.tmatesoft.hg.core.SessionContext; | 32 import org.tmatesoft.hg.core.SessionContext; | 
| 34 import org.tmatesoft.hg.repo.HgInvalidControlFileException; | 33 import org.tmatesoft.hg.repo.HgDataFile; | 
| 34 import org.tmatesoft.hg.repo.HgRuntimeException; | |
| 35 import org.tmatesoft.hg.repo.HgRepoConfig.ExtensionsSection; | 35 import org.tmatesoft.hg.repo.HgRepoConfig.ExtensionsSection; | 
| 36 import org.tmatesoft.hg.repo.HgRepository; | 36 import org.tmatesoft.hg.repo.HgRepository; | 
| 37 import org.tmatesoft.hg.util.PathRewrite; | 37 import org.tmatesoft.hg.util.PathRewrite; | 
| 38 | 38 | 
| 39 /** | 39 /** | 
| 71 * and if your project happen to use anything but filesystem default (say, UTF8 on cp1251 system), | 71 * and if your project happen to use anything but filesystem default (say, UTF8 on cp1251 system), | 
| 72 * native storage paths won't match | 72 * native storage paths won't match | 
| 73 */ | 73 */ | 
| 74 public static final String CFG_PROPERTY_FS_FILENAME_ENCODING = "hg.fs.filename.encoding"; | 74 public static final String CFG_PROPERTY_FS_FILENAME_ENCODING = "hg.fs.filename.encoding"; | 
| 75 | 75 | 
| 76 private int requiresFlags = 0; | |
| 77 private List<Filter.Factory> filterFactories; | 76 private List<Filter.Factory> filterFactories; | 
| 78 private final HgRepository repo; | 77 private final HgRepository repo; | 
| 79 private final File repoDir; | 78 private final File repoDir; | 
| 80 private final boolean isCaseSensitiveFileSystem; | 79 private final boolean isCaseSensitiveFileSystem; | 
| 81 private final boolean shallCacheRevlogsInRepo; | 80 private final boolean shallCacheRevlogsInRepo; | 
| 82 private final DataAccessProvider dataAccess; | 81 private final DataAccessProvider dataAccess; | 
| 83 | 82 | 
| 84 public Internals(HgRepository hgRepo, File hgDir) { | 83 @SuppressWarnings("unused") | 
| 84 private final int requiresFlags; | |
| 85 | |
| 86 private final PathRewrite dataPathHelper; // access to file storage area (usually under .hg/store/data/), with filenames mangled | |
| 87 private final PathRewrite repoPathHelper; // access to system files (under .hg/store if requires has 'store' flag) | |
| 88 | |
| 89 public Internals(HgRepository hgRepo, File hgDir) throws HgRuntimeException { | |
| 85 repo = hgRepo; | 90 repo = hgRepo; | 
| 86 repoDir = hgDir; | 91 repoDir = hgDir; | 
| 87 isCaseSensitiveFileSystem = !runningOnWindows(); | 92 isCaseSensitiveFileSystem = !runningOnWindows(); | 
| 88 SessionContext ctx = repo.getSessionContext(); | 93 SessionContext ctx = repo.getSessionContext(); | 
| 89 shallCacheRevlogsInRepo = new PropertyMarshal(ctx).getBoolean(CFG_PROPERTY_REVLOG_STREAM_CACHE, true); | 94 shallCacheRevlogsInRepo = new PropertyMarshal(ctx).getBoolean(CFG_PROPERTY_REVLOG_STREAM_CACHE, true); | 
| 90 dataAccess = new DataAccessProvider(ctx); | 95 dataAccess = new DataAccessProvider(ctx); | 
| 96 RepoInitializer repoInit = new RepoInitializer().initRequiresFromFile(repoDir); | |
| 97 requiresFlags = repoInit.getRequires(); | |
| 98 dataPathHelper = repoInit.buildDataFilesHelper(getContext()); | |
| 99 repoPathHelper = repoInit.buildStoreFilesHelper(); | |
| 91 } | 100 } | 
| 92 | 101 | 
| 93 public boolean isInvalid() { | 102 public boolean isInvalid() { | 
| 94 return !repoDir.exists() || !repoDir.isDirectory(); | 103 return !repoDir.exists() || !repoDir.isDirectory(); | 
| 95 } | 104 } | 
| 96 | 105 | 
| 106 /** | |
| 107 * Access files under ".hg/". | |
| 108 * File not necessarily exists, this method is merely a factory for Files at specific, configuration-dependent location. | |
| 109 * | |
| 110 * @param name shall be normalized path | |
| 111 */ | |
| 97 public File getFileFromRepoDir(String name) { | 112 public File getFileFromRepoDir(String name) { | 
| 98 return new File(repoDir, name); | 113 return new File(repoDir, name); | 
| 99 } | 114 } | 
| 115 | |
| 116 /** | |
| 117 * Access files under ".hg/store/" or ".hg/" depending on use of 'store' in requires. | |
| 118 * File not necessarily exists, this method is merely a factory for Files at specific, configuration-dependent location. | |
| 119 * | |
| 120 * @param name shall be normalized path | |
| 121 */ | |
| 122 public File getFileFromStoreDir(String name) { | |
| 123 CharSequence location = repoPathHelper.rewrite(name); | |
| 124 return new File(repoDir, location.toString()); | |
| 125 } | |
| 126 | |
| 127 /** | |
| 128 * Access files under ".hg/store/data", ".hg/store/dh/" or ".hg/data" according to settings in requires file. | |
| 129 * File not necessarily exists, this method is merely a factory for Files at specific, configuration-dependent location. | |
| 130 * | |
| 131 * @param name shall be normalized path, without .i or .d suffixes | |
| 132 */ | |
| 133 public File getFileFromDataDir(CharSequence path) { | |
| 134 CharSequence storagePath = dataPathHelper.rewrite(path); | |
| 135 return new File(repoDir, storagePath.toString()); | |
| 136 } | |
| 100 | 137 | 
| 101 public SessionContext getContext() { | 138 public SessionContext getContext() { | 
| 102 return repo.getSessionContext(); | 139 return repo.getSessionContext(); | 
| 103 } | 140 } | 
| 104 | 141 | 
| 108 | 145 | 
| 109 public DataAccessProvider getDataAccess() { | 146 public DataAccessProvider getDataAccess() { | 
| 110 return dataAccess; | 147 return dataAccess; | 
| 111 } | 148 } | 
| 112 | 149 | 
| 113 public void parseRequires() throws HgInvalidControlFileException { | |
| 114 File requiresFile =getFileFromRepoDir("requires"); | |
| 115 try { | |
| 116 new RequiresFile().parse(this, requiresFile); | |
| 117 } catch (IOException ex) { | |
| 118 throw new HgInvalidControlFileException("Parse failed", ex, requiresFile); | |
| 119 } | |
| 120 } | |
| 121 | |
| 122 public/*for tests, otherwise pkg*/ void setStorageConfig(int version, int flags) { | |
| 123 requiresFlags = flags; | |
| 124 } | |
| 125 | |
| 126 public PathRewrite buildNormalizePathRewrite() { | 150 public PathRewrite buildNormalizePathRewrite() { | 
| 127 if (runningOnWindows()) { | 151 if (runningOnWindows()) { | 
| 128 return new WinToNixPathRewrite(); | 152 return new WinToNixPathRewrite(); | 
| 129 } else { | 153 } else { | 
| 130 return new PathRewrite.Empty(); // or strip leading slash, perhaps? | 154 return new PathRewrite.Empty(); // or strip leading slash, perhaps? | 
| 131 } | |
| 132 } | |
| 133 | |
| 134 // XXX perhaps, should keep both fields right here, not in the HgRepository | |
| 135 public PathRewrite buildDataFilesHelper() { | |
| 136 return new RepoInitializer().setRequires(requiresFlags).buildDataFilesHelper(getContext()); | |
| 137 } | |
| 138 | |
| 139 public PathRewrite buildRepositoryFilesHelper() { | |
| 140 if ((requiresFlags & STORE) != 0) { | |
| 141 return new PathRewrite() { | |
| 142 public CharSequence rewrite(CharSequence path) { | |
| 143 return "store/" + path; | |
| 144 } | |
| 145 }; | |
| 146 } else { | |
| 147 return new PathRewrite.Empty(); | |
| 148 } | 155 } | 
| 149 } | 156 } | 
| 150 | 157 | 
| 151 public List<Filter.Factory> getFilters() { | 158 public List<Filter.Factory> getFilters() { | 
| 152 if (filterFactories == null) { | 159 if (filterFactories == null) { | 
| 190 cs = Charset.defaultCharset(); | 197 cs = Charset.defaultCharset(); | 
| 191 } | 198 } | 
| 192 } | 199 } | 
| 193 return cs; | 200 return cs; | 
| 194 } | 201 } | 
| 202 | |
| 203 /** | |
| 204 * Access to mangled name of a file in repository storage, may come handy for debug. | |
| 205 * @return mangled path of the repository file | |
| 206 */ | |
| 207 public CharSequence getStoragePath(HgDataFile df) { | |
| 208 return dataPathHelper.rewrite(df.getPath().toString()); | |
| 209 } | |
| 210 | |
| 195 | 211 | 
| 196 public static boolean runningOnWindows() { | 212 public static boolean runningOnWindows() { | 
| 197 return System.getProperty("os.name").indexOf("Windows") != -1; | 213 return System.getProperty("os.name").indexOf("Windows") != -1; | 
| 198 } | 214 } | 
| 199 | 215 | 
