comparison src/org/tmatesoft/hg/repo/HgRepository.java @ 610:5c68567b3645

Refresh tags, branches, bookmarks and ignore when their files (or csets in the repo) are changed
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 09 May 2013 21:06:48 +0200
parents e447384f3771
children f41dd9a3b8af
comparison
equal deleted inserted replaced
609:e4a71afd3c71 610:5c68567b3645
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.repo; 17 package org.tmatesoft.hg.repo;
18 18
19 import static org.tmatesoft.hg.repo.HgRepositoryFiles.*; 19 import static org.tmatesoft.hg.repo.HgRepositoryFiles.LastMessage;
20 import static org.tmatesoft.hg.util.LogFacility.Severity.*; 20 import static org.tmatesoft.hg.util.LogFacility.Severity.Warn;
21 21
22 import java.io.File; 22 import java.io.File;
23 import java.io.FileReader; 23 import java.io.FileReader;
24 import java.io.IOException; 24 import java.io.IOException;
25 import java.io.StringReader;
26 import java.nio.CharBuffer; 25 import java.nio.CharBuffer;
27 import java.util.ArrayList; 26 import java.util.ArrayList;
28 import java.util.Collections; 27 import java.util.Collections;
29 import java.util.List; 28 import java.util.List;
30 29
31 import org.tmatesoft.hg.core.Nodeid; 30 import org.tmatesoft.hg.core.Nodeid;
32 import org.tmatesoft.hg.core.SessionContext; 31 import org.tmatesoft.hg.core.SessionContext;
33 import org.tmatesoft.hg.internal.ByteArrayChannel;
34 import org.tmatesoft.hg.internal.ConfigFile; 32 import org.tmatesoft.hg.internal.ConfigFile;
35 import org.tmatesoft.hg.internal.DirstateReader; 33 import org.tmatesoft.hg.internal.DirstateReader;
36 import org.tmatesoft.hg.internal.Experimental; 34 import org.tmatesoft.hg.internal.Experimental;
37 import org.tmatesoft.hg.internal.Filter; 35 import org.tmatesoft.hg.internal.Filter;
38 import org.tmatesoft.hg.internal.Internals; 36 import org.tmatesoft.hg.internal.Internals;
39 import org.tmatesoft.hg.internal.PropertyMarshal; 37 import org.tmatesoft.hg.internal.PropertyMarshal;
40 import org.tmatesoft.hg.internal.RevlogStream; 38 import org.tmatesoft.hg.internal.RevlogStream;
41 import org.tmatesoft.hg.internal.SubrepoManager; 39 import org.tmatesoft.hg.internal.SubrepoManager;
42 import org.tmatesoft.hg.repo.ext.HgExtensionsManager; 40 import org.tmatesoft.hg.repo.ext.HgExtensionsManager;
43 import org.tmatesoft.hg.util.CancelledException;
44 import org.tmatesoft.hg.util.Pair; 41 import org.tmatesoft.hg.util.Pair;
45 import org.tmatesoft.hg.util.Path; 42 import org.tmatesoft.hg.util.Path;
46 import org.tmatesoft.hg.util.PathRewrite; 43 import org.tmatesoft.hg.util.PathRewrite;
47 import org.tmatesoft.hg.util.ProgressSupport; 44 import org.tmatesoft.hg.util.ProgressSupport;
48 45
108 private HgBranches branches; 105 private HgBranches branches;
109 private HgMergeState mergeState; 106 private HgMergeState mergeState;
110 private SubrepoManager subRepos; 107 private SubrepoManager subRepos;
111 private HgBookmarks bookmarks; 108 private HgBookmarks bookmarks;
112 private HgExtensionsManager extManager; 109 private HgExtensionsManager extManager;
113
114 private final org.tmatesoft.hg.internal.Internals impl;
115 private HgIgnore ignore; 110 private HgIgnore ignore;
116 private HgRepoConfig repoConfig; 111 private HgRepoConfig repoConfig;
112
113 private final org.tmatesoft.hg.internal.Internals impl;
117 114
118 /* 115 /*
119 * TODO [post-1.0] move to a better place, e.g. WorkingCopy container that tracks both dirstate and branches 116 * TODO [post-1.0] move to a better place, e.g. WorkingCopy container that tracks both dirstate and branches
120 * (and, perhaps, undo, lastcommit and other similar information), and is change listener so that we don't need to 117 * (and, perhaps, undo, lastcommit and other similar information), and is change listener so that we don't need to
121 * worry about this cached value become stale 118 * worry about this cached value become stale
155 } 152 }
156 public RevlogStream getChangelogStream() { 153 public RevlogStream getChangelogStream() {
157 return HgRepository.this.getChangelog().content; 154 return HgRepository.this.getChangelog().content;
158 } 155 }
159 }); 156 });
160 normalizePath = impl.buildNormalizePathRewrite(); 157 normalizePath = impl.buildNormalizePathRewrite();
161 } 158 }
162 159
163 @Override 160 @Override
164 public String toString() { 161 public String toString() {
165 return getClass().getSimpleName() + "[" + getLocation() + (isInvalid() ? "(BAD)" : "") + "]"; 162 return getClass().getSimpleName() + "[" + getLocation() + (isInvalid() ? "(BAD)" : "") + "]";
199 } 196 }
200 return manifest; 197 return manifest;
201 } 198 }
202 199
203 /** 200 /**
201 * Access snapshot of repository tags.
202 *
204 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em> 203 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em>
205 */ 204 */
206 public HgTags getTags() throws HgInvalidControlFileException { 205 public HgTags getTags() throws HgInvalidControlFileException {
207 if (tags == null) { 206 if (tags == null) {
208 tags = new HgTags(this); 207 tags = new HgTags(impl);
209 HgDataFile hgTags = getFileNode(HgTags.getPath()); 208 tags.read();
210 if (hgTags.exists()) { 209 } else {
211 for (int i = 0; i <= hgTags.getLastRevision(); i++) { // TODO post-1.0 in fact, would be handy to have walk(start,end) 210 tags.reloadIfChanged();
212 // method for data files as well, though it looks odd.
213 try {
214 ByteArrayChannel sink = new ByteArrayChannel();
215 hgTags.content(i, sink);
216 final String content = new String(sink.toArray(), "UTF8");
217 tags.readGlobal(new StringReader(content));
218 } catch (CancelledException ex) {
219 // IGNORE, can't happen, we did not configure cancellation
220 getSessionContext().getLog().dump(getClass(), Debug, ex, null);
221 } catch (IOException ex) {
222 // UnsupportedEncodingException can't happen (UTF8)
223 // only from readGlobal. Need to reconsider exceptions thrown from there:
224 // BufferedReader wraps String and unlikely to throw IOException, perhaps, log is enough?
225 getSessionContext().getLog().dump(getClass(), Error, ex, null);
226 // XXX need to decide what to do this. failure to read single revision shall not break complete cycle
227 }
228 }
229 }
230 File file2read = null;
231 try {
232 file2read = new File(getWorkingDir(), HgTags.getPath());
233 tags.readGlobal(file2read); // XXX replace with HgDataFile.workingCopy
234 file2read = impl.getFileFromRepoDir(HgLocalTags.getName()); // XXX pass internalrepo to readLocal, keep filename there
235 tags.readLocal(file2read);
236 } catch (IOException ex) {
237 getSessionContext().getLog().dump(getClass(), Error, ex, null);
238 throw new HgInvalidControlFileException("Failed to read tags", ex, file2read);
239 }
240 } 211 }
241 return tags; 212 return tags;
242 } 213 }
243 214
244 /** 215 /**
245 * Access branch information 216 * Access branch information. Returns a snapshot of branch information as it's available at the time of the call.
217 * If repository get changed, use this method to obtain an up-to-date state.
218 *
246 * @return branch manager instance, never <code>null</code> 219 * @return branch manager instance, never <code>null</code>
247 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em> 220 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em>
248 */ 221 */
249 public HgBranches getBranches() throws HgInvalidControlFileException { 222 public HgBranches getBranches() throws HgInvalidControlFileException {
223 final ProgressSupport ps = ProgressSupport.Factory.get(null);
250 if (branches == null) { 224 if (branches == null) {
251 branches = new HgBranches(impl); 225 branches = new HgBranches(impl);
252 branches.collect(ProgressSupport.Factory.get(null)); 226 branches.collect(ps);
227 } else {
228 branches.reloadIfChanged(ps);
253 } 229 }
254 return branches; 230 return branches;
255 } 231 }
256 232
257 /** 233 /**
368 */ 344 */
369 public HgIgnore getIgnore() throws HgInvalidControlFileException { 345 public HgIgnore getIgnore() throws HgInvalidControlFileException {
370 // TODO read config for additional locations 346 // TODO read config for additional locations
371 if (ignore == null) { 347 if (ignore == null) {
372 ignore = new HgIgnore(getToRepoPathHelper()); 348 ignore = new HgIgnore(getToRepoPathHelper());
373 File ignoreFile = new File(getWorkingDir(), HgIgnore.getPath()); 349 ignore.read(impl);
374 try { 350 } else {
375 final List<String> errors = ignore.read(ignoreFile); 351 ignore.reloadIfChanged(impl);
376 if (errors != null) {
377 getSessionContext().getLog().dump(getClass(), Warn, "Syntax errors parsing %s:\n%s", ignoreFile.getName(), Internals.join(errors, ",\n"));
378 }
379 } catch (IOException ex) {
380 final String m = String.format("Error reading %s file", ignoreFile);
381 throw new HgInvalidControlFileException(m, ex, ignoreFile);
382 }
383 } 352 }
384 return ignore; 353 return ignore;
385 } 354 }
386 355
387 /** 356 /**
463 */ 432 */
464 public HgBookmarks getBookmarks() throws HgInvalidControlFileException { 433 public HgBookmarks getBookmarks() throws HgInvalidControlFileException {
465 if (bookmarks == null) { 434 if (bookmarks == null) {
466 bookmarks = new HgBookmarks(impl); 435 bookmarks = new HgBookmarks(impl);
467 bookmarks.read(); 436 bookmarks.read();
437 } else {
438 bookmarks.reloadIfChanged();
468 } 439 }
469 return bookmarks; 440 return bookmarks;
470 } 441 }
471 442
472 public HgExtensionsManager getExtensions() { 443 public HgExtensionsManager getExtensions() {