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