tikhomirov@254: package org.tmatesoft.hg.test; tikhomirov@254: tikhomirov@255: import java.io.File; tikhomirov@255: import java.util.ArrayList; tikhomirov@255: import java.util.HashMap; tikhomirov@255: import java.util.LinkedList; tikhomirov@255: import java.util.List; tikhomirov@255: import java.util.Map; tikhomirov@254: tikhomirov@255: import org.tmatesoft.hg.core.HgChangeset; tikhomirov@255: import org.tmatesoft.hg.core.HgChangesetHandler; tikhomirov@255: import org.tmatesoft.hg.core.HgException; tikhomirov@255: import org.tmatesoft.hg.core.HgLogCommand; tikhomirov@255: import org.tmatesoft.hg.core.Nodeid; tikhomirov@254: import org.tmatesoft.hg.internal.Pool; tikhomirov@255: import org.tmatesoft.hg.repo.HgChangelog; tikhomirov@255: import org.tmatesoft.hg.repo.HgDataFile; tikhomirov@255: import org.tmatesoft.hg.repo.HgLookup; tikhomirov@255: import org.tmatesoft.hg.repo.HgManifest; tikhomirov@255: import org.tmatesoft.hg.repo.HgRepository; tikhomirov@255: import org.tmatesoft.hg.repo.HgTags; tikhomirov@254: import org.tmatesoft.hg.repo.HgTags.TagInfo; tikhomirov@255: import org.tmatesoft.hg.util.CancelledException; tikhomirov@255: import org.tmatesoft.hg.util.Path; tikhomirov@254: tikhomirov@254: /** tikhomirov@254: * @author Marc Strapetz tikhomirov@254: */ tikhomirov@254: public class MapTagsToFileRevisions { tikhomirov@254: tikhomirov@254: // Static ================================================================= tikhomirov@254: tikhomirov@255: public static void main(String[] args) throws Exception { tikhomirov@255: MapTagsToFileRevisions m = new MapTagsToFileRevisions(); tikhomirov@255: System.out.printf("Free mem: %,d\n", Runtime.getRuntime().freeMemory()); tikhomirov@255: m.main(); tikhomirov@255: m = null; tikhomirov@255: System.gc(); tikhomirov@255: System.out.printf("Free mem: %,d\n", Runtime.getRuntime().freeMemory()); tikhomirov@255: } tikhomirov@255: tikhomirov@255: private void main() throws HgException, CancelledException { tikhomirov@254: final long start = System.currentTimeMillis(); tikhomirov@254: final HgRepository repository = new HgLookup().detect(new File("/temp/hg/cpython")); tikhomirov@254: final HgTags tags = repository.getTags(); tikhomirov@254: // tikhomirov@254: // build cache tikhomirov@255: // tikhomirov@255: final TagInfo[] allTags = new TagInfo[tags.getTags().size()]; tikhomirov@255: tags.getTags().values().toArray(allTags); tikhomirov@255: // file2rev2tag value is array of revisions, always of allTags.length. Revision index in the array tikhomirov@255: // is index of corresponding TagInfo in allTags; tikhomirov@255: final Map file2rev2tag = new HashMap(); tikhomirov@255: System.out.printf("Collecting manifests for %d tags\n", allTags.length); tikhomirov@254: // effective translation of changeset revisions to their local indexes tikhomirov@254: final HgChangelog.RevisionMap clogrmap = repository.getChangelog().new RevisionMap().init(); tikhomirov@255: int[] tagLocalRevs = new int[allTags.length]; tikhomirov@255: for (int i = 0; i < allTags.length; i++) { tikhomirov@255: final Nodeid tagRevision = allTags[i].revision(); tikhomirov@255: tagLocalRevs[i] = clogrmap.localRevision(tagRevision); tikhomirov@254: } tikhomirov@255: System.out.printf("Prepared tag revisions to analyze: %d ms\n", System.currentTimeMillis() - start); tikhomirov@254: // tikhomirov@254: repository.getManifest().walk(new HgManifest.Inspector() { tikhomirov@255: private final ArrayList tagIndexAtRev = new ArrayList(); tikhomirov@255: private final Pool filenamePool = new Pool(); tikhomirov@255: private final Pool nodeidPool = new Pool(); tikhomirov@254: tikhomirov@254: public boolean begin(int mainfestRevision, Nodeid nid, int changelogRevision) { tikhomirov@254: Nodeid cset = clogrmap.revision(changelogRevision); tikhomirov@255: tagIndexAtRev.clear(); tikhomirov@255: for (int i = 0; i < allTags.length; i++) { tikhomirov@255: if (cset.equals(allTags[i].revision())) { tikhomirov@255: tagIndexAtRev.add(i); tikhomirov@255: } tikhomirov@255: } tikhomirov@255: if (tagIndexAtRev.isEmpty()) { tikhomirov@254: System.out.println("Can't happen, provided we iterate over revisions with tags only"); tikhomirov@254: } tikhomirov@254: return true; tikhomirov@254: } tikhomirov@254: tikhomirov@254: public boolean next(Nodeid nid, String fname, String flags) { tikhomirov@254: fname = filenamePool.unify(fname); tikhomirov@254: nid = nodeidPool.unify(nid); tikhomirov@255: Nodeid[] m = file2rev2tag.get(fname); tikhomirov@254: if (m == null) { tikhomirov@255: file2rev2tag.put(fname, m = new Nodeid[allTags.length]); tikhomirov@254: } tikhomirov@255: for (int tagIndex : tagIndexAtRev) { tikhomirov@255: if (m[tagIndex] != null) { tikhomirov@255: System.out.printf("There's another revision (%s) associated with tag %s already while we try to associate %s\n", m[tagIndex].shortNotation(), allTags[tagIndex].name(), nid.shortNotation()); tikhomirov@255: } tikhomirov@255: m[tagIndex] = nid; tikhomirov@254: } tikhomirov@254: return true; tikhomirov@254: } tikhomirov@254: tikhomirov@254: public boolean end(int manifestRevision) { tikhomirov@254: return true; tikhomirov@254: } tikhomirov@254: tikhomirov@254: }, tagLocalRevs); tikhomirov@255: System.out.printf("Cache built: %d ms\n", System.currentTimeMillis() - start); tikhomirov@254: // tikhomirov@254: // look up specific file. This part is fast. tikhomirov@254: final Path targetPath = Path.create("README"); tikhomirov@254: HgDataFile fileNode = repository.getFileNode(targetPath); tikhomirov@255: final Nodeid[] allTagsOfTheFile = file2rev2tag.get(targetPath.toString()); tikhomirov@254: // TODO if fileNode.isCopy, repeat for each getCopySourceName() tikhomirov@254: for (int localFileRev = 0; localFileRev < fileNode.getRevisionCount(); localFileRev++) { tikhomirov@254: Nodeid fileRev = fileNode.getRevision(localFileRev); tikhomirov@254: int changesetLocalRev = fileNode.getChangesetLocalRevision(localFileRev); tikhomirov@254: List associatedTags = new LinkedList(); tikhomirov@255: for (int i = 0; i < allTagsOfTheFile.length; i++) { tikhomirov@255: if (fileRev.equals(allTagsOfTheFile[i])) { tikhomirov@255: associatedTags.add(allTags[i].name()); tikhomirov@254: } tikhomirov@254: } tikhomirov@254: System.out.printf("%3d%7d%s\n", localFileRev, changesetLocalRev, associatedTags); tikhomirov@254: } tikhomirov@255: System.out.printf("Total time: %d ms\n", System.currentTimeMillis() - start); tikhomirov@255: System.out.printf("Free mem: %,d\n", Runtime.getRuntime().freeMemory()); tikhomirov@254: } tikhomirov@254: tikhomirov@254: public static void main2(String[] args) throws HgException, CancelledException { tikhomirov@254: final HgRepository repository = new HgLookup().detect(new File("/temp/hg/cpython")); tikhomirov@254: final Path targetPath = Path.create("README"); tikhomirov@254: final HgTags tags = repository.getTags(); tikhomirov@254: final Map tagToInfo = tags.getTags(); tikhomirov@254: final HgManifest manifest = repository.getManifest(); tikhomirov@254: final Map> changeSetRevisionToTags = new HashMap>(); tikhomirov@254: final HgDataFile fileNode = repository.getFileNode(targetPath); tikhomirov@254: for (String tagName : tagToInfo.keySet()) { tikhomirov@254: final HgTags.TagInfo info = tagToInfo.get(tagName); tikhomirov@254: final Nodeid nodeId = info.revision(); tikhomirov@254: // TODO: This is not correct as we can't be sure that file at the corresponding revision is actually our target file (which may have been renamed, etc.) tikhomirov@254: final Nodeid fileRevision = manifest.getFileRevision(repository.getChangelog().getLocalRevision(nodeId), targetPath); tikhomirov@254: if (fileRevision == null) { tikhomirov@254: continue; tikhomirov@254: } tikhomirov@254: tikhomirov@254: final Nodeid changeSetRevision = fileNode.getChangesetRevision(fileRevision); tikhomirov@254: List revisionTags = changeSetRevisionToTags.get(changeSetRevision); tikhomirov@254: if (revisionTags == null) { tikhomirov@254: revisionTags = new ArrayList(); tikhomirov@254: changeSetRevisionToTags.put(changeSetRevision, revisionTags); tikhomirov@254: } tikhomirov@254: revisionTags.add(tagName); tikhomirov@254: } tikhomirov@254: tikhomirov@254: final HgLogCommand logCommand = new HgLogCommand(repository); tikhomirov@254: logCommand.file(targetPath, true); tikhomirov@254: logCommand.execute(new HgChangesetHandler() { tikhomirov@254: public void next(HgChangeset changeset) { tikhomirov@254: if (changeset.getAffectedFiles().contains(targetPath)) { tikhomirov@254: System.out.println(changeset.getRevision() + " " + changeSetRevisionToTags.get(changeset.getNodeid())); tikhomirov@254: } tikhomirov@254: } tikhomirov@254: }); tikhomirov@254: } tikhomirov@254: }