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, |