Commit 85b8b18b6a07b74dd2631c3a647ca758660bf298

Russell Belfer 2013-06-19T15:22:48

Add fn to check pathspec for ignored files Command line Git sometimes generates an error message if given a pathspec that contains an exact match to an ignored file (provided --force isn't also given). This adds an internal function that makes it easy to check it that has happened. Right now, I'm not creating a public API for this because that would get a little more complicated with a need for callbacks for all invalid paths.

diff --git a/src/ignore.c b/src/ignore.c
index e150b95..cc90b0c 100644
--- a/src/ignore.c
+++ b/src/ignore.c
@@ -340,3 +340,61 @@ cleanup:
 	return error;
 }
 
+
+int git_ignore__check_pathspec_for_exact_ignores(
+	git_repository *repo,
+	git_vector *vspec,
+	bool no_fnmatch)
+{
+	int error = 0;
+	size_t i;
+	git_attr_fnmatch *match;
+	int ignored;
+	git_buf path = GIT_BUF_INIT;
+	const char *wd, *filename;
+	git_index *idx;
+
+	if ((error = git_repository__ensure_not_bare(
+			repo, "validate pathspec")) < 0 ||
+		(error = git_repository_index(&idx, repo)) < 0)
+		return error;
+
+	wd = git_repository_workdir(repo);
+
+	git_vector_foreach(vspec, i, match) {
+		/* skip wildcard matches (if they are being used) */
+		if ((match->flags & GIT_ATTR_FNMATCH_HASWILD) != 0 &&
+			!no_fnmatch)
+			continue;
+
+		filename = match->pattern;
+
+		/* if file is already in the index, it's fine */
+		if (git_index_get_bypath(idx, filename, 0) != NULL)
+			continue;
+
+		if ((error = git_buf_joinpath(&path, wd, filename)) < 0)
+			break;
+
+		/* is there a file on disk that matches this exactly? */
+		if (!git_path_isfile(path.ptr))
+			continue;
+
+		/* is that file ignored? */
+		if ((error = git_ignore_path_is_ignored(&ignored, repo, filename)) < 0)
+			break;
+
+		if (ignored) {
+			giterr_set(GITERR_INVALID, "pathspec contains ignored file '%s'",
+				filename);
+			error = GIT_EINVALIDSPEC;
+			break;
+		}
+	}
+
+	git_index_free(idx);
+	git_buf_free(&path);
+
+	return error;
+}
+
diff --git a/src/ignore.h b/src/ignore.h
index e00e4a8..cc114b0 100644
--- a/src/ignore.h
+++ b/src/ignore.h
@@ -41,4 +41,13 @@ extern void git_ignore__free(git_ignores *ign);
 
 extern int git_ignore__lookup(git_ignores *ign, const char *path, int *ignored);
 
+/* command line Git sometimes generates an error message if given a
+ * pathspec that contains an exact match to an ignored file (provided
+ * --force isn't also given).  This makes it easy to check it that has
+ * happened.  Returns GIT_EINVALIDSPEC if the pathspec contains ignored
+ * exact matches (that are not already present in the index).
+ */
+extern int git_ignore__check_pathspec_for_exact_ignores(
+	git_repository *repo, git_vector *pathspec, bool no_fnmatch);
+
 #endif