Mercurial > jhg
comparison src/org/tmatesoft/hg/core/HgChangeset.java @ 450:03fd8d079e9c smartgit3
Share PhasesHelper instance among few HgChangesets (mostly affects HgChangesetTreeHandler case)
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Thu, 07 Jun 2012 17:06:23 +0200 |
parents | d0e5dc3cae6e |
children | 7bcfbc255f48 |
comparison
equal
deleted
inserted
replaced
449:5787e912f60e | 450:03fd8d079e9c |
---|---|
15 * contact TMate Software at support@hg4j.com | 15 * contact TMate Software at support@hg4j.com |
16 */ | 16 */ |
17 package org.tmatesoft.hg.core; | 17 package org.tmatesoft.hg.core; |
18 | 18 |
19 import java.util.ArrayList; | 19 import java.util.ArrayList; |
20 import java.util.Arrays; | |
21 import java.util.Collections; | 20 import java.util.Collections; |
22 import java.util.HashSet; | |
23 import java.util.List; | 21 import java.util.List; |
24 import java.util.Map; | 22 import java.util.Map; |
25 | 23 |
26 import org.tmatesoft.hg.internal.PhasesHelper; | 24 import org.tmatesoft.hg.internal.PhasesHelper; |
25 import org.tmatesoft.hg.repo.HgChangelog; | |
27 import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; | 26 import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; |
28 import org.tmatesoft.hg.repo.HgChangelog; | |
29 import org.tmatesoft.hg.repo.HgPhase; | 27 import org.tmatesoft.hg.repo.HgPhase; |
30 import org.tmatesoft.hg.repo.HgRepository; | 28 import org.tmatesoft.hg.repo.HgRepository; |
31 import org.tmatesoft.hg.repo.HgStatusCollector; | 29 import org.tmatesoft.hg.repo.HgStatusCollector; |
32 import org.tmatesoft.hg.util.Path; | 30 import org.tmatesoft.hg.util.Path; |
33 | 31 |
39 * | 37 * |
40 * @author Artem Tikhomirov | 38 * @author Artem Tikhomirov |
41 * @author TMate Software Ltd. | 39 * @author TMate Software Ltd. |
42 */ | 40 */ |
43 public class HgChangeset implements Cloneable { | 41 public class HgChangeset implements Cloneable { |
44 private final HgStatusCollector statusHelper; | 42 |
45 private final Path.Source pathHelper; | 43 // these get initialized |
46 | |
47 private HgChangelog.ParentWalker parentHelper; | |
48 | |
49 // | |
50 private RawChangeset changeset; | 44 private RawChangeset changeset; |
45 private int revNumber; | |
51 private Nodeid nodeid; | 46 private Nodeid nodeid; |
52 | 47 |
53 // | 48 class ShareDataStruct { |
49 ShareDataStruct(HgStatusCollector statusCollector, Path.Source pathFactory) { | |
50 statusHelper = statusCollector; | |
51 pathHelper = pathFactory; | |
52 } | |
53 public final HgStatusCollector statusHelper; | |
54 public final Path.Source pathHelper; | |
55 | |
56 public HgChangelog.ParentWalker parentHelper; | |
57 public PhasesHelper phaseHelper; | |
58 }; | |
59 | |
60 // Helpers/utilities shared among few instances of HgChangeset | |
61 private final ShareDataStruct shared; | |
62 | |
63 // these are built on demand | |
54 private List<HgFileRevision> modifiedFiles, addedFiles; | 64 private List<HgFileRevision> modifiedFiles, addedFiles; |
55 private List<Path> deletedFiles; | 65 private List<Path> deletedFiles; |
56 private int revNumber; | |
57 private byte[] parent1, parent2; | 66 private byte[] parent1, parent2; |
58 private PhasesHelper phaseHelper; | 67 |
59 | 68 |
60 // XXX consider CommandContext with StatusCollector, PathPool etc. Commands optionally get CC through a cons or create new | 69 // XXX consider CommandContext with StatusCollector, PathPool etc. Commands optionally get CC through a cons or create new |
61 // and pass it around | 70 // and pass it around |
62 /*package-local*/HgChangeset(HgStatusCollector statusCollector, Path.Source pathFactory) { | 71 /*package-local*/HgChangeset(HgStatusCollector statusCollector, Path.Source pathFactory) { |
63 statusHelper = statusCollector; | 72 shared = new ShareDataStruct(statusCollector, pathFactory); |
64 pathHelper = pathFactory; | |
65 } | 73 } |
66 | 74 |
67 /*package-local*/ void init(int localRevNumber, Nodeid nid, RawChangeset rawChangeset) { | 75 /*package-local*/ void init(int localRevNumber, Nodeid nid, RawChangeset rawChangeset) { |
68 revNumber = localRevNumber; | 76 revNumber = localRevNumber; |
69 nodeid = nid; | 77 nodeid = nid; |
70 changeset = rawChangeset.clone(); | 78 changeset = rawChangeset.clone(); |
71 modifiedFiles = addedFiles = null; | 79 modifiedFiles = addedFiles = null; |
72 deletedFiles = null; | 80 deletedFiles = null; |
73 parent1 = parent2 = null; | 81 parent1 = parent2 = null; |
74 // keep references to parentHelper, statusHelper and pathHelper | 82 // keep references to shared (and everything in there: parentHelper, statusHelper, phaseHelper and pathHelper) |
75 } | 83 } |
76 | 84 |
77 /*package-local*/ void setParentHelper(HgChangelog.ParentWalker pw) { | 85 /*package-local*/ void setParentHelper(HgChangelog.ParentWalker pw) { |
78 parentHelper = pw; | 86 if (pw != null) { |
79 if (parentHelper != null) { | 87 if (pw.getRepo() != shared.statusHelper.getRepo()) { |
80 if (parentHelper.getRepo() != statusHelper.getRepo()) { | |
81 throw new IllegalArgumentException(); | 88 throw new IllegalArgumentException(); |
82 } | 89 } |
83 } | 90 } |
91 shared.parentHelper = pw; | |
84 } | 92 } |
85 | 93 |
86 public int getRevision() { | 94 public int getRevision() { |
87 return revNumber; | 95 return revNumber; |
88 } | 96 } |
114 // files listed, and thus this method would return empty list, while | 122 // files listed, and thus this method would return empty list, while |
115 // #getModifiedFiles() would return list with merged file(s) (because it uses status to get 'em, not | 123 // #getModifiedFiles() would return list with merged file(s) (because it uses status to get 'em, not |
116 // what #files() gives). | 124 // what #files() gives). |
117 ArrayList<Path> rv = new ArrayList<Path>(changeset.files().size()); | 125 ArrayList<Path> rv = new ArrayList<Path>(changeset.files().size()); |
118 for (String name : changeset.files()) { | 126 for (String name : changeset.files()) { |
119 rv.add(pathHelper.path(name)); | 127 rv.add(shared.pathHelper.path(name)); |
120 } | 128 } |
121 return rv; | 129 return rv; |
122 } | 130 } |
123 | 131 |
124 public List<HgFileRevision> getModifiedFiles() throws HgInvalidControlFileException { | 132 public List<HgFileRevision> getModifiedFiles() throws HgInvalidControlFileException { |
150 /** | 158 /** |
151 * @return never <code>null</code> | 159 * @return never <code>null</code> |
152 * @throws HgInvalidControlFileException if access to revlog index/data entry failed | 160 * @throws HgInvalidControlFileException if access to revlog index/data entry failed |
153 */ | 161 */ |
154 public Nodeid getFirstParentRevision() throws HgInvalidControlFileException { | 162 public Nodeid getFirstParentRevision() throws HgInvalidControlFileException { |
155 if (parentHelper != null) { | 163 if (shared.parentHelper != null) { |
156 return parentHelper.safeFirstParent(nodeid); | 164 return shared.parentHelper.safeFirstParent(nodeid); |
157 } | 165 } |
158 // read once for both p1 and p2 | 166 // read once for both p1 and p2 |
159 if (parent1 == null) { | 167 if (parent1 == null) { |
160 parent1 = new byte[20]; | 168 parent1 = new byte[20]; |
161 parent2 = new byte[20]; | 169 parent2 = new byte[20]; |
167 /** | 175 /** |
168 * @return never <code>null</code> | 176 * @return never <code>null</code> |
169 * @throws HgInvalidControlFileException if access to revlog index/data entry failed | 177 * @throws HgInvalidControlFileException if access to revlog index/data entry failed |
170 */ | 178 */ |
171 public Nodeid getSecondParentRevision() throws HgInvalidControlFileException { | 179 public Nodeid getSecondParentRevision() throws HgInvalidControlFileException { |
172 if (parentHelper != null) { | 180 if (shared.parentHelper != null) { |
173 return parentHelper.safeSecondParent(nodeid); | 181 return shared.parentHelper.safeSecondParent(nodeid); |
174 } | 182 } |
175 if (parent2 == null) { | 183 if (parent2 == null) { |
176 parent1 = new byte[20]; | 184 parent1 = new byte[20]; |
177 parent2 = new byte[20]; | 185 parent2 = new byte[20]; |
178 getRepo().getChangelog().parents(revNumber, new int[2], parent1, parent2); | 186 getRepo().getChangelog().parents(revNumber, new int[2], parent1, parent2); |
183 /** | 191 /** |
184 * Tells the phase this changeset belongs to. | 192 * Tells the phase this changeset belongs to. |
185 * @return one of {@link HgPhase} values | 193 * @return one of {@link HgPhase} values |
186 */ | 194 */ |
187 public HgPhase getPhase() throws HgInvalidControlFileException { | 195 public HgPhase getPhase() throws HgInvalidControlFileException { |
188 if (phaseHelper == null) { | 196 if (shared.phaseHelper == null) { |
189 // XXX would be handy to obtain ProgressSupport (perhaps, from statusHelper?) | 197 // XXX would be handy to obtain ProgressSupport (perhaps, from statusHelper?) |
190 // and pass it to #init(), so that there could be indication of file being read and cache being built | 198 // and pass it to #init(), so that there could be indication of file being read and cache being built |
191 phaseHelper = new PhasesHelper(getRepo(), parentHelper); | 199 synchronized (shared) { |
192 } | 200 // ensure field is initialized only once |
193 return phaseHelper.getPhase(this); | 201 if (shared.phaseHelper == null) { |
202 shared.phaseHelper = new PhasesHelper(getRepo(), shared.parentHelper); | |
203 } | |
204 } | |
205 } | |
206 return shared.phaseHelper.getPhase(this); | |
194 } | 207 } |
195 | 208 |
196 @Override | 209 @Override |
197 public HgChangeset clone() { | 210 public HgChangeset clone() { |
198 try { | 211 try { |
203 throw new InternalError(ex.toString()); | 216 throw new InternalError(ex.toString()); |
204 } | 217 } |
205 } | 218 } |
206 | 219 |
207 private HgRepository getRepo() { | 220 private HgRepository getRepo() { |
208 return statusHelper.getRepo(); | 221 return shared.statusHelper.getRepo(); |
209 } | 222 } |
210 | 223 |
211 private /*synchronized*/ void initFileChanges() throws HgInvalidControlFileException { | 224 private /*synchronized*/ void initFileChanges() throws HgInvalidControlFileException { |
212 ArrayList<Path> deleted = new ArrayList<Path>(); | 225 ArrayList<Path> deleted = new ArrayList<Path>(); |
213 ArrayList<HgFileRevision> modified = new ArrayList<HgFileRevision>(); | 226 ArrayList<HgFileRevision> modified = new ArrayList<HgFileRevision>(); |
214 ArrayList<HgFileRevision> added = new ArrayList<HgFileRevision>(); | 227 ArrayList<HgFileRevision> added = new ArrayList<HgFileRevision>(); |
215 HgStatusCollector.Record r = new HgStatusCollector.Record(); | 228 HgStatusCollector.Record r = new HgStatusCollector.Record(); |
216 statusHelper.change(revNumber, r); | 229 shared.statusHelper.change(revNumber, r); |
217 final HgRepository repo = getRepo(); | 230 final HgRepository repo = getRepo(); |
218 for (Path s : r.getModified()) { | 231 for (Path s : r.getModified()) { |
219 Nodeid nid = r.nodeidAfterChange(s); | 232 Nodeid nid = r.nodeidAfterChange(s); |
220 if (nid == null) { | 233 if (nid == null) { |
221 throw new HgBadStateException(); | 234 throw new HgBadStateException(); |