changeset 15:865bf07f381f

Basic hgignore handling
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Mon, 27 Dec 2010 00:50:02 +0100
parents 442dc6ee647b
children 254078595653
files design.txt src/com/tmate/hgkit/ll/HgIgnore.java src/com/tmate/hgkit/ll/LocalHgRepo.java
diffstat 3 files changed, 86 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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.
--- /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<String> 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<String>();
+		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;
+	}
+}
--- 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<String, SoftReference<RevlogStream>> streamsCache = new HashMap<String, SoftReference<RevlogStream>>();