Mercurial > jhg
comparison src/org/tmatesoft/hg/internal/Internals.java @ 490:b3c16d1aede0
Refactoring: move HgRepository's implementation aspects to Internals (which is now its imlementation counterpart and primary repository class to be used by other parts of the library)
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Thu, 16 Aug 2012 17:08:34 +0200 |
| parents | e31e85cf4d4c |
| children | ba36f66c32b4 |
comparison
equal
deleted
inserted
replaced
| 489:9c0138cda59a | 490:b3c16d1aede0 |
|---|---|
| 18 | 18 |
| 19 import static org.tmatesoft.hg.internal.RequiresFile.*; | 19 import static org.tmatesoft.hg.internal.RequiresFile.*; |
| 20 import static org.tmatesoft.hg.util.LogFacility.Severity.Error; | 20 import static org.tmatesoft.hg.util.LogFacility.Severity.Error; |
| 21 | 21 |
| 22 import java.io.File; | 22 import java.io.File; |
| 23 import java.io.FileOutputStream; | |
| 24 import java.io.IOException; | 23 import java.io.IOException; |
| 25 import java.nio.charset.Charset; | 24 import java.nio.charset.Charset; |
| 26 import java.util.ArrayList; | 25 import java.util.ArrayList; |
| 27 import java.util.Arrays; | 26 import java.util.Arrays; |
| 28 import java.util.Collections; | 27 import java.util.Collections; |
| 30 import java.util.LinkedHashSet; | 29 import java.util.LinkedHashSet; |
| 31 import java.util.List; | 30 import java.util.List; |
| 32 import java.util.StringTokenizer; | 31 import java.util.StringTokenizer; |
| 33 | 32 |
| 34 import org.tmatesoft.hg.core.SessionContext; | 33 import org.tmatesoft.hg.core.SessionContext; |
| 35 import org.tmatesoft.hg.repo.HgInternals; | |
| 36 import org.tmatesoft.hg.repo.HgInvalidControlFileException; | 34 import org.tmatesoft.hg.repo.HgInvalidControlFileException; |
| 37 import org.tmatesoft.hg.repo.HgRepoConfig.ExtensionsSection; | 35 import org.tmatesoft.hg.repo.HgRepoConfig.ExtensionsSection; |
| 38 import org.tmatesoft.hg.repo.HgRepository; | 36 import org.tmatesoft.hg.repo.HgRepository; |
| 39 import org.tmatesoft.hg.util.PathRewrite; | 37 import org.tmatesoft.hg.util.PathRewrite; |
| 40 | 38 |
| 75 */ | 73 */ |
| 76 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"; |
| 77 | 75 |
| 78 private int requiresFlags = 0; | 76 private int requiresFlags = 0; |
| 79 private List<Filter.Factory> filterFactories; | 77 private List<Filter.Factory> filterFactories; |
| 80 private final SessionContext sessionContext; | 78 private final HgRepository repo; |
| 79 private final File repoDir; | |
| 81 private final boolean isCaseSensitiveFileSystem; | 80 private final boolean isCaseSensitiveFileSystem; |
| 82 private final boolean shallCacheRevlogsInRepo; | 81 private final boolean shallCacheRevlogsInRepo; |
| 83 | 82 private final DataAccessProvider dataAccess; |
| 84 public Internals(SessionContext ctx) { | 83 |
| 85 sessionContext = ctx; | 84 public Internals(HgRepository hgRepo, File hgDir) { |
| 85 repo = hgRepo; | |
| 86 repoDir = hgDir; | |
| 86 isCaseSensitiveFileSystem = !runningOnWindows(); | 87 isCaseSensitiveFileSystem = !runningOnWindows(); |
| 88 SessionContext ctx = repo.getSessionContext(); | |
| 87 shallCacheRevlogsInRepo = new PropertyMarshal(ctx).getBoolean(CFG_PROPERTY_REVLOG_STREAM_CACHE, true); | 89 shallCacheRevlogsInRepo = new PropertyMarshal(ctx).getBoolean(CFG_PROPERTY_REVLOG_STREAM_CACHE, true); |
| 88 } | 90 dataAccess = new DataAccessProvider(ctx); |
| 89 | 91 } |
| 90 public void parseRequires(HgRepository hgRepo, File requiresFile) throws HgInvalidControlFileException { | 92 |
| 93 public boolean isInvalid() { | |
| 94 return !repoDir.exists() || !repoDir.isDirectory(); | |
| 95 } | |
| 96 | |
| 97 public File getFileFromRepoDir(String name) { | |
| 98 return new File(repoDir, name); | |
| 99 } | |
| 100 | |
| 101 public SessionContext getContext() { | |
| 102 return repo.getSessionContext(); | |
| 103 } | |
| 104 | |
| 105 public HgRepository getRepo() { | |
| 106 return repo; | |
| 107 } | |
| 108 | |
| 109 public DataAccessProvider getDataAccess() { | |
| 110 return dataAccess; | |
| 111 } | |
| 112 | |
| 113 public void parseRequires() throws HgInvalidControlFileException { | |
| 114 File requiresFile =getFileFromRepoDir("requires"); | |
| 91 try { | 115 try { |
| 92 new RequiresFile().parse(this, requiresFile); | 116 new RequiresFile().parse(this, requiresFile); |
| 93 } catch (IOException ex) { | 117 } catch (IOException ex) { |
| 94 throw new HgInvalidControlFileException("Parse failed", ex, requiresFile); | 118 throw new HgInvalidControlFileException("Parse failed", ex, requiresFile); |
| 95 } | 119 } |
| 107 } | 131 } |
| 108 } | 132 } |
| 109 | 133 |
| 110 // XXX perhaps, should keep both fields right here, not in the HgRepository | 134 // XXX perhaps, should keep both fields right here, not in the HgRepository |
| 111 public PathRewrite buildDataFilesHelper() { | 135 public PathRewrite buildDataFilesHelper() { |
| 112 // Note, tests in TestStorePath depend on the encoding not being cached | 136 return new RepoInitializer().setRequires(requiresFlags).buildDataFilesHelper(getContext()); |
| 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); | |
| 116 } | 137 } |
| 117 | 138 |
| 118 public PathRewrite buildRepositoryFilesHelper() { | 139 public PathRewrite buildRepositoryFilesHelper() { |
| 119 if ((requiresFlags & STORE) != 0) { | 140 if ((requiresFlags & STORE) != 0) { |
| 120 return new PathRewrite() { | 141 return new PathRewrite() { |
| 125 } else { | 146 } else { |
| 126 return new PathRewrite.Empty(); | 147 return new PathRewrite.Empty(); |
| 127 } | 148 } |
| 128 } | 149 } |
| 129 | 150 |
| 130 public List<Filter.Factory> getFilters(HgRepository hgRepo) { | 151 public List<Filter.Factory> getFilters() { |
| 131 if (filterFactories == null) { | 152 if (filterFactories == null) { |
| 132 filterFactories = new ArrayList<Filter.Factory>(); | 153 filterFactories = new ArrayList<Filter.Factory>(); |
| 133 ExtensionsSection cfg = hgRepo.getConfiguration().getExtensions(); | 154 ExtensionsSection cfg = repo.getConfiguration().getExtensions(); |
| 134 if (cfg.isEnabled("eol")) { | 155 if (cfg.isEnabled("eol")) { |
| 135 NewlineFilter.Factory ff = new NewlineFilter.Factory(); | 156 NewlineFilter.Factory ff = new NewlineFilter.Factory(); |
| 136 ff.initialize(hgRepo); | 157 ff.initialize(repo); |
| 137 filterFactories.add(ff); | 158 filterFactories.add(ff); |
| 138 } | 159 } |
| 139 if (cfg.isEnabled("keyword")) { | 160 if (cfg.isEnabled("keyword")) { |
| 140 KeywordFilter.Factory ff = new KeywordFilter.Factory(); | 161 KeywordFilter.Factory ff = new KeywordFilter.Factory(); |
| 141 ff.initialize(hgRepo); | 162 ff.initialize(repo); |
| 142 filterFactories.add(ff); | 163 filterFactories.add(ff); |
| 143 } | 164 } |
| 144 } | 165 } |
| 145 return filterFactories; | 166 return filterFactories; |
| 146 } | |
| 147 | |
| 148 public void initEmptyRepository(File hgDir) throws IOException { | |
| 149 hgDir.mkdir(); | |
| 150 FileOutputStream requiresFile = new FileOutputStream(new File(hgDir, "requires")); | |
| 151 StringBuilder sb = new StringBuilder(40); | |
| 152 sb.append("revlogv1\n"); | |
| 153 if ((requiresFlags & STORE) != 0) { | |
| 154 sb.append("store\n"); | |
| 155 } | |
| 156 if ((requiresFlags & FNCACHE) != 0) { | |
| 157 sb.append("fncache\n"); | |
| 158 } | |
| 159 if ((requiresFlags & DOTENCODE) != 0) { | |
| 160 sb.append("dotencode\n"); | |
| 161 } | |
| 162 requiresFile.write(sb.toString().getBytes()); | |
| 163 requiresFile.close(); | |
| 164 new File(hgDir, "store").mkdir(); // with that, hg verify says ok. | |
| 165 } | 167 } |
| 166 | 168 |
| 167 public boolean isCaseSensitiveFileSystem() { | 169 public boolean isCaseSensitiveFileSystem() { |
| 168 return isCaseSensitiveFileSystem; | 170 return isCaseSensitiveFileSystem; |
| 169 } | 171 } |
| 170 | 172 |
| 171 public EncodingHelper buildFileNameEncodingHelper() { | 173 public EncodingHelper buildFileNameEncodingHelper() { |
| 172 return new EncodingHelper(getFileEncoding(), sessionContext); | 174 SessionContext ctx = repo.getSessionContext(); |
| 173 } | 175 return new EncodingHelper(getFileEncoding(ctx), ctx); |
| 174 | 176 } |
| 175 private Charset getFileEncoding() { | 177 |
| 176 Object altEncoding = sessionContext.getConfigurationProperty(CFG_PROPERTY_FS_FILENAME_ENCODING, null); | 178 /*package-local*/ static Charset getFileEncoding(SessionContext ctx) { |
| 179 Object altEncoding = ctx.getConfigurationProperty(CFG_PROPERTY_FS_FILENAME_ENCODING, null); | |
| 177 Charset cs; | 180 Charset cs; |
| 178 if (altEncoding == null) { | 181 if (altEncoding == null) { |
| 179 cs = Charset.defaultCharset(); | 182 cs = Charset.defaultCharset(); |
| 180 } else { | 183 } else { |
| 181 try { | 184 try { |
| 182 cs = Charset.forName(altEncoding.toString()); | 185 cs = Charset.forName(altEncoding.toString()); |
| 183 } catch (IllegalArgumentException ex) { | 186 } catch (IllegalArgumentException ex) { |
| 184 // both IllegalCharsetNameException and UnsupportedCharsetException are subclasses of IAE, too | 187 // 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 | 188 // not severe enough to throw an exception, imo. Just record the fact it's bad ad we ignore it |
| 186 sessionContext.getLog().dump(Internals.class, Error, ex, String.format("Bad configuration value for filename encoding %s", altEncoding)); | 189 ctx.getLog().dump(Internals.class, Error, ex, String.format("Bad configuration value for filename encoding %s", altEncoding)); |
| 187 cs = Charset.defaultCharset(); | 190 cs = Charset.defaultCharset(); |
| 188 } | 191 } |
| 189 } | 192 } |
| 190 return cs; | 193 return cs; |
| 191 } | 194 } |
| 243 } | 246 } |
| 244 | 247 |
| 245 /** | 248 /** |
| 246 * @see http://www.selenic.com/mercurial/hgrc.5.html | 249 * @see http://www.selenic.com/mercurial/hgrc.5.html |
| 247 */ | 250 */ |
| 248 public ConfigFile readConfiguration(HgRepository hgRepo, File repoRoot) throws IOException { | 251 public ConfigFile readConfiguration() throws IOException { |
| 249 // XXX Internals now have sessionContext field, is there real need to extract one from the repo? | 252 SessionContext sessionCtx = repo.getSessionContext(); |
| 250 SessionContext sessionCtx = HgInternals.getContext(hgRepo); | |
| 251 ConfigFile configFile = new ConfigFile(sessionCtx); | 253 ConfigFile configFile = new ConfigFile(sessionCtx); |
| 252 File hgInstallRoot = findHgInstallRoot(sessionCtx); // may be null | 254 File hgInstallRoot = findHgInstallRoot(sessionCtx); // may be null |
| 253 // | 255 // |
| 254 if (runningOnWindows()) { | 256 if (runningOnWindows()) { |
| 255 if (hgInstallRoot != null) { | 257 if (hgInstallRoot != null) { |
| 286 configFile.addLocation(new File("/etc/mercurial/hgrc")); | 288 configFile.addLocation(new File("/etc/mercurial/hgrc")); |
| 287 configFile.addLocation(new File(System.getenv("HOME"), ".hgrc")); | 289 configFile.addLocation(new File(System.getenv("HOME"), ".hgrc")); |
| 288 } | 290 } |
| 289 // last one, overrides anything else | 291 // last one, overrides anything else |
| 290 // <repo>/.hg/hgrc | 292 // <repo>/.hg/hgrc |
| 291 configFile.addLocation(new File(repoRoot, "hgrc")); | 293 configFile.addLocation(getFileFromRepoDir("hgrc")); |
| 292 return configFile; | 294 return configFile; |
| 293 } | 295 } |
| 294 | 296 |
| 295 private static List<File> getWindowsConfigFilesPerInstall(File hgInstallDir) { | 297 private static List<File> getWindowsConfigFilesPerInstall(File hgInstallDir) { |
| 296 File f = new File(hgInstallDir, "Mercurial.ini"); | 298 File f = new File(hgInstallDir, "Mercurial.ini"); |
