Mercurial > jhg
comparison src/org/tmatesoft/hg/repo/HgManifest.java @ 414:bb278ccf9866
Pull changes from smartgit3 branch
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Wed, 21 Mar 2012 20:51:12 +0100 |
| parents | 7f27122011c3 63c5a9d7ca3f |
| children | ee8264d80747 |
comparison
equal
deleted
inserted
replaced
| 413:7f27122011c3 | 414:bb278ccf9866 |
|---|---|
| 50 * @author Artem Tikhomirov | 50 * @author Artem Tikhomirov |
| 51 * @author TMate Software Ltd. | 51 * @author TMate Software Ltd. |
| 52 */ | 52 */ |
| 53 public class HgManifest extends Revlog { | 53 public class HgManifest extends Revlog { |
| 54 private RevisionMapper revisionMap; | 54 private RevisionMapper revisionMap; |
| 55 private EncodingHelper encodingHelper; | |
| 55 | 56 |
| 56 public enum Flags { | 57 public enum Flags { |
| 57 Exec, Link; // FIXME REVISIT consider REGULAR instead of null | 58 Exec, Link; // FIXME REVISIT consider REGULAR instead of null |
| 58 | 59 |
| 59 static Flags parse(String flags) { | 60 static Flags parse(String flags) { |
| 94 } | 95 } |
| 95 throw new IllegalStateException(toString()); | 96 throw new IllegalStateException(toString()); |
| 96 } | 97 } |
| 97 } | 98 } |
| 98 | 99 |
| 99 /*package-local*/ HgManifest(HgRepository hgRepo, RevlogStream content) { | 100 /*package-local*/ HgManifest(HgRepository hgRepo, RevlogStream content, EncodingHelper eh) { |
| 100 super(hgRepo, content); | 101 super(hgRepo, content); |
| 102 encodingHelper = eh; | |
| 101 } | 103 } |
| 102 | 104 |
| 103 /** | 105 /** |
| 104 * Walks manifest revisions that correspond to specified range of changesets. The order in which manifest versions get reported | 106 * Walks manifest revisions that correspond to specified range of changesets. The order in which manifest versions get reported |
| 105 * to the inspector corresponds to physical order of manifest revisions, not that of changesets (with few exceptions as noted below). | 107 * to the inspector corresponds to physical order of manifest revisions, not that of changesets (with few exceptions as noted below). |
| 172 // there are tool-constructed repositories that got order of changeset revisions completely different from that of manifest | 174 // there are tool-constructed repositories that got order of changeset revisions completely different from that of manifest |
| 173 int x = manifestLast; | 175 int x = manifestLast; |
| 174 manifestLast = manifestFirst; | 176 manifestLast = manifestFirst; |
| 175 manifestFirst = x; | 177 manifestFirst = x; |
| 176 } | 178 } |
| 177 content.iterate(manifestFirst, manifestLast, true, new ManifestParser(inspector)); | 179 content.iterate(manifestFirst, manifestLast, true, new ManifestParser(inspector, encodingHelper)); |
| 178 } | 180 } |
| 179 | 181 |
| 180 /** | 182 /** |
| 181 * "Sparse" iteration of the manifest, more effective than accessing revisions one by one. | 183 * "Sparse" iteration of the manifest, more effective than accessing revisions one by one. |
| 182 * <p> Inspector is invoked for each changeset revision supplied, even when there's no manifest | 184 * <p> Inspector is invoked for each changeset revision supplied, even when there's no manifest |
| 192 public void walk(final Inspector inspector, int... revisionIndexes) throws HgInvalidRevisionException, HgInvalidControlFileException { | 194 public void walk(final Inspector inspector, int... revisionIndexes) throws HgInvalidRevisionException, HgInvalidControlFileException { |
| 193 if (inspector == null || revisionIndexes == null) { | 195 if (inspector == null || revisionIndexes == null) { |
| 194 throw new IllegalArgumentException(); | 196 throw new IllegalArgumentException(); |
| 195 } | 197 } |
| 196 int[] manifestRevs = toManifestRevisionIndexes(revisionIndexes, inspector); | 198 int[] manifestRevs = toManifestRevisionIndexes(revisionIndexes, inspector); |
| 197 content.iterate(manifestRevs, true, new ManifestParser(inspector)); | 199 content.iterate(manifestRevs, true, new ManifestParser(inspector, encodingHelper)); |
| 198 } | 200 } |
| 199 | 201 |
| 200 // | 202 // |
| 201 /** | 203 /** |
| 202 * Tells manifest revision number that corresponds to the given changeset. May return {@link HgRepository#BAD_REVISION} | 204 * Tells manifest revision number that corresponds to the given changeset. May return {@link HgRepository#BAD_REVISION} |
| 343 private static class PathProxy { | 345 private static class PathProxy { |
| 344 private byte[] data; | 346 private byte[] data; |
| 345 private int start; | 347 private int start; |
| 346 private final int hash, length; | 348 private final int hash, length; |
| 347 private Path result; | 349 private Path result; |
| 348 | 350 private final EncodingHelper encHelper; |
| 349 public PathProxy(byte[] data, int start, int length) { | 351 |
| 352 public PathProxy(byte[] data, int start, int length, EncodingHelper eh) { | |
| 350 this.data = data; | 353 this.data = data; |
| 351 this.start = start; | 354 this.start = start; |
| 352 this.length = length; | 355 this.length = length; |
| 356 this.encHelper = eh; | |
| 353 | 357 |
| 354 // copy from String.hashCode(). In fact, not necessarily match result of String(data).hashCode | 358 // copy from String.hashCode(). In fact, not necessarily match result of String(data).hashCode |
| 355 // just need some nice algorithm here | 359 // just need some nice algorithm here |
| 356 int h = 0; | 360 int h = 0; |
| 357 byte[] d = data; | 361 byte[] d = data; |
| 385 return hash; | 389 return hash; |
| 386 } | 390 } |
| 387 | 391 |
| 388 public Path freeze() { | 392 public Path freeze() { |
| 389 if (result == null) { | 393 if (result == null) { |
| 390 result = Path.create(EncodingHelper.fromManifest(data, start, length)); | 394 result = Path.create(encHelper.fromManifest(data, start, length)); |
| 391 // release reference to bigger data array, make a copy of relevant part only | 395 // release reference to bigger data array, make a copy of relevant part only |
| 392 // use original bytes, not those from String above to avoid cache misses due to different encodings | 396 // use original bytes, not those from String above to avoid cache misses due to different encodings |
| 393 byte[] d = new byte[length]; | 397 byte[] d = new byte[length]; |
| 394 System.arraycopy(data, start, d, 0, length); | 398 System.arraycopy(data, start, d, 0, length); |
| 395 data = d; | 399 data = d; |
| 405 private Pool2<Nodeid> nodeidPool, thisRevPool; | 409 private Pool2<Nodeid> nodeidPool, thisRevPool; |
| 406 private final Pool2<PathProxy> fnamePool; | 410 private final Pool2<PathProxy> fnamePool; |
| 407 private byte[] nodeidLookupBuffer = new byte[20]; // get reassigned each time new Nodeid is added to pool | 411 private byte[] nodeidLookupBuffer = new byte[20]; // get reassigned each time new Nodeid is added to pool |
| 408 private final ProgressSupport progressHelper; | 412 private final ProgressSupport progressHelper; |
| 409 private IterateControlMediator iterateControl; | 413 private IterateControlMediator iterateControl; |
| 414 private final EncodingHelper encHelper; | |
| 410 | 415 |
| 411 public ManifestParser(Inspector delegate) { | 416 public ManifestParser(Inspector delegate, EncodingHelper eh) { |
| 412 assert delegate != null; | 417 assert delegate != null; |
| 413 inspector = delegate; | 418 inspector = delegate; |
| 414 inspector2 = delegate instanceof Inspector2 ? (Inspector2) delegate : null; | 419 inspector2 = delegate instanceof Inspector2 ? (Inspector2) delegate : null; |
| 420 encHelper = eh; | |
| 415 nodeidPool = new Pool2<Nodeid>(); | 421 nodeidPool = new Pool2<Nodeid>(); |
| 416 fnamePool = new Pool2<PathProxy>(); | 422 fnamePool = new Pool2<PathProxy>(); |
| 417 thisRevPool = new Pool2<Nodeid>(); | 423 thisRevPool = new Pool2<Nodeid>(); |
| 418 progressHelper = ProgressSupport.Factory.get(delegate); | 424 progressHelper = ProgressSupport.Factory.get(delegate); |
| 419 } | 425 } |
| 433 byte[] data = da.byteArray(); | 439 byte[] data = da.byteArray(); |
| 434 for (i = 0; i < actualLen; i++) { | 440 for (i = 0; i < actualLen; i++) { |
| 435 int x = i; | 441 int x = i; |
| 436 for( ; data[i] != '\n' && i < actualLen; i++) { | 442 for( ; data[i] != '\n' && i < actualLen; i++) { |
| 437 if (fname == null && data[i] == 0) { | 443 if (fname == null && data[i] == 0) { |
| 438 PathProxy px = fnamePool.unify(new PathProxy(data, x, i - x)); | 444 PathProxy px = fnamePool.unify(new PathProxy(data, x, i - x, encHelper)); |
| 439 // if (cached = fnamePool.unify(px))== px then cacheMiss, else cacheHit | 445 // if (cached = fnamePool.unify(px))== px then cacheMiss, else cacheHit |
| 440 // cpython 0..10k: hits: 15 989 152, misses: 3020 | 446 // cpython 0..10k: hits: 15 989 152, misses: 3020 |
| 441 fname = px.freeze(); | 447 fname = px.freeze(); |
| 442 x = i+1; | 448 x = i+1; |
| 443 } | 449 } |
