Mercurial > jhg
comparison src/org/tmatesoft/hg/core/HgChangesetFileSneaker.java @ 690:b286222158be
Fix file.isCopy() use for status and cat commands
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Thu, 01 Aug 2013 21:45:47 +0200 |
parents | 3ca4ae7bdd38 |
children | 72fc7774b87e |
comparison
equal
deleted
inserted
replaced
689:5050ee565bd1 | 690:b286222158be |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2011-2012 TMate Software Ltd | 2 * Copyright (c) 2011-2013 TMate Software Ltd |
3 * | 3 * |
4 * This program is free software; you can redistribute it and/or modify | 4 * This program is free software; you can redistribute it and/or modify |
5 * it under the terms of the GNU General Public License as published by | 5 * it under the terms of the GNU General Public License as published by |
6 * the Free Software Foundation; version 2 of the License. | 6 * the Free Software Foundation; version 2 of the License. |
7 * | 7 * |
14 * the terms of a license other than GNU General Public License | 14 * the terms of a license other than GNU General Public License |
15 * contact TMate Software at support@hg4j.com | 15 * contact TMate Software at support@hg4j.com |
16 */ | 16 */ |
17 package org.tmatesoft.hg.core; | 17 package org.tmatesoft.hg.core; |
18 | 18 |
19 import java.util.ArrayDeque; | |
20 | |
19 import org.tmatesoft.hg.internal.ManifestRevision; | 21 import org.tmatesoft.hg.internal.ManifestRevision; |
20 import org.tmatesoft.hg.repo.HgDataFile; | 22 import org.tmatesoft.hg.repo.HgDataFile; |
21 import org.tmatesoft.hg.repo.HgInvalidStateException; | 23 import org.tmatesoft.hg.repo.HgInvalidStateException; |
22 import org.tmatesoft.hg.repo.HgManifest; | 24 import org.tmatesoft.hg.repo.HgManifest; |
25 import org.tmatesoft.hg.repo.HgManifest.Flags; | |
23 import org.tmatesoft.hg.repo.HgRepository; | 26 import org.tmatesoft.hg.repo.HgRepository; |
24 import org.tmatesoft.hg.repo.HgRuntimeException; | 27 import org.tmatesoft.hg.repo.HgRuntimeException; |
28 import org.tmatesoft.hg.util.Outcome; | |
29 import org.tmatesoft.hg.util.Pair; | |
25 import org.tmatesoft.hg.util.Path; | 30 import org.tmatesoft.hg.util.Path; |
26 import org.tmatesoft.hg.util.Outcome; | |
27 | 31 |
28 /** | 32 /** |
29 * Primary purpose is to provide information about file revisions at specific changeset. Multiple {@link #check(Path)} calls | 33 * Primary purpose is to provide information about file revisions at specific changeset. Multiple {@link #check(Path)} calls |
30 * are possible once {@link #changeset(Nodeid)} (and optionally, {@link #followRenames(boolean)}) were set. | 34 * are possible once {@link #changeset(Nodeid)} (and optionally, {@link #followRenames(boolean)}) were set. |
31 * | 35 * |
129 if (!dataFile.exists()) { | 133 if (!dataFile.exists()) { |
130 checkResult = new Outcome(Outcome.Kind.Success, String.format("File named %s is not known in the repository", file)); | 134 checkResult = new Outcome(Outcome.Kind.Success, String.format("File named %s is not known in the repository", file)); |
131 return checkResult; | 135 return checkResult; |
132 } | 136 } |
133 Nodeid toExtract = null; | 137 Nodeid toExtract = null; |
134 HgManifest.Flags extractRevFlags = null; | |
135 String phaseMsg = "Extract manifest revision failed"; | 138 String phaseMsg = "Extract manifest revision failed"; |
136 try { | 139 try { |
137 if (cachedManifest == null) { | 140 if (cachedManifest == null) { |
138 int csetRev = repo.getChangelog().getRevisionIndex(cset); | 141 int csetRev = repo.getChangelog().getRevisionIndex(cset); |
139 cachedManifest = new ManifestRevision(null, null); // XXX how about context and cached manifest revisions | 142 cachedManifest = new ManifestRevision(null, null); // XXX how about context and cached manifest revisions |
140 repo.getManifest().walk(csetRev, csetRev, cachedManifest); | 143 repo.getManifest().walk(csetRev, csetRev, cachedManifest); |
141 // cachedManifest shall be meaningful - changelog.getRevisionIndex() above ensures we've got version that exists. | 144 // cachedManifest shall be meaningful - changelog.getRevisionIndex() above ensures we've got version that exists. |
142 } | 145 } |
143 toExtract = cachedManifest.nodeid(file); | 146 toExtract = cachedManifest.nodeid(file); |
144 extractRevFlags = cachedManifest.flags(file); | |
145 phaseMsg = "Follow copy/rename failed"; | 147 phaseMsg = "Follow copy/rename failed"; |
146 if (toExtract == null && followRenames) { | 148 if (toExtract == null && followRenames) { |
147 while (toExtract == null && dataFile.isCopy()) { | 149 int csetIndex = repo.getChangelog().getRevisionIndex(cset); |
148 renamed = true; | 150 int ccFileRevIndex = dataFile.getLastRevision(); // copy candidate |
149 file = dataFile.getCopySourceName(); | 151 int csetFileEnds = dataFile.getChangesetRevisionIndex(ccFileRevIndex); |
150 dataFile = repo.getFileNode(file); | 152 if (csetIndex > csetFileEnds) { |
151 toExtract = cachedManifest.nodeid(file); | 153 return new Outcome(Outcome.Kind.Success, String.format("%s: last known changeset for the file %s is %d. Follow renames is possible towards older changesets only", phaseMsg, file, csetFileEnds)); |
152 extractRevFlags = cachedManifest.flags(file); | |
153 } | 154 } |
155 // XXX code is similar to that in HgStatusCollector#getOriginIfCopy. Why it's different in lastOrigin processing then? | |
156 // traceback stack keeps record of all files with isCopy(fileRev) == true we've tried to follow, so that we can try earlier file | |
157 // revisions in case followed fileRev didn't succeed | |
158 ArrayDeque<Pair<HgDataFile, Integer>> traceback = new ArrayDeque<Pair<HgDataFile, Integer>>(); | |
159 do { | |
160 int ccCsetIndex = dataFile.getChangesetRevisionIndex(ccFileRevIndex); | |
161 if (ccCsetIndex <= csetIndex) { | |
162 // present dataFile is our (distant) origin | |
163 toExtract = dataFile.getRevision(ccFileRevIndex); | |
164 renamed = true; | |
165 break; | |
166 } | |
167 if (!dataFile.isCopy(ccFileRevIndex)) { | |
168 // nothing left to return to when traceback.isEmpty() | |
169 while (ccFileRevIndex == 0 && !traceback.isEmpty()) { | |
170 Pair<HgDataFile, Integer> lastTurnPoint = traceback.pop(); | |
171 dataFile = lastTurnPoint.first(); | |
172 ccFileRevIndex = lastTurnPoint.second(); // generally ccFileRevIndex != 0 here, but doesn't hurt to check, hence while | |
173 // fall through to shift down from the file revision we've already looked at | |
174 } | |
175 ccFileRevIndex--; | |
176 continue; | |
177 } | |
178 if (ccFileRevIndex > 0) { | |
179 // there's no reason to memorize turn point if it's the very first revision | |
180 // of the file and we won't be able to try any other earlier revision | |
181 traceback.push(new Pair<HgDataFile, Integer>(dataFile, ccFileRevIndex)); | |
182 } | |
183 HgFileRevision origin = dataFile.getCopySource(ccFileRevIndex); | |
184 dataFile = repo.getFileNode(origin.getPath()); | |
185 ccFileRevIndex = dataFile.getRevisionIndex(origin.getRevision()); | |
186 } while (ccFileRevIndex >= 0); | |
187 // didn't get to csetIndex, no ancestor in file rename history found. | |
154 } | 188 } |
155 } catch (HgRuntimeException ex) { | 189 } catch (HgRuntimeException ex) { |
156 checkResult = new Outcome(Outcome.Kind.Failure, phaseMsg, ex); | 190 checkResult = new Outcome(Outcome.Kind.Failure, phaseMsg, ex); |
157 return checkResult; | 191 return checkResult; |
158 } | 192 } |
159 if (toExtract != null) { | 193 if (toExtract != null) { |
194 Flags extractRevFlags = cachedManifest.flags(dataFile.getPath()); | |
160 fileRevision = new HgFileRevision(repo, toExtract, extractRevFlags, dataFile.getPath()); | 195 fileRevision = new HgFileRevision(repo, toExtract, extractRevFlags, dataFile.getPath()); |
161 checkResult = new Outcome(Outcome.Kind.Success, String.format("File %s, revision %s found at changeset %s", dataFile.getPath(), toExtract.shortNotation(), cset.shortNotation())); | 196 checkResult = new Outcome(Outcome.Kind.Success, String.format("File %s, revision %s found at changeset %s", dataFile.getPath(), toExtract.shortNotation(), cset.shortNotation())); |
162 return checkResult; | 197 return checkResult; |
163 } | 198 } |
164 checkResult = new Outcome(Outcome.Kind.Success, String.format("File %s nor its origins were known at repository %s revision", file, cset.shortNotation())); | 199 checkResult = new Outcome(Outcome.Kind.Success, String.format("File %s nor its origins were known at revision %s", file, cset.shortNotation())); |
165 return checkResult; | 200 return checkResult; |
166 } | 201 } |
167 | 202 |
168 /** | 203 /** |
169 * Re-get latest check status object | 204 * Re-get latest check status object |