annotate hg4j/src/main/java/org/tmatesoft/hg/repo/HgDataFile.java @ 213:6ec4af642ba8 gradle

Project uses Gradle for build - actual changes
author Alexander Kitaev <kitaev@gmail.com>
date Tue, 10 May 2011 10:52:53 +0200
parents
children
rev   line source
213
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
1 /*
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
2 * Copyright (c) 2010-2011 TMate Software Ltd
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
3 *
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
4 * This program is free software; you can redistribute it and/or modify
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
5 * it under the terms of the GNU General Public License as published by
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
6 * the Free Software Foundation; version 2 of the License.
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
7 *
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
8 * This program is distributed in the hope that it will be useful,
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
11 * GNU General Public License for more details.
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
12 *
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
13 * For information on how to redistribute this software under
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
14 * the terms of a license other than GNU General Public License
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
15 * contact TMate Software at support@hg4j.com
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
16 */
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
17 package org.tmatesoft.hg.repo;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
18
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
19 import static org.tmatesoft.hg.repo.HgInternals.wrongLocalRevision;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
20 import static org.tmatesoft.hg.repo.HgRepository.*;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
21
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
22 import java.io.ByteArrayOutputStream;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
23 import java.io.IOException;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
24 import java.nio.ByteBuffer;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
25 import java.util.ArrayList;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
26 import java.util.Collection;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
27 import java.util.TreeMap;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
28
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
29 import org.tmatesoft.hg.core.HgDataStreamException;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
30 import org.tmatesoft.hg.core.HgException;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
31 import org.tmatesoft.hg.core.Nodeid;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
32 import org.tmatesoft.hg.internal.DataAccess;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
33 import org.tmatesoft.hg.internal.FilterByteChannel;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
34 import org.tmatesoft.hg.internal.RevlogStream;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
35 import org.tmatesoft.hg.util.ByteChannel;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
36 import org.tmatesoft.hg.util.CancelledException;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
37 import org.tmatesoft.hg.util.Path;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
38
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
39
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
40
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
41 /**
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
42 * ? name:HgFileNode?
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
43 *
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
44 * @author Artem Tikhomirov
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
45 * @author TMate Software Ltd.
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
46 */
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
47 public class HgDataFile extends Revlog {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
48
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
49 // absolute from repo root?
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
50 // slashes, unix-style?
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
51 // repo location agnostic, just to give info to user, not to access real storage
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
52 private final Path path;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
53 private Metadata metadata; // get initialized on first access to file content.
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
54
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
55 /*package-local*/HgDataFile(HgRepository hgRepo, Path filePath, RevlogStream content) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
56 super(hgRepo, content);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
57 path = filePath;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
58 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
59
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
60 /*package-local*/HgDataFile(HgRepository hgRepo, Path filePath) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
61 super(hgRepo);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
62 path = filePath;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
63 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
64
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
65 // exists is not the best name possible. now it means no file with such name was ever known to the repo.
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
66 // it might be confused with files existed before but lately removed.
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
67 public boolean exists() {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
68 return content != null; // XXX need better impl
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
69 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
70
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
71 // human-readable (i.e. "COPYING", not "store/data/_c_o_p_y_i_n_g.i")
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
72 public Path getPath() {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
73 return path; // hgRepo.backresolve(this) -> name? In this case, what about hashed long names?
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
74 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
75
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
76 public int length(Nodeid nodeid) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
77 return content.dataLength(getLocalRevision(nodeid));
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
78 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
79
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
80 public void workingCopy(ByteChannel sink) throws IOException, CancelledException {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
81 throw HgRepository.notImplemented();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
82 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
83
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
84 // public void content(int revision, ByteChannel sink, boolean applyFilters) throws HgDataStreamException, IOException, CancelledException {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
85 // byte[] content = content(revision);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
86 // final CancelSupport cancelSupport = CancelSupport.Factory.get(sink);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
87 // final ProgressSupport progressSupport = ProgressSupport.Factory.get(sink);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
88 // ByteBuffer buf = ByteBuffer.allocate(512);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
89 // int left = content.length;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
90 // progressSupport.start(left);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
91 // int offset = 0;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
92 // cancelSupport.checkCancelled();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
93 // ByteChannel _sink = applyFilters ? new FilterByteChannel(sink, getRepo().getFiltersFromRepoToWorkingDir(getPath())) : sink;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
94 // do {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
95 // buf.put(content, offset, Math.min(left, buf.remaining()));
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
96 // buf.flip();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
97 // cancelSupport.checkCancelled();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
98 // // XXX I may not rely on returned number of bytes but track change in buf position instead.
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
99 // int consumed = _sink.write(buf);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
100 // buf.compact();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
101 // offset += consumed;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
102 // left -= consumed;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
103 // progressSupport.worked(consumed);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
104 // } while (left > 0);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
105 // progressSupport.done(); // XXX shall specify whether #done() is invoked always or only if completed successfully.
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
106 // }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
107
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
108 /*XXX not sure distinct method contentWithFilters() is the best way to do, perhaps, callers shall add filters themselves?*/
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
109 public void contentWithFilters(int revision, ByteChannel sink) throws HgDataStreamException, IOException, CancelledException {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
110 content(revision, new FilterByteChannel(sink, getRepo().getFiltersFromRepoToWorkingDir(getPath())));
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
111 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
112
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
113 // for data files need to check heading of the file content for possible metadata
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
114 // @see http://mercurial.selenic.com/wiki/FileFormats#data.2BAC8-
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
115 public void content(int revision, ByteChannel sink) throws HgDataStreamException, IOException, CancelledException {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
116 if (revision == TIP) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
117 revision = getLastRevision();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
118 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
119 if (revision == WORKING_COPY) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
120 workingCopy(sink);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
121 return;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
122 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
123 if (wrongLocalRevision(revision) || revision == BAD_REVISION) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
124 throw new IllegalArgumentException(String.valueOf(revision));
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
125 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
126 if (sink == null) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
127 throw new IllegalArgumentException();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
128 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
129 if (metadata == null) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
130 metadata = new Metadata();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
131 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
132 ContentPipe insp;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
133 if (metadata.none(revision)) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
134 insp = new ContentPipe(sink, 0);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
135 } else if (metadata.known(revision)) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
136 insp = new ContentPipe(sink, metadata.dataOffset(revision));
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
137 } else {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
138 // do not know if there's metadata
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
139 insp = new MetadataContentPipe(sink, metadata);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
140 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
141 insp.checkCancelled();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
142 super.content.iterate(revision, revision, true, insp);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
143 try {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
144 insp.checkFailed();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
145 } catch (HgDataStreamException ex) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
146 throw ex;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
147 } catch (HgException ex) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
148 // shall not happen, unless we changed ContentPipe or its subclass
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
149 throw new HgDataStreamException(ex.getClass().getName(), ex);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
150 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
151 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
152
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
153 public void history(HgChangelog.Inspector inspector) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
154 history(0, getLastRevision(), inspector);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
155 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
156
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
157 public void history(int start, int end, HgChangelog.Inspector inspector) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
158 if (!exists()) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
159 throw new IllegalStateException("Can't get history of invalid repository file node");
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
160 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
161 final int last = getLastRevision();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
162 if (start < 0 || start > last) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
163 throw new IllegalArgumentException();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
164 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
165 if (end == TIP) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
166 end = last;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
167 } else if (end < start || end > last) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
168 throw new IllegalArgumentException();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
169 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
170 final int[] commitRevisions = new int[end - start + 1];
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
171 RevlogStream.Inspector insp = new RevlogStream.Inspector() {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
172 int count = 0;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
173
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
174 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
175 commitRevisions[count++] = linkRevision;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
176 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
177 };
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
178 content.iterate(start, end, false, insp);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
179 getRepo().getChangelog().range(inspector, commitRevisions);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
180 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
181
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
182 // for a given local revision of the file, find out local revision in the changelog
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
183 public int getChangesetLocalRevision(int revision) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
184 return content.linkRevision(revision);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
185 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
186
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
187 public Nodeid getChangesetRevision(Nodeid nid) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
188 int changelogRevision = getChangesetLocalRevision(getLocalRevision(nid));
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
189 return getRepo().getChangelog().getRevision(changelogRevision);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
190 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
191
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
192 public boolean isCopy() throws HgDataStreamException {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
193 if (metadata == null || !metadata.checked(0)) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
194 // content() always initializes metadata.
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
195 // FIXME this is expensive way to find out metadata, distinct RevlogStream.Iterator would be better.
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
196 // Alternatively, may parameterize MetadataContentPipe to do prepare only.
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
197 // For reference, when throwing CancelledException, hg status -A --rev 3:80 takes 70 ms
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
198 // however, if we just consume buffer instead (buffer.position(buffer.limit()), same command takes ~320ms
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
199 // (compared to command-line counterpart of 190ms)
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
200 try {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
201 content(0, new ByteChannel() { // No-op channel
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
202 public int write(ByteBuffer buffer) throws IOException, CancelledException {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
203 // pretend we consumed whole buffer
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
204 // int rv = buffer.remaining();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
205 // buffer.position(buffer.limit());
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
206 // return rv;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
207 throw new CancelledException();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
208 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
209 });
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
210 } catch (CancelledException ex) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
211 // it's ok, we did that
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
212 } catch (Exception ex) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
213 throw new HgDataStreamException("Can't initialize metadata", ex);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
214 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
215 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
216 if (!metadata.known(0)) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
217 return false;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
218 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
219 return metadata.find(0, "copy") != null;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
220 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
221
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
222 public Path getCopySourceName() throws HgDataStreamException {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
223 if (isCopy()) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
224 return Path.create(metadata.find(0, "copy"));
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
225 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
226 throw new UnsupportedOperationException(); // XXX REVISIT, think over if Exception is good (clients would check isCopy() anyway, perhaps null is sufficient?)
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
227 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
228
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
229 public Nodeid getCopySourceRevision() throws HgDataStreamException {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
230 if (isCopy()) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
231 return Nodeid.fromAscii(metadata.find(0, "copyrev")); // XXX reuse/cache Nodeid
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
232 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
233 throw new UnsupportedOperationException();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
234 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
235
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
236 @Override
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
237 public String toString() {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
238 StringBuilder sb = new StringBuilder(getClass().getSimpleName());
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
239 sb.append('(');
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
240 sb.append(getPath());
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
241 sb.append(')');
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
242 return sb.toString();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
243 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
244
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
245 private static final class MetadataEntry {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
246 private final String entry;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
247 private final int valueStart;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
248 /*package-local*/MetadataEntry(String key, String value) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
249 entry = key + value;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
250 valueStart = key.length();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
251 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
252 /*package-local*/boolean matchKey(String key) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
253 return key.length() == valueStart && entry.startsWith(key);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
254 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
255 // uncomment once/if needed
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
256 // public String key() {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
257 // return entry.substring(0, valueStart);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
258 // }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
259 public String value() {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
260 return entry.substring(valueStart);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
261 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
262 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
263
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
264 private static class Metadata {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
265 // XXX sparse array needed
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
266 private final TreeMap<Integer, Integer> offsets = new TreeMap<Integer, Integer>();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
267 private final TreeMap<Integer, MetadataEntry[]> entries = new TreeMap<Integer, MetadataEntry[]>();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
268
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
269 private final Integer NONE = new Integer(-1); // do not duplicate -1 integers at least within single file (don't want statics)
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
270
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
271 // true when there's metadata for given revision
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
272 boolean known(int revision) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
273 Integer i = offsets.get(revision);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
274 return i != null && NONE != i;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
275 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
276
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
277 // true when revision has been checked for metadata presence.
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
278 public boolean checked(int revision) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
279 return offsets.containsKey(revision);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
280 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
281
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
282 // true when revision has been checked and found not having any metadata
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
283 boolean none(int revision) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
284 Integer i = offsets.get(revision);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
285 return i == NONE;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
286 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
287
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
288 // mark revision as having no metadata.
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
289 void recordNone(int revision) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
290 Integer i = offsets.get(revision);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
291 if (i == NONE) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
292 return; // already there
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
293 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
294 if (i != null) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
295 throw new IllegalStateException(String.format("Trying to override Metadata state for revision %d (known offset: %d)", revision, i));
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
296 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
297 offsets.put(revision, NONE);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
298 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
299
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
300 // since this is internal class, callers are supposed to ensure arg correctness (i.e. ask known() before)
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
301 int dataOffset(int revision) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
302 return offsets.get(revision);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
303 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
304 void add(int revision, int dataOffset, Collection<MetadataEntry> e) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
305 assert !offsets.containsKey(revision);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
306 offsets.put(revision, dataOffset);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
307 entries.put(revision, e.toArray(new MetadataEntry[e.size()]));
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
308 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
309 String find(int revision, String key) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
310 for (MetadataEntry me : entries.get(revision)) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
311 if (me.matchKey(key)) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
312 return me.value();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
313 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
314 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
315 return null;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
316 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
317 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
318
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
319 private static class MetadataContentPipe extends ContentPipe {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
320
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
321 private final Metadata metadata;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
322
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
323 public MetadataContentPipe(ByteChannel sink, Metadata _metadata) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
324 super(sink, 0);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
325 metadata = _metadata;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
326 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
327
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
328 @Override
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
329 protected void prepare(int revisionNumber, DataAccess da) throws HgException, IOException {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
330 final int daLength = da.length();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
331 if (daLength < 4 || da.readByte() != 1 || da.readByte() != 10) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
332 metadata.recordNone(revisionNumber);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
333 da.reset();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
334 return;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
335 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
336 int lastEntryStart = 2;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
337 int lastColon = -1;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
338 ArrayList<MetadataEntry> _metadata = new ArrayList<MetadataEntry>();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
339 // XXX in fact, need smth like ByteArrayBuilder, similar to StringBuilder,
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
340 // which can't be used here because we can't convert bytes to chars as we read them
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
341 // (there might be multi-byte encoding), and we need to collect all bytes before converting to string
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
342 ByteArrayOutputStream bos = new ByteArrayOutputStream();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
343 String key = null, value = null;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
344 boolean byteOne = false;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
345 for (int i = 2; i < daLength; i++) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
346 byte b = da.readByte();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
347 if (b == '\n') {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
348 if (byteOne) { // i.e. \n follows 1
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
349 lastEntryStart = i+1;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
350 // XXX is it possible to have here incomplete key/value (i.e. if last pair didn't end with \n)
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
351 break;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
352 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
353 if (key == null || lastColon == -1 || i <= lastColon) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
354 throw new IllegalStateException(); // FIXME log instead and record null key in the metadata. Ex just to fail fast during dev
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
355 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
356 value = new String(bos.toByteArray()).trim();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
357 bos.reset();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
358 _metadata.add(new MetadataEntry(key, value));
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
359 key = value = null;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
360 lastColon = -1;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
361 lastEntryStart = i+1;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
362 continue;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
363 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
364 // byteOne has to be consumed up to this line, if not jet, consume it
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
365 if (byteOne) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
366 // insert 1 we've read on previous step into the byte builder
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
367 bos.write(1);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
368 // fall-through to consume current byte
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
369 byteOne = false;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
370 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
371 if (b == (int) ':') {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
372 assert value == null;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
373 key = new String(bos.toByteArray());
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
374 bos.reset();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
375 lastColon = i;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
376 } else if (b == 1) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
377 byteOne = true;
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
378 } else {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
379 bos.write(b);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
380 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
381 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
382 _metadata.trimToSize();
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
383 metadata.add(revisionNumber, lastEntryStart, _metadata);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
384 if (da.isEmpty() || !byteOne) {
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
385 throw new HgDataStreamException(String.format("Metadata for revision %d is not closed properly", revisionNumber), null);
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
386 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
387 // da is in prepared state (i.e. we consumed all bytes up to metadata end).
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
388 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
389 }
6ec4af642ba8 Project uses Gradle for build - actual changes
Alexander Kitaev <kitaev@gmail.com>
parents:
diff changeset
390 }