Mercurial > jhg
comparison src/org/tmatesoft/hg/repo/HgMergeState.java @ 348:a0864b2892cd
Expose errors reading mercurial control files with exception
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Thu, 24 Nov 2011 02:57:03 +0100 |
| parents | 75c452fdd76a |
| children | 2fadf8695f8a |
comparison
equal
deleted
inserted
replaced
| 347:8da7ade36c57 | 348:a0864b2892cd |
|---|---|
| 27 import java.util.Collections; | 27 import java.util.Collections; |
| 28 import java.util.List; | 28 import java.util.List; |
| 29 | 29 |
| 30 import org.tmatesoft.hg.core.HgBadStateException; | 30 import org.tmatesoft.hg.core.HgBadStateException; |
| 31 import org.tmatesoft.hg.core.HgFileRevision; | 31 import org.tmatesoft.hg.core.HgFileRevision; |
| 32 import org.tmatesoft.hg.core.HgInvalidControlFileException; | |
| 32 import org.tmatesoft.hg.core.Nodeid; | 33 import org.tmatesoft.hg.core.Nodeid; |
| 33 import org.tmatesoft.hg.internal.ManifestRevision; | 34 import org.tmatesoft.hg.internal.ManifestRevision; |
| 34 import org.tmatesoft.hg.internal.Pool; | 35 import org.tmatesoft.hg.internal.Pool; |
| 35 import org.tmatesoft.hg.util.Pair; | 36 import org.tmatesoft.hg.util.Pair; |
| 36 import org.tmatesoft.hg.util.Path; | 37 import org.tmatesoft.hg.util.Path; |
| 89 | 90 |
| 90 HgMergeState(HgRepository hgRepo) { | 91 HgMergeState(HgRepository hgRepo) { |
| 91 repo = hgRepo; | 92 repo = hgRepo; |
| 92 } | 93 } |
| 93 | 94 |
| 94 public void refresh() throws IOException/*XXX it's unlikely caller can do anything reasonable about IOException */ { | 95 public void refresh() throws HgInvalidControlFileException { |
| 95 entries = null; | 96 entries = null; |
| 96 // it's possible there are two parents but no merge/state, we shall report this case as 'merging', with proper | 97 // it's possible there are two parents but no merge/state, we shall report this case as 'merging', with proper |
| 97 // first and second parent values | 98 // first and second parent values |
| 98 stateParent = Nodeid.NULL; | 99 stateParent = Nodeid.NULL; |
| 99 Pool<Nodeid> nodeidPool = new Pool<Nodeid>(); | 100 Pool<Nodeid> nodeidPool = new Pool<Nodeid>(); |
| 103 final File f = new File(repo.getRepositoryRoot(), "merge/state"); | 104 final File f = new File(repo.getRepositoryRoot(), "merge/state"); |
| 104 if (!f.canRead()) { | 105 if (!f.canRead()) { |
| 105 // empty state | 106 // empty state |
| 106 return; | 107 return; |
| 107 } | 108 } |
| 108 ArrayList<Entry> result = new ArrayList<Entry>(); | 109 try { |
| 109 // FIXME need to settle use of Pool<Path> and PathPool | 110 ArrayList<Entry> result = new ArrayList<Entry>(); |
| 110 // latter is pool that can create objects on demand, former is just cache | 111 // FIXME need to settle use of Pool<Path> and PathPool |
| 111 PathPool pathPool = new PathPool(new PathRewrite.Empty()); | 112 // latter is pool that can create objects on demand, former is just cache |
| 112 final ManifestRevision m1 = new ManifestRevision(nodeidPool, fnamePool); | 113 PathPool pathPool = new PathPool(new PathRewrite.Empty()); |
| 113 final ManifestRevision m2 = new ManifestRevision(nodeidPool, fnamePool); | 114 final ManifestRevision m1 = new ManifestRevision(nodeidPool, fnamePool); |
| 114 if (!wcp2.isNull()) { | 115 final ManifestRevision m2 = new ManifestRevision(nodeidPool, fnamePool); |
| 115 final int rp2 = repo.getChangelog().getLocalRevision(wcp2); | 116 if (!wcp2.isNull()) { |
| 116 repo.getManifest().walk(rp2, rp2, m2); | 117 final int rp2 = repo.getChangelog().getLocalRevision(wcp2); |
| 117 } | 118 repo.getManifest().walk(rp2, rp2, m2); |
| 118 BufferedReader br = new BufferedReader(new FileReader(f)); | |
| 119 String s = br.readLine(); | |
| 120 stateParent = nodeidPool.unify(Nodeid.fromAscii(s)); | |
| 121 final int rp1 = repo.getChangelog().getLocalRevision(stateParent); | |
| 122 repo.getManifest().walk(rp1, rp1, m1); | |
| 123 while ((s = br.readLine()) != null) { | |
| 124 String[] r = s.split("\\00"); | |
| 125 Path p1fname = pathPool.path(r[3]); | |
| 126 Nodeid nidP1 = m1.nodeid(p1fname); | |
| 127 Nodeid nidCA = nodeidPool.unify(Nodeid.fromAscii(r[5])); | |
| 128 HgFileRevision p1 = new HgFileRevision(repo, nidP1, p1fname); | |
| 129 HgFileRevision ca; | |
| 130 if (nidCA == nidP1 && r[3].equals(r[4])) { | |
| 131 ca = p1; | |
| 132 } else { | |
| 133 ca = new HgFileRevision(repo, nidCA, pathPool.path(r[4])); | |
| 134 } | 119 } |
| 135 HgFileRevision p2; | 120 BufferedReader br = new BufferedReader(new FileReader(f)); |
| 136 if (!wcp2.isNull() || !r[6].equals(r[4])) { | 121 String s = br.readLine(); |
| 137 final Path p2fname = pathPool.path(r[6]); | 122 stateParent = nodeidPool.unify(Nodeid.fromAscii(s)); |
| 138 Nodeid nidP2 = m2.nodeid(p2fname); | 123 final int rp1 = repo.getChangelog().getLocalRevision(stateParent); |
| 139 if (nidP2 == null) { | 124 repo.getManifest().walk(rp1, rp1, m1); |
| 140 assert false : "There's not enough information (or I don't know where to look) in merge/state to find out what's the second parent"; | 125 while ((s = br.readLine()) != null) { |
| 141 nidP2 = NULL; | 126 String[] r = s.split("\\00"); |
| 127 Path p1fname = pathPool.path(r[3]); | |
| 128 Nodeid nidP1 = m1.nodeid(p1fname); | |
| 129 Nodeid nidCA = nodeidPool.unify(Nodeid.fromAscii(r[5])); | |
| 130 HgFileRevision p1 = new HgFileRevision(repo, nidP1, p1fname); | |
| 131 HgFileRevision ca; | |
| 132 if (nidCA == nidP1 && r[3].equals(r[4])) { | |
| 133 ca = p1; | |
| 134 } else { | |
| 135 ca = new HgFileRevision(repo, nidCA, pathPool.path(r[4])); | |
| 142 } | 136 } |
| 143 p2 = new HgFileRevision(repo, nidP2, p2fname); | 137 HgFileRevision p2; |
| 144 } else { | 138 if (!wcp2.isNull() || !r[6].equals(r[4])) { |
| 145 // no second parent known. no idea what to do here, assume linear merge, use common ancestor as parent | 139 final Path p2fname = pathPool.path(r[6]); |
| 146 p2 = ca; | 140 Nodeid nidP2 = m2.nodeid(p2fname); |
| 141 if (nidP2 == null) { | |
| 142 assert false : "There's not enough information (or I don't know where to look) in merge/state to find out what's the second parent"; | |
| 143 nidP2 = NULL; | |
| 144 } | |
| 145 p2 = new HgFileRevision(repo, nidP2, p2fname); | |
| 146 } else { | |
| 147 // no second parent known. no idea what to do here, assume linear merge, use common ancestor as parent | |
| 148 p2 = ca; | |
| 149 } | |
| 150 final Kind k; | |
| 151 if ("u".equals(r[1])) { | |
| 152 k = Kind.Unresolved; | |
| 153 } else if ("r".equals(r[1])) { | |
| 154 k = Kind.Resolved; | |
| 155 } else { | |
| 156 throw new HgBadStateException(r[1]); | |
| 157 } | |
| 158 Entry e = new Entry(k, pathPool.path(r[0]), p1, p2, ca); | |
| 159 result.add(e); | |
| 147 } | 160 } |
| 148 final Kind k; | 161 entries = result.toArray(new Entry[result.size()]); |
| 149 if ("u".equals(r[1])) { | 162 br.close(); |
| 150 k = Kind.Unresolved; | 163 pathPool.clear(); |
| 151 } else if ("r".equals(r[1])) { | 164 } catch (IOException ex) { |
| 152 k = Kind.Resolved; | 165 throw new HgInvalidControlFileException("Merge state read failed", ex, f); |
| 153 } else { | 166 } |
| 154 throw new HgBadStateException(r[1]); | |
| 155 } | |
| 156 Entry e = new Entry(k, pathPool.path(r[0]), p1, p2, ca); | |
| 157 result.add(e); | |
| 158 } | |
| 159 entries = result.toArray(new Entry[result.size()]); | |
| 160 br.close(); | |
| 161 pathPool.clear(); | |
| 162 } | 167 } |
| 163 | 168 |
| 164 /** | 169 /** |
| 165 * Repository is in 'merging' state when changeset to be committed got two parents. | 170 * Repository is in 'merging' state when changeset to be committed got two parents. |
| 166 * This method doesn't tell whether there are (un)resolved conflicts in the working copy, | 171 * This method doesn't tell whether there are (un)resolved conflicts in the working copy, |
