{"thread":{"id":"21446","subject":"[PATCH nd/sparse] Support directory exclusion from index","startedAt":"2009-10-31T14:09:23Z","lastAt":"2009-10-31T14:09:23Z","messageCount":1,"participants":["Nguyễn Thái Ngọc Duy"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"126523","messageId":"1256998163-979-1-git-send-email-pclouds@gmail.com","threadId":"21446","inReplyTo":null,"subject":"[PATCH nd/sparse] Support directory exclusion from index","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2009-10-31T14:09:23Z","receivedAt":"2009-10-31T14:09:23Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"The function excluded_from_list (or its public API excluded) is\ncurrently used to mark what entry is included in sparse checkout.\nBecause index does not have directories, the pattern \"foo\", while\nwould match directory \"foo\" on working directory, would not match\nagainst index.\n\nTo overcome this, if a pattern does not match, check if it matches\nparent directories too before moving on to the next pattern. This\nbehavior only applies to index matching.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n There is subtle difference, which might break things. When working\n with file system, it checks top-down, parent directories first.\n I do bottom-up.\n\n If/you/have/deep/directories sparse checkout may become slow.\n\n And my test broke :(\n\n dir.c                                |   24 ++++++++++++++++++++++--\n t/t1009-read-tree-sparse-checkout.sh |    4 ++--\n 2 files changed, 24 insertions(+), 4 deletions(-)\n\ndiff --git a/dir.c b/dir.c\nindex 3a8d3e6..82227e5 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -334,13 +334,15 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)\n }\n \n /* Scan the list and let the last match determine the fate.\n+ * dtype == NULL means matching against index, not working directory.\n  * Return 1 for exclude, 0 for include and -1 for undecided.\n  */\n-int excluded_from_list(const char *pathname,\n-\t\t       int pathlen, const char *basename, int *dtype,\n+int excluded_from_list(const char *pathname_,\n+\t\t       int pathlen_, const char *basename_, int *dtype,\n \t\t       struct exclude_list *el)\n {\n \tint i;\n+\tchar buf[PATH_MAX];\n \n \tif (el->nr) {\n \t\tfor (i = el->nr - 1; 0 <= i; i--) {\n@@ -348,6 +350,11 @@ int excluded_from_list(const char *pathname,\n \t\t\tconst char *exclude = x->pattern;\n \t\t\tint to_exclude = x->to_exclude;\n \n+\t\t\tconst char *pathname = pathname_;\n+\t\t\tconst char *basename = basename_;\n+\t\t\tint pathlen = pathlen_;\n+\n+recheck:\n \t\t\tif (x->flags & EXC_FLAG_MUSTBEDIR) {\n \t\t\t\tif (!dtype) {\n \t\t\t\t\tif (!prefixcmp(pathname, exclude))\n@@ -398,6 +405,19 @@ int excluded_from_list(const char *pathname,\n \t\t\t\t\t    return to_exclude;\n \t\t\t\t}\n \t\t\t}\n+\n+\t\t\tif (!dtype) { /* matching against index */\n+\t\t\t\tbasename = strrchr(pathname, '/');\n+\t\t\t\tif (basename) {\n+\t\t\t\t\tpathlen = basename-pathname;\n+\t\t\t\t\tmemcpy(buf, pathname, pathlen);\n+\t\t\t\t\tbuf[pathlen] = '\\0';\n+\t\t\t\t\tpathname = buf;\n+\t\t\t\t\tbasename = strrchr(pathname, '/');\n+\t\t\t\t\tbasename = (basename) ? basename+1 : pathname;\n+\t\t\t\t\tgoto recheck;\n+\t\t\t\t}\n+\t\t\t}\n \t\t}\n \t}\n \treturn -1; /* undecided */\ndiff --git a/t/t1009-read-tree-sparse-checkout.sh b/t/t1009-read-tree-sparse-checkout.sh\nindex 62246db..b57d237 100755\n--- a/t/t1009-read-tree-sparse-checkout.sh\n+++ b/t/t1009-read-tree-sparse-checkout.sh\n@@ -84,13 +84,13 @@ cat >expected.swt <<EOF\n H init.t\n H sub/added\n EOF\n-test_expect_failure 'match directories without trailing slash' '\n+test_expect_success 'match directories without trailing slash' '\n \techo init.t > .git/info/sparse-checkout &&\n \techo sub >> .git/info/sparse-checkout &&\n \tgit read-tree -m -u HEAD &&\n \tgit ls-files -t > result &&\n \ttest_cmp expected.swt result &&\n-\ttest ! -f init.t &&\n+\ttest -f init.t &&\n \ttest -f sub/added\n '\n \n-- \n1.6.5.2.216.g9c1ec\n"}]}