# HG changeset patch # User Artem Tikhomirov # Date 1293407402 -3600 # Node ID 865bf07f381ff7d1b742453568def92576af80b6 # Parent 442dc6ee647bd3f69a1678c49bed741f1ff648db Basic hgignore handling diff -r 442dc6ee647b -r 865bf07f381f design.txt --- a/design.txt Sun Dec 26 14:56:08 2010 +0100 +++ b/design.txt Mon Dec 27 00:50:02 2010 +0100 @@ -34,6 +34,8 @@ RevisionWalker (on manifest) and WorkingCopyWalker (io.File) talking to ? and/or dirstate +??? encodings of fncache, .hgignore, dirstate + >>>> Effective file read/data access ReadOperation, Revlog does: repo.getFileSystem().run(this.file, new ReadOperation(), long start=0, long end = -1) ReadOperation gets buffer (of whatever size, as decided by FS impl), parses it and then reports if needs more data. diff -r 442dc6ee647b -r 865bf07f381f src/com/tmate/hgkit/ll/HgIgnore.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/tmate/hgkit/ll/HgIgnore.java Mon Dec 27 00:50:02 2010 +0100 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2010 Artem Tikhomirov + */ +package com.tmate.hgkit.ll; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.Collections; +import java.util.Set; +import java.util.TreeSet; + +/** + * + * @author artem + */ +public class HgIgnore { + + private final LocalHgRepo repo; + private Set entries; + + public HgIgnore(LocalHgRepo localRepo) { + this.repo = localRepo; + } + + private void read() { + entries = Collections.emptySet(); + File hgignoreFile = new File(repo.getRepositoryRoot().getParentFile(), ".hgignore"); + if (!hgignoreFile.exists()) { + return; + } + entries = new TreeSet(); + try { + BufferedReader fr = new BufferedReader(new FileReader(hgignoreFile)); + String line; + while ((line = fr.readLine()) != null) { + // FIXME need to detect syntax:glob and other parameters + entries.add(line.trim()); // shall I account for local paths in the file (i.e. back-slashed on windows)? + } + } catch (IOException ex) { + ex.printStackTrace(); // log warn + } + } + + public void reset() { + // FIXME does anyone really need to clear HgIgnore? Perhaps, repo may return new instance each time, + // which is used throughout invocation and then discarded? + entries = null; + } + + public boolean isIgnored(String path) { + if (entries == null) { + read(); + } + if (entries.contains(path)) { + // easy part + return true; + } + // substrings are memory-friendly + int x = 0, i = path.indexOf('/', 0); + while (i != -1) { + if (entries.contains(path.substring(x, i))) { + return true; + } + // try one with ending slash + if (entries.contains(path.substring(x, i+1))) { // even if i is last index, i+1 is safe here + return true; + } + x = i+1; + i = path.indexOf('/', x); + } + return false; + } +} diff -r 442dc6ee647b -r 865bf07f381f src/com/tmate/hgkit/ll/LocalHgRepo.java --- a/src/com/tmate/hgkit/ll/LocalHgRepo.java Sun Dec 26 14:56:08 2010 +0100 +++ b/src/com/tmate/hgkit/ll/LocalHgRepo.java Mon Dec 27 00:50:02 2010 +0100 @@ -50,9 +50,18 @@ return new HgDirstate(this, new File(repoDir, "dirstate")); } + // package-local, see comment for loadDirstate + public final HgIgnore loadIgnore() { + return new HgIgnore(this); + } + /*package-local*/ DataAccessProvider getDataAccess() { return dataAccess; } + + /*package-local*/ File getRepositoryRoot() { + return repoDir; + } private final HashMap> streamsCache = new HashMap>();