comparison src/org/tmatesoft/hg/repo/HgManifest.java @ 412:63c5a9d7ca3f smartgit3

Follow-up for Issue 29: unify path translation for manifest and dirstate
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Wed, 21 Mar 2012 14:54:02 +0100
parents 6952d9ce97f1
children bb278ccf9866
comparison
equal deleted inserted replaced
411:464b4404e75d 412:63c5a9d7ca3f
49 * @author Artem Tikhomirov 49 * @author Artem Tikhomirov
50 * @author TMate Software Ltd. 50 * @author TMate Software Ltd.
51 */ 51 */
52 public class HgManifest extends Revlog { 52 public class HgManifest extends Revlog {
53 private RevisionMapper revisionMap; 53 private RevisionMapper revisionMap;
54 private EncodingHelper encodingHelper;
54 55
55 public enum Flags { 56 public enum Flags {
56 Exec, Link; 57 Exec, Link;
57 58
58 static Flags parse(String flags) { 59 static Flags parse(String flags) {
93 } 94 }
94 throw new IllegalStateException(toString()); 95 throw new IllegalStateException(toString());
95 } 96 }
96 } 97 }
97 98
98 /*package-local*/ HgManifest(HgRepository hgRepo, RevlogStream content) { 99 /*package-local*/ HgManifest(HgRepository hgRepo, RevlogStream content, EncodingHelper eh) {
99 super(hgRepo, content); 100 super(hgRepo, content);
101 encodingHelper = eh;
100 } 102 }
101 103
102 /** 104 /**
103 * Walks manifest revisions that correspond to specified range of changesets. The order in which manifest versions get reported 105 * Walks manifest revisions that correspond to specified range of changesets. The order in which manifest versions get reported
104 * to the inspector corresponds to physical order of manifest revisions, not that of changesets (with few exceptions as noted below). 106 * to the inspector corresponds to physical order of manifest revisions, not that of changesets (with few exceptions as noted below).
169 // there are tool-constructed repositories that got order of changeset revisions completely different from that of manifest 171 // there are tool-constructed repositories that got order of changeset revisions completely different from that of manifest
170 int x = manifestLast; 172 int x = manifestLast;
171 manifestLast = manifestFirst; 173 manifestLast = manifestFirst;
172 manifestFirst = x; 174 manifestFirst = x;
173 } 175 }
174 content.iterate(manifestFirst, manifestLast, true, new ManifestParser(inspector)); 176 content.iterate(manifestFirst, manifestLast, true, new ManifestParser(inspector, encodingHelper));
175 } 177 }
176 178
177 /** 179 /**
178 * "Sparse" iteration of the manifest, more effective than accessing revisions one by one. 180 * "Sparse" iteration of the manifest, more effective than accessing revisions one by one.
179 * <p> Inspector is invoked for each changeset revision supplied, even when there's no manifest 181 * <p> Inspector is invoked for each changeset revision supplied, even when there's no manifest
187 public void walk(final Inspector inspector, int... revisionIndexes) throws HgInvalidControlFileException{ 189 public void walk(final Inspector inspector, int... revisionIndexes) throws HgInvalidControlFileException{
188 if (inspector == null || revisionIndexes == null) { 190 if (inspector == null || revisionIndexes == null) {
189 throw new IllegalArgumentException(); 191 throw new IllegalArgumentException();
190 } 192 }
191 int[] manifestRevs = toManifestRevisionIndexes(revisionIndexes, inspector); 193 int[] manifestRevs = toManifestRevisionIndexes(revisionIndexes, inspector);
192 content.iterate(manifestRevs, true, new ManifestParser(inspector)); 194 content.iterate(manifestRevs, true, new ManifestParser(inspector, encodingHelper));
193 } 195 }
194 196
195 // 197 //
196 /** 198 /**
197 * Tells manifest revision number that corresponds to the given changeset. 199 * Tells manifest revision number that corresponds to the given changeset.
329 private static class PathProxy { 331 private static class PathProxy {
330 private byte[] data; 332 private byte[] data;
331 private int start; 333 private int start;
332 private final int hash, length; 334 private final int hash, length;
333 private Path result; 335 private Path result;
334 336 private final EncodingHelper encHelper;
335 public PathProxy(byte[] data, int start, int length) { 337
338 public PathProxy(byte[] data, int start, int length, EncodingHelper eh) {
336 this.data = data; 339 this.data = data;
337 this.start = start; 340 this.start = start;
338 this.length = length; 341 this.length = length;
342 this.encHelper = eh;
339 343
340 // copy from String.hashCode(). In fact, not necessarily match result of String(data).hashCode 344 // copy from String.hashCode(). In fact, not necessarily match result of String(data).hashCode
341 // just need some nice algorithm here 345 // just need some nice algorithm here
342 int h = 0; 346 int h = 0;
343 byte[] d = data; 347 byte[] d = data;
371 return hash; 375 return hash;
372 } 376 }
373 377
374 public Path freeze() { 378 public Path freeze() {
375 if (result == null) { 379 if (result == null) {
376 result = Path.create(EncodingHelper.fromManifest(data, start, length)); 380 result = Path.create(encHelper.fromManifest(data, start, length));
377 // release reference to bigger data array, make a copy of relevant part only 381 // release reference to bigger data array, make a copy of relevant part only
378 // use original bytes, not those from String above to avoid cache misses due to different encodings 382 // use original bytes, not those from String above to avoid cache misses due to different encodings
379 byte[] d = new byte[length]; 383 byte[] d = new byte[length];
380 System.arraycopy(data, start, d, 0, length); 384 System.arraycopy(data, start, d, 0, length);
381 data = d; 385 data = d;
391 private Pool2<Nodeid> nodeidPool, thisRevPool; 395 private Pool2<Nodeid> nodeidPool, thisRevPool;
392 private final Pool2<PathProxy> fnamePool; 396 private final Pool2<PathProxy> fnamePool;
393 private byte[] nodeidLookupBuffer = new byte[20]; // get reassigned each time new Nodeid is added to pool 397 private byte[] nodeidLookupBuffer = new byte[20]; // get reassigned each time new Nodeid is added to pool
394 private final ProgressSupport progressHelper; 398 private final ProgressSupport progressHelper;
395 private IterateControlMediator iterateControl; 399 private IterateControlMediator iterateControl;
400 private final EncodingHelper encHelper;
396 401
397 public ManifestParser(Inspector delegate) { 402 public ManifestParser(Inspector delegate, EncodingHelper eh) {
398 assert delegate != null; 403 assert delegate != null;
399 inspector = delegate; 404 inspector = delegate;
400 inspector2 = delegate instanceof Inspector2 ? (Inspector2) delegate : null; 405 inspector2 = delegate instanceof Inspector2 ? (Inspector2) delegate : null;
406 encHelper = eh;
401 nodeidPool = new Pool2<Nodeid>(); 407 nodeidPool = new Pool2<Nodeid>();
402 fnamePool = new Pool2<PathProxy>(); 408 fnamePool = new Pool2<PathProxy>();
403 thisRevPool = new Pool2<Nodeid>(); 409 thisRevPool = new Pool2<Nodeid>();
404 progressHelper = ProgressSupport.Factory.get(delegate); 410 progressHelper = ProgressSupport.Factory.get(delegate);
405 } 411 }
419 byte[] data = da.byteArray(); 425 byte[] data = da.byteArray();
420 for (i = 0; i < actualLen; i++) { 426 for (i = 0; i < actualLen; i++) {
421 int x = i; 427 int x = i;
422 for( ; data[i] != '\n' && i < actualLen; i++) { 428 for( ; data[i] != '\n' && i < actualLen; i++) {
423 if (fname == null && data[i] == 0) { 429 if (fname == null && data[i] == 0) {
424 PathProxy px = fnamePool.unify(new PathProxy(data, x, i - x)); 430 PathProxy px = fnamePool.unify(new PathProxy(data, x, i - x, encHelper));
425 // if (cached = fnamePool.unify(px))== px then cacheMiss, else cacheHit 431 // if (cached = fnamePool.unify(px))== px then cacheMiss, else cacheHit
426 // cpython 0..10k: hits: 15 989 152, misses: 3020 432 // cpython 0..10k: hits: 15 989 152, misses: 3020
427 fname = px.freeze(); 433 fname = px.freeze();
428 x = i+1; 434 x = i+1;
429 } 435 }