comparison src/org/tmatesoft/hg/core/HgFileInformer.java @ 417:ccd7d25e5aea

New and better name for HgFileInformer - HgChangesetFileSneaker. Explain (comments) ties between HgManifest, HgDataFile, HgChangesetFileSneaker and reasons for method placement
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 22 Mar 2012 20:14:06 +0100
parents ee8264d80747
children
comparison
equal deleted inserted replaced
416:d30083c80d52 417:ccd7d25e5aea
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 org.tmatesoft.hg.internal.ManifestRevision;
20 import org.tmatesoft.hg.repo.HgDataFile;
21 import org.tmatesoft.hg.repo.HgManifest;
22 import org.tmatesoft.hg.repo.HgRepository; 19 import org.tmatesoft.hg.repo.HgRepository;
23 import org.tmatesoft.hg.util.Path; 20
24 import org.tmatesoft.hg.util.Status;
25 21
26 /** 22 /**
27 * Primary purpose is to provide information about file revisions at specific changeset. Multiple {@link #check(Path)} calls 23 * @deprecated Use {@link HgChangesetFileSneaker} directly
28 * are possible once {@link #changeset(Nodeid)} (and optionally, {@link #followRenames(boolean)}) were set.
29 *
30 * <p>Sample:
31 * <pre><code>
32 * HgFileInformer i = new HgFileInformer(hgRepo).changeset(Nodeid.fromString("<40 digits>")).followRenames(true);
33 * if (i.check(file)) {
34 * HgCatCommand catCmd = new HgCatCommand(hgRepo).revision(i.getFileRevision());
35 * catCmd.execute(...);
36 * ...
37 * }
38 * </pre></code>
39 *
40 * FIXME need better name. It's more about manifest of specific changeset, rather than informing (about) files
41 * TODO may add #manifest(Nodeid) to select manifest according to its revision (not only changeset revision as it's now)
42 *
43 * @author Artem Tikhomirov 24 * @author Artem Tikhomirov
44 * @author TMate Software Ltd. 25 * @author TMate Software Ltd.
45 */ 26 */
46 public class HgFileInformer { 27 @Deprecated
47 28 public class HgFileInformer extends HgChangesetFileSneaker {
48 private final HgRepository repo; 29
49 private boolean followRenames;
50 private Nodeid cset;
51 private ManifestRevision cachedManifest;
52 private HgFileRevision fileRevision;
53 private boolean renamed;
54 private Status checkResult;
55
56 public HgFileInformer(HgRepository hgRepo) { 30 public HgFileInformer(HgRepository hgRepo) {
57 repo = hgRepo; 31 super(hgRepo);
58 }
59
60 /**
61 * Select specific changelog revision
62 *
63 * @param nid changeset identifier
64 * @return <code>this</code> for convenience
65 */
66 public HgFileInformer changeset(Nodeid nid) {
67 if (nid == null || nid.isNull()) {
68 throw new IllegalArgumentException();
69 }
70 cset = nid;
71 cachedManifest = null;
72 fileRevision = null;
73 return this;
74 }
75
76 /**
77 * Whether to check file origins, default is false (look up only the name supplied)
78 *
79 * @param follow <code>true</code> to check copy/rename origin of the file if it is a copy.
80 * @return <code>this</code> for convenience
81 */
82 public HgFileInformer followRenames(boolean follow) {
83 followRenames = follow;
84 fileRevision = null;
85 return this;
86 }
87
88 /**
89 * Shortcut to perform {@link #check(Path)} and {@link #exists()}. Result of the check may be accessed via {@link #getCheckStatus()}.
90 *
91 * @param file name of the file in question
92 * @return <code>true</code> if file is known at the selected changeset.
93 * @throws IllegalArgumentException if {@link #changeset(Nodeid)} not specified or file argument is bad.
94 * @throws HgInvalidControlFileException if access to revlog index/data entry failed
95 */
96 public boolean checkExists(Path file) throws HgInvalidControlFileException {
97 check(file);
98 if (!checkResult.isOk() && checkResult.getException() instanceof HgInvalidControlFileException) {
99 throw (HgInvalidControlFileException) checkResult.getException();
100 }
101 return checkResult.isOk() && exists();
102 }
103
104 /**
105 * Find file (or its origin, if {@link #followRenames(boolean)} was set to <code>true</code>) among files known at specified {@link #changeset(Nodeid)}.
106 *
107 * @param file name of the file in question
108 * @return status object that describes outcome, {@link Status#isOk() Ok} status indicates successful completion of the operation, but doesn't imply
109 * file existence, use {@link #exists()} for that purpose. Message of the status may provide further hints on what exactly had happened.
110 * @throws IllegalArgumentException if {@link #changeset(Nodeid)} not specified or file argument is bad.
111 */
112 public Status check(Path file) {
113 fileRevision = null;
114 checkResult = null;
115 renamed = false;
116 if (cset == null || file == null || file.isDirectory()) {
117 throw new IllegalArgumentException();
118 }
119 HgDataFile dataFile = repo.getFileNode(file);
120 if (!dataFile.exists()) {
121 checkResult = new Status(Status.Kind.OK, String.format("File named %s is not known in the repository", file));
122 return checkResult;
123 }
124 Nodeid toExtract = null;
125 HgManifest.Flags extractRevFlags = null;
126 String phaseMsg = "Extract manifest revision failed";
127 try {
128 if (cachedManifest == null) {
129 int csetRev = repo.getChangelog().getRevisionIndex(cset);
130 cachedManifest = new ManifestRevision(null, null); // XXX how about context and cached manifest revisions
131 repo.getManifest().walk(csetRev, csetRev, cachedManifest);
132 // cachedManifest shall be meaningful - changelog.getRevisionIndex() above ensures we've got version that exists.
133 }
134 toExtract = cachedManifest.nodeid(file);
135 extractRevFlags = cachedManifest.flags(file);
136 phaseMsg = "Follow copy/rename failed";
137 if (toExtract == null && followRenames) {
138 while (toExtract == null && dataFile.isCopy()) {
139 renamed = true;
140 file = dataFile.getCopySourceName();
141 dataFile = repo.getFileNode(file);
142 toExtract = cachedManifest.nodeid(file);
143 extractRevFlags = cachedManifest.flags(file);
144 }
145 }
146 } catch (HgException ex) {
147 checkResult = new Status(Status.Kind.ERROR, phaseMsg, ex);
148 return checkResult;
149 }
150 if (toExtract != null) {
151 fileRevision = new HgFileRevision(repo, toExtract, extractRevFlags, dataFile.getPath());
152 checkResult = new Status(Status.Kind.OK, String.format("File %s, revision %s found at changeset %s", dataFile.getPath(), toExtract.shortNotation(), cset.shortNotation()));
153 return checkResult;
154 }
155 checkResult = new Status(Status.Kind.OK, String.format("File %s nor its origins were known at repository %s revision", file, cset.shortNotation()));
156 return checkResult;
157 }
158
159 /**
160 * Re-get latest check status object
161 */
162 public Status getCheckStatus() {
163 assertCheckRan();
164 return checkResult;
165 }
166
167 /**
168 * @return result of the last {@link #check(Path)} call.
169 */
170 public boolean exists() {
171 assertCheckRan();
172 return fileRevision != null;
173 }
174
175 /**
176 * @return <code>true</code> if checked file was known by another name at the time of specified changeset.
177 */
178 public boolean hasAnotherName() {
179 assertCheckRan();
180 return renamed;
181 }
182
183 /**
184 * @return holder for file revision information
185 */
186 public HgFileRevision getFileRevision() {
187 assertCheckRan();
188 return fileRevision;
189 }
190
191 /**
192 * Name of the checked file as it was known at the time of the specified changeset.
193 *
194 * @return handy shortcut for <code>getFileRevision().getPath()</code>
195 */
196 public Path filename() {
197 assertCheckRan();
198 return fileRevision.getPath();
199 }
200
201 /**
202 * Revision of the checked file
203 *
204 * @return handy shortcut for <code>getFileRevision().getRevision()</code>
205 */
206 public Nodeid revision() {
207 assertCheckRan();
208 return fileRevision.getRevision();
209 }
210
211 private void assertCheckRan() {
212 if (checkResult == null) {
213 throw new HgBadStateException("Shall invoke #check(Path) first");
214 }
215 } 32 }
216 } 33 }