Mercurial > jhg
comparison src/org/tmatesoft/hg/internal/CommitFacility.java @ 618:7c0d2ce340b8
Refactor approach how content finds it way down to a commit revision
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Thu, 16 May 2013 19:46:13 +0200 |
parents | 65c01508f002 |
children | 868b2ffdcd5c |
comparison
equal
deleted
inserted
replaced
617:65c01508f002 | 618:7c0d2ce340b8 |
---|---|
23 import static org.tmatesoft.hg.util.LogFacility.Severity.Error; | 23 import static org.tmatesoft.hg.util.LogFacility.Severity.Error; |
24 | 24 |
25 import java.io.File; | 25 import java.io.File; |
26 import java.io.FileOutputStream; | 26 import java.io.FileOutputStream; |
27 import java.io.IOException; | 27 import java.io.IOException; |
28 import java.nio.ByteBuffer; | |
29 import java.util.ArrayList; | 28 import java.util.ArrayList; |
30 import java.util.HashMap; | 29 import java.util.HashMap; |
31 import java.util.LinkedHashMap; | 30 import java.util.LinkedHashMap; |
32 import java.util.Map; | 31 import java.util.Map; |
33 import java.util.Set; | 32 import java.util.Set; |
36 | 35 |
37 import org.tmatesoft.hg.core.HgCommitCommand; | 36 import org.tmatesoft.hg.core.HgCommitCommand; |
38 import org.tmatesoft.hg.core.HgIOException; | 37 import org.tmatesoft.hg.core.HgIOException; |
39 import org.tmatesoft.hg.core.HgRepositoryLockException; | 38 import org.tmatesoft.hg.core.HgRepositoryLockException; |
40 import org.tmatesoft.hg.core.Nodeid; | 39 import org.tmatesoft.hg.core.Nodeid; |
40 import org.tmatesoft.hg.internal.DataSerializer.DataSource; | |
41 import org.tmatesoft.hg.repo.HgChangelog; | 41 import org.tmatesoft.hg.repo.HgChangelog; |
42 import org.tmatesoft.hg.repo.HgDataFile; | 42 import org.tmatesoft.hg.repo.HgDataFile; |
43 import org.tmatesoft.hg.util.Pair; | 43 import org.tmatesoft.hg.util.Pair; |
44 import org.tmatesoft.hg.util.Path; | 44 import org.tmatesoft.hg.util.Path; |
45 | 45 |
51 * @author TMate Software Ltd. | 51 * @author TMate Software Ltd. |
52 */ | 52 */ |
53 public final class CommitFacility { | 53 public final class CommitFacility { |
54 private final Internals repo; | 54 private final Internals repo; |
55 private final int p1Commit, p2Commit; | 55 private final int p1Commit, p2Commit; |
56 private Map<Path, Pair<HgDataFile, ByteDataSupplier>> files = new LinkedHashMap<Path, Pair<HgDataFile, ByteDataSupplier>>(); | 56 private Map<Path, Pair<HgDataFile, DataSource>> files = new LinkedHashMap<Path, Pair<HgDataFile, DataSource>>(); |
57 private Set<Path> removals = new TreeSet<Path>(); | 57 private Set<Path> removals = new TreeSet<Path>(); |
58 private String branch, user; | 58 private String branch, user; |
59 | 59 |
60 public CommitFacility(Internals hgRepo, int parentCommit) { | 60 public CommitFacility(Internals hgRepo, int parentCommit) { |
61 this(hgRepo, parentCommit, NO_REVISION); | 61 this(hgRepo, parentCommit, NO_REVISION); |
72 | 72 |
73 public boolean isMerge() { | 73 public boolean isMerge() { |
74 return p1Commit != NO_REVISION && p2Commit != NO_REVISION; | 74 return p1Commit != NO_REVISION && p2Commit != NO_REVISION; |
75 } | 75 } |
76 | 76 |
77 public void add(HgDataFile dataFile, ByteDataSupplier content) { | 77 public void add(HgDataFile dataFile, DataSource content) { |
78 if (content == null) { | 78 if (content == null) { |
79 throw new IllegalArgumentException(); | 79 throw new IllegalArgumentException(); |
80 } | 80 } |
81 removals.remove(dataFile.getPath()); | 81 removals.remove(dataFile.getPath()); |
82 files.put(dataFile.getPath(), new Pair<HgDataFile, ByteDataSupplier>(dataFile, content)); | 82 files.put(dataFile.getPath(), new Pair<HgDataFile, DataSource>(dataFile, content)); |
83 } | 83 } |
84 | 84 |
85 public void forget(HgDataFile dataFile) { | 85 public void forget(HgDataFile dataFile) { |
86 files.remove(dataFile.getPath()); | 86 files.remove(dataFile.getPath()); |
87 removals.add(dataFile.getPath()); | 87 removals.add(dataFile.getPath()); |
136 } | 136 } |
137 // | 137 // |
138 // Register new/changed | 138 // Register new/changed |
139 LinkedHashMap<Path, RevlogStream> newlyAddedFiles = new LinkedHashMap<Path, RevlogStream>(); | 139 LinkedHashMap<Path, RevlogStream> newlyAddedFiles = new LinkedHashMap<Path, RevlogStream>(); |
140 ArrayList<Path> touchInDirstate = new ArrayList<Path>(); | 140 ArrayList<Path> touchInDirstate = new ArrayList<Path>(); |
141 for (Pair<HgDataFile, ByteDataSupplier> e : files.values()) { | 141 for (Pair<HgDataFile, DataSource> e : files.values()) { |
142 HgDataFile df = e.first(); | 142 HgDataFile df = e.first(); |
143 DataSource bds = e.second(); | |
143 Pair<Integer, Integer> fp = fileParents.get(df.getPath()); | 144 Pair<Integer, Integer> fp = fileParents.get(df.getPath()); |
144 if (fp == null) { | 145 if (fp == null) { |
145 // NEW FILE | 146 // NEW FILE |
146 fp = new Pair<Integer, Integer>(NO_REVISION, NO_REVISION); | 147 fp = new Pair<Integer, Integer>(NO_REVISION, NO_REVISION); |
147 } | |
148 ByteDataSupplier bds = e.second(); | |
149 // FIXME quickfix, instead, pass ByteDataSupplier directly to RevlogStreamWriter | |
150 ByteBuffer bb = ByteBuffer.allocate(2048); | |
151 ByteArrayChannel bac = new ByteArrayChannel(); | |
152 while (bds.read(bb) != -1) { | |
153 bb.flip(); | |
154 bac.write(bb); | |
155 bb.clear(); | |
156 } | 148 } |
157 RevlogStream contentStream; | 149 RevlogStream contentStream; |
158 if (df.exists()) { | 150 if (df.exists()) { |
159 contentStream = repo.getImplAccess().getStream(df); | 151 contentStream = repo.getImplAccess().getStream(df); |
160 } else { | 152 } else { |
163 // FIXME df doesn't get df.content updated, and clients | 155 // FIXME df doesn't get df.content updated, and clients |
164 // that would attempt to access newly added file after commit would fail | 156 // that would attempt to access newly added file after commit would fail |
165 // (despite the fact the file is in there) | 157 // (despite the fact the file is in there) |
166 } | 158 } |
167 RevlogStreamWriter fileWriter = new RevlogStreamWriter(repo, contentStream, transaction); | 159 RevlogStreamWriter fileWriter = new RevlogStreamWriter(repo, contentStream, transaction); |
168 Nodeid fileRev = fileWriter.addRevision(bac.toArray(), clogRevisionIndex, fp.first(), fp.second()); | 160 Nodeid fileRev = fileWriter.addRevision(bds, clogRevisionIndex, fp.first(), fp.second()); |
169 newManifestRevision.put(df.getPath(), fileRev); | 161 newManifestRevision.put(df.getPath(), fileRev); |
170 touchInDirstate.add(df.getPath()); | 162 touchInDirstate.add(df.getPath()); |
171 } | 163 } |
172 // | 164 // |
173 // Manifest | 165 // Manifest |
174 final ManifestEntryBuilder manifestBuilder = new ManifestEntryBuilder(); | 166 final ManifestEntryBuilder manifestBuilder = new ManifestEntryBuilder(repo.buildFileNameEncodingHelper()); |
175 for (Map.Entry<Path, Nodeid> me : newManifestRevision.entrySet()) { | 167 for (Map.Entry<Path, Nodeid> me : newManifestRevision.entrySet()) { |
176 manifestBuilder.add(me.getKey().toString(), me.getValue()); | 168 manifestBuilder.add(me.getKey().toString(), me.getValue()); |
177 } | 169 } |
178 RevlogStreamWriter manifestWriter = new RevlogStreamWriter(repo, repo.getImplAccess().getManifestStream(), transaction); | 170 RevlogStreamWriter manifestWriter = new RevlogStreamWriter(repo, repo.getImplAccess().getManifestStream(), transaction); |
179 Nodeid manifestRev = manifestWriter.addRevision(manifestBuilder.build(), clogRevisionIndex, manifestParents.first(), manifestParents.second()); | 171 Nodeid manifestRev = manifestWriter.addRevision(manifestBuilder, clogRevisionIndex, manifestParents.first(), manifestParents.second()); |
180 // | 172 // |
181 // Changelog | 173 // Changelog |
182 final ChangelogEntryBuilder changelogBuilder = new ChangelogEntryBuilder(); | 174 final ChangelogEntryBuilder changelogBuilder = new ChangelogEntryBuilder(); |
183 changelogBuilder.setModified(files.keySet()); | 175 changelogBuilder.setModified(files.keySet()); |
184 changelogBuilder.branch(branch == null ? DEFAULT_BRANCH_NAME : branch); | 176 changelogBuilder.branch(branch == null ? DEFAULT_BRANCH_NAME : branch); |
185 changelogBuilder.user(String.valueOf(user)); | 177 changelogBuilder.user(String.valueOf(user)); |
186 byte[] clogContent = changelogBuilder.build(manifestRev, message); | 178 changelogBuilder.manifest(manifestRev).comment(message); |
187 RevlogStreamWriter changelogWriter = new RevlogStreamWriter(repo, repo.getImplAccess().getChangelogStream(), transaction); | 179 RevlogStreamWriter changelogWriter = new RevlogStreamWriter(repo, repo.getImplAccess().getChangelogStream(), transaction); |
188 Nodeid changesetRev = changelogWriter.addRevision(clogContent, clogRevisionIndex, p1Commit, p2Commit); | 180 Nodeid changesetRev = changelogWriter.addRevision(changelogBuilder, clogRevisionIndex, p1Commit, p2Commit); |
189 // TODO move fncache update to an external facility, along with dirstate and bookmark update | 181 // TODO move fncache update to an external facility, along with dirstate and bookmark update |
190 if (!newlyAddedFiles.isEmpty() && repo.fncacheInUse()) { | 182 if (!newlyAddedFiles.isEmpty() && repo.fncacheInUse()) { |
191 FNCacheFile fncache = new FNCacheFile(repo); | 183 FNCacheFile fncache = new FNCacheFile(repo); |
192 for (Path p : newlyAddedFiles.keySet()) { | 184 for (Path p : newlyAddedFiles.keySet()) { |
193 fncache.addIndex(p); | 185 fncache.addIndex(p); |
263 return NO_REVISION; | 255 return NO_REVISION; |
264 } | 256 } |
265 return repo.getManifest().getRevisionIndex(manifestRev); | 257 return repo.getManifest().getRevisionIndex(manifestRev); |
266 } | 258 } |
267 */ | 259 */ |
268 | |
269 // unlike DataAccess (which provides structured access), this one | |
270 // deals with a sequence of bytes, when there's no need in structure of the data | |
271 // FIXME java.nio.ReadableByteChannel or ByteStream/ByteSequence(read, length, reset) | |
272 // SHALL be inline with util.ByteChannel, reading bytes from HgDataFile, preferably DataAccess#readBytes(BB) to match API, | |
273 // and a wrap for ByteVector | |
274 public interface ByteDataSupplier { // TODO look if can resolve DataAccess in HgCloneCommand visibility issue | |
275 // FIXME needs lifecycle, e.g. for supplier that reads from WC | |
276 int read(ByteBuffer buf); | |
277 } | |
278 | |
279 public interface ByteDataConsumer { | |
280 void write(ByteBuffer buf); | |
281 } | |
282 } | 260 } |