# HG changeset patch # User Artem Tikhomirov # Date 1315957961 -7200 # Node ID 8faad08c709b8d16751e1476e7b6df224c00c434 # Parent 086a326f181f8e1190e6f0acfc3136262b076236 Expose dirstate to allow pre-configuration of FileIterators for status collection in particular diff -r 086a326f181f -r 8faad08c709b cmdline/org/tmatesoft/hg/console/Main.java --- a/cmdline/org/tmatesoft/hg/console/Main.java Mon Sep 12 14:11:45 2011 +0200 +++ b/cmdline/org/tmatesoft/hg/console/Main.java Wed Sep 14 01:52:41 2011 +0200 @@ -40,6 +40,7 @@ import org.tmatesoft.hg.repo.HgBranches; import org.tmatesoft.hg.repo.HgChangelog; import org.tmatesoft.hg.repo.HgDataFile; +import org.tmatesoft.hg.repo.HgDirstate; import org.tmatesoft.hg.repo.HgInternals; import org.tmatesoft.hg.repo.HgManifest; import org.tmatesoft.hg.repo.HgMergeState; @@ -51,6 +52,8 @@ import org.tmatesoft.hg.repo.HgSubrepoLocation.Kind; import org.tmatesoft.hg.repo.HgWorkingCopyStatusCollector; import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; +import org.tmatesoft.hg.repo.HgDirstate.EntryKind; +import org.tmatesoft.hg.repo.HgDirstate.Record; import org.tmatesoft.hg.util.FileWalker; import org.tmatesoft.hg.util.Pair; import org.tmatesoft.hg.util.Path; @@ -86,12 +89,12 @@ // m.testParents(); // m.testEffectiveFileLog(); // m.testCatAtCsetRevision(); - m.testMergeState(); +// m.testMergeState(); // m.testFileStatus(); // m.dumpBranches(); // m.inflaterLengthException(); // m.dumpIgnored(); -// m.dumpDirstate(); + m.dumpDirstate(); // m.testStatusInternals(); // m.catCompleteHistory(); // m.dumpCompleteManifestLow(); @@ -325,6 +328,14 @@ private void dumpDirstate() { new HgInternals(hgRepo).dumpDirstate(); + HgWorkingCopyStatusCollector wcc = HgWorkingCopyStatusCollector.create(hgRepo, new Path.Matcher.Any()); + wcc.getDirstate().walk(new HgDirstate.Inspector() { + + public boolean next(EntryKind kind, Record entry) { + System.out.printf("%s %s\n", kind, entry.name()); + return true; + } + }); } diff -r 086a326f181f -r 8faad08c709b src/org/tmatesoft/hg/repo/HgDirstate.java --- a/src/org/tmatesoft/hg/repo/HgDirstate.java Mon Sep 12 14:11:45 2011 +0200 +++ b/src/org/tmatesoft/hg/repo/HgDirstate.java Wed Sep 14 01:52:41 2011 +0200 @@ -42,7 +42,11 @@ * @author Artem Tikhomirov * @author TMate Software Ltd. */ -class HgDirstate /* XXX RepoChangeListener */{ +public final class HgDirstate /* XXX RepoChangeListener */{ + + public enum EntryKind { + Normal, Added, Removed, Merged, // order is being used in code of this class, don't change unless any use is checked + } private final HgRepository repo; private final File dirstateFile; @@ -54,7 +58,7 @@ private Pair parents; private String currentBranch; - public HgDirstate(HgRepository hgRepo, File dirstate, PathPool pathPool) { + /*package-local*/ HgDirstate(HgRepository hgRepo, File dirstate, PathPool pathPool) { repo = hgRepo; dirstateFile = dirstate; // XXX decide whether file names shall be kept local to reader (see #branches()) or passed from outside this.pathPool = pathPool; @@ -126,7 +130,7 @@ } /** - * @return array of length 2 with working copy parents, non null. + * @return pair of working copy parents, with {@link Nodeid#NULL} for missing values. */ public Pair parents() { if (parents == null) { @@ -138,7 +142,7 @@ /** * @return pair of parents, both {@link Nodeid#NULL} if dirstate is not available */ - public static Pair readParents(HgRepository repo, File dirstateFile) { + /*package-local*/ static Pair readParents(HgRepository repo, File dirstateFile) { // do not read whole dirstate if all we need is WC parent information if (dirstateFile == null || !dirstateFile.exists()) { return new Pair(NULL, NULL); @@ -157,10 +161,10 @@ } /** - * XXX is it really proper place for the method? * @return branch associated with the working directory */ public String branch() { + // XXX is it really proper place for the method? if (currentBranch == null) { currentBranch = readBranch(repo); } @@ -171,7 +175,7 @@ * XXX is it really proper place for the method? * @return branch associated with the working directory */ - public static String readBranch(HgRepository repo) { + /*package-local*/ static String readBranch(HgRepository repo) { String branch = HgRepository.DEFAULT_BRANCH_NAME; File branchFile = new File(repo.getRepositoryRoot(), "branch"); if (branchFile.exists()) { @@ -193,7 +197,9 @@ // new, modifiable collection /*package-local*/ TreeSet all() { - read(); + if (normal == null) { + read(); + } TreeSet rv = new TreeSet(); @SuppressWarnings("unchecked") Map[] all = new Map[] { normal, added, removed, merged }; @@ -239,16 +245,33 @@ } } - /*package-local*/ static class Record { - final int mode; - // it seems Dirstate keeps local file size (i.e. that with any filters already applied). + public void walk(Inspector inspector) { + if (normal == null) { + read(); + } + @SuppressWarnings("unchecked") + Map[] all = new Map[] { normal, added, removed, merged }; + for (int i = 0; i < all.length; i++) { + EntryKind k = EntryKind.values()[i]; + for (Record r : all[i].values()) { + if (!inspector.next(k, r)) { + return; + } + } + } + } + + public interface Inspector { + boolean next(EntryKind kind, Record entry); + } + + public static final class Record { + private final int mode, size, time; + // Dirstate keeps local file size (i.e. that with any filters already applied). // Thus, can't compare directly to HgDataFile.length() - final int size; - final int time; - final Path name1; - final Path name2; + private final Path name1, name2; - public Record(int fmode, int fsize, int ftime, Path name1, Path name2) { + /*package-local*/ Record(int fmode, int fsize, int ftime, Path name1, Path name2) { mode = fmode; size = fsize; time = ftime; @@ -256,5 +279,24 @@ this.name2 = name2; } + + public Path name() { + return name1; + } + + /** + * @return non-null for copy/move + */ + public Path copySource() { + return name2; + } + + public int modificationTime() { + return time; + } + + public int size() { + return size; + } } } diff -r 086a326f181f -r 8faad08c709b src/org/tmatesoft/hg/repo/HgWorkingCopyStatusCollector.java --- a/src/org/tmatesoft/hg/repo/HgWorkingCopyStatusCollector.java Mon Sep 12 14:11:45 2011 +0200 +++ b/src/org/tmatesoft/hg/repo/HgWorkingCopyStatusCollector.java Wed Sep 14 01:52:41 2011 +0200 @@ -95,8 +95,11 @@ this.pathPool = pathPool; } - - private HgDirstate getDirstate() { + /** + * Access to directory state information this collector uses. + * @return directory state holder, never null + */ + public HgDirstate getDirstate() { if (dirstate == null) { dirstate = repo.loadDirstate(getPathPool()); } @@ -252,10 +255,10 @@ HgDirstate.Record r; if ((r = getDirstate().checkNormal(fname)) != null) { // either clean or modified - final boolean timestampEqual = f.lastModified() == r.time, sizeEqual = r.size == f.length(); + final boolean timestampEqual = f.lastModified() == r.modificationTime(), sizeEqual = r.size() == f.length(); if (timestampEqual && sizeEqual) { inspector.clean(fname); - } else if (!sizeEqual && r.size >= 0) { + } else if (!sizeEqual && r.size() >= 0) { inspector.modified(fname); } else { // size is the same or unknown, and, perhaps, different timestamp @@ -269,10 +272,10 @@ } } } else if ((r = getDirstate().checkAdded(fname)) != null) { - if (r.name2 == null) { + if (r.copySource() == null) { inspector.added(fname); } else { - inspector.copied(getPathPool().path(r.name2), fname); + inspector.copied(r.copySource(), fname); } } else if ((r = getDirstate().checkRemoved(fname)) != null) { inspector.removed(fname); @@ -303,9 +306,9 @@ // FIXME report to a mediator, continue status collection } } else if ((r = getDirstate().checkAdded(fname)) != null) { - if (r.name2 != null && baseRevNames.contains(r.name2)) { - baseRevNames.remove(r.name2); // XXX surely I shall not report rename source as Removed? - inspector.copied(r.name2, fname); + if (r.copySource() != null && baseRevNames.contains(r.copySource())) { + baseRevNames.remove(r.copySource()); // XXX surely I shall not report rename source as Removed? + inspector.copied(r.copySource(), fname); return; } // fall-through, report as added @@ -320,12 +323,12 @@ if ((r = getDirstate().checkNormal(fname)) != null && nid1.equals(nidFromDirstate)) { // regular file, was the same up to WC initialization. Check if was modified since, and, if not, report right away // same code as in #checkLocalStatusAgainstFile - final boolean timestampEqual = f.lastModified() == r.time, sizeEqual = r.size == f.length(); + final boolean timestampEqual = f.lastModified() == r.modificationTime(), sizeEqual = r.size() == f.length(); boolean handled = false; if (timestampEqual && sizeEqual) { inspector.clean(fname); handled = true; - } else if (!sizeEqual && r.size >= 0) { + } else if (!sizeEqual && r.size() >= 0) { inspector.modified(fname); handled = true; } else if (!todoCheckFlagsEqual(f, flags)) {