comparison src/org/tmatesoft/hg/repo/HgWorkingCopyStatusCollector.java @ 280:35125450c804

Erroneous and slow status for working copies based on non-tip revision
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Fri, 02 Sep 2011 13:40:09 +0200
parents 6d1804fe0ed7
children e51dd9a14b6f
comparison
equal deleted inserted replaced
279:23e3ea855097 280:35125450c804
57 private final HgRepository repo; 57 private final HgRepository repo;
58 private final FileIterator repoWalker; 58 private final FileIterator repoWalker;
59 private HgDirstate dirstate; 59 private HgDirstate dirstate;
60 private HgStatusCollector baseRevisionCollector; 60 private HgStatusCollector baseRevisionCollector;
61 private PathPool pathPool; 61 private PathPool pathPool;
62 private ManifestRevision dirstateParentManifest;
63 62
64 public HgWorkingCopyStatusCollector(HgRepository hgRepo) { 63 public HgWorkingCopyStatusCollector(HgRepository hgRepo) {
65 this(hgRepo, new HgInternals(hgRepo).createWorkingDirWalker(null)); 64 this(hgRepo, new HgInternals(hgRepo).createWorkingDirWalker(null));
66 } 65 }
67 66
143 } 142 }
144 repoWalker.reset(); 143 repoWalker.reset();
145 final PathPool pp = getPathPool(); 144 final PathPool pp = getPathPool();
146 while (repoWalker.hasNext()) { 145 while (repoWalker.hasNext()) {
147 repoWalker.next(); 146 repoWalker.next();
148 Path fname = pp.path(repoWalker.name()); 147 final Path fname = pp.path(repoWalker.name());
149 File f = repoWalker.file(); 148 File f = repoWalker.file();
150 if (!f.exists()) { 149 if (!f.exists()) {
151 // file coming from iterator doesn't exist. 150 // file coming from iterator doesn't exist.
152 if (knownEntries.remove(fname.toString())) { 151 if (knownEntries.remove(fname.toString())) {
153 if (getDirstate().checkRemoved(fname) == null) { 152 if (getDirstate().checkRemoved(fname) == null) {
235 234
236 private void checkLocalStatusAgainstFile(Path fname, File f, HgStatusInspector inspector) { 235 private void checkLocalStatusAgainstFile(Path fname, File f, HgStatusInspector inspector) {
237 HgDirstate.Record r; 236 HgDirstate.Record r;
238 if ((r = getDirstate().checkNormal(fname)) != null) { 237 if ((r = getDirstate().checkNormal(fname)) != null) {
239 // either clean or modified 238 // either clean or modified
240 if (f.lastModified() / 1000 == r.time && r.size == f.length()) { 239 final boolean timestampEqual = getFileModificationTime(f) == r.time, sizeEqual = r.size == f.length();
241 inspector.clean(getPathPool().path(fname)); 240 if (timestampEqual && sizeEqual) {
242 } else { 241 inspector.clean(fname);
242 } else if (!sizeEqual && r.size >= 0) {
243 inspector.modified(fname);
244 } else {
245 // size is the same or unknown, and, perhaps, different timestamp
243 // check actual content to avoid false modified files 246 // check actual content to avoid false modified files
244 HgDataFile df = repo.getFileNode(fname); 247 HgDataFile df = repo.getFileNode(fname);
245 if (!areTheSame(f, df, HgRepository.TIP)) { 248 if (!areTheSame(f, df, HgRepository.TIP)) {
246 inspector.modified(df.getPath()); 249 inspector.modified(df.getPath());
247 } else { 250 } else {
248 inspector.clean(df.getPath()); 251 inspector.clean(df.getPath());
249 } 252 }
250 } 253 }
251 } else if ((r = getDirstate().checkAdded(fname)) != null) { 254 } else if ((r = getDirstate().checkAdded(fname)) != null) {
252 if (r.name2 == null) { 255 if (r.name2 == null) {
253 inspector.added(getPathPool().path(fname)); 256 inspector.added(fname);
254 } else { 257 } else {
255 inspector.copied(getPathPool().path(r.name2), getPathPool().path(fname)); 258 inspector.copied(getPathPool().path(r.name2), fname);
256 } 259 }
257 } else if ((r = getDirstate().checkRemoved(fname)) != null) { 260 } else if ((r = getDirstate().checkRemoved(fname)) != null) {
258 inspector.removed(getPathPool().path(fname)); 261 inspector.removed(fname);
259 } else if ((r = getDirstate().checkMerged(fname)) != null) { 262 } else if ((r = getDirstate().checkMerged(fname)) != null) {
260 inspector.modified(getPathPool().path(fname)); 263 inspector.modified(fname);
261 } 264 }
265 }
266
267 // return mtime analog, directly comparable to dirstate's mtime.
268 private static int getFileModificationTime(File f) {
269 return (int) (f.lastModified() / 1000);
262 } 270 }
263 271
264 // XXX refactor checkLocalStatus methods in more OO way 272 // XXX refactor checkLocalStatus methods in more OO way
265 private void checkLocalStatusAgainstBaseRevision(Set<String> baseRevNames, ManifestRevision collect, int baseRevision, Path fname, File f, HgStatusInspector inspector) { 273 private void checkLocalStatusAgainstBaseRevision(Set<String> baseRevNames, ManifestRevision collect, int baseRevision, Path fname, File f, HgStatusInspector inspector) {
266 // fname is in the dirstate, either Normal, Added, Removed or Merged 274 // fname is in the dirstate, either Normal, Added, Removed or Merged
294 return; 302 return;
295 } 303 }
296 inspector.added(fname); 304 inspector.added(fname);
297 } else { 305 } else {
298 // was known; check whether clean or modified 306 // was known; check whether clean or modified
299 // when added - seems to be the case of a file added once again, hence need to check if content is different 307 if ((r = getDirstate().checkNormal(fname)) != null) {
300 if ((r = getDirstate().checkNormal(fname)) != null || (r = getDirstate().checkMerged(fname)) != null || (r = getDirstate().checkAdded(fname)) != null) { 308 final boolean timestampEqual = getFileModificationTime(f) == r.time, sizeEqual = r.size == f.length();
309 if (timestampEqual && sizeEqual) {
310 inspector.clean(fname);
311 baseRevNames.remove(fname.toString()); // consumed, processed, handled.
312 return;
313 } else if (!sizeEqual && r.size >= 0) {
314 inspector.modified(fname);
315 baseRevNames.remove(fname.toString()); // consumed, processed, handled.
316 return;
317 }
318 // otherwise, shall check actual content (size not the same, or unknown (-1 or -2), or timestamp is different)
319 // FALL THROUGH
320 }
321 if (r != null /*Normal dirstate, but needs extra check*/ || (r = getDirstate().checkMerged(fname)) != null || (r = getDirstate().checkAdded(fname)) != null) {
322 // when added - seems to be the case of a file added once again, hence need to check if content is different
301 // either clean or modified 323 // either clean or modified
302 HgDataFile fileNode = repo.getFileNode(fname); 324 if (r.size != -1 /*XXX what about ==-2?*/&& r.size != f.length() || !todoCheckFlagsEqual(f, flags)) {
303 int lengthAtRevision;
304 try {
305 lengthAtRevision = fileNode.length(nid1);
306 } catch (HgDataStreamException ex) {
307 ex.printStackTrace(); // XXX log error
308 lengthAtRevision = -1; // compare file content then
309 }
310 // XXX is it safe with respect to filters (keyword, eol) to compare lengthAtRevision (unprocessed) with size
311 // from dirstate, which I assume is size of processed data?
312 if (r.size != -1 && r.size /* XXX File.length() ?! */ != lengthAtRevision || flags != todoGenerateFlags(fname /*java.io.File*/)) {
313 inspector.modified(fname); 325 inspector.modified(fname);
314 } else { 326 } else {
315 // check actual content to see actual changes 327 // check actual content to see actual changes
328 HgDataFile fileNode = repo.getFileNode(fname);
316 if (areTheSame(f, fileNode, fileNode.getLocalRevision(nid1))) { 329 if (areTheSame(f, fileNode, fileNode.getLocalRevision(nid1))) {
317 inspector.clean(fname); 330 inspector.clean(fname);
318 } else { 331 } else {
319 inspector.modified(fname); 332 inspector.modified(fname);
320 } 333 }
410 ex.printStackTrace(); 423 ex.printStackTrace();
411 } 424 }
412 return false; 425 return false;
413 } 426 }
414 427
415 private static String todoGenerateFlags(Path fname) { 428 private static boolean todoCheckFlagsEqual(File f, String manifestFlags) {
416 // FIXME implement 429 // FIXME implement
417 return null; 430 return true;
418 } 431 }
419 432
420 /** 433 /**
421 * Configure status collector to consider only subset of a working copy tree. Tries to be as effective as possible, and to 434 * Configure status collector to consider only subset of a working copy tree. Tries to be as effective as possible, and to
422 * traverse only relevant part of working copy on the filesystem. 435 * traverse only relevant part of working copy on the filesystem.