Commits

Anonymous committed 0ca14a5

Start adding interfaces to read in partial trees

The same way "git-diff-tree" can limit its output to just a set of matches,
we can read in just a partial tree for comparison purposes.

Comments (0)

Files changed (4)

 extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type);
 
 /* Read a tree into the cache */
-extern int read_tree(void *buffer, unsigned long size, int stage);
+extern int read_tree(void *buffer, unsigned long size, int stage, char **paths);
 
 extern int write_sha1_from_fd(const unsigned char *sha1, int fd);
 extern int write_sha1_to_fd(int fd, const unsigned char *sha1);
 	tree = read_object_with_reference(sha1, "tree", &size, NULL);
 	if (!tree)
 		die("bad tree object %s", tree_name);
-	if (read_tree(tree, size, 1))
+	if (read_tree(tree, size, 1, NULL))
 		die("unable to read tree object %s", tree_name);
 
 	ret = diff_cache(active_cache, active_nr);
 	buffer = read_object_with_reference(sha1, "tree", &size, NULL);
 	if (!buffer)
 		return -1;
-	ret = read_tree(buffer, size, stage);
+	ret = read_tree(buffer, size, stage, NULL);
 	free(buffer);
 	return ret;
 }
 	return add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);
 }
 
+static int match_tree_entry(const char *base, int baselen, const char *path, unsigned int mode, char **paths)
+{
+	char *match;
+	int pathlen;
+
+	if (!paths)
+		return 1;
+	pathlen = strlen(path);
+	while ((match = *paths++) != NULL) {
+		int matchlen = strlen(match);
+
+		if (baselen >= matchlen) {
+			/* If it doesn't match, move along... */
+			if (strncmp(base, match, matchlen))
+				continue;
+			/* The base is a subdirectory of a path which was specified. */
+			return 1;
+		}
+
+		/* Does the base match? */
+		if (strncmp(base, match, baselen))
+			continue;
+
+		match += baselen;
+		matchlen -= baselen;
+
+		if (pathlen > matchlen)
+			continue;
+
+		if (matchlen > pathlen) {
+			if (match[pathlen] != '/')
+				continue;
+			if (!S_ISDIR(mode))
+				continue;
+		}
+
+		if (strncmp(path, match, pathlen))
+			continue;
+	}
+	return 0;
+}
+
 static int read_tree_recursive(void *buffer, unsigned long size,
-			       const char *base, int baselen, int stage)
+			       const char *base, int baselen,
+			       int stage, char **match)
 {
 	while (size) {
 		int len = strlen(buffer)+1;
 		buffer = sha1 + 20;
 		size -= len + 20;
 
+		if (!match_tree_entry(base, baselen, path, mode, match))
+			continue;
+
 		if (S_ISDIR(mode)) {
 			int retval;
 			int pathlen = strlen(path);
 			newbase[baselen + pathlen] = '/';
 			retval = read_tree_recursive(eltbuf, eltsize,
 						     newbase,
-						     baselen + pathlen + 1, stage);
+						     baselen + pathlen + 1,
+						     stage, match);
 			free(eltbuf);
 			free(newbase);
 			if (retval)
 	return 0;
 }
 
-int read_tree(void *buffer, unsigned long size, int stage)
+int read_tree(void *buffer, unsigned long size, int stage, char **match)
 {
-	return read_tree_recursive(buffer, size, "", 0, stage);
+	return read_tree_recursive(buffer, size, "", 0, stage, match);
 }
 
 struct tree *lookup_tree(const unsigned char *sha1)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.