Mercurial > hg4j
comparison src/org/tmatesoft/hg/repo/HgBranches.java @ 340:a54bfe0db959
IAE using stale data from branchheads file (invalid due to repository rollback)
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Thu, 17 Nov 2011 06:16:20 +0100 |
parents | 8952f89be195 |
children | a0864b2892cd |
comparison
equal
deleted
inserted
replaced
339:863356c2847e | 340:a54bfe0db959 |
---|---|
52 | 52 |
53 HgBranches(HgRepository hgRepo) { | 53 HgBranches(HgRepository hgRepo) { |
54 repo = hgRepo; | 54 repo = hgRepo; |
55 } | 55 } |
56 | 56 |
57 private int readCache() { | 57 private int readCache() /*XXX throws parse errors, e.g. may fail with NumberFormatException */{ |
58 File branchheadsCache = getCacheFile(); | 58 File branchheadsCache = getCacheFile(); |
59 int lastInCache = -1; | 59 int lastInCache = -1; |
60 if (!branchheadsCache.canRead()) { | 60 if (!branchheadsCache.canRead()) { |
61 return lastInCache; | 61 return lastInCache; |
62 } | 62 } |
69 if (line == null || line.trim().length() == 0) { | 69 if (line == null || line.trim().length() == 0) { |
70 return lastInCache; | 70 return lastInCache; |
71 } | 71 } |
72 String[] cacheIdentity = spacePattern.split(line.trim()); | 72 String[] cacheIdentity = spacePattern.split(line.trim()); |
73 lastInCache = Integer.parseInt(cacheIdentity[1]); | 73 lastInCache = Integer.parseInt(cacheIdentity[1]); |
74 // XXX may want to check if nodeid of cset from repo.getChangelog() of lastInCache index match cacheIdentity[0] | 74 final int lastKnownRepoRevIndex = repo.getChangelog().getLastRevision(); |
75 // | 75 if (lastInCache > lastKnownRepoRevIndex || !repo.getChangelog().getRevision(lastKnownRepoRevIndex).equals(Nodeid.fromAscii(cacheIdentity[0]))) { |
76 // there are chances cache file got invalid entries due to e.g. rollback operation | |
77 return -1; | |
78 } | |
76 while ((line = br.readLine()) != null) { | 79 while ((line = br.readLine()) != null) { |
77 String[] elements = spacePattern.split(line.trim()); | 80 String[] elements = spacePattern.split(line.trim()); |
78 if (elements.length != 2) { | 81 if (elements.length != 2) { |
79 // bad entry | 82 // bad entry |
80 continue; | 83 continue; |
110 void collect(final ProgressSupport ps) { | 113 void collect(final ProgressSupport ps) { |
111 branches.clear(); | 114 branches.clear(); |
112 ps.start(1 + repo.getChangelog().getRevisionCount() * 2); | 115 ps.start(1 + repo.getChangelog().getRevisionCount() * 2); |
113 // | 116 // |
114 int lastCached = readCache(); | 117 int lastCached = readCache(); |
115 /* | |
116 * Next code was supposed to fill missing aspects of the BranchInfo, but is too slow | |
117 * | |
118 if (lastCached != -1 && lastCached <= repo.getChangelog().getLastRevision()) { | |
119 LinkedList<BranchInfo> incompleteBranches = new LinkedList<HgBranches.BranchInfo>(branches.values()); | |
120 for (BranchInfo bi : incompleteBranches) { | |
121 LinkedList<Nodeid> closedHeads = new LinkedList<Nodeid>(); | |
122 for (Nodeid h : bi.getHeads()) { | |
123 if ("1".equals(repo.getChangelog().changeset(h).extras().get("close"))) { | |
124 closedHeads.add(h); | |
125 } | |
126 } | |
127 HashSet<Nodeid> earliest = new HashSet<Nodeid>(bi.getHeads()); | |
128 HashSet<Nodeid> visited = new HashSet<Nodeid>(); | |
129 ArrayList<Nodeid> parents = new ArrayList<Nodeid>(2); | |
130 HashSet<Nodeid> candidate = new HashSet<Nodeid>(); | |
131 do { | |
132 candidate.clear(); | |
133 for (Nodeid e : earliest) { | |
134 parents.clear(); | |
135 if (pw.appendParentsOf(e, parents)) { | |
136 // at least one parent | |
137 Nodeid p1 = parents.get(0); | |
138 if (p1 != null && !visited.contains(p1) && bi.getName().equals(repo.getChangelog().changeset(p1).branch())) { | |
139 visited.add(p1); | |
140 candidate.add(p1); | |
141 } | |
142 Nodeid p2 = parents.size() > 1 ? parents.get(1) : null; | |
143 if (p2 != null && !visited.contains(p2) && bi.getName().equals(repo.getChangelog().changeset(p2).branch())) { | |
144 visited.add(p2); | |
145 candidate.add(p2); | |
146 } | |
147 } | |
148 } | |
149 if (!candidate.isEmpty()) { | |
150 earliest.clear(); | |
151 earliest.addAll(candidate); | |
152 } | |
153 } while (!candidate.isEmpty()); | |
154 // earliest can't be empty, we've started with non-empty heads. | |
155 Nodeid first = null; | |
156 if (earliest.size() == 1) { | |
157 first = earliest.iterator().next(); | |
158 } else { | |
159 int earliestRevNum = Integer.MAX_VALUE; | |
160 for (Nodeid e : earliest) { | |
161 int x = repo.getChangelog().getLocalRevision(e); | |
162 if (x < earliestRevNum) { | |
163 earliestRevNum = x; | |
164 first = e; | |
165 } | |
166 } | |
167 } | |
168 assert first != null; | |
169 System.out.println("Updated branch " + bi.getName()); | |
170 branches.put(bi.getName(), new BranchInfo(bi.getName(), first, bi.getHeads().toArray(new Nodeid[0]), closedHeads.size() == bi.getHeads().size())); | |
171 } | |
172 } | |
173 */ | |
174 isCacheActual = lastCached == repo.getChangelog().getLastRevision(); | 118 isCacheActual = lastCached == repo.getChangelog().getLastRevision(); |
175 if (!isCacheActual) { | 119 if (!isCacheActual) { |
176 final HgChangelog.ParentWalker pw = repo.getChangelog().new ParentWalker(); | 120 final HgChangelog.ParentWalker pw = repo.getChangelog().new ParentWalker(); |
177 pw.init(); | 121 pw.init(); |
178 ps.worked(repo.getChangelog().getRevisionCount()); | 122 ps.worked(repo.getChangelog().getRevisionCount()); |