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