Mercurial > hg4j
comparison src/org/tmatesoft/hg/repo/HgDataFile.java @ 388:b015f3918120
Work on FIXME: correct HgDataFile#workingCopy with tests; BasicSessionContext with property override; platform-specific options to internals
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Wed, 15 Feb 2012 22:57:56 +0100 |
parents | 994b5813a925 |
children | 0ae53c32ecef |
comparison
equal
deleted
inserted
replaced
387:cdea37239b01 | 388:b015f3918120 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2010-2011 TMate Software Ltd | 2 * Copyright (c) 2010-2012 TMate Software Ltd |
3 * | 3 * |
4 * This program is free software; you can redistribute it and/or modify | 4 * This program is free software; you can redistribute it and/or modify |
5 * it under the terms of the GNU General Public License as published by | 5 * it under the terms of the GNU General Public License as published by |
6 * the Free Software Foundation; version 2 of the License. | 6 * the Free Software Foundation; version 2 of the License. |
7 * | 7 * |
43 import org.tmatesoft.hg.internal.IntMap; | 43 import org.tmatesoft.hg.internal.IntMap; |
44 import org.tmatesoft.hg.internal.RevlogStream; | 44 import org.tmatesoft.hg.internal.RevlogStream; |
45 import org.tmatesoft.hg.util.ByteChannel; | 45 import org.tmatesoft.hg.util.ByteChannel; |
46 import org.tmatesoft.hg.util.CancelSupport; | 46 import org.tmatesoft.hg.util.CancelSupport; |
47 import org.tmatesoft.hg.util.CancelledException; | 47 import org.tmatesoft.hg.util.CancelledException; |
48 import org.tmatesoft.hg.util.LogFacility; | |
48 import org.tmatesoft.hg.util.Pair; | 49 import org.tmatesoft.hg.util.Pair; |
49 import org.tmatesoft.hg.util.Path; | 50 import org.tmatesoft.hg.util.Path; |
50 import org.tmatesoft.hg.util.ProgressSupport; | 51 import org.tmatesoft.hg.util.ProgressSupport; |
51 | 52 |
52 | 53 |
159 getRepo().getContext().getLog().info(getClass(), ex, null); | 160 getRepo().getContext().getLog().info(getClass(), ex, null); |
160 } | 161 } |
161 } | 162 } |
162 } | 163 } |
163 } else { | 164 } else { |
164 // FIXME not TIP, but revision according to dirstate!!! | 165 final Pair<Nodeid, Nodeid> wcParents = getRepo().getWorkingCopyParents(); |
165 // add tests for this case | 166 Nodeid p = wcParents.first().isNull() ? wcParents.second() : wcParents.first(); |
166 contentWithFilters(TIP, sink); | 167 if (p.isNull()) { |
168 // no dirstate parents - no content | |
169 return; | |
170 } | |
171 final HgChangelog clog = getRepo().getChangelog(); | |
172 // common case to avoid searching complete changelog for nodeid match | |
173 final Nodeid tipRev = clog.getRevision(TIP); | |
174 final int csetRevIndex; | |
175 if (tipRev.equals(p)) { | |
176 csetRevIndex = clog.getLastRevision(); | |
177 } else { | |
178 // bad luck, need to search honestly | |
179 csetRevIndex = getRepo().getChangelog().getRevisionIndex(p); | |
180 } | |
181 Nodeid fileRev = getRepo().getManifest().getFileRevision(csetRevIndex, getPath()); | |
182 final int fileRevIndex = getRevisionIndex(fileRev); | |
183 contentWithFilters(fileRevIndex, sink); | |
167 } | 184 } |
168 } | 185 } |
169 | 186 |
170 // public void content(int revision, ByteChannel sink, boolean applyFilters) throws HgDataStreamException, IOException, CancelledException { | 187 // public void content(int revision, ByteChannel sink, boolean applyFilters) throws HgDataStreamException, IOException, CancelledException { |
171 // byte[] content = content(revision); | 188 // byte[] content = content(revision); |
229 } | 246 } |
230 if (metadata == null) { | 247 if (metadata == null) { |
231 metadata = new Metadata(); | 248 metadata = new Metadata(); |
232 } | 249 } |
233 ErrorHandlingInspector insp; | 250 ErrorHandlingInspector insp; |
251 final LogFacility lf = getRepo().getContext().getLog(); | |
234 if (metadata.none(fileRevisionIndex)) { | 252 if (metadata.none(fileRevisionIndex)) { |
235 insp = new ContentPipe(sink, 0, getRepo().getContext().getLog()); | 253 insp = new ContentPipe(sink, 0, lf); |
236 } else if (metadata.known(fileRevisionIndex)) { | 254 } else if (metadata.known(fileRevisionIndex)) { |
237 insp = new ContentPipe(sink, metadata.dataOffset(fileRevisionIndex), getRepo().getContext().getLog()); | 255 insp = new ContentPipe(sink, metadata.dataOffset(fileRevisionIndex), lf); |
238 } else { | 256 } else { |
239 // do not know if there's metadata | 257 // do not know if there's metadata |
240 insp = new MetadataInspector(metadata, getPath(), new ContentPipe(sink, 0, getRepo().getContext().getLog())); | 258 insp = new MetadataInspector(metadata, lf, getPath(), new ContentPipe(sink, 0, lf)); |
241 } | 259 } |
242 insp.checkCancelled(); | 260 insp.checkCancelled(); |
243 super.content.iterate(fileRevisionIndex, fileRevisionIndex, true, insp); | 261 super.content.iterate(fileRevisionIndex, fileRevisionIndex, true, insp); |
244 try { | 262 try { |
245 insp.checkFailed(); // XXX is there real need to throw IOException from ContentPipe? | 263 insp.checkFailed(); // XXX is there real need to throw IOException from ContentPipe? |
507 } | 525 } |
508 | 526 |
509 private static final class MetadataEntry { | 527 private static final class MetadataEntry { |
510 private final String entry; | 528 private final String entry; |
511 private final int valueStart; | 529 private final int valueStart; |
530 | |
531 // key may be null | |
512 /*package-local*/MetadataEntry(String key, String value) { | 532 /*package-local*/MetadataEntry(String key, String value) { |
513 entry = key + value; | 533 if (key == null) { |
514 valueStart = key.length(); | 534 entry = value; |
535 valueStart = -1; // not 0 to tell between key == null and key == "" | |
536 } else { | |
537 entry = key + value; | |
538 valueStart = key.length(); | |
539 } | |
515 } | 540 } |
516 /*package-local*/boolean matchKey(String key) { | 541 /*package-local*/boolean matchKey(String key) { |
517 return key.length() == valueStart && entry.startsWith(key); | 542 return key == null ? valueStart == -1 : key.length() == valueStart && entry.startsWith(key); |
518 } | 543 } |
519 // uncomment once/if needed | 544 // uncomment once/if needed |
520 // public String key() { | 545 // public String key() { |
521 // return entry.substring(0, valueStart); | 546 // return entry.substring(0, valueStart); |
522 // } | 547 // } |
523 public String value() { | 548 public String value() { |
524 return entry.substring(valueStart); | 549 return valueStart == -1 ? entry : entry.substring(valueStart); |
525 } | 550 } |
526 } | 551 } |
527 | 552 |
528 private static class Metadata { | 553 private static class Metadata { |
529 private static class Record { | 554 private static class Record { |
588 } | 613 } |
589 } | 614 } |
590 | 615 |
591 private static class MetadataInspector extends ErrorHandlingInspector implements RevlogStream.Inspector { | 616 private static class MetadataInspector extends ErrorHandlingInspector implements RevlogStream.Inspector { |
592 private final Metadata metadata; | 617 private final Metadata metadata; |
593 private final Path fname; // need this only for error reporting | |
594 private final RevlogStream.Inspector delegate; | 618 private final RevlogStream.Inspector delegate; |
595 | 619 private final Path fname; // need these only for error reporting |
596 public MetadataInspector(Metadata _metadata, Path file, RevlogStream.Inspector chain) { | 620 private final LogFacility log; |
621 | |
622 public MetadataInspector(Metadata _metadata, LogFacility logFacility, Path file, RevlogStream.Inspector chain) { | |
597 metadata = _metadata; | 623 metadata = _metadata; |
598 fname = file; | 624 fname = file; |
625 log = logFacility; | |
599 delegate = chain; | 626 delegate = chain; |
600 setCancelSupport(CancelSupport.Factory.get(chain)); | 627 setCancelSupport(CancelSupport.Factory.get(chain)); |
601 } | 628 } |
602 | 629 |
603 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) throws HgException { | 630 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) throws HgException { |
645 // XXX is it possible to have here incomplete key/value (i.e. if last pair didn't end with \n) | 672 // XXX is it possible to have here incomplete key/value (i.e. if last pair didn't end with \n) |
646 // if yes, need to set metadataIsComplete to true in that case as well | 673 // if yes, need to set metadataIsComplete to true in that case as well |
647 break; | 674 break; |
648 } | 675 } |
649 if (key == null || lastColon == -1 || i <= lastColon) { | 676 if (key == null || lastColon == -1 || i <= lastColon) { |
650 throw new IllegalStateException(); // FIXME log instead and record null key in the metadata. Ex just to fail fast during dev | 677 log.error(getClass(), "Missing key in file revision metadata at index %d", i); |
651 } | 678 } |
652 value = new String(bos.toByteArray()).trim(); | 679 value = new String(bos.toByteArray()).trim(); |
653 bos.reset(); | 680 bos.reset(); |
654 _metadata.add(new MetadataEntry(key, value)); | 681 _metadata.add(new MetadataEntry(key, value)); |
655 key = value = null; | 682 key = value = null; |