tikhomirov@501: /* tikhomirov@628: * Copyright (c) 2012-2013 TMate Software Ltd tikhomirov@501: * tikhomirov@501: * This program is free software; you can redistribute it and/or modify tikhomirov@501: * it under the terms of the GNU General Public License as published by tikhomirov@501: * the Free Software Foundation; version 2 of the License. tikhomirov@501: * tikhomirov@501: * This program is distributed in the hope that it will be useful, tikhomirov@501: * but WITHOUT ANY WARRANTY; without even the implied warranty of tikhomirov@501: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the tikhomirov@501: * GNU General Public License for more details. tikhomirov@501: * tikhomirov@501: * For information on how to redistribute this software under tikhomirov@501: * the terms of a license other than GNU General Public License tikhomirov@501: * contact TMate Software at support@hg4j.com tikhomirov@501: */ tikhomirov@501: package org.tmatesoft.hg.repo.ext; tikhomirov@501: tikhomirov@501: import java.io.File; tikhomirov@501: import java.util.ArrayList; tikhomirov@501: import java.util.HashMap; tikhomirov@501: import java.util.Iterator; tikhomirov@501: import java.util.Map; tikhomirov@501: import java.util.NoSuchElementException; tikhomirov@501: tikhomirov@501: import org.tmatesoft.hg.core.HgBadNodeidFormatException; tikhomirov@501: import org.tmatesoft.hg.core.HgIOException; tikhomirov@501: import org.tmatesoft.hg.core.Nodeid; tikhomirov@501: import org.tmatesoft.hg.internal.Internals; tikhomirov@501: import org.tmatesoft.hg.internal.LineReader; tikhomirov@501: import org.tmatesoft.hg.repo.HgInvalidStateException; tikhomirov@501: tikhomirov@501: /** tikhomirov@501: * Support for standard Rebase extension. tikhomirov@501: * tikhomirov@501: * @see http://mercurial.selenic.com/wiki/RebaseExtension tikhomirov@501: * @since 1.1 tikhomirov@501: * @author Artem Tikhomirov tikhomirov@501: * @author TMate Software Ltd. tikhomirov@501: */ tikhomirov@501: public class Rebase { tikhomirov@501: private Internals repo; tikhomirov@501: private Nodeid workingDirParent; tikhomirov@501: private Nodeid destRevision; tikhomirov@501: private Nodeid externalParent; tikhomirov@501: private Map state; tikhomirov@501: private boolean collapse; tikhomirov@501: private boolean keepOriginalRevisions; tikhomirov@501: private boolean keepBranchNames; tikhomirov@501: tikhomirov@501: /*package-local*/ Rebase(Internals internalRepo) { tikhomirov@501: repo = internalRepo; tikhomirov@501: } tikhomirov@501: tikhomirov@501: public Rebase refresh() throws HgIOException { tikhomirov@501: workingDirParent = null; tikhomirov@501: destRevision = null; tikhomirov@501: externalParent = null; tikhomirov@501: state = null; tikhomirov@501: File f = repo.getFileFromRepoDir("rebasestate"); tikhomirov@501: if (!f.exists()) { tikhomirov@501: return this; tikhomirov@501: } tikhomirov@501: state = new HashMap(); tikhomirov@501: try { tikhomirov@501: LineReader lr = new LineReader(f, repo.getSessionContext().getLog()); tikhomirov@501: ArrayList contents = new ArrayList(); tikhomirov@501: lr.read(new LineReader.SimpleLineCollector(), contents); tikhomirov@501: Iterator it = contents.iterator(); tikhomirov@501: workingDirParent = Nodeid.fromAscii(it.next()); tikhomirov@501: destRevision = Nodeid.fromAscii(it.next()); tikhomirov@501: externalParent = Nodeid.fromAscii(it.next()); tikhomirov@501: collapse = "1".equals(it.next()); tikhomirov@501: keepOriginalRevisions = "1".equals(it.next()); tikhomirov@501: keepBranchNames = "1".equals(it.next()); tikhomirov@501: final String nullmerge = "-2"; tikhomirov@501: while (it.hasNext()) { tikhomirov@501: String line = it.next(); tikhomirov@501: int x = line.indexOf(':'); tikhomirov@501: if (x == -1) { tikhomirov@501: throw new HgInvalidStateException(line); tikhomirov@501: } tikhomirov@501: Nodeid oldRev = Nodeid.fromAscii(line.substring(0, x)); tikhomirov@501: Nodeid newRev; tikhomirov@501: if (line.regionMatches(x+1, nullmerge, 0, nullmerge.length())) { tikhomirov@501: newRev = null; tikhomirov@501: } else { tikhomirov@501: newRev = Nodeid.fromAscii(line.substring(x+1)); tikhomirov@501: } tikhomirov@501: state.put(oldRev, newRev); tikhomirov@501: } tikhomirov@501: } catch (NoSuchElementException ex) { tikhomirov@501: throw new HgIOException("Bad format of rebase state file", f); tikhomirov@501: } catch (HgBadNodeidFormatException ex) { tikhomirov@501: throw new HgIOException("Bad format of rebase state file", ex, f); tikhomirov@501: } tikhomirov@501: return this; tikhomirov@501: } tikhomirov@501: tikhomirov@501: /** tikhomirov@501: * Tells whether rebase process was interrupted to manually resolve a merge tikhomirov@501: * and can be resumed or aborted. tikhomirov@501: * tikhomirov@501: * @return true when rebase is in progress tikhomirov@501: */ tikhomirov@501: public boolean isRebaseInProgress() { tikhomirov@501: return state != null; tikhomirov@501: } tikhomirov@501: tikhomirov@501: public Nodeid getWorkingDirParent() { tikhomirov@501: assert isRebaseInProgress(); tikhomirov@501: return workingDirParent; tikhomirov@501: } tikhomirov@501: tikhomirov@501: public Nodeid getTarget() { tikhomirov@501: assert isRebaseInProgress(); tikhomirov@501: return destRevision; tikhomirov@501: } tikhomirov@501: tikhomirov@501: public Nodeid getExternalParent() { tikhomirov@501: assert isRebaseInProgress(); tikhomirov@501: assert collapse; tikhomirov@501: return externalParent; tikhomirov@501: } tikhomirov@501: tikhomirov@501: public boolean isCollapse() { tikhomirov@501: return collapse; tikhomirov@501: } tikhomirov@501: tikhomirov@501: public boolean isKeepOriginalRevisions() { tikhomirov@501: return keepOriginalRevisions; tikhomirov@501: } tikhomirov@501: tikhomirov@501: public boolean isKeepBranchNames() { tikhomirov@501: return keepBranchNames; tikhomirov@501: } tikhomirov@501: }