Mercurial > jhg
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. | 
