comparison src/org/tmatesoft/hg/repo/HgRepository.java @ 388:b015f3918120

Work on FIXME: correct HgDataFile#workingCopy with tests; BasicSessionContext with property override; platform-specific options to internals
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Wed, 15 Feb 2012 22:57:56 +0100
parents 2fadf8695f8a
children 0ae53c32ecef 30922c728341
comparison
equal deleted inserted replaced
387:cdea37239b01 388:b015f3918120
1 /* 1 /*
2 * Copyright (c) 2010-2011 TMate Software Ltd 2 * Copyright (c) 2010-2012 TMate Software Ltd
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License. 6 * the Free Software Foundation; version 2 of the License.
7 * 7 *
32 import org.tmatesoft.hg.internal.ByteArrayChannel; 32 import org.tmatesoft.hg.internal.ByteArrayChannel;
33 import org.tmatesoft.hg.internal.ConfigFile; 33 import org.tmatesoft.hg.internal.ConfigFile;
34 import org.tmatesoft.hg.internal.DataAccessProvider; 34 import org.tmatesoft.hg.internal.DataAccessProvider;
35 import org.tmatesoft.hg.internal.Experimental; 35 import org.tmatesoft.hg.internal.Experimental;
36 import org.tmatesoft.hg.internal.Filter; 36 import org.tmatesoft.hg.internal.Filter;
37 import org.tmatesoft.hg.internal.Internals;
38 import org.tmatesoft.hg.internal.RevlogStream; 37 import org.tmatesoft.hg.internal.RevlogStream;
39 import org.tmatesoft.hg.internal.SubrepoManager; 38 import org.tmatesoft.hg.internal.SubrepoManager;
40 import org.tmatesoft.hg.util.CancelledException; 39 import org.tmatesoft.hg.util.CancelledException;
41 import org.tmatesoft.hg.util.Pair; 40 import org.tmatesoft.hg.util.Pair;
42 import org.tmatesoft.hg.util.Path; 41 import org.tmatesoft.hg.util.Path;
71 private final String repoLocation; 70 private final String repoLocation;
72 private final DataAccessProvider dataAccess; 71 private final DataAccessProvider dataAccess;
73 private final PathRewrite normalizePath; 72 private final PathRewrite normalizePath;
74 private final PathRewrite dataPathHelper; 73 private final PathRewrite dataPathHelper;
75 private final PathRewrite repoPathHelper; 74 private final PathRewrite repoPathHelper;
76 private final boolean isCaseSensitiveFileSystem; // FIXME keep this inside Internals impl and delegate to Internals all os/fs-specific tasks
77 private final SessionContext sessionContext; 75 private final SessionContext sessionContext;
78 76
79 private HgChangelog changelog; 77 private HgChangelog changelog;
80 private HgManifest manifest; 78 private HgManifest manifest;
81 private HgTags tags; 79 private HgTags tags;
84 private SubrepoManager subRepos; 82 private SubrepoManager subRepos;
85 83
86 // XXX perhaps, shall enable caching explicitly 84 // XXX perhaps, shall enable caching explicitly
87 private final HashMap<Path, SoftReference<RevlogStream>> streamsCache = new HashMap<Path, SoftReference<RevlogStream>>(); 85 private final HashMap<Path, SoftReference<RevlogStream>> streamsCache = new HashMap<Path, SoftReference<RevlogStream>>();
88 86
89 private final org.tmatesoft.hg.internal.Internals impl = new org.tmatesoft.hg.internal.Internals(); 87 private final org.tmatesoft.hg.internal.Internals impl;
90 private HgIgnore ignore; 88 private HgIgnore ignore;
91 private HgRepoConfig repoConfig; 89 private HgRepoConfig repoConfig;
92 90
93 HgRepository(String repositoryPath) { 91 HgRepository(String repositoryPath) {
94 repoDir = null; 92 repoDir = null;
96 repoLocation = repositoryPath; 94 repoLocation = repositoryPath;
97 dataAccess = null; 95 dataAccess = null;
98 dataPathHelper = repoPathHelper = null; 96 dataPathHelper = repoPathHelper = null;
99 normalizePath = null; 97 normalizePath = null;
100 sessionContext = null; 98 sessionContext = null;
101 isCaseSensitiveFileSystem = !Internals.runningOnWindows(); 99 impl = null;
102 } 100 }
103 101
104 HgRepository(SessionContext ctx, String repositoryPath, File repositoryRoot) { 102 HgRepository(SessionContext ctx, String repositoryPath, File repositoryRoot) {
105 assert ".hg".equals(repositoryRoot.getName()) && repositoryRoot.isDirectory(); 103 assert ".hg".equals(repositoryRoot.getName()) && repositoryRoot.isDirectory();
106 assert repositoryPath != null; 104 assert repositoryPath != null;
109 repoDir = repositoryRoot; 107 repoDir = repositoryRoot;
110 workingDir = repoDir.getParentFile(); 108 workingDir = repoDir.getParentFile();
111 if (workingDir == null) { 109 if (workingDir == null) {
112 throw new IllegalArgumentException(repoDir.toString()); 110 throw new IllegalArgumentException(repoDir.toString());
113 } 111 }
112 impl = new org.tmatesoft.hg.internal.Internals(ctx);
114 repoLocation = repositoryPath; 113 repoLocation = repositoryPath;
115 sessionContext = ctx; 114 sessionContext = ctx;
116 dataAccess = new DataAccessProvider(ctx); 115 dataAccess = new DataAccessProvider(ctx);
117 final boolean runningOnWindows = Internals.runningOnWindows();
118 isCaseSensitiveFileSystem = !runningOnWindows;
119 if (runningOnWindows) {
120 normalizePath = new PathRewrite() {
121
122 public CharSequence rewrite(CharSequence p) {
123 // TODO handle . and .. (although unlikely to face them from GUI client)
124 String path = p.toString();
125 path = path.replace('\\', '/').replace("//", "/");
126 if (path.startsWith("/")) {
127 path = path.substring(1);
128 }
129 return path;
130 }
131 };
132 } else {
133 normalizePath = new PathRewrite.Empty(); // or strip leading slash, perhaps?
134 }
135 impl.parseRequires(this, new File(repoDir, "requires")); 116 impl.parseRequires(this, new File(repoDir, "requires"));
117 normalizePath = impl.buildNormalizePathRewrite();
136 dataPathHelper = impl.buildDataFilesHelper(); 118 dataPathHelper = impl.buildDataFilesHelper();
137 repoPathHelper = impl.buildRepositoryFilesHelper(); 119 repoPathHelper = impl.buildRepositoryFilesHelper();
138 } 120 }
139 121
140 @Override 122 @Override
149 public boolean isInvalid() { 131 public boolean isInvalid() {
150 return repoDir == null || !repoDir.exists() || !repoDir.isDirectory(); 132 return repoDir == null || !repoDir.exists() || !repoDir.isDirectory();
151 } 133 }
152 134
153 public HgChangelog getChangelog() { 135 public HgChangelog getChangelog() {
154 if (this.changelog == null) { 136 if (changelog == null) {
155 CharSequence storagePath = repoPathHelper.rewrite("00changelog.i"); 137 CharSequence storagePath = repoPathHelper.rewrite("00changelog.i");
156 RevlogStream content = resolve(Path.create(storagePath), true); 138 RevlogStream content = resolve(Path.create(storagePath), true);
157 this.changelog = new HgChangelog(this, content); 139 changelog = new HgChangelog(this, content);
158 } 140 }
159 return this.changelog; 141 return changelog;
160 } 142 }
161 143
162 public HgManifest getManifest() { 144 public HgManifest getManifest() {
163 if (this.manifest == null) { 145 if (manifest == null) {
164 RevlogStream content = resolve(Path.create(repoPathHelper.rewrite("00manifest.i")), true); 146 RevlogStream content = resolve(Path.create(repoPathHelper.rewrite("00manifest.i")), true);
165 this.manifest = new HgManifest(this, content); 147 manifest = new HgManifest(this, content);
166 } 148 }
167 return this.manifest; 149 return manifest;
168 } 150 }
169 151
170 public HgTags getTags() throws HgInvalidControlFileException { 152 public HgTags getTags() throws HgInvalidControlFileException {
171 if (tags == null) { 153 if (tags == null) {
172 tags = new HgTags(this); 154 tags = new HgTags(this);
314 296
315 // 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) 297 // 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)
316 // XXX consider passing Path pool or factory to produce (shared) Path instead of Strings 298 // XXX consider passing Path pool or factory to produce (shared) Path instead of Strings
317 /*package-local*/ final HgDirstate loadDirstate(PathPool pathPool) throws HgInvalidControlFileException { 299 /*package-local*/ final HgDirstate loadDirstate(PathPool pathPool) throws HgInvalidControlFileException {
318 PathRewrite canonicalPath = null; 300 PathRewrite canonicalPath = null;
319 if (!isCaseSensitiveFileSystem) { 301 if (!impl.isCaseSensitiveFileSystem()) {
320 canonicalPath = new PathRewrite() { 302 canonicalPath = new PathRewrite() {
321 303
322 public CharSequence rewrite(CharSequence path) { 304 public CharSequence rewrite(CharSequence path) {
323 return path.toString().toLowerCase(); 305 return path.toString().toLowerCase();
324 } 306 }
367 return cached; 349 return cached;
368 } 350 }
369 File f = new File(repoDir, path.toString()); 351 File f = new File(repoDir, path.toString());
370 if (f.exists()) { 352 if (f.exists()) {
371 RevlogStream s = new RevlogStream(dataAccess, f); 353 RevlogStream s = new RevlogStream(dataAccess, f);
372 streamsCache.put(path, new SoftReference<RevlogStream>(s)); 354 if (impl.shallCacheRevlogs()) {
355 streamsCache.put(path, new SoftReference<RevlogStream>(s));
356 }
373 return s; 357 return s;
374 } else { 358 } else {
375 if (shallFakeNonExistent) { 359 if (shallFakeNonExistent) {
376 try { 360 try {
377 File fake = File.createTempFile(f.getName(), null); 361 File fake = File.createTempFile(f.getName(), null);