# HG changeset patch # User Artem Tikhomirov # Date 1367954871 -7200 # Node ID e1b29756f901ea2a9b111fd4c081343d9e9627e9 # Parent 66f1cc23b906809fccd4be2ff7e3d7d5d694ab02 Clean, organize and resolve some TODOs and FIXMEs: minor refactorings and comments diff -r 66f1cc23b906 -r e1b29756f901 src/org/tmatesoft/hg/internal/ByteArrayChannel.java --- a/src/org/tmatesoft/hg/internal/ByteArrayChannel.java Tue May 07 16:52:46 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/ByteArrayChannel.java Tue May 07 21:27:51 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 TMate Software Ltd + * Copyright (c) 2011-2013 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 @@ -23,7 +23,8 @@ import org.tmatesoft.hg.util.ByteChannel; /** - * + * {@link ByteChannel} implementation that serializes data into a byte array + * * @author Artem Tikhomirov * @author TMate Software Ltd. */ @@ -48,7 +49,10 @@ } } - // TODO document what happens on write after toArray() in each case + /* + * {@link #toArray()} calls do not clear data collected so far, subsequent {@link #write(ByteBuffer)} + * augment collected content. + */ public int write(ByteBuffer buffer) { int rv = buffer.remaining(); if (buffers == null) { @@ -58,9 +62,13 @@ copy.put(buffer); buffers.add(copy); } + result = null; return rv; } + /** + * @return content accumulated so far + */ public byte[] toArray() { if (result != null) { return result; @@ -84,7 +92,6 @@ bb.get(result, off, bb.limit()); off += bb.limit(); } - buffers.clear(); return result; } } diff -r 66f1cc23b906 -r e1b29756f901 src/org/tmatesoft/hg/internal/ConfigFile.java --- a/src/org/tmatesoft/hg/internal/ConfigFile.java Tue May 07 16:52:46 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/ConfigFile.java Tue May 07 21:27:51 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 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 @@ -183,7 +183,7 @@ private Map section = new LinkedHashMap(); private File contextFile; - // TODO "" and lists + // TODO [post-1.1] "" and lists // XXX perhaps, single string to keep whole section with substrings for keys/values to minimize number of arrays (String.value) public boolean consume(String line, ConfigFile cfg) throws IOException { int x; @@ -237,7 +237,7 @@ // include failure doesn't propagate private void processInclude(String includeValue, ConfigFile cfg) { File f; - // TODO handle environment variable expansion + // TODO [post-1.1] handle environment variable expansion if (includeValue.startsWith("~/")) { f = new File(System.getProperty("user.home"), includeValue.substring(2)); } else { diff -r 66f1cc23b906 -r e1b29756f901 src/org/tmatesoft/hg/internal/DataAccess.java --- a/src/org/tmatesoft/hg/internal/DataAccess.java Tue May 07 16:52:46 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/DataAccess.java Tue May 07 21:27:51 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012 TMate Software Ltd + * Copyright (c) 2010-2013 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 @@ -99,9 +99,10 @@ } throw new IOException(String.format("No data, can't read %d bytes", length)); } - // reads bytes into ByteBuffer, up to its limit or total data length, whichever smaller - // TODO post-1.0 perhaps, in DataAccess paradigm (when we read known number of bytes, we shall pass specific byte count to read) - // for 1.0, it's ok as it's our internal class + /** + * reads bytes into ByteBuffer, up to its limit or total data length, whichever smaller. + * XXX perhaps, in DataAccess paradigm (when we read known number of bytes, we shall pass specific byte count to read) + */ public void readBytes(ByteBuffer buf) throws IOException { // int toRead = Math.min(buf.remaining(), (int) length()); // if (buf.hasArray()) { @@ -111,7 +112,7 @@ // readBytes(bb, 0, bb.length); // buf.put(bb); // } - // TODO post-1.0 optimize to read as much as possible at once + // TODO [post-1.1] optimize to read as much as possible at once while (!isEmpty() && buf.hasRemaining()) { buf.put(readByte()); } @@ -120,8 +121,14 @@ throw new UnsupportedOperationException(); } - // XXX decide whether may or may not change position in the DataAccess - // TODO REVISIT exception handling may not be right, initially just for the sake of quick test + /** + * Content of this DataAccess as byte array. + * Note, likely changes position in the DataAccess. + * Might provide direct access to underlying data structure in certain cases, do not alter. + * + * @return byte array of {@link #length()} size, filled with data + * @throws IOException + */ public byte[] byteArray() throws IOException { reset(); byte[] rv = new byte[length()]; diff -r 66f1cc23b906 -r e1b29756f901 src/org/tmatesoft/hg/internal/DataAccessProvider.java --- a/src/org/tmatesoft/hg/internal/DataAccessProvider.java Tue May 07 16:52:46 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/DataAccessProvider.java Tue May 07 21:27:51 2013 +0200 @@ -54,8 +54,6 @@ private final int mapioMagicBoundary; private final int bufferSize, mapioBufSize; private final SessionContext context; - // not the right place for the property, but DAP is the only place currently available to RevlogStream to get the value - private final boolean shallMergePatches; public DataAccessProvider(SessionContext ctx) { context = ctx; @@ -63,7 +61,6 @@ mapioMagicBoundary = mapioBoundaryValue(pm.getInt(CFG_PROPERTY_MAPIO_LIMIT, DEFAULT_MAPIO_LIMIT)); bufferSize = pm.getInt(CFG_PROPERTY_FILE_BUFFER_SIZE, DEFAULT_FILE_BUFFER); mapioBufSize = pm.getInt(CFG_PROPERTY_MAPIO_BUFFER_SIZE, DEFAULT_MAPIO_BUFFER); - shallMergePatches = pm.getBoolean(Internals.CFG_PROPERTY_PATCH_MERGE, false); } public DataAccessProvider(SessionContext ctx, int mapioBoundary, int regularBufferSize, int mapioBufferSize) { @@ -71,14 +68,8 @@ mapioMagicBoundary = mapioBoundaryValue(mapioBoundary); bufferSize = regularBufferSize; mapioBufSize = mapioBufferSize; - shallMergePatches = new PropertyMarshal(ctx).getBoolean(Internals.CFG_PROPERTY_PATCH_MERGE, false); } - // TODO [post-1.1] find a better place for this option, it's unrelated to the DAP - public boolean shallMergePatches() { - return shallMergePatches; - } - // ensure contract of CFG_PROPERTY_MAPIO_LIMIT, for mapioBoundary == 0 use MAX_VALUE so that no file is memmap-ed private static int mapioBoundaryValue(int mapioBoundary) { return mapioBoundary == 0 ? Integer.MAX_VALUE : mapioBoundary; diff -r 66f1cc23b906 -r e1b29756f901 src/org/tmatesoft/hg/internal/Internals.java --- a/src/org/tmatesoft/hg/internal/Internals.java Tue May 07 16:52:46 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/Internals.java Tue May 07 21:27:51 2013 +0200 @@ -125,6 +125,7 @@ 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) + private final boolean shallMergePatches; private final RevlogStreamFactory streamProvider; public Internals(HgRepository hgRepo, File hgDir, ImplAccess implementationAccess) throws HgRuntimeException { @@ -138,8 +139,10 @@ requiresFlags = repoInit.getRequires(); dataPathHelper = repoInit.buildDataFilesHelper(getSessionContext()); repoPathHelper = repoInit.buildStoreFilesHelper(); - boolean shallCacheRevlogsInRepo = new PropertyMarshal(ctx).getBoolean(CFG_PROPERTY_REVLOG_STREAM_CACHE, true); + final PropertyMarshal pm = new PropertyMarshal(ctx); + boolean shallCacheRevlogsInRepo = pm.getBoolean(CFG_PROPERTY_REVLOG_STREAM_CACHE, true); streamProvider = new RevlogStreamFactory(this, shallCacheRevlogsInRepo); + shallMergePatches = pm.getBoolean(Internals.CFG_PROPERTY_PATCH_MERGE, false); } public boolean isInvalid() { @@ -266,6 +269,16 @@ return requiresFlags; } + boolean shallMergePatches() { + return shallMergePatches; + } + + RevlogChangeMonitor getRevlogTracker(File f) { + // TODO decide whether to use one monitor per multiple files or + // an instance per file; and let SessionContext pass alternative implementation) + return new RevlogChangeMonitor(f); + } + public static boolean runningOnWindows() { return System.getProperty("os.name").indexOf("Windows") != -1; } @@ -390,7 +403,7 @@ if (f.canRead() && f.isDirectory()) { return listConfigFiles(f); } - // TODO post-1.0 query registry, e.g. with + // TODO [post-1.1] query registry, e.g. with // Runtime.exec("reg query HKLM\Software\Mercurial") // f = new File("C:\\Mercurial\\Mercurial.ini"); diff -r 66f1cc23b906 -r e1b29756f901 src/org/tmatesoft/hg/internal/RevlogStream.java --- a/src/org/tmatesoft/hg/internal/RevlogStream.java Tue May 07 16:52:46 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/RevlogStream.java Tue May 07 21:27:51 2013 +0200 @@ -50,6 +50,8 @@ */ public class RevlogStream { + static final int INLINEDATA = 1 << 16; + /* * makes sense for index with inline data only - actual offset of the record in the .i file (record entry + revision * record size)) * @@ -63,7 +65,7 @@ private boolean inline = false; private final File indexFile; private File dataFile; - private final DataAccessProvider dataAccess; + private final Internals repo; // keeps last complete revision we've read. Note, this cached revision doesn't help // for subsequent #iterate() calls with the same revision (Inspector needs more data than // we currently cache here, perhaps, we shall cache everything it wants to cover same @@ -77,14 +79,10 @@ private List observers; private boolean shallDropDerivedCaches = false; - // if we need anything else from HgRepo, might replace DAP parameter with HgRepo and query it for DAP. - public RevlogStream(DataAccessProvider dap, File indexFile) { - this.dataAccess = dap; + public RevlogStream(Internals hgRepo, File indexFile) { + repo = hgRepo; this.indexFile = indexFile; - // TODO in fact, shall ask Internals for an instance (there we'll decide whether to use - // one monitor per multiple files or an instance per file; and let SessionContext pass - // alternative implementation) - changeTracker = new RevlogChangeMonitor(indexFile); + changeTracker = repo.getRevlogTracker(indexFile); } /** @@ -94,18 +92,22 @@ /*package*/ DataAccess getIndexStream(boolean shortRead) { // shortRead hint helps to avoid mmap files when only // few bytes are to be read (i.e. #dataLength()) + DataAccessProvider dataAccess = repo.getDataAccess(); return dataAccess.createReader(indexFile, shortRead); } /*package*/ DataAccess getDataStream() { + DataAccessProvider dataAccess = repo.getDataAccess(); return dataAccess.createReader(getDataFile(), false); } /*package*/ DataSerializer getIndexStreamWriter() { + DataAccessProvider dataAccess = repo.getDataAccess(); return dataAccess.createWriter(indexFile, true); } /*package*/ DataSerializer getDataStreamWriter() { + DataAccessProvider dataAccess = repo.getDataAccess(); return dataAccess.createWriter(getDataFile(), true); } @@ -301,14 +303,12 @@ HgInternals.checkRevlogRange(start, end, indexSize-1); // XXX may cache [start .. end] from index with a single read (pre-read) - ReaderN1 r = new ReaderN1(needData, inspector, dataAccess.shallMergePatches()); + ReaderN1 r = new ReaderN1(needData, inspector, repo.shallMergePatches()); try { r.start(end - start + 1, getLastRevisionRead()); r.range(start, end); } catch (IOException ex) { throw new HgInvalidControlFileException(String.format("Failed reading [%d..%d]", start, end), ex, indexFile); - } catch (HgInvalidControlFileException ex) { - throw ex; } finally { CachedRevision cr = r.finish(); setLastRevisionRead(cr); @@ -334,7 +334,7 @@ throw new HgInvalidRevisionException(String.format("Can't iterate [%d, %d] in range [0..%d]", sortedRevisions[0], sortedRevisions[sortedRevisions.length - 1], indexSize), null, sortedRevisions[sortedRevisions.length - 1]); } - ReaderN1 r = new ReaderN1(needData, inspector, dataAccess.shallMergePatches()); + ReaderN1 r = new ReaderN1(needData, inspector, repo.shallMergePatches()); try { r.start(sortedRevisions.length, getLastRevisionRead()); for (int i = 0; i < sortedRevisions.length; ) { @@ -354,10 +354,7 @@ } } catch (IOException ex) { final int c = sortedRevisions.length; - throw new HgInvalidControlFileException(String.format("Failed reading %d revisions in [%d; %d]",c, sortedRevisions[0], sortedRevisions[c-1]), ex, indexFile); - } catch (HgInvalidControlFileException ex) { - // TODO post-1.0 fill HgRuntimeException with appropriate file (either index or data, depending on error source) - throw ex; + throw new HgInvalidControlFileException(String.format("Failed reading %d revisions in [%d; %d]", c, sortedRevisions[0], sortedRevisions[c-1]), ex, indexFile); } finally { CachedRevision cr = r.finish(); setLastRevisionRead(cr); @@ -488,7 +485,6 @@ } int versionField = da.readInt(); da.readInt(); // just to skip next 4 bytes of offset + flags - final int INLINEDATA = 1 << 16; inline = (versionField & INLINEDATA) != 0; IntVector resBases, resOffsets = null; int entryCountGuess = Internals.ltoi(da.longLength() / REVLOGV1_RECORD_SIZE); @@ -592,7 +588,7 @@ // next are transient values, for range() use only private final Inflater inflater = new Inflater(); // can share buffer between instances of InflaterDataAccess as I never read any two of them in parallel - private final byte[] inflaterBuffer = new byte[10 * 1024]; // TODO consider using DAP.DEFAULT_FILE_BUFFER + private final byte[] inflaterBuffer = new byte[10 * 1024]; // TODO [post-1.1] consider using DAP.DEFAULT_FILE_BUFFER private final byte[] nodeidBuf = new byte[20]; // revlog record fields private long offset; @@ -829,9 +825,22 @@ public interface Inspector { - // XXX boolean retVal to indicate whether to continue? - // TODO specify nodeid and data length, and reuse policy (i.e. if revlog stream doesn't reuse nodeid[] for each call) - // implementers shall not invoke DataAccess.done(), it's accomplished by #iterate at appropraite moment + /** + * XXX boolean retVal to indicate whether to continue? + * + * Implementers shall not invoke DataAccess.done(), it's accomplished by #iterate at appropriate moment + * + * @param revisionIndex absolute index of revision in revlog being iterated + * @param actualLen length of the user data at this revision + * @param baseRevision last revision known to hold complete revision (other hold patches). + * if baseRevision != revisionIndex, data for this revision is a result of a sequence of patches + * @param linkRevision index of corresponding changeset revision + * @param parent1Revision index of first parent revision in this revlog, or {@link HgRepository#NO_REVISION} + * @param parent2Revision index of second parent revision in this revlog, or {@link HgRepository#NO_REVISION} + * @param nodeid 20-byte buffer, shared between invocations + * @param data access to revision content of actualLen size, or null if no data has been requested with + * {@link RevlogStream#iterate(int[], boolean, Inspector)} + */ void next(int revisionIndex, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[/*20*/] nodeid, DataAccess data); } diff -r 66f1cc23b906 -r e1b29756f901 src/org/tmatesoft/hg/internal/RevlogStreamFactory.java --- a/src/org/tmatesoft/hg/internal/RevlogStreamFactory.java Tue May 07 16:52:46 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/RevlogStreamFactory.java Tue May 07 21:27:51 2013 +0200 @@ -49,7 +49,7 @@ * Creates a stream for specified file, doesn't cache stream */ /*package-local*/ RevlogStream create(File f) { - return new RevlogStream(repo.getDataAccess(), f); + return new RevlogStream(repo, f); } /** diff -r 66f1cc23b906 -r e1b29756f901 src/org/tmatesoft/hg/internal/RevlogStreamWriter.java --- a/src/org/tmatesoft/hg/internal/RevlogStreamWriter.java Tue May 07 16:52:46 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/RevlogStreamWriter.java Tue May 07 21:27:51 2013 +0200 @@ -29,7 +29,7 @@ /** * - * TODO separate operation to check if index is too big and split into index+data + * TODO [post-1.1] separate operation to check if index is too big and split into index+data * * @author Artem Tikhomirov * @author TMate Software Ltd. @@ -255,8 +255,7 @@ if (offset == 0) { int version = 1 /* RevlogNG */; if (isInline) { - final int INLINEDATA = 1 << 16; // FIXME extract constant - version |= INLINEDATA; + version |= RevlogStream.INLINEDATA; } header.putInt(version); header.putInt(0); diff -r 66f1cc23b906 -r e1b29756f901 src/org/tmatesoft/hg/repo/HgDataFile.java --- a/src/org/tmatesoft/hg/repo/HgDataFile.java Tue May 07 16:52:46 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgDataFile.java Tue May 07 21:27:51 2013 +0200 @@ -572,7 +572,6 @@ } catch (IOException ex) { recordFailure(ex); } catch (HgInvalidControlFileException ex) { - // TODO RevlogStream, where this RevlogStream.Inspector goes, shall set File (as it's the only one having access to it) recordFailure(ex.isRevisionIndexSet() ? ex : ex.setRevisionIndex(revisionNumber)); } } diff -r 66f1cc23b906 -r e1b29756f901 src/org/tmatesoft/hg/repo/HgInternals.java --- a/src/org/tmatesoft/hg/repo/HgInternals.java Tue May 07 16:52:46 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgInternals.java Tue May 07 21:27:51 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 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 @@ -144,7 +144,7 @@ // Impl note: simple source is enough as files in the working dir are all unique // even if they might get reused (i.e. after FileIterator#reset() and walking once again), // path caching is better to be done in the code which knows that path are being reused - return new FileWalker(repo.getSessionContext(), repoRoot, pathSrc, workindDirScope); + return new FileWalker(repo, repoRoot, pathSrc, workindDirScope); } // Convenient check of revision index for validity (not all negative values are wrong as long as we use negative constants) diff -r 66f1cc23b906 -r e1b29756f901 src/org/tmatesoft/hg/repo/HgManifest.java --- a/src/org/tmatesoft/hg/repo/HgManifest.java Tue May 07 16:52:46 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgManifest.java Tue May 07 21:27:51 2013 +0200 @@ -109,7 +109,19 @@ } throw new IllegalStateException(new String(data, start, length)); } - + + static Flags parse(int dirstateFileMode) { + // source/include/linux/stat.h + final int S_IFLNK = 0120000, S_IXUSR = 00100; + if ((dirstateFileMode & S_IFLNK) == S_IFLNK) { + return Link; + } + if ((dirstateFileMode & S_IXUSR) == S_IXUSR) { + return Exec; + } + return RegularFile; + } + String nativeString() { if (this == Exec) { return "x"; diff -r 66f1cc23b906 -r e1b29756f901 src/org/tmatesoft/hg/repo/HgWorkingCopyStatusCollector.java --- a/src/org/tmatesoft/hg/repo/HgWorkingCopyStatusCollector.java Tue May 07 16:52:46 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgWorkingCopyStatusCollector.java Tue May 07 21:27:51 2013 +0200 @@ -375,8 +375,7 @@ } else { HgDataFile df = repo.getFileNode(fname); if (!df.exists()) { - // TODO pass Internals right into HgWCSC cons - Internals implRepo = HgInternals.getImplementationRepo(repo); + Internals implRepo = repo.getImplHelper(); 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); } @@ -496,7 +495,7 @@ // only those left in baseRevNames after processing are reported as removed } - // TODO think over if content comparison may be done more effectively by e.g. calculating nodeid for a local file and comparing it with nodeid from manifest + // TODO [post-1.1] think over if content comparison may be done more effectively by e.g. calculating nodeid for a local file and comparing it with nodeid from manifest // we don't need to tell exact difference, hash should be enough to detect difference, and it doesn't involve reading historical file content, and it's relatively // cheap to calc hash on a file (no need to keep it completely in memory). OTOH, if I'm right that the next approach is used for nodeids: // changeset nodeid + hash(actual content) => entry (Nodeid) in the next Manifest @@ -624,16 +623,7 @@ } private boolean checkFlagsEqual(FileInfo f, int dirstateFileMode) { - // source/include/linux/stat.h - final int S_IFLNK = 0120000, S_IXUSR = 00100; - // TODO post-1.0 HgManifest.Flags.parse(int) - if ((dirstateFileMode & S_IFLNK) == S_IFLNK) { - return checkFlagsEqual(f, HgManifest.Flags.Link); - } - if ((dirstateFileMode & S_IXUSR) == S_IXUSR) { - return checkFlagsEqual(f, HgManifest.Flags.Exec); - } - return checkFlagsEqual(f, HgManifest.Flags.RegularFile); // no flags + return checkFlagsEqual(f, HgManifest.Flags.parse(dirstateFileMode)); } /** diff -r 66f1cc23b906 -r e1b29756f901 src/org/tmatesoft/hg/repo/Revlog.java --- a/src/org/tmatesoft/hg/repo/Revlog.java Tue May 07 16:52:46 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/Revlog.java Tue May 07 21:27:51 2013 +0200 @@ -251,7 +251,7 @@ } catch (IOException ex) { HgInvalidControlFileException e = new HgInvalidControlFileException(String.format("Access to revision %d content failed", revisionIndex), ex, null); e.setRevisionIndex(revisionIndex); - // TODO post 1.0 e.setFileName(content.getIndexFile() or this.getHumanFriendlyPath()) - shall decide whether + // TODO [post 1.1] e.setFileName(content.getIndexFile() or this.getHumanFriendlyPath()) - shall decide whether // protected abstract getHFPath() with impl in HgDataFile, HgManifest and HgChangelog or path is data of either Revlog or RevlogStream // Do the same (add file name) below throw e; @@ -375,7 +375,7 @@ }); if (parentInsp != null && _start > 0) { assert missingParents.size() > 0; // in fact, more relaxed than assert. rather 'assume' - // TODO int[] IntMap#keys() or even sort of iterator that can modify values + // TODO [post-1.1] int[] IntMap#keys() or even sort of iterator that can modify values for (int k = missingParents.firstKey(), l = missingParents.lastKey(); k <= l; k++) { if (missingParents.containsKey(k)) { Nodeid nid = getRepo().getChangelog().getRevision(k); @@ -433,7 +433,8 @@ } /* - * class with cancel and few other exceptions support. TODO consider general superclass to share with e.g. HgManifestCommand.Mediator + * class with cancel and few other exceptions support. + * TODO [post-1.1] consider general superclass to share with e.g. HgManifestCommand.Mediator */ protected abstract static class ErrorHandlingInspector implements RevlogStream.Inspector, CancelSupport { private Exception failure; diff -r 66f1cc23b906 -r e1b29756f901 src/org/tmatesoft/hg/util/FileWalker.java --- a/src/org/tmatesoft/hg/util/FileWalker.java Tue May 07 16:52:46 2013 +0200 +++ b/src/org/tmatesoft/hg/util/FileWalker.java Tue May 07 21:27:51 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 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 @@ -41,19 +41,25 @@ private RegularFileInfo nextFile; private Path nextPath; - // TODO FileWalker to accept SessionContext.Source and SessionContext to implement SessionContext.Source - // (if it doesn't break binary compatibility) public FileWalker(SessionContext ctx, File dir, Path.Source pathFactory) { this(ctx, dir, pathFactory, null); } + + /** + * @see FileWalker#FileWalker(SessionContext, File, Path.Source, Matcher) + */ + public FileWalker(SessionContext.Source ctxSource, File dir, Path.Source pathFactory, Path.Matcher scopeMatcher) { + this(ctxSource.getSessionContext(), dir, pathFactory, scopeMatcher); + } /** + * Implementation of {@link FileIterator} with regular {@link java.io.File}. * - * @param dir - * @param pathFactory + * @param dir directory to start at, not null + * @param pathFactory factory to create {@link Path} instances, not null * @param scopeMatcher - this matcher shall be capable to tell not only files of interest, but * also whether directories shall be traversed or not (Paths it gets in {@link Path.Matcher#accept(Path)} may - * point to directories) + * point to directories); may be null */ public FileWalker(SessionContext ctx, File dir, Path.Source pathFactory, Path.Matcher scopeMatcher) { sessionContext = ctx; diff -r 66f1cc23b906 -r e1b29756f901 test/org/tmatesoft/hg/test/TestCheckout.java --- a/test/org/tmatesoft/hg/test/TestCheckout.java Tue May 07 16:52:46 2013 +0200 +++ b/test/org/tmatesoft/hg/test/TestCheckout.java Tue May 07 21:27:51 2013 +0200 @@ -124,7 +124,7 @@ repo = new HgLookup().detect(testRepoLoc); new HgCheckoutCommand(repo).clean(true).changeset(0).execute(); - FileWalker fw = new FileWalker(repo.getSessionContext(), testRepoLoc, new Path.SimpleSource()); + FileWalker fw = new FileWalker(repo, testRepoLoc, new Path.SimpleSource(), null); int execFound, linkFound, regularFound; execFound = linkFound = regularFound = 0; while(fw.hasNext()) { diff -r 66f1cc23b906 -r e1b29756f901 test/org/tmatesoft/hg/test/TestFileFlags.java --- a/test/org/tmatesoft/hg/test/TestFileFlags.java Tue May 07 16:52:46 2013 +0200 +++ b/test/org/tmatesoft/hg/test/TestFileFlags.java Tue May 07 21:27:51 2013 +0200 @@ -65,7 +65,7 @@ public void testFlagsInWorkingCopy() throws Exception { File repoRoot = repo.getWorkingDir(); Path.Source pathSrc = new Path.SimpleSource(new PathRewrite.Composite(new RelativePathRewrite(repoRoot), repo.getToRepoPathHelper())); - FileWalker fw = new FileWalker(repo.getSessionContext(), repoRoot, pathSrc); + FileWalker fw = new FileWalker(repo, repoRoot, pathSrc, null); if (Internals.runningOnWindows()) { System.out.println("Executing tests on Windows, no actual file flags in working area are checked");