comparison src/org/tmatesoft/hg/repo/HgDirstate.java @ 290:8faad08c709b

Expose dirstate to allow pre-configuration of FileIterators for status collection in particular
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Wed, 14 Sep 2011 01:52:41 +0200
parents 7232b94f2ae3
children 1483e57541ef
comparison
equal deleted inserted replaced
289:086a326f181f 290:8faad08c709b
40 * @see http://mercurial.selenic.com/wiki/FileFormats#dirstate 40 * @see http://mercurial.selenic.com/wiki/FileFormats#dirstate
41 * 41 *
42 * @author Artem Tikhomirov 42 * @author Artem Tikhomirov
43 * @author TMate Software Ltd. 43 * @author TMate Software Ltd.
44 */ 44 */
45 class HgDirstate /* XXX RepoChangeListener */{ 45 public final class HgDirstate /* XXX RepoChangeListener */{
46
47 public enum EntryKind {
48 Normal, Added, Removed, Merged, // order is being used in code of this class, don't change unless any use is checked
49 }
46 50
47 private final HgRepository repo; 51 private final HgRepository repo;
48 private final File dirstateFile; 52 private final File dirstateFile;
49 private final PathPool pathPool; 53 private final PathPool pathPool;
50 private Map<Path, Record> normal; 54 private Map<Path, Record> normal;
52 private Map<Path, Record> removed; 56 private Map<Path, Record> removed;
53 private Map<Path, Record> merged; 57 private Map<Path, Record> merged;
54 private Pair<Nodeid, Nodeid> parents; 58 private Pair<Nodeid, Nodeid> parents;
55 private String currentBranch; 59 private String currentBranch;
56 60
57 public HgDirstate(HgRepository hgRepo, File dirstate, PathPool pathPool) { 61 /*package-local*/ HgDirstate(HgRepository hgRepo, File dirstate, PathPool pathPool) {
58 repo = hgRepo; 62 repo = hgRepo;
59 dirstateFile = dirstate; // XXX decide whether file names shall be kept local to reader (see #branches()) or passed from outside 63 dirstateFile = dirstate; // XXX decide whether file names shall be kept local to reader (see #branches()) or passed from outside
60 this.pathPool = pathPool; 64 this.pathPool = pathPool;
61 } 65 }
62 66
124 parents = null; 128 parents = null;
125 return new Pair<Nodeid, Nodeid>(n1, n2); 129 return new Pair<Nodeid, Nodeid>(n1, n2);
126 } 130 }
127 131
128 /** 132 /**
129 * @return array of length 2 with working copy parents, non null. 133 * @return pair of working copy parents, with {@link Nodeid#NULL} for missing values.
130 */ 134 */
131 public Pair<Nodeid,Nodeid> parents() { 135 public Pair<Nodeid,Nodeid> parents() {
132 if (parents == null) { 136 if (parents == null) {
133 parents = readParents(repo, dirstateFile); 137 parents = readParents(repo, dirstateFile);
134 } 138 }
136 } 140 }
137 141
138 /** 142 /**
139 * @return pair of parents, both {@link Nodeid#NULL} if dirstate is not available 143 * @return pair of parents, both {@link Nodeid#NULL} if dirstate is not available
140 */ 144 */
141 public static Pair<Nodeid, Nodeid> readParents(HgRepository repo, File dirstateFile) { 145 /*package-local*/ static Pair<Nodeid, Nodeid> readParents(HgRepository repo, File dirstateFile) {
142 // do not read whole dirstate if all we need is WC parent information 146 // do not read whole dirstate if all we need is WC parent information
143 if (dirstateFile == null || !dirstateFile.exists()) { 147 if (dirstateFile == null || !dirstateFile.exists()) {
144 return new Pair<Nodeid,Nodeid>(NULL, NULL); 148 return new Pair<Nodeid,Nodeid>(NULL, NULL);
145 } 149 }
146 DataAccess da = repo.getDataAccess().create(dirstateFile); 150 DataAccess da = repo.getDataAccess().create(dirstateFile);
155 da.done(); 159 da.done();
156 } 160 }
157 } 161 }
158 162
159 /** 163 /**
160 * XXX is it really proper place for the method?
161 * @return branch associated with the working directory 164 * @return branch associated with the working directory
162 */ 165 */
163 public String branch() { 166 public String branch() {
167 // XXX is it really proper place for the method?
164 if (currentBranch == null) { 168 if (currentBranch == null) {
165 currentBranch = readBranch(repo); 169 currentBranch = readBranch(repo);
166 } 170 }
167 return currentBranch; 171 return currentBranch;
168 } 172 }
169 173
170 /** 174 /**
171 * XXX is it really proper place for the method? 175 * XXX is it really proper place for the method?
172 * @return branch associated with the working directory 176 * @return branch associated with the working directory
173 */ 177 */
174 public static String readBranch(HgRepository repo) { 178 /*package-local*/ static String readBranch(HgRepository repo) {
175 String branch = HgRepository.DEFAULT_BRANCH_NAME; 179 String branch = HgRepository.DEFAULT_BRANCH_NAME;
176 File branchFile = new File(repo.getRepositoryRoot(), "branch"); 180 File branchFile = new File(repo.getRepositoryRoot(), "branch");
177 if (branchFile.exists()) { 181 if (branchFile.exists()) {
178 try { 182 try {
179 BufferedReader r = new BufferedReader(new FileReader(branchFile)); 183 BufferedReader r = new BufferedReader(new FileReader(branchFile));
191 return branch; 195 return branch;
192 } 196 }
193 197
194 // new, modifiable collection 198 // new, modifiable collection
195 /*package-local*/ TreeSet<Path> all() { 199 /*package-local*/ TreeSet<Path> all() {
196 read(); 200 if (normal == null) {
201 read();
202 }
197 TreeSet<Path> rv = new TreeSet<Path>(); 203 TreeSet<Path> rv = new TreeSet<Path>();
198 @SuppressWarnings("unchecked") 204 @SuppressWarnings("unchecked")
199 Map<Path, Record>[] all = new Map[] { normal, added, removed, merged }; 205 Map<Path, Record>[] all = new Map[] { normal, added, removed, merged };
200 for (int i = 0; i < all.length; i++) { 206 for (int i = 0; i < all.length; i++) {
201 for (Record r : all[i].values()) { 207 for (Record r : all[i].values()) {
237 } 243 }
238 System.out.println(); 244 System.out.println();
239 } 245 }
240 } 246 }
241 247
242 /*package-local*/ static class Record { 248 public void walk(Inspector inspector) {
243 final int mode; 249 if (normal == null) {
244 // it seems Dirstate keeps local file size (i.e. that with any filters already applied). 250 read();
251 }
252 @SuppressWarnings("unchecked")
253 Map<Path, Record>[] all = new Map[] { normal, added, removed, merged };
254 for (int i = 0; i < all.length; i++) {
255 EntryKind k = EntryKind.values()[i];
256 for (Record r : all[i].values()) {
257 if (!inspector.next(k, r)) {
258 return;
259 }
260 }
261 }
262 }
263
264 public interface Inspector {
265 boolean next(EntryKind kind, Record entry);
266 }
267
268 public static final class Record {
269 private final int mode, size, time;
270 // Dirstate keeps local file size (i.e. that with any filters already applied).
245 // Thus, can't compare directly to HgDataFile.length() 271 // Thus, can't compare directly to HgDataFile.length()
246 final int size; 272 private final Path name1, name2;
247 final int time; 273
248 final Path name1; 274 /*package-local*/ Record(int fmode, int fsize, int ftime, Path name1, Path name2) {
249 final Path name2;
250
251 public Record(int fmode, int fsize, int ftime, Path name1, Path name2) {
252 mode = fmode; 275 mode = fmode;
253 size = fsize; 276 size = fsize;
254 time = ftime; 277 time = ftime;
255 this.name1 = name1; 278 this.name1 = name1;
256 this.name2 = name2; 279 this.name2 = name2;
257 280
258 } 281 }
282
283 public Path name() {
284 return name1;
285 }
286
287 /**
288 * @return non-<code>null</code> for copy/move
289 */
290 public Path copySource() {
291 return name2;
292 }
293
294 public int modificationTime() {
295 return time;
296 }
297
298 public int size() {
299 return size;
300 }
259 } 301 }
260 } 302 }