Mercurial > hg4j
diff src/org/tmatesoft/hg/repo/HgMergeState.java @ 231:1792b37650f2
Introduced access to conflict resolution information (merge state)
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Wed, 01 Jun 2011 05:44:25 +0200 |
parents | |
children | 3fbfce107f94 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/tmatesoft/hg/repo/HgMergeState.java Wed Jun 01 05:44:25 2011 +0200 @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2011 TMate Software Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For information on how to redistribute this software under + * the terms of a license other than GNU General Public License + * contact TMate Software at support@hg4j.com + */ +package org.tmatesoft.hg.repo; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.tmatesoft.hg.core.HgBadStateException; +import org.tmatesoft.hg.core.HgFileRevision; +import org.tmatesoft.hg.core.HgLogCommand.FileRevision; +import org.tmatesoft.hg.core.Nodeid; +import org.tmatesoft.hg.internal.Pool; +import org.tmatesoft.hg.repo.HgStatusCollector.ManifestRevisionInspector; +import org.tmatesoft.hg.util.Path; +import org.tmatesoft.hg.util.PathPool; +import org.tmatesoft.hg.util.PathRewrite; + +/** + * + * @author Artem Tikhomirov + * @author TMate Software Ltd. + */ +public class HgMergeState { + private Nodeid wcp1, wcp2; + + public enum Kind { + Resolved, Unresolved; + } + + public static class Entry { + private final Kind state; + private final HgFileRevision parent1; + private final HgFileRevision parent2; + private final HgFileRevision ancestor; + private final Path wcFile; + + /*package-local*/Entry(Kind s, Path actualCopy, HgFileRevision p1, HgFileRevision p2, HgFileRevision ca) { + if (p1 == null || p2 == null || ca == null || actualCopy == null) { + throw new IllegalArgumentException(); + } + state = s; + wcFile = actualCopy; + parent1 = p1; + parent2 = p2; + ancestor = ca; + } + + public Kind getState() { + return state; + } + public Path getActualFile() { + return wcFile; + } + public HgFileRevision getFirstParent() { + return parent1; + } + public HgFileRevision getSecondParent() { + return parent2; + } + public HgFileRevision getCommonAncestor() { + return ancestor; + } + } + + private final HgRepository repo; + private Entry[] entries; + + HgMergeState(HgRepository hgRepo) { + repo = hgRepo; + } + + public void refresh() throws IOException/*XXX it's unlikely caller can do anything reasonable about IOException */ { + entries = null; + final File f = new File(repo.getRepositoryRoot(), "merge/state"); + if (!f.canRead()) { + // empty state + return; + } + Nodeid[] wcParents = repo.loadDirstate().parents(); + wcp1 = wcParents[0]; wcp2 = wcParents[1]; + ArrayList<Entry> result = new ArrayList<Entry>(); + PathPool pathPool = new PathPool(new PathRewrite.Empty()); + Pool<Nodeid> nodeidPool = new Pool<Nodeid>(); + Pool<String> fnamePool = new Pool<String>(); + final ManifestRevisionInspector m1 = new ManifestRevisionInspector(nodeidPool, fnamePool); + final ManifestRevisionInspector m2 = new ManifestRevisionInspector(nodeidPool, fnamePool); + final int rp1 = repo.getChangelog().getLocalRevision(wcp1); + final int rp2 = repo.getChangelog().getLocalRevision(wcp2); + repo.getManifest().walk(rp1, rp1, m1); + repo.getManifest().walk(rp2, rp2, m2); + BufferedReader br = new BufferedReader(new FileReader(f)); + String s = br.readLine(); + Nodeid n = Nodeid.fromAscii(s); + if (!wcp1.equals(n)) { + throw new AssertionError("I assume merge/state records revision of the wc we merge into"); + } + while ((s = br.readLine()) != null) { + String[] r = s.split("\\00"); + HgFileRevision p1 = new HgFileRevision(repo, m1.nodeid(r[3]), pathPool.path(r[3])); + HgFileRevision ca = new HgFileRevision(repo, Nodeid.fromAscii(r[5]), pathPool.path(r[4])); + HgFileRevision p2 = new HgFileRevision(repo, m2.nodeid(r[6]), pathPool.path(r[6])); + final Kind k; + if ("u".equals(r[1])) { + k = Kind.Unresolved; + } else if ("r".equals(r[1])) { + k = Kind.Resolved; + } else { + throw new HgBadStateException(r[1]); + } + Entry e = new Entry(k, pathPool.path(r[0]), p1, p2, ca); + result.add(e); + } + entries = result.toArray(new Entry[result.size()]); + br.close(); + pathPool.clear(); + } + + public Nodeid getFirstParent() { + if (wcp1 == null) { + throw new HgBadStateException("Call #refresh() first"); + } + return wcp1; + } + + public Nodeid getSecondParent() { + if (wcp2 == null) { + throw new HgBadStateException("Call #refresh() first"); + } + return wcp2; + } + + public List<Entry> getConflicts() { + return entries == null ? Collections.<Entry>emptyList() : Arrays.asList(entries); + } +}