comparison src/org/tmatesoft/hg/repo/HgManifest.java @ 607:66f1cc23b906

Refresh revlogs if a change to a file has been detected; do not force reload of the whole repository
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Tue, 07 May 2013 16:52:46 +0200
parents 8143c1f77d45
children e1b29756f901
comparison
equal deleted inserted replaced
606:5daa42067e7c 607:66f1cc23b906
53 */ 53 */
54 public final class HgManifest extends Revlog { 54 public final class HgManifest extends Revlog {
55 private RevisionMapper revisionMap; 55 private RevisionMapper revisionMap;
56 private final EncodingHelper encodingHelper; 56 private final EncodingHelper encodingHelper;
57 private final Path.Source pathFactory; 57 private final Path.Source pathFactory;
58 private final RevlogStream.Observer revisionMapCleaner = new RevlogStream.Observer() {
59 public void reloaded(RevlogStream src) {
60 revisionMap = null;
61 // TODO RevlogDerivedCache<T> class, to wrap revisionMap and super.revisionLookup
62 // and their respective cleanup observers, or any other all-in-one alternative
63 // not to keep both field and it's cleaner
64 }
65 };
58 66
59 /** 67 /**
60 * File flags recorded in manifest 68 * File flags recorded in manifest
61 */ 69 */
62 public enum Flags { 70 public enum Flags {
242 } 250 }
243 if (changesetRevisionIndex == HgRepository.WORKING_COPY || changesetRevisionIndex == HgRepository.BAD_REVISION) { 251 if (changesetRevisionIndex == HgRepository.WORKING_COPY || changesetRevisionIndex == HgRepository.BAD_REVISION) {
244 throw new HgInvalidRevisionException("Can't use constants like WORKING_COPY or BAD_REVISION", null, changesetRevisionIndex); 252 throw new HgInvalidRevisionException("Can't use constants like WORKING_COPY or BAD_REVISION", null, changesetRevisionIndex);
245 } 253 }
246 // revisionNumber == TIP is processed by RevisionMapper 254 // revisionNumber == TIP is processed by RevisionMapper
247 if (revisionMap == null) { 255 if (revisionMap == null || content.shallDropDerivedCaches()) {
248 revisionMap = new RevisionMapper(super.revisionLookup == null); 256 content.detach(revisionMapCleaner);
249 content.iterate(0, TIP, false, revisionMap); 257 final boolean buildOwnLookup = super.revisionLookup == null;
250 revisionMap.fixReusedManifests(); 258 RevisionMapper rmap = new RevisionMapper(buildOwnLookup);
251 if (super.useRevisionLookup && super.revisionLookup == null) { 259 content.iterate(0, TIP, false, rmap);
260 rmap.fixReusedManifests();
261 if (buildOwnLookup && super.useRevisionLookup) {
252 // reuse RevisionLookup if there's none yet 262 // reuse RevisionLookup if there's none yet
253 super.revisionLookup = revisionMap.manifestNodeids; 263 super.setRevisionLookup(rmap.manifestNodeids);
254 } 264 }
255 revisionMap.manifestNodeids = null; 265 rmap.manifestNodeids = null;
266 revisionMap = rmap;
267 // although in most cases modified manifest is accessed through one of the methods in this class
268 // and hence won't have a chance till this moment to be reloaded via revisionMapCleaner
269 // (RevlogStream sends events on attempt to read revlog, and so far we haven't tried to read anything,
270 // it's still reasonable to have this cleaner attached, just in case any method from Revlog base class
271 // has been called (e.g. getLastRevision())
272 content.attach(revisionMapCleaner);
256 } 273 }
257 return revisionMap.at(changesetRevisionIndex); 274 return revisionMap.at(changesetRevisionIndex);
258 } 275 }
259 276
260 /** 277 /**
330 assert resMap.size() <= 1; // size() == 0 if not found 347 assert resMap.size() <= 1; // size() == 0 if not found
331 // can't use changesetRevIndex as key - it might have been TIP 348 // can't use changesetRevIndex as key - it might have been TIP
332 return resMap.size() == 0 ? null : resMap.get(resMap.firstKey()); 349 return resMap.size() == 0 ? null : resMap.get(resMap.firstKey());
333 } 350 }
334 351
352
353 /*package-local*/ void dropCachesOnChangelogChange() {
354 // sort of a hack as it may happen that #fromChangelog()
355 // is invoked for modified repository where revisionMap still points to an old state
356 // Since there's no access to RevlogStream in #fromChangelog() if there's revisionMap
357 // in place, there's no chance for RevlogStream to detect the change and to dispatch
358 // change notification so that revisionMap got cleared.
359 revisionMap = null;
360 }
335 361
336 /** 362 /**
337 * @param changelogRevisionIndexes non-null 363 * @param changelogRevisionIndexes non-null
338 * @param inspector may be null if reporting of missing manifests is not needed 364 * @param inspector may be null if reporting of missing manifests is not needed
339 * @throws HgInvalidRevisionException if arguments specify non-existent revision index 365 * @throws HgInvalidRevisionException if arguments specify non-existent revision index