Mercurial > hg4j
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 } |