void (@NotNull PairProcessor<? super Revision, ? super String> processor) { Map<Long, Revision> revMap = new HashMap<>(); for (RevisionItem r : getRevisions()) { revMap.put(r.revision.getChangeSetId(), r.revision); } if (revMap.isEmpty()) return; myVcs.accept(new ChangeVisitor() { final RootEntry root = ContainerUtil.getFirstItem(revMap.values()).getRoot().copy(); String path = myGateway.getPathOrUrl(myFile); { processContent(revMap.get(null)); } private boolean processContent(@Nullable Revision revision) { if (revision == null) return true; Entry entry = root.findEntry(path); Content content = entry == null ? null : entry.getContent(); String text = content == null ? null : content.getString(entry, myGateway); return processor.process(revision, text); } @Override public void begin(ChangeSet c) { ProgressManager.checkCanceled(); if (Thread.currentThread().isInterrupted()) { throw new ProcessCanceledException(); } } @Override public void end(ChangeSet c) throws StopVisitingException { if (!processContent(revMap.get(c.getId()))) { stop(); } } @Override public void visit(StructuralChange c) { if (c.affectsPath(path)) { c.revertOn(root, false); path = c.revertPath(path); } } }); }