# HG changeset patch # User Artem Tikhomirov # Date 1350578173 -7200 # Node ID ba36f66c32b48f180626f0c2cfd7d651d0048e4d # Parent e4eaa23e34426183acddef9dd7566432a3d8ec9f Refactor to keep knowledge about repository control files and their location in respect to .hg/ in a single place (facilitate future adoption of shared repositories) diff -r e4eaa23e3442 -r ba36f66c32b4 src/org/tmatesoft/hg/core/HgChangeset.java --- a/src/org/tmatesoft/hg/core/HgChangeset.java Thu Oct 18 16:27:32 2012 +0200 +++ b/src/org/tmatesoft/hg/core/HgChangeset.java Thu Oct 18 18:36:13 2012 +0200 @@ -24,6 +24,7 @@ import org.tmatesoft.hg.internal.PhasesHelper; import org.tmatesoft.hg.repo.HgChangelog; import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; +import org.tmatesoft.hg.repo.HgInternals; import org.tmatesoft.hg.repo.HgPhase; import org.tmatesoft.hg.repo.HgInvalidStateException; import org.tmatesoft.hg.repo.HgRepository; @@ -264,7 +265,7 @@ synchronized (shared) { // ensure field is initialized only once if (shared.phaseHelper == null) { - shared.phaseHelper = new PhasesHelper(getRepo(), shared.parentHelper); + shared.phaseHelper = new PhasesHelper(HgInternals.getImplementationRepo(getRepo()), shared.parentHelper); } } } diff -r e4eaa23e3442 -r ba36f66c32b4 src/org/tmatesoft/hg/core/HgUpdateConfigCommand.java --- a/src/org/tmatesoft/hg/core/HgUpdateConfigCommand.java Thu Oct 18 16:27:32 2012 +0200 +++ b/src/org/tmatesoft/hg/core/HgUpdateConfigCommand.java Thu Oct 18 18:36:13 2012 +0200 @@ -52,7 +52,7 @@ public static HgUpdateConfigCommand forRepository(HgRepository hgRepo) { // XXX HgRepository to implement SessionContext.Provider (with getContext())? - return new HgUpdateConfigCommand(hgRepo.getSessionContext(), new File(HgInternals.getRepositoryDir(hgRepo), "hgrc")); + return new HgUpdateConfigCommand(hgRepo.getSessionContext(), HgInternals.getImplementationRepo(hgRepo).getFileFromRepoDir("hgrc")); } public static HgUpdateConfigCommand forUser(SessionContext ctx) { diff -r e4eaa23e3442 -r ba36f66c32b4 src/org/tmatesoft/hg/internal/Internals.java --- a/src/org/tmatesoft/hg/internal/Internals.java Thu Oct 18 16:27:32 2012 +0200 +++ b/src/org/tmatesoft/hg/internal/Internals.java Thu Oct 18 18:36:13 2012 +0200 @@ -16,7 +16,6 @@ */ package org.tmatesoft.hg.internal; -import static org.tmatesoft.hg.internal.RequiresFile.*; import static org.tmatesoft.hg.util.LogFacility.Severity.Error; import java.io.File; @@ -31,7 +30,8 @@ import java.util.StringTokenizer; import org.tmatesoft.hg.core.SessionContext; -import org.tmatesoft.hg.repo.HgInvalidControlFileException; +import org.tmatesoft.hg.repo.HgDataFile; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.repo.HgRepoConfig.ExtensionsSection; import org.tmatesoft.hg.repo.HgRepository; import org.tmatesoft.hg.util.PathRewrite; @@ -73,30 +73,67 @@ */ public static final String CFG_PROPERTY_FS_FILENAME_ENCODING = "hg.fs.filename.encoding"; - private int requiresFlags = 0; private List filterFactories; private final HgRepository repo; private final File repoDir; private final boolean isCaseSensitiveFileSystem; private final boolean shallCacheRevlogsInRepo; private final DataAccessProvider dataAccess; + + @SuppressWarnings("unused") + private final int requiresFlags; - public Internals(HgRepository hgRepo, File hgDir) { + private final PathRewrite dataPathHelper; // access to file storage area (usually under .hg/store/data/), with filenames mangled + private final PathRewrite repoPathHelper; // access to system files (under .hg/store if requires has 'store' flag) + + public Internals(HgRepository hgRepo, File hgDir) throws HgRuntimeException { repo = hgRepo; repoDir = hgDir; isCaseSensitiveFileSystem = !runningOnWindows(); SessionContext ctx = repo.getSessionContext(); shallCacheRevlogsInRepo = new PropertyMarshal(ctx).getBoolean(CFG_PROPERTY_REVLOG_STREAM_CACHE, true); dataAccess = new DataAccessProvider(ctx); + RepoInitializer repoInit = new RepoInitializer().initRequiresFromFile(repoDir); + requiresFlags = repoInit.getRequires(); + dataPathHelper = repoInit.buildDataFilesHelper(getContext()); + repoPathHelper = repoInit.buildStoreFilesHelper(); } public boolean isInvalid() { return !repoDir.exists() || !repoDir.isDirectory(); } + /** + * Access files under ".hg/". + * File not necessarily exists, this method is merely a factory for Files at specific, configuration-dependent location. + * + * @param name shall be normalized path + */ public File getFileFromRepoDir(String name) { return new File(repoDir, name); } + + /** + * Access files under ".hg/store/" or ".hg/" depending on use of 'store' in requires. + * File not necessarily exists, this method is merely a factory for Files at specific, configuration-dependent location. + * + * @param name shall be normalized path + */ + public File getFileFromStoreDir(String name) { + CharSequence location = repoPathHelper.rewrite(name); + return new File(repoDir, location.toString()); + } + + /** + * Access files under ".hg/store/data", ".hg/store/dh/" or ".hg/data" according to settings in requires file. + * File not necessarily exists, this method is merely a factory for Files at specific, configuration-dependent location. + * + * @param name shall be normalized path, without .i or .d suffixes + */ + public File getFileFromDataDir(CharSequence path) { + CharSequence storagePath = dataPathHelper.rewrite(path); + return new File(repoDir, storagePath.toString()); + } public SessionContext getContext() { return repo.getSessionContext(); @@ -110,19 +147,6 @@ return dataAccess; } - public void parseRequires() throws HgInvalidControlFileException { - File requiresFile =getFileFromRepoDir("requires"); - try { - new RequiresFile().parse(this, requiresFile); - } catch (IOException ex) { - throw new HgInvalidControlFileException("Parse failed", ex, requiresFile); - } - } - - public/*for tests, otherwise pkg*/ void setStorageConfig(int version, int flags) { - requiresFlags = flags; - } - public PathRewrite buildNormalizePathRewrite() { if (runningOnWindows()) { return new WinToNixPathRewrite(); @@ -131,23 +155,6 @@ } } - // XXX perhaps, should keep both fields right here, not in the HgRepository - public PathRewrite buildDataFilesHelper() { - return new RepoInitializer().setRequires(requiresFlags).buildDataFilesHelper(getContext()); - } - - public PathRewrite buildRepositoryFilesHelper() { - if ((requiresFlags & STORE) != 0) { - return new PathRewrite() { - public CharSequence rewrite(CharSequence path) { - return "store/" + path; - } - }; - } else { - return new PathRewrite.Empty(); - } - } - public List getFilters() { if (filterFactories == null) { filterFactories = new ArrayList(); @@ -192,6 +199,15 @@ } return cs; } + + /** + * Access to mangled name of a file in repository storage, may come handy for debug. + * @return mangled path of the repository file + */ + public CharSequence getStoragePath(HgDataFile df) { + return dataPathHelper.rewrite(df.getPath().toString()); + } + public static boolean runningOnWindows() { return System.getProperty("os.name").indexOf("Windows") != -1; diff -r e4eaa23e3442 -r ba36f66c32b4 src/org/tmatesoft/hg/internal/PhasesHelper.java --- a/src/org/tmatesoft/hg/internal/PhasesHelper.java Thu Oct 18 16:27:32 2012 +0200 +++ b/src/org/tmatesoft/hg/internal/PhasesHelper.java Thu Oct 18 18:36:13 2012 +0200 @@ -33,7 +33,6 @@ import org.tmatesoft.hg.core.HgChangeset; import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.repo.HgChangelog; -import org.tmatesoft.hg.repo.HgInternals; import org.tmatesoft.hg.repo.HgInvalidControlFileException; import org.tmatesoft.hg.repo.HgParentChildMap; import org.tmatesoft.hg.repo.HgPhase; @@ -50,24 +49,24 @@ */ public final class PhasesHelper { - private final HgRepository repo; + private final Internals repo; private final HgParentChildMap parentHelper; private Boolean repoSupporsPhases; private List draftPhaseRoots; private List secretPhaseRoots; private RevisionDescendants[][] phaseDescendants = new RevisionDescendants[HgPhase.values().length][]; - public PhasesHelper(HgRepository hgRepo) { - this(hgRepo, null); + public PhasesHelper(Internals internalRepo) { + this(internalRepo, null); } - public PhasesHelper(HgRepository hgRepo, HgParentChildMap pw) { - repo = hgRepo; + public PhasesHelper(Internals internalRepo, HgParentChildMap pw) { + repo = internalRepo; parentHelper = pw; } public HgRepository getRepo() { - return repo; + return repo.getRepo(); } public boolean isCapableOfPhases() throws HgInvalidControlFileException { @@ -90,7 +89,7 @@ } // csetRev is only used when parentHelper is available if (parentHelper != null && (csetRev == null || csetRev.isNull())) { - csetRev = repo.getChangelog().getRevision(csetRevIndex); + csetRev = getRepo().getChangelog().getRevision(csetRevIndex); } for (HgPhase phase : new HgPhase[] {HgPhase.Secret, HgPhase.Draft }) { @@ -121,8 +120,7 @@ } private Boolean readRoots() throws HgInvalidControlFileException { - // FIXME shall access phaseroots through HgRepository#repoPathHelper - File phaseroots = new File(HgInternals.getRepositoryDir(repo), "store/phaseroots"); + File phaseroots = repo.getFileFromStoreDir("phaseroots"); BufferedReader br = null; try { if (!phaseroots.exists()) { @@ -137,13 +135,13 @@ continue; } if (lc.length != 2) { - repo.getSessionContext().getLog().dump(getClass(), Warn, "Bad line in phaseroots:%s", line); + repo.getContext().getLog().dump(getClass(), Warn, "Bad line in phaseroots:%s", line); continue; } int phaseIndex = Integer.parseInt(lc[0]); Nodeid rootRev = Nodeid.fromAscii(lc[1]); - if (!repo.getChangelog().isKnown(rootRev)) { - repo.getSessionContext().getLog().dump(getClass(), Warn, "Phase(%d) root node %s doesn't exist in the repository, ignored.", phaseIndex, rootRev); + if (!getRepo().getChangelog().isKnown(rootRev)) { + repo.getContext().getLog().dump(getClass(), Warn, "Phase(%d) root node %s doesn't exist in the repository, ignored.", phaseIndex, rootRev); continue; } HgPhase phase = HgPhase.parse(phaseIndex); @@ -162,7 +160,7 @@ try { br.close(); } catch (IOException ex) { - repo.getSessionContext().getLog().dump(getClass(), Info, ex, null); + repo.getContext().getLog().dump(getClass(), Info, ex, null); // ignore the exception otherwise } } @@ -191,7 +189,7 @@ int[] roots = toIndexes(getPhaseRoots(phase)); RevisionDescendants[] rv = new RevisionDescendants[roots.length]; for (int i = 0; i < roots.length; i++) { - rv[i] = new RevisionDescendants(repo, roots[i]); + rv[i] = new RevisionDescendants(getRepo(), roots[i]); rv[i].build(); } return rv; @@ -200,7 +198,7 @@ private int[] toIndexes(List roots) throws HgInvalidControlFileException { int[] rv = new int[roots.size()]; for (int i = 0; i < rv.length; i++) { - rv[i] = repo.getChangelog().getRevisionIndex(roots.get(i)); + rv[i] = getRepo().getChangelog().getRevisionIndex(roots.get(i)); } return rv; } diff -r e4eaa23e3442 -r ba36f66c32b4 src/org/tmatesoft/hg/internal/RepoInitializer.java --- a/src/org/tmatesoft/hg/internal/RepoInitializer.java Thu Oct 18 16:27:32 2012 +0200 +++ b/src/org/tmatesoft/hg/internal/RepoInitializer.java Thu Oct 18 18:36:13 2012 +0200 @@ -24,6 +24,7 @@ import java.nio.charset.Charset; import org.tmatesoft.hg.core.SessionContext; +import org.tmatesoft.hg.repo.HgInvalidControlFileException; import org.tmatesoft.hg.util.PathRewrite; /** @@ -39,6 +40,16 @@ public RepoInitializer() { } + public RepoInitializer initRequiresFromFile(File repoDir) throws HgInvalidControlFileException { + File requiresFile = new File(repoDir, "requires"); // not #getFileFromRepoDir() just in case it gets modified later + try { + int flags = new RequiresFile().parse(requiresFile); + return setRequires(flags); + } catch (IOException ex) { + throw new HgInvalidControlFileException("Parse failed", ex, requiresFile); + } + } + public RepoInitializer setRequires(int flags) { requiresFlags = flags; return this; @@ -48,9 +59,9 @@ return requiresFlags; } - public void initEmptyRepository(File hgDir) throws IOException { - hgDir.mkdir(); - FileOutputStream requiresFile = new FileOutputStream(new File(hgDir, "requires")); + public void initEmptyRepository(File repoDir) throws IOException { + repoDir.mkdirs(); + FileOutputStream requiresFile = new FileOutputStream(new File(repoDir, "requires")); StringBuilder sb = new StringBuilder(40); sb.append("revlogv1\n"); if ((requiresFlags & STORE) != 0) { @@ -64,7 +75,7 @@ } requiresFile.write(sb.toString().getBytes()); requiresFile.close(); - new File(hgDir, "store").mkdir(); // with that, hg verify says ok. + new File(repoDir, "store").mkdir(); // with that, hg verify says ok. } public PathRewrite buildDataFilesHelper(SessionContext ctx) { @@ -72,4 +83,16 @@ // StoragePathHelper needs fine-grained control over char encoding, hence doesn't use EncodingHelper return new StoragePathHelper((requiresFlags & STORE) != 0, (requiresFlags & FNCACHE) != 0, (requiresFlags & DOTENCODE) != 0, cs); } + + public PathRewrite buildStoreFilesHelper() { + if ((requiresFlags & STORE) != 0) { + return new PathRewrite() { + public CharSequence rewrite(CharSequence path) { + return "store/" + path; + } + }; + } else { + return new PathRewrite.Empty(); + } + } } diff -r e4eaa23e3442 -r ba36f66c32b4 src/org/tmatesoft/hg/internal/RequiresFile.java --- a/src/org/tmatesoft/hg/internal/RequiresFile.java Thu Oct 18 16:27:32 2012 +0200 +++ b/src/org/tmatesoft/hg/internal/RequiresFile.java Thu Oct 18 18:36:13 2012 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 TMate Software Ltd + * Copyright (c) 2011-2012 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,36 +28,43 @@ * @author TMate Software Ltd. */ public class RequiresFile { - public static final int STORE = 1; - public static final int FNCACHE = 2; - public static final int DOTENCODE = 4; + public static final int STORE = 1 << 0; + public static final int FNCACHE = 1 << 1; + public static final int DOTENCODE = 1 << 2; + public static final int REVLOGV0 = 1 << 31; + public static final int REVLOGV1 = 1 << 30; public RequiresFile() { } - public void parse(Internals repoImpl, File requiresFile) throws IOException { + /** + * Settings from requires file as bits + */ + public int parse(File requiresFile) throws IOException { if (!requiresFile.exists()) { - return; + // TODO check what's going on in Mercurial if no requires exist + return 0; } BufferedReader br = null; try { - boolean revlogv1 = false; - boolean store = false; - boolean fncache = false; - boolean dotencode = false; br = new BufferedReader(new InputStreamReader(new FileInputStream(requiresFile))); String line; + int flags = 0; while ((line = br.readLine()) != null) { - revlogv1 |= "revlogv1".equals(line); - store |= "store".equals(line); - fncache |= "fncache".equals(line); - dotencode |= "dotencode".equals(line); + if ("revlogv1".equals(line)) { + flags |= REVLOGV1; + } else if ("store".equals(line)) { + flags |= STORE; + } else if ("fncache".equals(line)) { + flags |= FNCACHE; + } else if ("dotencode".equals(line)) { + flags |= DOTENCODE; + } } - int flags = 0; - flags += store ? STORE : 0; - flags += fncache ? FNCACHE : 0; - flags += dotencode ? DOTENCODE : 0; - repoImpl.setStorageConfig(revlogv1 ? 1 : 0, flags); + if ((flags & REVLOGV1) == 0) { + flags |= REVLOGV0; // TODO check if there's no special flag for V0 indeed + } + return flags; } finally { if (br != null) { br.close(); diff -r e4eaa23e3442 -r ba36f66c32b4 src/org/tmatesoft/hg/repo/HgInternals.java --- a/src/org/tmatesoft/hg/repo/HgInternals.java Thu Oct 18 16:27:32 2012 +0200 +++ b/src/org/tmatesoft/hg/repo/HgInternals.java Thu Oct 18 18:36:13 2012 +0200 @@ -88,11 +88,11 @@ public HgSubrepoLocation newSubrepo(Path loc, String src, Kind kind, Nodeid rev) { return new HgSubrepoLocation(repo, loc, src, kind, rev); } + + public static Internals getImplementationRepo(HgRepository hgRepo) { + return hgRepo.getImplHelper(); + } - public static File getRepositoryDir(HgRepository hgRepo) { - return hgRepo.getRepositoryRoot(); - } - /** * @param source where to read definitions from * @param globPathRewrite null to use default, or pass an instance to override defaults diff -r e4eaa23e3442 -r ba36f66c32b4 src/org/tmatesoft/hg/repo/HgRepository.java --- a/src/org/tmatesoft/hg/repo/HgRepository.java Thu Oct 18 16:27:32 2012 +0200 +++ b/src/org/tmatesoft/hg/repo/HgRepository.java Thu Oct 18 18:36:13 2012 +0200 @@ -99,9 +99,12 @@ private final File repoDir; // .hg folder private final File workingDir; // .hg/../ private final String repoLocation; - private final PathRewrite normalizePath; // normalized slashes but otherwise regular file names - private final PathRewrite dataPathHelper; // access to file storage area (usually under .hg/store/data/), with filenames mangled - private final PathRewrite repoPathHelper; // access to system files + /* + * normalized slashes but otherwise regular file names + * the only front-end path rewrite, kept here as rest of the library shall + * not bother with names normalization. + */ + private final PathRewrite normalizePath; private final SessionContext sessionContext; private HgChangelog changelog; @@ -131,7 +134,6 @@ repoDir = null; workingDir = null; repoLocation = repositoryPath; - dataPathHelper = repoPathHelper = null; normalizePath = null; sessionContext = null; impl = null; @@ -153,10 +155,7 @@ repoLocation = repositoryPath; sessionContext = ctx; impl = new org.tmatesoft.hg.internal.Internals(this, repositoryRoot); - impl.parseRequires(); normalizePath = impl.buildNormalizePathRewrite(); - dataPathHelper = impl.buildDataFilesHelper(); - repoPathHelper = impl.buildRepositoryFilesHelper(); } @Override @@ -185,8 +184,12 @@ public HgChangelog getChangelog() { if (changelog == null) { - CharSequence storagePath = repoPathHelper.rewrite("00changelog.i"); - RevlogStream content = resolve(Path.create(storagePath), true); + File chlogFile = impl.getFileFromStoreDir("00changelog.i"); + if (!chlogFile.exists()) { + // fake its existence + chlogFile = fakeNonExistentFile(chlogFile); + } + RevlogStream content = new RevlogStream(impl.getDataAccess(), chlogFile); changelog = new HgChangelog(this, content); } return changelog; @@ -194,7 +197,11 @@ public HgManifest getManifest() { if (manifest == null) { - RevlogStream content = resolve(Path.create(repoPathHelper.rewrite("00manifest.i")), true); + File manifestFile = impl.getFileFromStoreDir("00manifest.i"); + if (!manifestFile.exists()) { + manifestFile = fakeNonExistentFile(manifestFile); + } + RevlogStream content = new RevlogStream(impl.getDataAccess(), manifestFile); manifest = new HgManifest(this, content, impl.buildFileNameEncodingHelper()); } return manifest; @@ -267,19 +274,12 @@ public HgDataFile getFileNode(String path) { CharSequence nPath = normalizePath.rewrite(path); - CharSequence storagePath = dataPathHelper.rewrite(nPath); - RevlogStream content = resolve(Path.create(storagePath), false); Path p = Path.create(nPath); - if (content == null) { - return new HgDataFile(this, p); - } - return new HgDataFile(this, p, content); + return getFileNode(p); } public HgDataFile getFileNode(Path path) { - CharSequence storagePath = dataPathHelper.rewrite(path.toString()); - RevlogStream content = resolve(Path.create(storagePath), false); - // XXX no content when no file? or HgDataFile.exists() to detect that? + RevlogStream content = resolveStoreFile(path); if (content == null) { return new HgDataFile(this, path); } @@ -347,16 +347,6 @@ return repoConfig; } - // shall be of use only for internal classes - /*package-local*/ File getRepositoryRoot() { - return repoDir; - } - - /*package-local, debug*/String getStoragePath(HgDataFile df) { - // may come handy for debug - return dataPathHelper.rewrite(df.getPath().toString()).toString(); - } - // XXX package-local, unless there are cases when required from outside (guess, working dir/revision walkers may hide dirstate access and no public visibility needed) // XXX consider passing Path pool or factory to produce (shared) Path instead of Strings /*package-local*/ final HgDirstate loadDirstate(Path.Source pathFactory) throws HgInvalidControlFileException { @@ -459,7 +449,7 @@ public HgRepositoryLock getStoreLock() { if (storeLock == null) { int timeout = getLockTimeout(); - File fl = impl.getFileFromRepoDir(repoPathHelper.rewrite("lock").toString()); + File fl = impl.getFileFromStoreDir("lock"); synchronized (this) { if (storeLock == null) { storeLock = new HgRepositoryLock(fl, timeout); @@ -491,33 +481,35 @@ /** * Perhaps, should be separate interface, like ContentLookup - * path - repository storage path (i.e. one usually with .i or .d) + * @param path - normalized file name + * @return null if path doesn't resolve to a existing file */ - /*package-local*/ RevlogStream resolve(Path path, boolean shallFakeNonExistent) { + /*package-local*/ RevlogStream resolveStoreFile(Path path) { final SoftReference ref = streamsCache.get(path); RevlogStream cached = ref == null ? null : ref.get(); if (cached != null) { return cached; } - File f = new File(repoDir, path.toString()); + File f = impl.getFileFromDataDir(path); if (f.exists()) { RevlogStream s = new RevlogStream(impl.getDataAccess(), f); if (impl.shallCacheRevlogs()) { streamsCache.put(path, new SoftReference(s)); } return s; - } else { - if (shallFakeNonExistent) { - try { - File fake = File.createTempFile(f.getName(), null); - fake.deleteOnExit(); - return new RevlogStream(impl.getDataAccess(), fake); - } catch (IOException ex) { - getSessionContext().getLog().dump(getClass(), Info, ex, null); - } - } } - return null; // XXX empty stream instead? + return null; + } + + private File fakeNonExistentFile(File expected) throws HgInvalidFileException { + try { + File fake = File.createTempFile(expected.getName(), null); + fake.deleteOnExit(); + return fake; + } catch (IOException ex) { + getSessionContext().getLog().dump(getClass(), Info, ex, null); + throw new HgInvalidFileException(String.format("Failed to fake existence of file %s", expected), ex); + } } /*package-local*/ List getFiltersFromRepoToWorkingDir(Path p) { diff -r e4eaa23e3442 -r ba36f66c32b4 src/org/tmatesoft/hg/repo/HgWorkingCopyStatusCollector.java --- a/src/org/tmatesoft/hg/repo/HgWorkingCopyStatusCollector.java Thu Oct 18 16:27:32 2012 +0200 +++ b/src/org/tmatesoft/hg/repo/HgWorkingCopyStatusCollector.java Thu Oct 18 18:36:13 2012 +0200 @@ -350,7 +350,9 @@ } else { HgDataFile df = repo.getFileNode(fname); if (!df.exists()) { - String msg = String.format("File %s known as normal in dirstate (%d, %d), doesn't exist at %s", fname, r.modificationTime(), r.size(), repo.getStoragePath(df)); + // TODO pass Internals right into HgWCSC cons + Internals implRepo = HgInternals.getImplementationRepo(repo); + String msg = String.format("File %s known as normal in dirstate (%d, %d), doesn't exist at %s", fname, r.modificationTime(), r.size(), implRepo.getStoragePath(df)); throw new HgInvalidFileException(msg, null).setFileName(fname); } Nodeid rev = getDirstateParentManifest().nodeid(fname); diff -r e4eaa23e3442 -r ba36f66c32b4 src/org/tmatesoft/hg/repo/ext/MqManager.java --- a/src/org/tmatesoft/hg/repo/ext/MqManager.java Thu Oct 18 16:27:32 2012 +0200 +++ b/src/org/tmatesoft/hg/repo/ext/MqManager.java Thu Oct 18 18:36:13 2012 +0200 @@ -28,6 +28,7 @@ import java.util.Map; import org.tmatesoft.hg.core.Nodeid; +import org.tmatesoft.hg.internal.Internals; import org.tmatesoft.hg.internal.LineReader; import org.tmatesoft.hg.repo.HgInternals; import org.tmatesoft.hg.repo.HgInvalidControlFileException; @@ -63,16 +64,16 @@ public void refresh() throws HgInvalidControlFileException { applied = allKnown = Collections.emptyList(); queueNames = Collections.emptyList(); - File repoDir = HgInternals.getRepositoryDir(repo); + Internals repoImpl = HgInternals.getImplementationRepo(repo); final LogFacility log = repo.getSessionContext().getLog(); try { - File queues = new File(repoDir, "patches.queues"); + File queues = repoImpl.getFileFromRepoDir("patches.queues"); if (queues.isFile()) { LineReader lr = new LineReader(queues, log).trimLines(true).skipEmpty(true); lr.read(new LineReader.SimpleLineCollector(), queueNames = new LinkedList()); } final String queueLocation; // path under .hg to patch queue information (status, series and diff files) - File activeQueueFile = new File(repoDir, "patches.queue"); + File activeQueueFile = repoImpl.getFileFromRepoDir("patches.queue"); // file is there only if it's not default queue ('patches') that is active if (activeQueueFile.isFile()) { ArrayList contents = new ArrayList(); @@ -99,8 +100,8 @@ return Path.create(sb); } }; - final File fileStatus = new File(repoDir, queueLocation + "status"); - final File fileSeries = new File(repoDir, queueLocation + "series"); + final File fileStatus = repoImpl.getFileFromRepoDir(queueLocation + "status"); + final File fileSeries = repoImpl.getFileFromRepoDir(queueLocation + "series"); if (fileStatus.isFile()) { new LineReader(fileStatus, log).read(new LineReader.LineConsumer>() { diff -r e4eaa23e3442 -r ba36f66c32b4 test/org/tmatesoft/hg/test/TestPhases.java --- a/test/org/tmatesoft/hg/test/TestPhases.java Thu Oct 18 16:27:32 2012 +0200 +++ b/test/org/tmatesoft/hg/test/TestPhases.java Thu Oct 18 18:36:13 2012 +0200 @@ -25,6 +25,7 @@ import org.junit.Test; import org.tmatesoft.hg.internal.PhasesHelper; import org.tmatesoft.hg.repo.HgChangelog; +import org.tmatesoft.hg.repo.HgInternals; import org.tmatesoft.hg.repo.HgLookup; import org.tmatesoft.hg.repo.HgParentChildMap; import org.tmatesoft.hg.repo.HgPhase; @@ -45,7 +46,7 @@ HgRepository repo = Configuration.get().find("test-phases"); HgPhase[] expected = readPhases(repo); final long start = System.nanoTime(); - PhasesHelper ph = new PhasesHelper(repo, null); + PhasesHelper ph = new PhasesHelper(HgInternals.getImplementationRepo(repo), null); initAndCheck(ph, expected); final long end = System.nanoTime(); // μ == \u03bc @@ -60,7 +61,7 @@ HgParentChildMap pw = new HgParentChildMap(repo.getChangelog()); pw.init(); final long start2 = System.nanoTime(); - PhasesHelper ph = new PhasesHelper(repo, pw); + PhasesHelper ph = new PhasesHelper(HgInternals.getImplementationRepo(repo), pw); initAndCheck(ph, expected); final long end = System.nanoTime(); System.out.printf("With ParentWalker(simulates log command for whole repo): %,d μs (pw init: %,d ns)\n", (end - start1)/1000, start2 - start1);