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;