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();