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,