Improve and comment git_ignore__pop_dir This just cleans up the improved logic for popping ignore dirs and documents why the complex behavior is needed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
diff --git a/src/ignore.c b/src/ignore.c
index ca63f0b..0c35d04 100644
--- a/src/ignore.c
+++ b/src/ignore.c
@@ -168,15 +168,25 @@ int git_ignore__pop_dir(git_ignores *ign)
{
if (ign->ign_path.length > 0) {
git_attr_file *file = git_vector_last(&ign->ign_path);
- size_t keylen = strlen(file->key);
-
- while (keylen && file->key[keylen] != '/')
- keylen--;
- keylen -= 1; /* because we will skip "0#" prefix */
-
- if (ign->dir.size > keylen &&
- !memcmp(ign->dir.ptr + ign->dir.size - keylen,
- file->key + 2, keylen))
+ const char *start, *end, *scan;
+ size_t keylen;
+
+ /* - ign->dir looks something like "a/b" (or "a/b/c/d")
+ * - file->key looks something like "0#a/b/.gitignore
+ *
+ * We are popping the last directory off ign->dir. We also want to
+ * remove the file from the vector if the directory part of the key
+ * matches the ign->dir path. We need to test if the "a/b" part of
+ * the file key matches the path we are about to pop.
+ */
+
+ for (start = end = scan = &file->key[2]; *scan; ++scan)
+ if (*scan == '/')
+ end = scan; /* point 'end' to last '/' in key */
+ keylen = (end - start) + 1;
+
+ if (ign->dir.size >= keylen &&
+ !memcmp(ign->dir.ptr + ign->dir.size - keylen, start, keylen))
git_vector_pop(&ign->ign_path);
git_buf_rtruncate_at_char(&ign->dir, '/');