tikhomirov@596: /* tikhomirov@596: * Copyright (c) 2013 TMate Software Ltd tikhomirov@596: * tikhomirov@596: * This program is free software; you can redistribute it and/or modify tikhomirov@596: * it under the terms of the GNU General Public License as published by tikhomirov@596: * the Free Software Foundation; version 2 of the License. tikhomirov@596: * tikhomirov@596: * This program is distributed in the hope that it will be useful, tikhomirov@596: * but WITHOUT ANY WARRANTY; without even the implied warranty of tikhomirov@596: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the tikhomirov@596: * GNU General Public License for more details. tikhomirov@596: * tikhomirov@596: * For information on how to redistribute this software under tikhomirov@596: * the terms of a license other than GNU General Public License tikhomirov@596: * contact TMate Software at support@hg4j.com tikhomirov@596: */ tikhomirov@596: package org.tmatesoft.hg.internal; tikhomirov@596: tikhomirov@596: import static org.tmatesoft.hg.core.HgIterateDirection.NewToOld; tikhomirov@691: import static org.tmatesoft.hg.core.HgIterateDirection.OldToNew; tikhomirov@596: tikhomirov@596: import java.util.Collections; tikhomirov@596: import java.util.LinkedList; tikhomirov@596: tikhomirov@596: import org.tmatesoft.hg.core.HgIterateDirection; tikhomirov@596: import org.tmatesoft.hg.core.Nodeid; tikhomirov@691: import org.tmatesoft.hg.internal.FileRenameHistory.Chunk; tikhomirov@596: import org.tmatesoft.hg.repo.HgDataFile; tikhomirov@628: import org.tmatesoft.hg.repo.HgRuntimeException; tikhomirov@596: tikhomirov@596: /** tikhomirov@596: * History of a file, with copy/renames, and corresponding revision information. tikhomirov@596: * Facility for file history iteration. tikhomirov@596: * tikhomirov@624: * TODO [post-1.1] Utilize in HgLogCommand and anywhere else we need to follow file history tikhomirov@596: * tikhomirov@596: * @author Artem Tikhomirov tikhomirov@596: * @author TMate Software Ltd. tikhomirov@596: */ tikhomirov@596: public class FileHistory { tikhomirov@596: tikhomirov@596: private LinkedList fileCompleteHistory = new LinkedList(); tikhomirov@596: private final HgDataFile df; tikhomirov@596: private final int csetTo; tikhomirov@596: private final int csetFrom; tikhomirov@596: tikhomirov@596: public FileHistory(HgDataFile file, int fromChangeset, int toChangeset) { tikhomirov@596: df = file; tikhomirov@596: csetFrom = fromChangeset; tikhomirov@596: csetTo = toChangeset; tikhomirov@596: } tikhomirov@596: tikhomirov@596: public int getStartChangeset() { tikhomirov@596: return csetFrom; tikhomirov@596: } tikhomirov@596: tikhomirov@596: public int getEndChangeset() { tikhomirov@596: return csetTo; tikhomirov@596: } tikhomirov@596: tikhomirov@628: public void build() throws HgRuntimeException { tikhomirov@596: fileCompleteHistory.clear(); // just in case, #build() is not expected to be called more than once tikhomirov@691: Nodeid fileRev = df.getRepo().getManifest().getFileRevision(csetTo, df.getPath()); tikhomirov@691: int fileRevIndex = df.getRevisionIndex(fileRev); tikhomirov@691: FileRenameHistory frh = new FileRenameHistory(csetFrom, csetTo); tikhomirov@691: if (frh.isOutOfRange(df, fileRevIndex)) { tikhomirov@691: return; tikhomirov@691: } tikhomirov@691: frh.build(df, fileRevIndex); tikhomirov@691: FileRevisionHistoryChunk prevChunk = null; tikhomirov@691: for (Chunk c : frh.iterate(OldToNew)) { tikhomirov@691: FileRevisionHistoryChunk fileHistory = new FileRevisionHistoryChunk(c.file(), c.firstCset(), c.lastCset(), c.firstFileRev(), c.lastFileRev()); tikhomirov@691: fileHistory.init(); tikhomirov@691: if (fileHistory.revisionCount() == 0) { tikhomirov@691: // no revisions on our cset range of interest tikhomirov@691: continue; tikhomirov@596: } tikhomirov@691: if (prevChunk != null) { tikhomirov@691: prevChunk.linkTo(fileHistory); tikhomirov@691: } tikhomirov@691: fileCompleteHistory.addLast(fileHistory); // to get the list in old-to-new order tikhomirov@691: prevChunk = fileHistory; tikhomirov@691: } tikhomirov@596: // fileCompleteHistory is in (origin, intermediate target, ultimate target) order tikhomirov@596: } tikhomirov@596: tikhomirov@596: public Iterable iterate(HgIterateDirection order) { tikhomirov@596: if (order == NewToOld) { tikhomirov@596: return ReverseIterator.reversed(fileCompleteHistory); tikhomirov@596: } tikhomirov@596: return Collections.unmodifiableList(fileCompleteHistory); tikhomirov@596: } tikhomirov@596: }