{"thread":{"id":"51795","subject":"[PATCH 0/5] Refactor excludes library","startedAt":"2019-09-03T18:04:59Z","lastAt":"2019-09-06T20:34:10Z","messageCount":11,"participants":["Derrick Stolee via GitGitGadget","Elijah Newren","Jeff King","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"381738","messageId":"pull.329.git.gitgitgadget@gmail.com","threadId":"51795","inReplyTo":null,"subject":"[PATCH 0/5] Refactor excludes library","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2019-09-03T18:04:54Z","receivedAt":"2019-09-03T18:04:59Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"The exclude library defined in dir.h was originally written for the\n.gitignore feature, but has since been used for .gitattributes and\nsparse-checkout. In the later applications, these patterns are used for \ninclusion rather than exclusion, so the name is confusing. This gets\nparticularly bad when looking at how the sparse-checkout feature uses\nis_excluded_from_list() to really mean \"should be included in the working\ndirectory\".\n\nThis series performs several renames of structs and methods to generalize\nthe exclude library to be a \"pattern matching\" library. Instead of a list of\nexcludes, we have a list of path patterns. It is up to the consumer to\ndecide what to do with a match. The .gitignore logic will still treat the\npatterns as a list of exclusions, the sparse-checkout logic treats the\npatterns as a list of inclusions.\n\nFor this reason, some methods and structs in dir.h retain \"exclude\" in their\nname. These are limited to things consumed only by the .gitignore feature\n(as far as I can tell).\n\nMost of these changes are mechanical find-and-replaces, with the exception\nof some variable names and the last patch.\n\nThe last patch, \"unpack-trees: rename 'is_excluded_from_list()'\", performs a\nmore meaningful refactor. The method is_excluded_from_list() was only used\nby sparse-checkout (inside the clear_ce_flags() methods) to see if a path\nshould be included in the working directory. The return value of \"1 for\nexcluded\" was confusing. Instead, use a new enum value. This required\nchanging several method prototypes inside unpack-trees.c.\n\nThis refactor was inspired by Elijah Newren's feedback [1] on my\nsparse-checkout builtin RFC. I am working on a few other orthogonal changes\nto make to the existing sparse-checkout behavior before I resubmit that RFC.\n\nI had started working on v2.23.0, but found adjacent-diff conflicts with\nmd/list-objects-filter-combo [2] and js/partial-clone-sparse-blob [3]. Those\nbranches are independent, but the conflicts with\nmd/list-objects-filter-combo were more severe (and that branch seems closer\nto merging) so this is based on md/list-object-filter-combo. Hopefully the\nconflicts with js/partial-clone-sparse-blob are clear enough to resolve\neasily.\n\nThanks, -Stolee\n\n[1] \nhttps://public-inbox.org/git/CABPp-BFMtO=7UGVZPbqh3tthSetvz5F=W3S=RsryPSuchmZeZw@mail.gmail.com/\nRe: [PATCH 8/9] sparse-checkout: use hashmaps for cone patterns\n\n[2] https://public-inbox.org/git/cover.1558030802.git.matvore@google.com/\n[RFC PATCH 0/3] implement composite filters\n\n[3] https://public-inbox.org/git/20190828201824.1255-1-jon@jonsimons.org/\n[PATCH 0/2] partial-clone: fix two issues with sparse filter handling\n\nDerrick Stolee (5):\n  treewide: rename 'struct exclude' to 'struct path_pattern'\n  treewide: rename 'struct exclude_list' to 'struct pattern_list'\n  treewide: rename 'EXCL_FLAG_' to 'PATTERN_FLAG_'\n  treewide: rename 'exclude' methods to 'pattern'\n  unpack-trees: rename 'is_excluded_from_list()'\n\n Documentation/RelNotes/2.7.1.txt              |   2 +-\n Documentation/RelNotes/2.8.0.txt              |   2 +-\n .../technical/api-directory-listing.txt       |   6 +-\n attr.c                                        |  10 +-\n builtin/check-ignore.c                        |  34 +--\n builtin/clean.c                               |  12 +-\n builtin/ls-files.c                            |   8 +-\n dir.c                                         | 284 +++++++++---------\n dir.h                                         |  71 +++--\n list-objects-filter.c                         |  37 +--\n unpack-trees.c                                |  67 +++--\n unpack-trees.h                                |   4 +-\n 12 files changed, 285 insertions(+), 252 deletions(-)\n\n\nbase-commit: 90d21f9ebf6906f0ebb4fb1b20ec9536072e2916\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-329%2Fderrickstolee%2Fexclude-refactor-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-329/derrickstolee/exclude-refactor-v1\nPull-Request: https://github.com/gitgitgadget/git/pull/329\n-- \ngitgitgadget\n"},{"id":"381739","messageId":"8cdffbd1c82c34a7dbdb18cb396e5e422889aad6.1567533893.git.gitgitgadget@gmail.com","threadId":"51795","inReplyTo":"pull.329.git.gitgitgadget@gmail.com","subject":"[PATCH 1/5] treewide: rename 'struct exclude' to 'struct path_pattern'","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2019-09-03T18:04:55Z","receivedAt":"2019-09-03T18:05:01Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <dstolee@microsoft.com>\n\nThe first consumer of pattern-matching filenames was the\n.gitignore feature. In that context, storing a list of patterns\nas a list of 'struct exclude' items makes sense. However, the\nsparse-checkout feature then adopted these structures and methods,\nbut with the opposite meaning: these patterns match the files\nthat should be included!\n\nIt would be clearer to rename this entire library as a \"pattern\nmatching\" library, and the callers apply exclusion/inclusion\nlogic accordingly based on their needs.\n\nThis commit renames 'struct exclude' to 'struct path_pattern'\nand renames several variable names to match. 'struct pattern'\nwas already taken by attr.c, and this more completely describes\nthat the patterns are specific to file paths.\n\nSigned-off-by: Derrick Stolee <dstolee@microsoft.com>\n---\n builtin/check-ignore.c |  34 ++++++------\n dir.c                  | 115 +++++++++++++++++++++--------------------\n dir.h                  |   8 +--\n 3 files changed, 80 insertions(+), 77 deletions(-)\n\ndiff --git a/builtin/check-ignore.c b/builtin/check-ignore.c\nindex 599097304b..9a0f234514 100644\n--- a/builtin/check-ignore.c\n+++ b/builtin/check-ignore.c\n@@ -32,19 +32,19 @@ static const struct option check_ignore_options[] = {\n \tOPT_END()\n };\n \n-static void output_exclude(const char *path, struct exclude *exclude)\n+static void output_pattern(const char *path, struct path_pattern *pattern)\n {\n-\tchar *bang  = (exclude && exclude->flags & EXC_FLAG_NEGATIVE)  ? \"!\" : \"\";\n-\tchar *slash = (exclude && exclude->flags & EXC_FLAG_MUSTBEDIR) ? \"/\" : \"\";\n+\tchar *bang  = (pattern && pattern->flags & EXC_FLAG_NEGATIVE)  ? \"!\" : \"\";\n+\tchar *slash = (pattern && pattern->flags & EXC_FLAG_MUSTBEDIR) ? \"/\" : \"\";\n \tif (!nul_term_line) {\n \t\tif (!verbose) {\n \t\t\twrite_name_quoted(path, stdout, '\\n');\n \t\t} else {\n-\t\t\tif (exclude) {\n-\t\t\t\tquote_c_style(exclude->el->src, NULL, stdout, 0);\n+\t\t\tif (pattern) {\n+\t\t\t\tquote_c_style(pattern->el->src, NULL, stdout, 0);\n \t\t\t\tprintf(\":%d:%s%s%s\\t\",\n-\t\t\t\t       exclude->srcpos,\n-\t\t\t\t       bang, exclude->pattern, slash);\n+\t\t\t\t       pattern->srcpos,\n+\t\t\t\t       bang, pattern->pattern, slash);\n \t\t\t}\n \t\t\telse {\n \t\t\t\tprintf(\"::\\t\");\n@@ -56,11 +56,11 @@ static void output_exclude(const char *path, struct exclude *exclude)\n \t\tif (!verbose) {\n \t\t\tprintf(\"%s%c\", path, '\\0');\n \t\t} else {\n-\t\t\tif (exclude)\n+\t\t\tif (pattern)\n \t\t\t\tprintf(\"%s%c%d%c%s%s%s%c%s%c\",\n-\t\t\t\t       exclude->el->src, '\\0',\n-\t\t\t\t       exclude->srcpos, '\\0',\n-\t\t\t\t       bang, exclude->pattern, slash, '\\0',\n+\t\t\t\t       pattern->el->src, '\\0',\n+\t\t\t\t       pattern->srcpos, '\\0',\n+\t\t\t\t       bang, pattern->pattern, slash, '\\0',\n \t\t\t\t       path, '\\0');\n \t\t\telse\n \t\t\t\tprintf(\"%c%c%c%s%c\", '\\0', '\\0', '\\0', path, '\\0');\n@@ -74,7 +74,7 @@ static int check_ignore(struct dir_struct *dir,\n \tconst char *full_path;\n \tchar *seen;\n \tint num_ignored = 0, i;\n-\tstruct exclude *exclude;\n+\tstruct path_pattern *pattern;\n \tstruct pathspec pathspec;\n \n \tif (!argc) {\n@@ -103,15 +103,15 @@ static int check_ignore(struct dir_struct *dir,\n \tseen = find_pathspecs_matching_against_index(&pathspec, &the_index);\n \tfor (i = 0; i < pathspec.nr; i++) {\n \t\tfull_path = pathspec.items[i].match;\n-\t\texclude = NULL;\n+\t\tpattern = NULL;\n \t\tif (!seen[i]) {\n \t\t\tint dtype = DT_UNKNOWN;\n-\t\t\texclude = last_exclude_matching(dir, &the_index,\n+\t\t\tpattern = last_exclude_matching(dir, &the_index,\n \t\t\t\t\t\t\tfull_path, &dtype);\n \t\t}\n-\t\tif (!quiet && (exclude || show_non_matching))\n-\t\t\toutput_exclude(pathspec.items[i].original, exclude);\n-\t\tif (exclude)\n+\t\tif (!quiet && (pattern || show_non_matching))\n+\t\t\toutput_pattern(pathspec.items[i].original, pattern);\n+\t\tif (pattern)\n \t\t\tnum_ignored++;\n \t}\n \tfree(seen);\ndiff --git a/dir.c b/dir.c\nindex ba4a51c296..4128d59d7a 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -602,27 +602,27 @@ void parse_exclude_pattern(const char **pattern,\n void add_exclude(const char *string, const char *base,\n \t\t int baselen, struct exclude_list *el, int srcpos)\n {\n-\tstruct exclude *x;\n+\tstruct path_pattern *pattern;\n \tint patternlen;\n \tunsigned flags;\n \tint nowildcardlen;\n \n \tparse_exclude_pattern(&string, &patternlen, &flags, &nowildcardlen);\n \tif (flags & EXC_FLAG_MUSTBEDIR) {\n-\t\tFLEXPTR_ALLOC_MEM(x, pattern, string, patternlen);\n+\t\tFLEXPTR_ALLOC_MEM(pattern, pattern, string, patternlen);\n \t} else {\n-\t\tx = xmalloc(sizeof(*x));\n-\t\tx->pattern = string;\n+\t\tpattern = xmalloc(sizeof(*pattern));\n+\t\tpattern->pattern = string;\n \t}\n-\tx->patternlen = patternlen;\n-\tx->nowildcardlen = nowildcardlen;\n-\tx->base = base;\n-\tx->baselen = baselen;\n-\tx->flags = flags;\n-\tx->srcpos = srcpos;\n-\tALLOC_GROW(el->excludes, el->nr + 1, el->alloc);\n-\tel->excludes[el->nr++] = x;\n-\tx->el = el;\n+\tpattern->patternlen = patternlen;\n+\tpattern->nowildcardlen = nowildcardlen;\n+\tpattern->base = base;\n+\tpattern->baselen = baselen;\n+\tpattern->flags = flags;\n+\tpattern->srcpos = srcpos;\n+\tALLOC_GROW(el->patterns, el->nr + 1, el->alloc);\n+\tel->patterns[el->nr++] = pattern;\n+\tpattern->el = el;\n }\n \n static int read_skip_worktree_file_from_index(const struct index_state *istate,\n@@ -651,8 +651,8 @@ void clear_exclude_list(struct exclude_list *el)\n \tint i;\n \n \tfor (i = 0; i < el->nr; i++)\n-\t\tfree(el->excludes[i]);\n-\tfree(el->excludes);\n+\t\tfree(el->patterns[i]);\n+\tfree(el->patterns);\n \tfree(el->filebuf);\n \n \tmemset(el, 0, sizeof(*el));\n@@ -1021,51 +1021,54 @@ int match_pathname(const char *pathname, int pathlen,\n  * any, determines the fate.  Returns the exclude_list element which\n  * matched, or NULL for undecided.\n  */\n-static struct exclude *last_exclude_matching_from_list(const char *pathname,\n+static struct path_pattern *last_exclude_matching_from_list(const char *pathname,\n \t\t\t\t\t\t       int pathlen,\n \t\t\t\t\t\t       const char *basename,\n \t\t\t\t\t\t       int *dtype,\n \t\t\t\t\t\t       struct exclude_list *el,\n \t\t\t\t\t\t       struct index_state *istate)\n {\n-\tstruct exclude *exc = NULL; /* undecided */\n+\tstruct path_pattern *res = NULL; /* undecided */\n \tint i;\n \n \tif (!el->nr)\n \t\treturn NULL;\t/* undefined */\n \n \tfor (i = el->nr - 1; 0 <= i; i--) {\n-\t\tstruct exclude *x = el->excludes[i];\n-\t\tconst char *exclude = x->pattern;\n-\t\tint prefix = x->nowildcardlen;\n+\t\tstruct path_pattern *pattern = el->patterns[i];\n+\t\tconst char *exclude = pattern->pattern;\n+\t\tint prefix = pattern->nowildcardlen;\n \n-\t\tif (x->flags & EXC_FLAG_MUSTBEDIR) {\n+\t\tif (pattern->flags & EXC_FLAG_MUSTBEDIR) {\n \t\t\tif (*dtype == DT_UNKNOWN)\n \t\t\t\t*dtype = get_dtype(NULL, istate, pathname, pathlen);\n \t\t\tif (*dtype != DT_DIR)\n \t\t\t\tcontinue;\n \t\t}\n \n-\t\tif (x->flags & EXC_FLAG_NODIR) {\n+\t\tif (pattern->flags & EXC_FLAG_NODIR) {\n \t\t\tif (match_basename(basename,\n \t\t\t\t\t   pathlen - (basename - pathname),\n-\t\t\t\t\t   exclude, prefix, x->patternlen,\n-\t\t\t\t\t   x->flags)) {\n-\t\t\t\texc = x;\n+\t\t\t\t\t   exclude, prefix, pattern->patternlen,\n+\t\t\t\t\t   pattern->flags)) {\n+\t\t\t\tres = pattern;\n \t\t\t\tbreak;\n \t\t\t}\n \t\t\tcontinue;\n \t\t}\n \n-\t\tassert(x->baselen == 0 || x->base[x->baselen - 1] == '/');\n+\t\tassert(pattern->baselen == 0 ||\n+\t\t       pattern->base[pattern->baselen - 1] == '/');\n \t\tif (match_pathname(pathname, pathlen,\n-\t\t\t\t   x->base, x->baselen ? x->baselen - 1 : 0,\n-\t\t\t\t   exclude, prefix, x->patternlen, x->flags)) {\n-\t\t\texc = x;\n+\t\t\t\t   pattern->base,\n+\t\t\t\t   pattern->baselen ? pattern->baselen - 1 : 0,\n+\t\t\t\t   exclude, prefix, pattern->patternlen,\n+\t\t\t\t   pattern->flags)) {\n+\t\t\tres = pattern;\n \t\t\tbreak;\n \t\t}\n \t}\n-\treturn exc;\n+\treturn res;\n }\n \n /*\n@@ -1076,30 +1079,30 @@ int is_excluded_from_list(const char *pathname,\n \t\t\t  int pathlen, const char *basename, int *dtype,\n \t\t\t  struct exclude_list *el, struct index_state *istate)\n {\n-\tstruct exclude *exclude;\n-\texclude = last_exclude_matching_from_list(pathname, pathlen, basename,\n+\tstruct path_pattern *pattern;\n+\tpattern = last_exclude_matching_from_list(pathname, pathlen, basename,\n \t\t\t\t\t\t  dtype, el, istate);\n-\tif (exclude)\n-\t\treturn exclude->flags & EXC_FLAG_NEGATIVE ? 0 : 1;\n+\tif (pattern)\n+\t\treturn pattern->flags & EXC_FLAG_NEGATIVE ? 0 : 1;\n \treturn -1; /* undecided */\n }\n \n-static struct exclude *last_exclude_matching_from_lists(struct dir_struct *dir,\n-\t\t\t\t\t\t\tstruct index_state *istate,\n-\t\tconst char *pathname, int pathlen, const char *basename,\n-\t\tint *dtype_p)\n+static struct path_pattern *last_exclude_matching_from_lists(\n+\t\tstruct dir_struct *dir, struct index_state *istate,\n+\t\tconst char *pathname, int pathlen,\n+\t\tconst char *basename, int *dtype_p)\n {\n \tint i, j;\n \tstruct exclude_list_group *group;\n-\tstruct exclude *exclude;\n+\tstruct path_pattern *pattern;\n \tfor (i = EXC_CMDL; i <= EXC_FILE; i++) {\n \t\tgroup = &dir->exclude_list_group[i];\n \t\tfor (j = group->nr - 1; j >= 0; j--) {\n-\t\t\texclude = last_exclude_matching_from_list(\n+\t\t\tpattern = last_exclude_matching_from_list(\n \t\t\t\tpathname, pathlen, basename, dtype_p,\n \t\t\t\t&group->el[j], istate);\n-\t\t\tif (exclude)\n-\t\t\t\treturn exclude;\n+\t\t\tif (pattern)\n+\t\t\t\treturn pattern;\n \t\t}\n \t}\n \treturn NULL;\n@@ -1132,7 +1135,7 @@ static void prep_exclude(struct dir_struct *dir,\n \t\t\tbreak;\n \t\tel = &group->el[dir->exclude_stack->exclude_ix];\n \t\tdir->exclude_stack = stk->prev;\n-\t\tdir->exclude = NULL;\n+\t\tdir->pattern = NULL;\n \t\tfree((char *)el->src); /* see strbuf_detach() below */\n \t\tclear_exclude_list(el);\n \t\tfree(stk);\n@@ -1140,7 +1143,7 @@ static void prep_exclude(struct dir_struct *dir,\n \t}\n \n \t/* Skip traversing into sub directories if the parent is excluded */\n-\tif (dir->exclude)\n+\tif (dir->pattern)\n \t\treturn;\n \n \t/*\n@@ -1189,15 +1192,15 @@ static void prep_exclude(struct dir_struct *dir,\n \t\tif (stk->baselen) {\n \t\t\tint dt = DT_DIR;\n \t\t\tdir->basebuf.buf[stk->baselen - 1] = 0;\n-\t\t\tdir->exclude = last_exclude_matching_from_lists(dir,\n+\t\t\tdir->pattern = last_exclude_matching_from_lists(dir,\n \t\t\t\t\t\t\t\t\tistate,\n \t\t\t\tdir->basebuf.buf, stk->baselen - 1,\n \t\t\t\tdir->basebuf.buf + current, &dt);\n \t\t\tdir->basebuf.buf[stk->baselen - 1] = '/';\n-\t\t\tif (dir->exclude &&\n-\t\t\t    dir->exclude->flags & EXC_FLAG_NEGATIVE)\n-\t\t\t\tdir->exclude = NULL;\n-\t\t\tif (dir->exclude) {\n+\t\t\tif (dir->pattern &&\n+\t\t\t    dir->pattern->flags & EXC_FLAG_NEGATIVE)\n+\t\t\t\tdir->pattern = NULL;\n+\t\t\tif (dir->pattern) {\n \t\t\t\tdir->exclude_stack = stk;\n \t\t\t\treturn;\n \t\t\t}\n@@ -1223,7 +1226,7 @@ static void prep_exclude(struct dir_struct *dir,\n \t\t\t/*\n \t\t\t * dir->basebuf gets reused by the traversal, but we\n \t\t\t * need fname to remain unchanged to ensure the src\n-\t\t\t * member of each struct exclude correctly\n+\t\t\t * member of each struct path_pattern correctly\n \t\t\t * back-references its source file.  Other invocations\n \t\t\t * of add_exclude_list provide stable strings, so we\n \t\t\t * strbuf_detach() and free() here in the caller.\n@@ -1266,7 +1269,7 @@ static void prep_exclude(struct dir_struct *dir,\n  * Returns the exclude_list element which matched, or NULL for\n  * undecided.\n  */\n-struct exclude *last_exclude_matching(struct dir_struct *dir,\n+struct path_pattern *last_exclude_matching(struct dir_struct *dir,\n \t\t\t\t      struct index_state *istate,\n \t\t\t\t      const char *pathname,\n \t\t\t\t      int *dtype_p)\n@@ -1277,8 +1280,8 @@ struct exclude *last_exclude_matching(struct dir_struct *dir,\n \n \tprep_exclude(dir, istate, pathname, basename-pathname);\n \n-\tif (dir->exclude)\n-\t\treturn dir->exclude;\n+\tif (dir->pattern)\n+\t\treturn dir->pattern;\n \n \treturn last_exclude_matching_from_lists(dir, istate, pathname, pathlen,\n \t\t\tbasename, dtype_p);\n@@ -1292,10 +1295,10 @@ struct exclude *last_exclude_matching(struct dir_struct *dir,\n int is_excluded(struct dir_struct *dir, struct index_state *istate,\n \t\tconst char *pathname, int *dtype_p)\n {\n-\tstruct exclude *exclude =\n+\tstruct path_pattern *pattern =\n \t\tlast_exclude_matching(dir, istate, pathname, dtype_p);\n-\tif (exclude)\n-\t\treturn exclude->flags & EXC_FLAG_NEGATIVE ? 0 : 1;\n+\tif (pattern)\n+\t\treturn pattern->flags & EXC_FLAG_NEGATIVE ? 0 : 1;\n \treturn 0;\n }\n \ndiff --git a/dir.h b/dir.h\nindex 680079bbe3..e8b90fc482 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -16,7 +16,7 @@ struct dir_entry {\n #define EXC_FLAG_MUSTBEDIR 8\n #define EXC_FLAG_NEGATIVE 16\n \n-struct exclude {\n+struct path_pattern {\n \t/*\n \t * This allows callers of last_exclude_matching() etc.\n \t * to determine the origin of the matching pattern.\n@@ -54,7 +54,7 @@ struct exclude_list {\n \t/* origin of list, e.g. path to filename, or descriptive string */\n \tconst char *src;\n \n-\tstruct exclude **excludes;\n+\tstruct path_pattern **patterns;\n };\n \n /*\n@@ -191,7 +191,7 @@ struct dir_struct {\n \t * matching exclude struct if the directory is excluded.\n \t */\n \tstruct exclude_stack *exclude_stack;\n-\tstruct exclude *exclude;\n+\tstruct path_pattern *pattern;\n \tstruct strbuf basebuf;\n \n \t/* Enable untracked file cache if set */\n@@ -248,7 +248,7 @@ int match_pathname(const char *, int,\n \t\t   const char *, int,\n \t\t   const char *, int, int, unsigned);\n \n-struct exclude *last_exclude_matching(struct dir_struct *dir,\n+struct path_pattern *last_exclude_matching(struct dir_struct *dir,\n \t\t\t\t      struct index_state *istate,\n \t\t\t\t      const char *name, int *dtype);\n \n-- \ngitgitgadget\n\n"},{"id":"381740","messageId":"908c92205488f986de4aa0bfb432ce87fde6cfa9.1567533893.git.gitgitgadget@gmail.com","threadId":"51795","inReplyTo":"pull.329.git.gitgitgadget@gmail.com","subject":"[PATCH 2/5] treewide: rename 'struct exclude_list' to 'struct pattern_list'","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2019-09-03T18:04:56Z","receivedAt":"2019-09-03T18:05:01Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <dstolee@microsoft.com>\n\nThe first consumer of pattern-matching filenames was the\n.gitignore feature. In that context, storing a list of patterns\nas a 'struct exclude_list'  makes sense. However, the\nsparse-checkout feature then adopted these structures and methods,\nbut with the opposite meaning: these patterns match the files\nthat should be included!\n\nIt would be clearer to rename this entire library as a \"pattern\nmatching\" library, and the callers apply exclusion/inclusion\nlogic accordingly based on their needs.\n\nThis commit renames 'struct exclude_list' to 'struct pattern_list'\nand renames several variables called 'el' to 'pl'.\n\nSigned-off-by: Derrick Stolee <dstolee@microsoft.com>\n---\n builtin/check-ignore.c |   4 +-\n builtin/clean.c        |  12 ++---\n builtin/ls-files.c     |   6 +--\n dir.c                  | 106 ++++++++++++++++++++---------------------\n dir.h                  |  18 +++----\n list-objects-filter.c  |   8 ++--\n unpack-trees.c         |  42 ++++++++--------\n unpack-trees.h         |   4 +-\n 8 files changed, 100 insertions(+), 100 deletions(-)\n\ndiff --git a/builtin/check-ignore.c b/builtin/check-ignore.c\nindex 9a0f234514..97108ccb9c 100644\n--- a/builtin/check-ignore.c\n+++ b/builtin/check-ignore.c\n@@ -41,7 +41,7 @@ static void output_pattern(const char *path, struct path_pattern *pattern)\n \t\t\twrite_name_quoted(path, stdout, '\\n');\n \t\t} else {\n \t\t\tif (pattern) {\n-\t\t\t\tquote_c_style(pattern->el->src, NULL, stdout, 0);\n+\t\t\t\tquote_c_style(pattern->pl->src, NULL, stdout, 0);\n \t\t\t\tprintf(\":%d:%s%s%s\\t\",\n \t\t\t\t       pattern->srcpos,\n \t\t\t\t       bang, pattern->pattern, slash);\n@@ -58,7 +58,7 @@ static void output_pattern(const char *path, struct path_pattern *pattern)\n \t\t} else {\n \t\t\tif (pattern)\n \t\t\t\tprintf(\"%s%c%d%c%s%s%s%c%s%c\",\n-\t\t\t\t       pattern->el->src, '\\0',\n+\t\t\t\t       pattern->pl->src, '\\0',\n \t\t\t\t       pattern->srcpos, '\\0',\n \t\t\t\t       bang, pattern->pattern, slash, '\\0',\n \t\t\t\t       path, '\\0');\ndiff --git a/builtin/clean.c b/builtin/clean.c\nindex aaba4af3c2..d8c847d9fd 100644\n--- a/builtin/clean.c\n+++ b/builtin/clean.c\n@@ -647,7 +647,7 @@ static int filter_by_patterns_cmd(void)\n \tstruct strbuf confirm = STRBUF_INIT;\n \tstruct strbuf **ignore_list;\n \tstruct string_list_item *item;\n-\tstruct exclude_list *el;\n+\tstruct pattern_list *pl;\n \tint changed = -1, i;\n \n \tfor (;;) {\n@@ -670,7 +670,7 @@ static int filter_by_patterns_cmd(void)\n \t\t\tbreak;\n \n \t\tmemset(&dir, 0, sizeof(dir));\n-\t\tel = add_exclude_list(&dir, EXC_CMDL, \"manual exclude\");\n+\t\tpl = add_exclude_list(&dir, EXC_CMDL, \"manual exclude\");\n \t\tignore_list = strbuf_split_max(&confirm, ' ', 0);\n \n \t\tfor (i = 0; ignore_list[i]; i++) {\n@@ -678,7 +678,7 @@ static int filter_by_patterns_cmd(void)\n \t\t\tif (!ignore_list[i]->len)\n \t\t\t\tcontinue;\n \n-\t\t\tadd_exclude(ignore_list[i]->buf, \"\", 0, el, -(i+1));\n+\t\t\tadd_exclude(ignore_list[i]->buf, \"\", 0, pl, -(i+1));\n \t\t}\n \n \t\tchanged = 0;\n@@ -900,7 +900,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)\n \tstruct pathspec pathspec;\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct string_list exclude_list = STRING_LIST_INIT_NODUP;\n-\tstruct exclude_list *el;\n+\tstruct pattern_list *pl;\n \tstruct string_list_item *item;\n \tconst char *qname;\n \tstruct option options[] = {\n@@ -957,9 +957,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)\n \tif (!ignored)\n \t\tsetup_standard_excludes(&dir);\n \n-\tel = add_exclude_list(&dir, EXC_CMDL, \"--exclude option\");\n+\tpl = add_exclude_list(&dir, EXC_CMDL, \"--exclude option\");\n \tfor (i = 0; i < exclude_list.nr; i++)\n-\t\tadd_exclude(exclude_list.items[i].string, \"\", 0, el, -(i+1));\n+\t\tadd_exclude(exclude_list.items[i].string, \"\", 0, pl, -(i+1));\n \n \tparse_pathspec(&pathspec, 0,\n \t\t       PATHSPEC_PREFER_CWD,\ndiff --git a/builtin/ls-files.c b/builtin/ls-files.c\nindex 7f83c9a6f2..df8918a128 100644\n--- a/builtin/ls-files.c\n+++ b/builtin/ls-files.c\n@@ -516,7 +516,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)\n \tint require_work_tree = 0, show_tag = 0, i;\n \tconst char *max_prefix;\n \tstruct dir_struct dir;\n-\tstruct exclude_list *el;\n+\tstruct pattern_list *pl;\n \tstruct string_list exclude_list = STRING_LIST_INIT_NODUP;\n \tstruct option builtin_ls_files_options[] = {\n \t\t/* Think twice before adding \"--nul\" synonym to this */\n@@ -594,9 +594,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)\n \n \targc = parse_options(argc, argv, prefix, builtin_ls_files_options,\n \t\t\tls_files_usage, 0);\n-\tel = add_exclude_list(&dir, EXC_CMDL, \"--exclude option\");\n+\tpl = add_exclude_list(&dir, EXC_CMDL, \"--exclude option\");\n \tfor (i = 0; i < exclude_list.nr; i++) {\n-\t\tadd_exclude(exclude_list.items[i].string, \"\", 0, el, --exclude_args);\n+\t\tadd_exclude(exclude_list.items[i].string, \"\", 0, pl, --exclude_args);\n \t}\n \tif (show_tag || show_valid_bit || show_fsmonitor_bit) {\n \t\ttag_cached = \"H \";\ndiff --git a/dir.c b/dir.c\nindex 4128d59d7a..b522d61ee0 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -600,7 +600,7 @@ void parse_exclude_pattern(const char **pattern,\n }\n \n void add_exclude(const char *string, const char *base,\n-\t\t int baselen, struct exclude_list *el, int srcpos)\n+\t\t int baselen, struct pattern_list *pl, int srcpos)\n {\n \tstruct path_pattern *pattern;\n \tint patternlen;\n@@ -620,9 +620,9 @@ void add_exclude(const char *string, const char *base,\n \tpattern->baselen = baselen;\n \tpattern->flags = flags;\n \tpattern->srcpos = srcpos;\n-\tALLOC_GROW(el->patterns, el->nr + 1, el->alloc);\n-\tel->patterns[el->nr++] = pattern;\n-\tpattern->el = el;\n+\tALLOC_GROW(pl->patterns, pl->nr + 1, pl->alloc);\n+\tpl->patterns[pl->nr++] = pattern;\n+\tpattern->pl = pl;\n }\n \n static int read_skip_worktree_file_from_index(const struct index_state *istate,\n@@ -643,19 +643,19 @@ static int read_skip_worktree_file_from_index(const struct index_state *istate,\n }\n \n /*\n- * Frees memory within el which was allocated for exclude patterns and\n- * the file buffer.  Does not free el itself.\n+ * Frees memory within pl which was allocated for exclude patterns and\n+ * the file buffer.  Does not free pl itself.\n  */\n-void clear_exclude_list(struct exclude_list *el)\n+void clear_exclude_list(struct pattern_list *pl)\n {\n \tint i;\n \n-\tfor (i = 0; i < el->nr; i++)\n-\t\tfree(el->patterns[i]);\n-\tfree(el->patterns);\n-\tfree(el->filebuf);\n+\tfor (i = 0; i < pl->nr; i++)\n+\t\tfree(pl->patterns[i]);\n+\tfree(pl->patterns);\n+\tfree(pl->filebuf);\n \n-\tmemset(el, 0, sizeof(*el));\n+\tmemset(pl, 0, sizeof(*pl));\n }\n \n static void trim_trailing_spaces(char *buf)\n@@ -764,19 +764,19 @@ static void invalidate_directory(struct untracked_cache *uc,\n \n static int add_excludes_from_buffer(char *buf, size_t size,\n \t\t\t\t    const char *base, int baselen,\n-\t\t\t\t    struct exclude_list *el);\n+\t\t\t\t    struct pattern_list *pl);\n \n /*\n  * Given a file with name \"fname\", read it (either from disk, or from\n  * an index if 'istate' is non-null), parse it and store the\n- * exclude rules in \"el\".\n+ * exclude rules in \"pl\".\n  *\n  * If \"ss\" is not NULL, compute SHA-1 of the exclude file and fill\n  * stat data from disk (only valid if add_excludes returns zero). If\n  * ss_valid is non-zero, \"ss\" must contain good value as input.\n  */\n static int add_excludes(const char *fname, const char *base, int baselen,\n-\t\t\tstruct exclude_list *el, struct index_state *istate,\n+\t\t\tstruct pattern_list *pl, struct index_state *istate,\n \t\t\tstruct oid_stat *oid_stat)\n {\n \tstruct stat st;\n@@ -837,21 +837,21 @@ static int add_excludes(const char *fname, const char *base, int baselen,\n \t\t}\n \t}\n \n-\tadd_excludes_from_buffer(buf, size, base, baselen, el);\n+\tadd_excludes_from_buffer(buf, size, base, baselen, pl);\n \treturn 0;\n }\n \n static int add_excludes_from_buffer(char *buf, size_t size,\n \t\t\t\t    const char *base, int baselen,\n-\t\t\t\t    struct exclude_list *el)\n+\t\t\t\t    struct pattern_list *pl)\n {\n \tint i, lineno = 1;\n \tchar *entry;\n \n-\tel->filebuf = buf;\n+\tpl->filebuf = buf;\n \n \tif (skip_utf8_bom(&buf, size))\n-\t\tsize -= buf - el->filebuf;\n+\t\tsize -= buf - pl->filebuf;\n \n \tentry = buf;\n \n@@ -860,7 +860,7 @@ static int add_excludes_from_buffer(char *buf, size_t size,\n \t\t\tif (entry != buf + i && entry[0] != '#') {\n \t\t\t\tbuf[i - (i && buf[i-1] == '\\r')] = 0;\n \t\t\t\ttrim_trailing_spaces(entry);\n-\t\t\t\tadd_exclude(entry, base, baselen, el, lineno);\n+\t\t\t\tadd_exclude(entry, base, baselen, pl, lineno);\n \t\t\t}\n \t\t\tlineno++;\n \t\t\tentry = buf + i + 1;\n@@ -870,16 +870,16 @@ static int add_excludes_from_buffer(char *buf, size_t size,\n }\n \n int add_excludes_from_file_to_list(const char *fname, const char *base,\n-\t\t\t\t   int baselen, struct exclude_list *el,\n+\t\t\t\t   int baselen, struct pattern_list *pl,\n \t\t\t\t   struct index_state *istate)\n {\n-\treturn add_excludes(fname, base, baselen, el, istate, NULL);\n+\treturn add_excludes(fname, base, baselen, pl, istate, NULL);\n }\n \n int add_excludes_from_blob_to_list(\n \tstruct object_id *oid,\n \tconst char *base, int baselen,\n-\tstruct exclude_list *el)\n+\tstruct pattern_list *pl)\n {\n \tchar *buf;\n \tsize_t size;\n@@ -889,22 +889,22 @@ int add_excludes_from_blob_to_list(\n \tif (r != 1)\n \t\treturn r;\n \n-\tadd_excludes_from_buffer(buf, size, base, baselen, el);\n+\tadd_excludes_from_buffer(buf, size, base, baselen, pl);\n \treturn 0;\n }\n \n-struct exclude_list *add_exclude_list(struct dir_struct *dir,\n+struct pattern_list *add_exclude_list(struct dir_struct *dir,\n \t\t\t\t      int group_type, const char *src)\n {\n-\tstruct exclude_list *el;\n+\tstruct pattern_list *pl;\n \tstruct exclude_list_group *group;\n \n \tgroup = &dir->exclude_list_group[group_type];\n-\tALLOC_GROW(group->el, group->nr + 1, group->alloc);\n-\tel = &group->el[group->nr++];\n-\tmemset(el, 0, sizeof(*el));\n-\tel->src = src;\n-\treturn el;\n+\tALLOC_GROW(group->pl, group->nr + 1, group->alloc);\n+\tpl = &group->pl[group->nr++];\n+\tmemset(pl, 0, sizeof(*pl));\n+\tpl->src = src;\n+\treturn pl;\n }\n \n /*\n@@ -913,7 +913,7 @@ struct exclude_list *add_exclude_list(struct dir_struct *dir,\n static void add_excludes_from_file_1(struct dir_struct *dir, const char *fname,\n \t\t\t\t     struct oid_stat *oid_stat)\n {\n-\tstruct exclude_list *el;\n+\tstruct pattern_list *pl;\n \t/*\n \t * catch setup_standard_excludes() that's called before\n \t * dir->untracked is assigned. That function behaves\n@@ -921,8 +921,8 @@ static void add_excludes_from_file_1(struct dir_struct *dir, const char *fname,\n \t */\n \tif (!dir->untracked)\n \t\tdir->unmanaged_exclude_files++;\n-\tel = add_exclude_list(dir, EXC_FILE, fname);\n-\tif (add_excludes(fname, \"\", 0, el, NULL, oid_stat) < 0)\n+\tpl = add_exclude_list(dir, EXC_FILE, fname);\n+\tif (add_excludes(fname, \"\", 0, pl, NULL, oid_stat) < 0)\n \t\tdie(_(\"cannot use %s as an exclude file\"), fname);\n }\n \n@@ -1025,17 +1025,17 @@ static struct path_pattern *last_exclude_matching_from_list(const char *pathname\n \t\t\t\t\t\t       int pathlen,\n \t\t\t\t\t\t       const char *basename,\n \t\t\t\t\t\t       int *dtype,\n-\t\t\t\t\t\t       struct exclude_list *el,\n+\t\t\t\t\t\t       struct pattern_list *pl,\n \t\t\t\t\t\t       struct index_state *istate)\n {\n \tstruct path_pattern *res = NULL; /* undecided */\n \tint i;\n \n-\tif (!el->nr)\n+\tif (!pl->nr)\n \t\treturn NULL;\t/* undefined */\n \n-\tfor (i = el->nr - 1; 0 <= i; i--) {\n-\t\tstruct path_pattern *pattern = el->patterns[i];\n+\tfor (i = pl->nr - 1; 0 <= i; i--) {\n+\t\tstruct path_pattern *pattern = pl->patterns[i];\n \t\tconst char *exclude = pattern->pattern;\n \t\tint prefix = pattern->nowildcardlen;\n \n@@ -1077,11 +1077,11 @@ static struct path_pattern *last_exclude_matching_from_list(const char *pathname\n  */\n int is_excluded_from_list(const char *pathname,\n \t\t\t  int pathlen, const char *basename, int *dtype,\n-\t\t\t  struct exclude_list *el, struct index_state *istate)\n+\t\t\t  struct pattern_list *pl, struct index_state *istate)\n {\n \tstruct path_pattern *pattern;\n \tpattern = last_exclude_matching_from_list(pathname, pathlen, basename,\n-\t\t\t\t\t\t  dtype, el, istate);\n+\t\t\t\t\t\t  dtype, pl, istate);\n \tif (pattern)\n \t\treturn pattern->flags & EXC_FLAG_NEGATIVE ? 0 : 1;\n \treturn -1; /* undecided */\n@@ -1100,7 +1100,7 @@ static struct path_pattern *last_exclude_matching_from_lists(\n \t\tfor (j = group->nr - 1; j >= 0; j--) {\n \t\t\tpattern = last_exclude_matching_from_list(\n \t\t\t\tpathname, pathlen, basename, dtype_p,\n-\t\t\t\t&group->el[j], istate);\n+\t\t\t\t&group->pl[j], istate);\n \t\t\tif (pattern)\n \t\t\t\treturn pattern;\n \t\t}\n@@ -1117,7 +1117,7 @@ static void prep_exclude(struct dir_struct *dir,\n \t\t\t const char *base, int baselen)\n {\n \tstruct exclude_list_group *group;\n-\tstruct exclude_list *el;\n+\tstruct pattern_list *pl;\n \tstruct exclude_stack *stk = NULL;\n \tstruct untracked_cache_dir *untracked;\n \tint current;\n@@ -1133,11 +1133,11 @@ static void prep_exclude(struct dir_struct *dir,\n \t\tif (stk->baselen <= baselen &&\n \t\t    !strncmp(dir->basebuf.buf, base, stk->baselen))\n \t\t\tbreak;\n-\t\tel = &group->el[dir->exclude_stack->exclude_ix];\n+\t\tpl = &group->pl[dir->exclude_stack->exclude_ix];\n \t\tdir->exclude_stack = stk->prev;\n \t\tdir->pattern = NULL;\n-\t\tfree((char *)el->src); /* see strbuf_detach() below */\n-\t\tclear_exclude_list(el);\n+\t\tfree((char *)pl->src); /* see strbuf_detach() below */\n+\t\tclear_exclude_list(pl);\n \t\tfree(stk);\n \t\tgroup->nr--;\n \t}\n@@ -1184,7 +1184,7 @@ static void prep_exclude(struct dir_struct *dir,\n \t\tstk->baselen = cp - base;\n \t\tstk->exclude_ix = group->nr;\n \t\tstk->ucd = untracked;\n-\t\tel = add_exclude_list(dir, EXC_DIRS, NULL);\n+\t\tpl = add_exclude_list(dir, EXC_DIRS, NULL);\n \t\tstrbuf_add(&dir->basebuf, base + current, stk->baselen - current);\n \t\tassert(stk->baselen == dir->basebuf.len);\n \n@@ -1234,8 +1234,8 @@ static void prep_exclude(struct dir_struct *dir,\n \t\t\tstruct strbuf sb = STRBUF_INIT;\n \t\t\tstrbuf_addbuf(&sb, &dir->basebuf);\n \t\t\tstrbuf_addstr(&sb, dir->exclude_per_dir);\n-\t\t\tel->src = strbuf_detach(&sb, NULL);\n-\t\t\tadd_excludes(el->src, el->src, stk->baselen, el, istate,\n+\t\t\tpl->src = strbuf_detach(&sb, NULL);\n+\t\t\tadd_excludes(pl->src, pl->src, stk->baselen, pl, istate,\n \t\t\t\t     untracked ? &oid_stat : NULL);\n \t\t}\n \t\t/*\n@@ -2530,18 +2530,18 @@ void clear_directory(struct dir_struct *dir)\n {\n \tint i, j;\n \tstruct exclude_list_group *group;\n-\tstruct exclude_list *el;\n+\tstruct pattern_list *pl;\n \tstruct exclude_stack *stk;\n \n \tfor (i = EXC_CMDL; i <= EXC_FILE; i++) {\n \t\tgroup = &dir->exclude_list_group[i];\n \t\tfor (j = 0; j < group->nr; j++) {\n-\t\t\tel = &group->el[j];\n+\t\t\tpl = &group->pl[j];\n \t\t\tif (i == EXC_DIRS)\n-\t\t\t\tfree((char *)el->src);\n-\t\t\tclear_exclude_list(el);\n+\t\t\t\tfree((char *)pl->src);\n+\t\t\tclear_exclude_list(pl);\n \t\t}\n-\t\tfree(group->el);\n+\t\tfree(group->pl);\n \t}\n \n \tstk = dir->exclude_stack;\ndiff --git a/dir.h b/dir.h\nindex e8b90fc482..4114d6bf78 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -21,7 +21,7 @@ struct path_pattern {\n \t * This allows callers of last_exclude_matching() etc.\n \t * to determine the origin of the matching pattern.\n \t */\n-\tstruct exclude_list *el;\n+\tstruct pattern_list *pl;\n \n \tconst char *pattern;\n \tint patternlen;\n@@ -44,7 +44,7 @@ struct path_pattern {\n  * can also be used to represent the list of --exclude values passed\n  * via CLI args.\n  */\n-struct exclude_list {\n+struct pattern_list {\n \tint nr;\n \tint alloc;\n \n@@ -72,7 +72,7 @@ struct exclude_stack {\n \n struct exclude_list_group {\n \tint nr, alloc;\n-\tstruct exclude_list *el;\n+\tstruct pattern_list *pl;\n };\n \n struct oid_stat {\n@@ -232,7 +232,7 @@ int read_directory(struct dir_struct *, struct index_state *istate,\n \n int is_excluded_from_list(const char *pathname, int pathlen,\n \t\t\t  const char *basename, int *dtype,\n-\t\t\t  struct exclude_list *el,\n+\t\t\t  struct pattern_list *pl,\n \t\t\t  struct index_state *istate);\n struct dir_entry *dir_add_ignored(struct dir_struct *dir,\n \t\t\t\t  struct index_state *istate,\n@@ -256,18 +256,18 @@ int is_excluded(struct dir_struct *dir,\n \t\tstruct index_state *istate,\n \t\tconst char *name, int *dtype);\n \n-struct exclude_list *add_exclude_list(struct dir_struct *dir,\n+struct pattern_list *add_exclude_list(struct dir_struct *dir,\n \t\t\t\t      int group_type, const char *src);\n int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,\n-\t\t\t\t   struct exclude_list *el, struct  index_state *istate);\n+\t\t\t\t   struct pattern_list *pl, struct  index_state *istate);\n void add_excludes_from_file(struct dir_struct *, const char *fname);\n int add_excludes_from_blob_to_list(struct object_id *oid,\n \t\t\t\t   const char *base, int baselen,\n-\t\t\t\t   struct exclude_list *el);\n+\t\t\t\t   struct pattern_list *pl);\n void parse_exclude_pattern(const char **string, int *patternlen, unsigned *flags, int *nowildcardlen);\n void add_exclude(const char *string, const char *base,\n-\t\t int baselen, struct exclude_list *el, int srcpos);\n-void clear_exclude_list(struct exclude_list *el);\n+\t\t int baselen, struct pattern_list *pl, int srcpos);\n+void clear_exclude_list(struct pattern_list *pl);\n void clear_directory(struct dir_struct *dir);\n \n int repo_file_exists(struct repository *repo, const char *path);\ndiff --git a/list-objects-filter.c b/list-objects-filter.c\nindex d664264d65..a1fedf8bd8 100644\n--- a/list-objects-filter.c\n+++ b/list-objects-filter.c\n@@ -347,7 +347,7 @@ struct frame {\n };\n \n struct filter_sparse_data {\n-\tstruct exclude_list el;\n+\tstruct pattern_list pl;\n \n \tsize_t nr, alloc;\n \tstruct frame *array_frame;\n@@ -374,7 +374,7 @@ static enum list_objects_filter_result filter_sparse(\n \t\tassert(obj->type == OBJ_TREE);\n \t\tdtype = DT_DIR;\n \t\tval = is_excluded_from_list(pathname, strlen(pathname),\n-\t\t\t\t\t    filename, &dtype, &filter_data->el,\n+\t\t\t\t\t    filename, &dtype, &filter_data->pl,\n \t\t\t\t\t    r->index);\n \t\tif (val < 0)\n \t\t\tval = filter_data->array_frame[filter_data->nr - 1].defval;\n@@ -436,7 +436,7 @@ static enum list_objects_filter_result filter_sparse(\n \n \t\tdtype = DT_REG;\n \t\tval = is_excluded_from_list(pathname, strlen(pathname),\n-\t\t\t\t\t    filename, &dtype, &filter_data->el,\n+\t\t\t\t\t    filename, &dtype, &filter_data->pl,\n \t\t\t\t\t    r->index);\n \t\tif (val < 0)\n \t\t\tval = frame->defval;\n@@ -483,7 +483,7 @@ static void filter_sparse_oid__init(\n {\n \tstruct filter_sparse_data *d = xcalloc(1, sizeof(*d));\n \tif (add_excludes_from_blob_to_list(filter_options->sparse_oid_value,\n-\t\t\t\t\t   NULL, 0, &d->el) < 0)\n+\t\t\t\t\t   NULL, 0, &d->pl) < 0)\n \t\tdie(\"could not load filter specification\");\n \n \tALLOC_GROW(d->array_frame, d->nr + 1, d->alloc);\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 50189909b8..c4dc21affb 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -1265,7 +1265,7 @@ static int clear_ce_flags_1(struct index_state *istate,\n \t\t\t    struct cache_entry **cache, int nr,\n \t\t\t    struct strbuf *prefix,\n \t\t\t    int select_mask, int clear_mask,\n-\t\t\t    struct exclude_list *el, int defval);\n+\t\t\t    struct pattern_list *pl, int defval);\n \n /* Whole directory matching */\n static int clear_ce_flags_dir(struct index_state *istate,\n@@ -1273,12 +1273,12 @@ static int clear_ce_flags_dir(struct index_state *istate,\n \t\t\t      struct strbuf *prefix,\n \t\t\t      char *basename,\n \t\t\t      int select_mask, int clear_mask,\n-\t\t\t      struct exclude_list *el, int defval)\n+\t\t\t      struct pattern_list *pl, int defval)\n {\n \tstruct cache_entry **cache_end;\n \tint dtype = DT_DIR;\n \tint ret = is_excluded_from_list(prefix->buf, prefix->len,\n-\t\t\t\t\tbasename, &dtype, el, istate);\n+\t\t\t\t\tbasename, &dtype, pl, istate);\n \tint rc;\n \n \tstrbuf_addch(prefix, '/');\n@@ -1294,7 +1294,7 @@ static int clear_ce_flags_dir(struct index_state *istate,\n \t}\n \n \t/*\n-\t * TODO: check el, if there are no patterns that may conflict\n+\t * TODO: check pl, if there are no patterns that may conflict\n \t * with ret (iow, we know in advance the incl/excl\n \t * decision for the entire directory), clear flag here without\n \t * calling clear_ce_flags_1(). That function will call\n@@ -1303,14 +1303,14 @@ static int clear_ce_flags_dir(struct index_state *istate,\n \trc = clear_ce_flags_1(istate, cache, cache_end - cache,\n \t\t\t      prefix,\n \t\t\t      select_mask, clear_mask,\n-\t\t\t      el, ret);\n+\t\t\t      pl, ret);\n \tstrbuf_setlen(prefix, prefix->len - 1);\n \treturn rc;\n }\n \n /*\n  * Traverse the index, find every entry that matches according to\n- * o->el. Do \"ce_flags &= ~clear_mask\" on those entries. Return the\n+ * o->pl. Do \"ce_flags &= ~clear_mask\" on those entries. Return the\n  * number of traversed entries.\n  *\n  * If select_mask is non-zero, only entries whose ce_flags has on of\n@@ -1327,7 +1327,7 @@ static int clear_ce_flags_1(struct index_state *istate,\n \t\t\t    struct cache_entry **cache, int nr,\n \t\t\t    struct strbuf *prefix,\n \t\t\t    int select_mask, int clear_mask,\n-\t\t\t    struct exclude_list *el, int defval)\n+\t\t\t    struct pattern_list *pl, int defval)\n {\n \tstruct cache_entry **cache_end = cache + nr;\n \n@@ -1362,7 +1362,7 @@ static int clear_ce_flags_1(struct index_state *istate,\n \t\t\t\t\t\t       prefix,\n \t\t\t\t\t\t       prefix->buf + prefix->len - len,\n \t\t\t\t\t\t       select_mask, clear_mask,\n-\t\t\t\t\t\t       el, defval);\n+\t\t\t\t\t\t       pl, defval);\n \n \t\t\t/* clear_c_f_dir eats a whole dir already? */\n \t\t\tif (processed) {\n@@ -1374,7 +1374,7 @@ static int clear_ce_flags_1(struct index_state *istate,\n \t\t\tstrbuf_addch(prefix, '/');\n \t\t\tcache += clear_ce_flags_1(istate, cache, cache_end - cache,\n \t\t\t\t\t\t  prefix,\n-\t\t\t\t\t\t  select_mask, clear_mask, el, defval);\n+\t\t\t\t\t\t  select_mask, clear_mask, pl, defval);\n \t\t\tstrbuf_setlen(prefix, prefix->len - len - 1);\n \t\t\tcontinue;\n \t\t}\n@@ -1382,7 +1382,7 @@ static int clear_ce_flags_1(struct index_state *istate,\n \t\t/* Non-directory */\n \t\tdtype = ce_to_dtype(ce);\n \t\tret = is_excluded_from_list(ce->name, ce_namelen(ce),\n-\t\t\t\t\t    name, &dtype, el, istate);\n+\t\t\t\t\t    name, &dtype, pl, istate);\n \t\tif (ret < 0)\n \t\t\tret = defval;\n \t\tif (ret > 0)\n@@ -1394,7 +1394,7 @@ static int clear_ce_flags_1(struct index_state *istate,\n \n static int clear_ce_flags(struct index_state *istate,\n \t\t\t  int select_mask, int clear_mask,\n-\t\t\t  struct exclude_list *el)\n+\t\t\t  struct pattern_list *pl)\n {\n \tstatic struct strbuf prefix = STRBUF_INIT;\n \n@@ -1405,13 +1405,13 @@ static int clear_ce_flags(struct index_state *istate,\n \t\t\t\tistate->cache_nr,\n \t\t\t\t&prefix,\n \t\t\t\tselect_mask, clear_mask,\n-\t\t\t\tel, 0);\n+\t\t\t\tpl, 0);\n }\n \n /*\n  * Set/Clear CE_NEW_SKIP_WORKTREE according to $GIT_DIR/info/sparse-checkout\n  */\n-static void mark_new_skip_worktree(struct exclude_list *el,\n+static void mark_new_skip_worktree(struct pattern_list *pl,\n \t\t\t\t   struct index_state *istate,\n \t\t\t\t   int select_flag, int skip_wt_flag)\n {\n@@ -1437,7 +1437,7 @@ static void mark_new_skip_worktree(struct exclude_list *el,\n \t * 2. Widen worktree according to sparse-checkout file.\n \t * Matched entries will have skip_wt_flag cleared (i.e. \"in\")\n \t */\n-\tclear_ce_flags(istate, select_flag, skip_wt_flag, el);\n+\tclear_ce_flags(istate, select_flag, skip_wt_flag, pl);\n }\n \n static int verify_absent(const struct cache_entry *,\n@@ -1453,21 +1453,21 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options\n {\n \tint i, ret;\n \tstatic struct cache_entry *dfc;\n-\tstruct exclude_list el;\n+\tstruct pattern_list pl;\n \n \tif (len > MAX_UNPACK_TREES)\n \t\tdie(\"unpack_trees takes at most %d trees\", MAX_UNPACK_TREES);\n \n \ttrace_performance_enter();\n-\tmemset(&el, 0, sizeof(el));\n+\tmemset(&pl, 0, sizeof(pl));\n \tif (!core_apply_sparse_checkout || !o->update)\n \t\to->skip_sparse_checkout = 1;\n \tif (!o->skip_sparse_checkout) {\n \t\tchar *sparse = git_pathdup(\"info/sparse-checkout\");\n-\t\tif (add_excludes_from_file_to_list(sparse, \"\", 0, &el, NULL) < 0)\n+\t\tif (add_excludes_from_file_to_list(sparse, \"\", 0, &pl, NULL) < 0)\n \t\t\to->skip_sparse_checkout = 1;\n \t\telse\n-\t\t\to->el = &el;\n+\t\t\to->pl = &pl;\n \t\tfree(sparse);\n \t}\n \n@@ -1498,7 +1498,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options\n \t * Sparse checkout loop #1: set NEW_SKIP_WORKTREE on existing entries\n \t */\n \tif (!o->skip_sparse_checkout)\n-\t\tmark_new_skip_worktree(o->el, o->src_index, 0, CE_NEW_SKIP_WORKTREE);\n+\t\tmark_new_skip_worktree(o->pl, o->src_index, 0, CE_NEW_SKIP_WORKTREE);\n \n \tif (!dfc)\n \t\tdfc = xcalloc(1, cache_entry_size(0));\n@@ -1563,7 +1563,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options\n \t\t * If the will have NEW_SKIP_WORKTREE, also set CE_SKIP_WORKTREE\n \t\t * so apply_sparse_checkout() won't attempt to remove it from worktree\n \t\t */\n-\t\tmark_new_skip_worktree(o->el, &o->result, CE_ADDED, CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE);\n+\t\tmark_new_skip_worktree(o->pl, &o->result, CE_ADDED, CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE);\n \n \t\tret = 0;\n \t\tfor (i = 0; i < o->result.cache_nr; i++) {\n@@ -1631,7 +1631,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options\n \n done:\n \ttrace_performance_leave(\"unpack_trees\");\n-\tclear_exclude_list(&el);\n+\tclear_exclude_list(&pl);\n \treturn ret;\n \n return_failed:\ndiff --git a/unpack-trees.h b/unpack-trees.h\nindex d344d7d296..f2eee0c7c5 100644\n--- a/unpack-trees.h\n+++ b/unpack-trees.h\n@@ -10,7 +10,7 @@\n \n struct cache_entry;\n struct unpack_trees_options;\n-struct exclude_list;\n+struct pattern_list;\n \n typedef int (*merge_fn_t)(const struct cache_entry * const *src,\n \t\tstruct unpack_trees_options *options);\n@@ -83,7 +83,7 @@ struct unpack_trees_options {\n \tstruct index_state *src_index;\n \tstruct index_state result;\n \n-\tstruct exclude_list *el; /* for internal use */\n+\tstruct pattern_list *pl; /* for internal use */\n };\n \n int unpack_trees(unsigned n, struct tree_desc *t,\n-- \ngitgitgadget\n\n"},{"id":"381741","messageId":"7972c559ff13dd2c108dcfba913e14733c9cb7d2.1567533893.git.gitgitgadget@gmail.com","threadId":"51795","inReplyTo":"pull.329.git.gitgitgadget@gmail.com","subject":"[PATCH 3/5] treewide: rename 'EXCL_FLAG_' to 'PATTERN_FLAG_'","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2019-09-03T18:04:56Z","receivedAt":"2019-09-03T18:05:02Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <dstolee@microsoft.com>\n\nThe first consumer of pattern-matching filenames was the\n.gitignore feature. In that context, storing a list of patterns\nas a 'struct exclude_list'  makes sense. However, the\nsparse-checkout feature then adopted these structures and methods,\nbut with the opposite meaning: these patterns match the files\nthat should be included!\n\nIt would be clearer to rename this entire library as a \"pattern\nmatching\" library, and the callers apply exclusion/inclusion\nlogic accordingly based on their needs.\n\nThis commit replaces 'EXCL_FLAG_' to 'PATTERN_FLAG_' in the\nnames of the flags used on 'struct path_pattern'.\n\nSigned-off-by: Derrick Stolee <dstolee@microsoft.com>\n---\n attr.c                 |  8 ++++----\n builtin/check-ignore.c |  4 ++--\n dir.c                  | 22 +++++++++++-----------\n dir.h                  | 10 +++++-----\n 4 files changed, 22 insertions(+), 22 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex 93dc16b59c..d90239869a 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -259,7 +259,7 @@ struct pattern {\n \tconst char *pattern;\n \tint patternlen;\n \tint nowildcardlen;\n-\tunsigned flags;\t\t/* EXC_FLAG_* */\n+\tunsigned flags;\t\t/* PATTERN_FLAG_* */\n };\n \n /*\n@@ -404,7 +404,7 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,\n \t\t\t\t      &res->u.pat.patternlen,\n \t\t\t\t      &res->u.pat.flags,\n \t\t\t\t      &res->u.pat.nowildcardlen);\n-\t\tif (res->u.pat.flags & EXC_FLAG_NEGATIVE) {\n+\t\tif (res->u.pat.flags & PATTERN_FLAG_NEGATIVE) {\n \t\t\twarning(_(\"Negative patterns are ignored in git attributes\\n\"\n \t\t\t\t  \"Use '\\\\!' for literal leading exclamation.\"));\n \t\t\tgoto fail_return;\n@@ -991,10 +991,10 @@ static int path_matches(const char *pathname, int pathlen,\n \tint prefix = pat->nowildcardlen;\n \tint isdir = (pathlen && pathname[pathlen - 1] == '/');\n \n-\tif ((pat->flags & EXC_FLAG_MUSTBEDIR) && !isdir)\n+\tif ((pat->flags & PATTERN_FLAG_MUSTBEDIR) && !isdir)\n \t\treturn 0;\n \n-\tif (pat->flags & EXC_FLAG_NODIR) {\n+\tif (pat->flags & PATTERN_FLAG_NODIR) {\n \t\treturn match_basename(pathname + basename_offset,\n \t\t\t\t      pathlen - basename_offset - isdir,\n \t\t\t\t      pattern, prefix,\ndiff --git a/builtin/check-ignore.c b/builtin/check-ignore.c\nindex 97108ccb9c..28b8f14999 100644\n--- a/builtin/check-ignore.c\n+++ b/builtin/check-ignore.c\n@@ -34,8 +34,8 @@ static const struct option check_ignore_options[] = {\n \n static void output_pattern(const char *path, struct path_pattern *pattern)\n {\n-\tchar *bang  = (pattern && pattern->flags & EXC_FLAG_NEGATIVE)  ? \"!\" : \"\";\n-\tchar *slash = (pattern && pattern->flags & EXC_FLAG_MUSTBEDIR) ? \"/\" : \"\";\n+\tchar *bang  = (pattern && pattern->flags & PATTERN_FLAG_NEGATIVE)  ? \"!\" : \"\";\n+\tchar *slash = (pattern && pattern->flags & PATTERN_FLAG_MUSTBEDIR) ? \"/\" : \"\";\n \tif (!nul_term_line) {\n \t\tif (!verbose) {\n \t\t\twrite_name_quoted(path, stdout, '\\n');\ndiff --git a/dir.c b/dir.c\nindex b522d61ee0..640f10973e 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -571,20 +571,20 @@ void parse_exclude_pattern(const char **pattern,\n \n \t*flags = 0;\n \tif (*p == '!') {\n-\t\t*flags |= EXC_FLAG_NEGATIVE;\n+\t\t*flags |= PATTERN_FLAG_NEGATIVE;\n \t\tp++;\n \t}\n \tlen = strlen(p);\n \tif (len && p[len - 1] == '/') {\n \t\tlen--;\n-\t\t*flags |= EXC_FLAG_MUSTBEDIR;\n+\t\t*flags |= PATTERN_FLAG_MUSTBEDIR;\n \t}\n \tfor (i = 0; i < len; i++) {\n \t\tif (p[i] == '/')\n \t\t\tbreak;\n \t}\n \tif (i == len)\n-\t\t*flags |= EXC_FLAG_NODIR;\n+\t\t*flags |= PATTERN_FLAG_NODIR;\n \t*nowildcardlen = simple_length(p);\n \t/*\n \t * we should have excluded the trailing slash from 'p' too,\n@@ -594,7 +594,7 @@ void parse_exclude_pattern(const char **pattern,\n \tif (*nowildcardlen > len)\n \t\t*nowildcardlen = len;\n \tif (*p == '*' && no_wildcard(p + 1))\n-\t\t*flags |= EXC_FLAG_ENDSWITH;\n+\t\t*flags |= PATTERN_FLAG_ENDSWITH;\n \t*pattern = p;\n \t*patternlen = len;\n }\n@@ -608,7 +608,7 @@ void add_exclude(const char *string, const char *base,\n \tint nowildcardlen;\n \n \tparse_exclude_pattern(&string, &patternlen, &flags, &nowildcardlen);\n-\tif (flags & EXC_FLAG_MUSTBEDIR) {\n+\tif (flags & PATTERN_FLAG_MUSTBEDIR) {\n \t\tFLEXPTR_ALLOC_MEM(pattern, pattern, string, patternlen);\n \t} else {\n \t\tpattern = xmalloc(sizeof(*pattern));\n@@ -940,7 +940,7 @@ int match_basename(const char *basename, int basenamelen,\n \t\tif (patternlen == basenamelen &&\n \t\t    !fspathncmp(pattern, basename, basenamelen))\n \t\t\treturn 1;\n-\t} else if (flags & EXC_FLAG_ENDSWITH) {\n+\t} else if (flags & PATTERN_FLAG_ENDSWITH) {\n \t\t/* \"*literal\" matching against \"fooliteral\" */\n \t\tif (patternlen - 1 <= basenamelen &&\n \t\t    !fspathncmp(pattern + 1,\n@@ -1039,14 +1039,14 @@ static struct path_pattern *last_exclude_matching_from_list(const char *pathname\n \t\tconst char *exclude = pattern->pattern;\n \t\tint prefix = pattern->nowildcardlen;\n \n-\t\tif (pattern->flags & EXC_FLAG_MUSTBEDIR) {\n+\t\tif (pattern->flags & PATTERN_FLAG_MUSTBEDIR) {\n \t\t\tif (*dtype == DT_UNKNOWN)\n \t\t\t\t*dtype = get_dtype(NULL, istate, pathname, pathlen);\n \t\t\tif (*dtype != DT_DIR)\n \t\t\t\tcontinue;\n \t\t}\n \n-\t\tif (pattern->flags & EXC_FLAG_NODIR) {\n+\t\tif (pattern->flags & PATTERN_FLAG_NODIR) {\n \t\t\tif (match_basename(basename,\n \t\t\t\t\t   pathlen - (basename - pathname),\n \t\t\t\t\t   exclude, prefix, pattern->patternlen,\n@@ -1083,7 +1083,7 @@ int is_excluded_from_list(const char *pathname,\n \tpattern = last_exclude_matching_from_list(pathname, pathlen, basename,\n \t\t\t\t\t\t  dtype, pl, istate);\n \tif (pattern)\n-\t\treturn pattern->flags & EXC_FLAG_NEGATIVE ? 0 : 1;\n+\t\treturn pattern->flags & PATTERN_FLAG_NEGATIVE ? 0 : 1;\n \treturn -1; /* undecided */\n }\n \n@@ -1198,7 +1198,7 @@ static void prep_exclude(struct dir_struct *dir,\n \t\t\t\tdir->basebuf.buf + current, &dt);\n \t\t\tdir->basebuf.buf[stk->baselen - 1] = '/';\n \t\t\tif (dir->pattern &&\n-\t\t\t    dir->pattern->flags & EXC_FLAG_NEGATIVE)\n+\t\t\t    dir->pattern->flags & PATTERN_FLAG_NEGATIVE)\n \t\t\t\tdir->pattern = NULL;\n \t\t\tif (dir->pattern) {\n \t\t\t\tdir->exclude_stack = stk;\n@@ -1298,7 +1298,7 @@ int is_excluded(struct dir_struct *dir, struct index_state *istate,\n \tstruct path_pattern *pattern =\n \t\tlast_exclude_matching(dir, istate, pathname, dtype_p);\n \tif (pattern)\n-\t\treturn pattern->flags & EXC_FLAG_NEGATIVE ? 0 : 1;\n+\t\treturn pattern->flags & PATTERN_FLAG_NEGATIVE ? 0 : 1;\n \treturn 0;\n }\n \ndiff --git a/dir.h b/dir.h\nindex 4114d6bf78..87eb10662f 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -11,10 +11,10 @@ struct dir_entry {\n \tchar name[FLEX_ARRAY]; /* more */\n };\n \n-#define EXC_FLAG_NODIR 1\n-#define EXC_FLAG_ENDSWITH 4\n-#define EXC_FLAG_MUSTBEDIR 8\n-#define EXC_FLAG_NEGATIVE 16\n+#define PATTERN_FLAG_NODIR 1\n+#define PATTERN_FLAG_ENDSWITH 4\n+#define PATTERN_FLAG_MUSTBEDIR 8\n+#define PATTERN_FLAG_NEGATIVE 16\n \n struct path_pattern {\n \t/*\n@@ -28,7 +28,7 @@ struct path_pattern {\n \tint nowildcardlen;\n \tconst char *base;\n \tint baselen;\n-\tunsigned flags;\t\t/* EXC_FLAG_* */\n+\tunsigned flags;\t\t/* PATTERN_FLAG_* */\n \n \t/*\n \t * Counting starts from 1 for line numbers in ignore files,\n-- \ngitgitgadget\n\n"},{"id":"381743","messageId":"d9a62c76339b64325a13d5f483f673450aa90c2b.1567533893.git.gitgitgadget@gmail.com","threadId":"51795","inReplyTo":"pull.329.git.gitgitgadget@gmail.com","subject":"[PATCH 5/5] unpack-trees: rename 'is_excluded_from_list()'","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2019-09-03T18:04:58Z","receivedAt":"2019-09-03T18:05:03Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <dstolee@microsoft.com>\n\nThe first consumer of pattern-matching filenames was the\n.gitignore feature. In that context, storing a list of patterns\nas a 'struct exclude_list'  makes sense. However, the\nsparse-checkout feature then adopted these structures and methods,\nbut with the opposite meaning: these patterns match the files\nthat should be included!\n\nNow that this library is renamed to use 'struct pattern_list'\nand 'struct pattern', we can now rename the method used by\nthe sparse-checkout feature to determine which paths should\nappear in the working directory.\n\nThe method is_excluded_from_list() is only used by the\nsparse-checkout logic in unpack-trees and list-objects-filter.\nThe confusing part is that it returned 1 for \"excluded\" (i.e.\nit matches the list of exclusions) but that really manes that\nthe path matched the list of patterns for _inclusion_ in the\nworking directory.\n\nRename the method to be path_matches_pattern_list() and have\nit return an explicit 'enum pattern_match_result'. Here, the\nvalues MATCHED = 1, UNMATCHED = 0, and UNDECIDED = -1 agree\nwith the previous integer values. This shift allows future\nconsumers to better understand what the retur values mean,\nand provides more type checking for handling those values.\n\nSigned-off-by: Derrick Stolee <dstolee@microsoft.com>\n---\n dir.c                 | 25 +++++++++++++++++--------\n dir.h                 | 21 +++++++++++++++++----\n list-objects-filter.c | 29 +++++++++++++++--------------\n unpack-trees.c        | 39 +++++++++++++++++++++++----------------\n 4 files changed, 72 insertions(+), 42 deletions(-)\n\ndiff --git a/dir.c b/dir.c\nindex b057bd3d95..34972abdaf 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -1072,19 +1072,28 @@ static struct path_pattern *last_matching_pattern_from_list(const char *pathname\n }\n \n /*\n- * Scan the list and let the last match determine the fate.\n- * Return 1 for exclude, 0 for include and -1 for undecided.\n+ * Scan the list of patterns to determine if the ordered list\n+ * of patterns matches on 'pathname'.\n+ *\n+ * Return 1 for a match, 0 for not matched and -1 for undecided.\n  */\n-int is_excluded_from_list(const char *pathname,\n-\t\t\t  int pathlen, const char *basename, int *dtype,\n-\t\t\t  struct pattern_list *pl, struct index_state *istate)\n+enum pattern_match_result path_matches_pattern_list(\n+\t\t\t\tconst char *pathname, int pathlen,\n+\t\t\t\tconst char *basename, int *dtype,\n+\t\t\t\tstruct pattern_list *pl,\n+\t\t\t\tstruct index_state *istate)\n {\n \tstruct path_pattern *pattern;\n \tpattern = last_matching_pattern_from_list(pathname, pathlen, basename,\n \t\t\t\t\t\t  dtype, pl, istate);\n-\tif (pattern)\n-\t\treturn pattern->flags & PATTERN_FLAG_NEGATIVE ? 0 : 1;\n-\treturn -1; /* undecided */\n+\tif (pattern) {\n+\t\tif (pattern->flags & PATTERN_FLAG_NEGATIVE)\n+\t\t\treturn NOT_MATCHED;\n+\t\telse\n+\t\t\treturn MATCHED;\n+\t}\n+\n+\treturn UNDECIDED;\n }\n \n static struct path_pattern *last_matching_pattern_from_lists(\ndiff --git a/dir.h b/dir.h\nindex 7babf31d88..608696c958 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -230,10 +230,23 @@ int read_directory(struct dir_struct *, struct index_state *istate,\n \t\t   const char *path, int len,\n \t\t   const struct pathspec *pathspec);\n \n-int is_excluded_from_list(const char *pathname, int pathlen,\n-\t\t\t  const char *basename, int *dtype,\n-\t\t\t  struct pattern_list *pl,\n-\t\t\t  struct index_state *istate);\n+enum pattern_match_result {\n+\tUNDECIDED = -1,\n+\tNOT_MATCHED = 0,\n+\tMATCHED = 1,\n+};\n+\n+/*\n+ * Scan the list of patterns to determine if the ordered list\n+ * of patterns matches on 'pathname'.\n+ *\n+ * Return 1 for a match, 0 for not matched and -1 for undecided.\n+ */\n+enum pattern_match_result path_matches_pattern_list(const char *pathname,\n+\t\t\t\tint pathlen,\n+\t\t\t\tconst char *basename, int *dtype,\n+\t\t\t\tstruct pattern_list *pl,\n+\t\t\t\tstruct index_state *istate);\n struct dir_entry *dir_add_ignored(struct dir_struct *dir,\n \t\t\t\t  struct index_state *istate,\n \t\t\t\t  const char *pathname, int len);\ndiff --git a/list-objects-filter.c b/list-objects-filter.c\nindex ccd58e61c3..d624f1c898 100644\n--- a/list-objects-filter.c\n+++ b/list-objects-filter.c\n@@ -328,12 +328,12 @@ static void filter_blobs_limit__init(\n  */\n struct frame {\n \t/*\n-\t * defval is the usual default include/exclude value that\n+\t * default_match is the usual default include/exclude value that\n \t * should be inherited as we recurse into directories based\n \t * upon pattern matching of the directory itself or of a\n \t * containing directory.\n \t */\n-\tint defval;\n+\tenum pattern_match_result default_match;\n \n \t/*\n \t * 1 if the directory (recursively) contains any provisionally\n@@ -363,8 +363,9 @@ static enum list_objects_filter_result filter_sparse(\n \tvoid *filter_data_)\n {\n \tstruct filter_sparse_data *filter_data = filter_data_;\n-\tint val, dtype;\n+\tint dtype;\n \tstruct frame *frame;\n+\tenum pattern_match_result match;\n \n \tswitch (filter_situation) {\n \tdefault:\n@@ -373,15 +374,15 @@ static enum list_objects_filter_result filter_sparse(\n \tcase LOFS_BEGIN_TREE:\n \t\tassert(obj->type == OBJ_TREE);\n \t\tdtype = DT_DIR;\n-\t\tval = is_excluded_from_list(pathname, strlen(pathname),\n-\t\t\t\t\t    filename, &dtype, &filter_data->pl,\n-\t\t\t\t\t    r->index);\n-\t\tif (val < 0)\n-\t\t\tval = filter_data->array_frame[filter_data->nr - 1].defval;\n+\t\tmatch = path_matches_pattern_list(pathname, strlen(pathname),\n+\t\t\t\t\t\t  filename, &dtype, &filter_data->pl,\n+\t\t\t\t\t\t  r->index);\n+\t\tif (match == UNDECIDED)\n+\t\t\tmatch = filter_data->array_frame[filter_data->nr - 1].default_match;\n \n \t\tALLOC_GROW(filter_data->array_frame, filter_data->nr + 1,\n \t\t\t   filter_data->alloc);\n-\t\tfilter_data->array_frame[filter_data->nr].defval = val;\n+\t\tfilter_data->array_frame[filter_data->nr].default_match = match;\n \t\tfilter_data->array_frame[filter_data->nr].child_prov_omit = 0;\n \t\tfilter_data->nr++;\n \n@@ -435,12 +436,12 @@ static enum list_objects_filter_result filter_sparse(\n \t\tframe = &filter_data->array_frame[filter_data->nr - 1];\n \n \t\tdtype = DT_REG;\n-\t\tval = is_excluded_from_list(pathname, strlen(pathname),\n+\t\tmatch = path_matches_pattern_list(pathname, strlen(pathname),\n \t\t\t\t\t    filename, &dtype, &filter_data->pl,\n \t\t\t\t\t    r->index);\n-\t\tif (val < 0)\n-\t\t\tval = frame->defval;\n-\t\tif (val > 0) {\n+\t\tif (match == UNDECIDED)\n+\t\t\tmatch = frame->default_match;\n+\t\tif (match == MATCHED) {\n \t\t\tif (omits)\n \t\t\t\toidset_remove(omits, &obj->oid);\n \t\t\treturn LOFR_MARK_SEEN | LOFR_DO_SHOW;\n@@ -487,7 +488,7 @@ static void filter_sparse_oid__init(\n \t\tdie(\"could not load filter specification\");\n \n \tALLOC_GROW(d->array_frame, d->nr + 1, d->alloc);\n-\td->array_frame[d->nr].defval = 0; /* default to include */\n+\td->array_frame[d->nr].default_match = 0; /* default to include */\n \td->array_frame[d->nr].child_prov_omit = 0;\n \td->nr++;\n \ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 902a799aeb..cd548f4fa2 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -1265,7 +1265,8 @@ static int clear_ce_flags_1(struct index_state *istate,\n \t\t\t    struct cache_entry **cache, int nr,\n \t\t\t    struct strbuf *prefix,\n \t\t\t    int select_mask, int clear_mask,\n-\t\t\t    struct pattern_list *pl, int defval);\n+\t\t\t    struct pattern_list *pl,\n+\t\t\t    enum pattern_match_result default_match);\n \n /* Whole directory matching */\n static int clear_ce_flags_dir(struct index_state *istate,\n@@ -1273,19 +1274,21 @@ static int clear_ce_flags_dir(struct index_state *istate,\n \t\t\t      struct strbuf *prefix,\n \t\t\t      char *basename,\n \t\t\t      int select_mask, int clear_mask,\n-\t\t\t      struct pattern_list *pl, int defval)\n+\t\t\t      struct pattern_list *pl,\n+\t\t\t      enum pattern_match_result default_match)\n {\n \tstruct cache_entry **cache_end;\n \tint dtype = DT_DIR;\n-\tint ret = is_excluded_from_list(prefix->buf, prefix->len,\n-\t\t\t\t\tbasename, &dtype, pl, istate);\n \tint rc;\n+\tenum pattern_match_result ret;\n+\tret = path_matches_pattern_list(prefix->buf, prefix->len,\n+\t\t\t\t\tbasename, &dtype, pl, istate);\n \n \tstrbuf_addch(prefix, '/');\n \n \t/* If undecided, use matching result of parent dir in defval */\n-\tif (ret < 0)\n-\t\tret = defval;\n+\tif (ret == UNDECIDED)\n+\t\tret = default_match;\n \n \tfor (cache_end = cache; cache_end != cache + nr; cache_end++) {\n \t\tstruct cache_entry *ce = *cache_end;\n@@ -1298,7 +1301,7 @@ static int clear_ce_flags_dir(struct index_state *istate,\n \t * with ret (iow, we know in advance the incl/excl\n \t * decision for the entire directory), clear flag here without\n \t * calling clear_ce_flags_1(). That function will call\n-\t * the expensive is_excluded_from_list() on every entry.\n+\t * the expensive path_matches_pattern_list() on every entry.\n \t */\n \trc = clear_ce_flags_1(istate, cache, cache_end - cache,\n \t\t\t      prefix,\n@@ -1327,7 +1330,8 @@ static int clear_ce_flags_1(struct index_state *istate,\n \t\t\t    struct cache_entry **cache, int nr,\n \t\t\t    struct strbuf *prefix,\n \t\t\t    int select_mask, int clear_mask,\n-\t\t\t    struct pattern_list *pl, int defval)\n+\t\t\t    struct pattern_list *pl,\n+\t\t\t    enum pattern_match_result default_match)\n {\n \tstruct cache_entry **cache_end = cache + nr;\n \n@@ -1338,7 +1342,8 @@ static int clear_ce_flags_1(struct index_state *istate,\n \twhile(cache != cache_end) {\n \t\tstruct cache_entry *ce = *cache;\n \t\tconst char *name, *slash;\n-\t\tint len, dtype, ret;\n+\t\tint len, dtype;\n+\t\tenum pattern_match_result ret;\n \n \t\tif (select_mask && !(ce->ce_flags & select_mask)) {\n \t\t\tcache++;\n@@ -1362,7 +1367,7 @@ static int clear_ce_flags_1(struct index_state *istate,\n \t\t\t\t\t\t       prefix,\n \t\t\t\t\t\t       prefix->buf + prefix->len - len,\n \t\t\t\t\t\t       select_mask, clear_mask,\n-\t\t\t\t\t\t       pl, defval);\n+\t\t\t\t\t\t       pl, default_match);\n \n \t\t\t/* clear_c_f_dir eats a whole dir already? */\n \t\t\tif (processed) {\n@@ -1374,18 +1379,20 @@ static int clear_ce_flags_1(struct index_state *istate,\n \t\t\tstrbuf_addch(prefix, '/');\n \t\t\tcache += clear_ce_flags_1(istate, cache, cache_end - cache,\n \t\t\t\t\t\t  prefix,\n-\t\t\t\t\t\t  select_mask, clear_mask, pl, defval);\n+\t\t\t\t\t\t  select_mask, clear_mask, pl,\n+\t\t\t\t\t\t  default_match);\n \t\t\tstrbuf_setlen(prefix, prefix->len - len - 1);\n \t\t\tcontinue;\n \t\t}\n \n \t\t/* Non-directory */\n \t\tdtype = ce_to_dtype(ce);\n-\t\tret = is_excluded_from_list(ce->name, ce_namelen(ce),\n-\t\t\t\t\t    name, &dtype, pl, istate);\n-\t\tif (ret < 0)\n-\t\t\tret = defval;\n-\t\tif (ret > 0)\n+\t\tret = path_matches_pattern_list(ce->name,\n+\t\t\t\t\t\tce_namelen(ce),\n+\t\t\t\t\t\tname, &dtype, pl, istate);\n+\t\tif (ret == UNDECIDED)\n+\t\t\tret = default_match;\n+\t\tif (ret == MATCHED)\n \t\t\tce->ce_flags &= ~clear_mask;\n \t\tcache++;\n \t}\n-- \ngitgitgadget\n"},{"id":"381742","messageId":"53ca8ec87791773edf056435dac9644f3935f421.1567533893.git.gitgitgadget@gmail.com","threadId":"51795","inReplyTo":"pull.329.git.gitgitgadget@gmail.com","subject":"[PATCH 4/5] treewide: rename 'exclude' methods to 'pattern'","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2019-09-03T18:04:57Z","receivedAt":"2019-09-03T18:05:04Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <dstolee@microsoft.com>\n\nThe first consumer of pattern-matching filenames was the\n.gitignore feature. In that context, storing a list of patterns\nas a 'struct exclude_list'  makes sense. However, the\nsparse-checkout feature then adopted these structures and methods,\nbut with the opposite meaning: these patterns match the files\nthat should be included!\n\nIt would be clearer to rename this entire library as a \"pattern\nmatching\" library, and the callers apply exclusion/inclusion\nlogic accordingly based on their needs.\n\nThis commit renames several methods defined in dir.h to make\nmore sense with the renamed 'struct exclude_list' to 'struct\npattern_list' and 'struct exclude' to 'struct path_pattern':\n\n * last_exclude_matching() -> last_matching_pattern()\n * parse_exclude() -> parse_path_pattern()\n\nIn addition, the word 'exclude' was replaced with 'pattern'\nin the methods below:\n\n * add_exclude_list()\n * add_excludes_from_file_to_list()\n * add_excludes_from_file()\n * add_excludes_from_blob_to_list()\n * add_exclude()\n * clear_exclude_list()\n\nA few methods with the word \"exclude\" remain. These will\nbe handled seperately. In particular, the method\n\"is_excluded()\" is concretely about the .gitignore file\nrelative to a specific directory. This is the important\nboundary between library and consumer: is_excluded() cares\nabout .gitignore, but is_excluded() calls\nlast_matching_pattern() to make that decision.\n\nSigned-off-by: Derrick Stolee <dstolee@microsoft.com>\n---\n Documentation/RelNotes/2.7.1.txt              |  2 +-\n Documentation/RelNotes/2.8.0.txt              |  2 +-\n .../technical/api-directory-listing.txt       |  6 +-\n attr.c                                        |  2 +-\n builtin/check-ignore.c                        |  2 +-\n builtin/clean.c                               |  8 +-\n builtin/ls-files.c                            |  6 +-\n dir.c                                         | 78 +++++++++----------\n dir.h                                         | 22 +++---\n list-objects-filter.c                         |  2 +-\n unpack-trees.c                                |  4 +-\n 11 files changed, 67 insertions(+), 67 deletions(-)\n\ndiff --git a/Documentation/RelNotes/2.7.1.txt b/Documentation/RelNotes/2.7.1.txt\nindex 6553d69e33..6323feaf64 100644\n--- a/Documentation/RelNotes/2.7.1.txt\n+++ b/Documentation/RelNotes/2.7.1.txt\n@@ -10,7 +10,7 @@ Fixes since v2.7\n    setting GIT_WORK_TREE environment themselves.\n \n  * The \"exclude_list\" structure has the usual \"alloc, nr\" pair of\n-   fields to be used by ALLOC_GROW(), but clear_exclude_list() forgot\n+   fields to be used by ALLOC_GROW(), but clear_pattern_list() forgot\n    to reset 'alloc' to 0 when it cleared 'nr' to discard the managed\n    array.\n \ndiff --git a/Documentation/RelNotes/2.8.0.txt b/Documentation/RelNotes/2.8.0.txt\nindex 25079710fa..5fbe1b86ee 100644\n--- a/Documentation/RelNotes/2.8.0.txt\n+++ b/Documentation/RelNotes/2.8.0.txt\n@@ -270,7 +270,7 @@ notes for details).\n    setting GIT_WORK_TREE environment themselves.\n \n  * The \"exclude_list\" structure has the usual \"alloc, nr\" pair of\n-   fields to be used by ALLOC_GROW(), but clear_exclude_list() forgot\n+   fields to be used by ALLOC_GROW(), but clear_pattern_list() forgot\n    to reset 'alloc' to 0 when it cleared 'nr' to discard the managed\n    array.\n \ndiff --git a/Documentation/technical/api-directory-listing.txt b/Documentation/technical/api-directory-listing.txt\nindex 5abb8e8b1f..76b6e4f71b 100644\n--- a/Documentation/technical/api-directory-listing.txt\n+++ b/Documentation/technical/api-directory-listing.txt\n@@ -111,11 +111,11 @@ marked. If you to exclude files, make sure you have loaded index first.\n * Prepare `struct dir_struct dir` and clear it with `memset(&dir, 0,\n   sizeof(dir))`.\n \n-* To add single exclude pattern, call `add_exclude_list()` and then\n-  `add_exclude()`.\n+* To add single exclude pattern, call `add_pattern_list()` and then\n+  `add_pattern()`.\n \n * To add patterns from a file (e.g. `.git/info/exclude`), call\n-  `add_excludes_from_file()` , and/or set `dir.exclude_per_dir`.  A\n+  `add_patterns_from_file()` , and/or set `dir.exclude_per_dir`.  A\n   short-hand function `setup_standard_excludes()` can be used to set\n   up the standard set of exclude settings.\n \ndiff --git a/attr.c b/attr.c\nindex d90239869a..d02d081e28 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -400,7 +400,7 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,\n \t\tchar *p = (char *)&(res->state[num_attr]);\n \t\tmemcpy(p, name, namelen);\n \t\tres->u.pat.pattern = p;\n-\t\tparse_exclude_pattern(&res->u.pat.pattern,\n+\t\tparse_path_pattern(&res->u.pat.pattern,\n \t\t\t\t      &res->u.pat.patternlen,\n \t\t\t\t      &res->u.pat.flags,\n \t\t\t\t      &res->u.pat.nowildcardlen);\ndiff --git a/builtin/check-ignore.c b/builtin/check-ignore.c\nindex 28b8f14999..5a4f92395f 100644\n--- a/builtin/check-ignore.c\n+++ b/builtin/check-ignore.c\n@@ -106,7 +106,7 @@ static int check_ignore(struct dir_struct *dir,\n \t\tpattern = NULL;\n \t\tif (!seen[i]) {\n \t\t\tint dtype = DT_UNKNOWN;\n-\t\t\tpattern = last_exclude_matching(dir, &the_index,\n+\t\t\tpattern = last_matching_pattern(dir, &the_index,\n \t\t\t\t\t\t\tfull_path, &dtype);\n \t\t}\n \t\tif (!quiet && (pattern || show_non_matching))\ndiff --git a/builtin/clean.c b/builtin/clean.c\nindex d8c847d9fd..4920c92593 100644\n--- a/builtin/clean.c\n+++ b/builtin/clean.c\n@@ -670,7 +670,7 @@ static int filter_by_patterns_cmd(void)\n \t\t\tbreak;\n \n \t\tmemset(&dir, 0, sizeof(dir));\n-\t\tpl = add_exclude_list(&dir, EXC_CMDL, \"manual exclude\");\n+\t\tpl = add_pattern_list(&dir, EXC_CMDL, \"manual exclude\");\n \t\tignore_list = strbuf_split_max(&confirm, ' ', 0);\n \n \t\tfor (i = 0; ignore_list[i]; i++) {\n@@ -678,7 +678,7 @@ static int filter_by_patterns_cmd(void)\n \t\t\tif (!ignore_list[i]->len)\n \t\t\t\tcontinue;\n \n-\t\t\tadd_exclude(ignore_list[i]->buf, \"\", 0, pl, -(i+1));\n+\t\t\tadd_pattern(ignore_list[i]->buf, \"\", 0, pl, -(i+1));\n \t\t}\n \n \t\tchanged = 0;\n@@ -957,9 +957,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)\n \tif (!ignored)\n \t\tsetup_standard_excludes(&dir);\n \n-\tpl = add_exclude_list(&dir, EXC_CMDL, \"--exclude option\");\n+\tpl = add_pattern_list(&dir, EXC_CMDL, \"--exclude option\");\n \tfor (i = 0; i < exclude_list.nr; i++)\n-\t\tadd_exclude(exclude_list.items[i].string, \"\", 0, pl, -(i+1));\n+\t\tadd_pattern(exclude_list.items[i].string, \"\", 0, pl, -(i+1));\n \n \tparse_pathspec(&pathspec, 0,\n \t\t       PATHSPEC_PREFER_CWD,\ndiff --git a/builtin/ls-files.c b/builtin/ls-files.c\nindex df8918a128..5acc396949 100644\n--- a/builtin/ls-files.c\n+++ b/builtin/ls-files.c\n@@ -492,7 +492,7 @@ static int option_parse_exclude_from(const struct option *opt,\n \tBUG_ON_OPT_NEG(unset);\n \n \texc_given = 1;\n-\tadd_excludes_from_file(dir, arg);\n+\tadd_patterns_from_file(dir, arg);\n \n \treturn 0;\n }\n@@ -594,9 +594,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)\n \n \targc = parse_options(argc, argv, prefix, builtin_ls_files_options,\n \t\t\tls_files_usage, 0);\n-\tpl = add_exclude_list(&dir, EXC_CMDL, \"--exclude option\");\n+\tpl = add_pattern_list(&dir, EXC_CMDL, \"--exclude option\");\n \tfor (i = 0; i < exclude_list.nr; i++) {\n-\t\tadd_exclude(exclude_list.items[i].string, \"\", 0, pl, --exclude_args);\n+\t\tadd_pattern(exclude_list.items[i].string, \"\", 0, pl, --exclude_args);\n \t}\n \tif (show_tag || show_valid_bit || show_fsmonitor_bit) {\n \t\ttag_cached = \"H \";\ndiff --git a/dir.c b/dir.c\nindex 640f10973e..b057bd3d95 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -561,7 +561,7 @@ int no_wildcard(const char *string)\n \treturn string[simple_length(string)] == '\\0';\n }\n \n-void parse_exclude_pattern(const char **pattern,\n+void parse_path_pattern(const char **pattern,\n \t\t\t   int *patternlen,\n \t\t\t   unsigned *flags,\n \t\t\t   int *nowildcardlen)\n@@ -599,7 +599,7 @@ void parse_exclude_pattern(const char **pattern,\n \t*patternlen = len;\n }\n \n-void add_exclude(const char *string, const char *base,\n+void add_pattern(const char *string, const char *base,\n \t\t int baselen, struct pattern_list *pl, int srcpos)\n {\n \tstruct path_pattern *pattern;\n@@ -607,7 +607,7 @@ void add_exclude(const char *string, const char *base,\n \tunsigned flags;\n \tint nowildcardlen;\n \n-\tparse_exclude_pattern(&string, &patternlen, &flags, &nowildcardlen);\n+\tparse_path_pattern(&string, &patternlen, &flags, &nowildcardlen);\n \tif (flags & PATTERN_FLAG_MUSTBEDIR) {\n \t\tFLEXPTR_ALLOC_MEM(pattern, pattern, string, patternlen);\n \t} else {\n@@ -646,7 +646,7 @@ static int read_skip_worktree_file_from_index(const struct index_state *istate,\n  * Frees memory within pl which was allocated for exclude patterns and\n  * the file buffer.  Does not free pl itself.\n  */\n-void clear_exclude_list(struct pattern_list *pl)\n+void clear_pattern_list(struct pattern_list *pl)\n {\n \tint i;\n \n@@ -762,7 +762,7 @@ static void invalidate_directory(struct untracked_cache *uc,\n \t\tdir->dirs[i]->recurse = 0;\n }\n \n-static int add_excludes_from_buffer(char *buf, size_t size,\n+static int add_patterns_from_buffer(char *buf, size_t size,\n \t\t\t\t    const char *base, int baselen,\n \t\t\t\t    struct pattern_list *pl);\n \n@@ -772,10 +772,10 @@ static int add_excludes_from_buffer(char *buf, size_t size,\n  * exclude rules in \"pl\".\n  *\n  * If \"ss\" is not NULL, compute SHA-1 of the exclude file and fill\n- * stat data from disk (only valid if add_excludes returns zero). If\n+ * stat data from disk (only valid if add_patterns returns zero). If\n  * ss_valid is non-zero, \"ss\" must contain good value as input.\n  */\n-static int add_excludes(const char *fname, const char *base, int baselen,\n+static int add_patterns(const char *fname, const char *base, int baselen,\n \t\t\tstruct pattern_list *pl, struct index_state *istate,\n \t\t\tstruct oid_stat *oid_stat)\n {\n@@ -837,11 +837,11 @@ static int add_excludes(const char *fname, const char *base, int baselen,\n \t\t}\n \t}\n \n-\tadd_excludes_from_buffer(buf, size, base, baselen, pl);\n+\tadd_patterns_from_buffer(buf, size, base, baselen, pl);\n \treturn 0;\n }\n \n-static int add_excludes_from_buffer(char *buf, size_t size,\n+static int add_patterns_from_buffer(char *buf, size_t size,\n \t\t\t\t    const char *base, int baselen,\n \t\t\t\t    struct pattern_list *pl)\n {\n@@ -860,7 +860,7 @@ static int add_excludes_from_buffer(char *buf, size_t size,\n \t\t\tif (entry != buf + i && entry[0] != '#') {\n \t\t\t\tbuf[i - (i && buf[i-1] == '\\r')] = 0;\n \t\t\t\ttrim_trailing_spaces(entry);\n-\t\t\t\tadd_exclude(entry, base, baselen, pl, lineno);\n+\t\t\t\tadd_pattern(entry, base, baselen, pl, lineno);\n \t\t\t}\n \t\t\tlineno++;\n \t\t\tentry = buf + i + 1;\n@@ -869,14 +869,14 @@ static int add_excludes_from_buffer(char *buf, size_t size,\n \treturn 0;\n }\n \n-int add_excludes_from_file_to_list(const char *fname, const char *base,\n+int add_patterns_from_file_to_list(const char *fname, const char *base,\n \t\t\t\t   int baselen, struct pattern_list *pl,\n \t\t\t\t   struct index_state *istate)\n {\n-\treturn add_excludes(fname, base, baselen, pl, istate, NULL);\n+\treturn add_patterns(fname, base, baselen, pl, istate, NULL);\n }\n \n-int add_excludes_from_blob_to_list(\n+int add_patterns_from_blob_to_list(\n \tstruct object_id *oid,\n \tconst char *base, int baselen,\n \tstruct pattern_list *pl)\n@@ -889,11 +889,11 @@ int add_excludes_from_blob_to_list(\n \tif (r != 1)\n \t\treturn r;\n \n-\tadd_excludes_from_buffer(buf, size, base, baselen, pl);\n+\tadd_patterns_from_buffer(buf, size, base, baselen, pl);\n \treturn 0;\n }\n \n-struct pattern_list *add_exclude_list(struct dir_struct *dir,\n+struct pattern_list *add_pattern_list(struct dir_struct *dir,\n \t\t\t\t      int group_type, const char *src)\n {\n \tstruct pattern_list *pl;\n@@ -910,7 +910,7 @@ struct pattern_list *add_exclude_list(struct dir_struct *dir,\n /*\n  * Used to set up core.excludesfile and .git/info/exclude lists.\n  */\n-static void add_excludes_from_file_1(struct dir_struct *dir, const char *fname,\n+static void add_patterns_from_file_1(struct dir_struct *dir, const char *fname,\n \t\t\t\t     struct oid_stat *oid_stat)\n {\n \tstruct pattern_list *pl;\n@@ -921,15 +921,15 @@ static void add_excludes_from_file_1(struct dir_struct *dir, const char *fname,\n \t */\n \tif (!dir->untracked)\n \t\tdir->unmanaged_exclude_files++;\n-\tpl = add_exclude_list(dir, EXC_FILE, fname);\n-\tif (add_excludes(fname, \"\", 0, pl, NULL, oid_stat) < 0)\n+\tpl = add_pattern_list(dir, EXC_FILE, fname);\n+\tif (add_patterns(fname, \"\", 0, pl, NULL, oid_stat) < 0)\n \t\tdie(_(\"cannot use %s as an exclude file\"), fname);\n }\n \n-void add_excludes_from_file(struct dir_struct *dir, const char *fname)\n+void add_patterns_from_file(struct dir_struct *dir, const char *fname)\n {\n \tdir->unmanaged_exclude_files++; /* see validate_untracked_cache() */\n-\tadd_excludes_from_file_1(dir, fname, NULL);\n+\tadd_patterns_from_file_1(dir, fname, NULL);\n }\n \n int match_basename(const char *basename, int basenamelen,\n@@ -1021,7 +1021,7 @@ int match_pathname(const char *pathname, int pathlen,\n  * any, determines the fate.  Returns the exclude_list element which\n  * matched, or NULL for undecided.\n  */\n-static struct path_pattern *last_exclude_matching_from_list(const char *pathname,\n+static struct path_pattern *last_matching_pattern_from_list(const char *pathname,\n \t\t\t\t\t\t       int pathlen,\n \t\t\t\t\t\t       const char *basename,\n \t\t\t\t\t\t       int *dtype,\n@@ -1080,14 +1080,14 @@ int is_excluded_from_list(const char *pathname,\n \t\t\t  struct pattern_list *pl, struct index_state *istate)\n {\n \tstruct path_pattern *pattern;\n-\tpattern = last_exclude_matching_from_list(pathname, pathlen, basename,\n+\tpattern = last_matching_pattern_from_list(pathname, pathlen, basename,\n \t\t\t\t\t\t  dtype, pl, istate);\n \tif (pattern)\n \t\treturn pattern->flags & PATTERN_FLAG_NEGATIVE ? 0 : 1;\n \treturn -1; /* undecided */\n }\n \n-static struct path_pattern *last_exclude_matching_from_lists(\n+static struct path_pattern *last_matching_pattern_from_lists(\n \t\tstruct dir_struct *dir, struct index_state *istate,\n \t\tconst char *pathname, int pathlen,\n \t\tconst char *basename, int *dtype_p)\n@@ -1098,7 +1098,7 @@ static struct path_pattern *last_exclude_matching_from_lists(\n \tfor (i = EXC_CMDL; i <= EXC_FILE; i++) {\n \t\tgroup = &dir->exclude_list_group[i];\n \t\tfor (j = group->nr - 1; j >= 0; j--) {\n-\t\t\tpattern = last_exclude_matching_from_list(\n+\t\t\tpattern = last_matching_pattern_from_list(\n \t\t\t\tpathname, pathlen, basename, dtype_p,\n \t\t\t\t&group->pl[j], istate);\n \t\t\tif (pattern)\n@@ -1137,7 +1137,7 @@ static void prep_exclude(struct dir_struct *dir,\n \t\tdir->exclude_stack = stk->prev;\n \t\tdir->pattern = NULL;\n \t\tfree((char *)pl->src); /* see strbuf_detach() below */\n-\t\tclear_exclude_list(pl);\n+\t\tclear_pattern_list(pl);\n \t\tfree(stk);\n \t\tgroup->nr--;\n \t}\n@@ -1184,7 +1184,7 @@ static void prep_exclude(struct dir_struct *dir,\n \t\tstk->baselen = cp - base;\n \t\tstk->exclude_ix = group->nr;\n \t\tstk->ucd = untracked;\n-\t\tpl = add_exclude_list(dir, EXC_DIRS, NULL);\n+\t\tpl = add_pattern_list(dir, EXC_DIRS, NULL);\n \t\tstrbuf_add(&dir->basebuf, base + current, stk->baselen - current);\n \t\tassert(stk->baselen == dir->basebuf.len);\n \n@@ -1192,7 +1192,7 @@ static void prep_exclude(struct dir_struct *dir,\n \t\tif (stk->baselen) {\n \t\t\tint dt = DT_DIR;\n \t\t\tdir->basebuf.buf[stk->baselen - 1] = 0;\n-\t\t\tdir->pattern = last_exclude_matching_from_lists(dir,\n+\t\t\tdir->pattern = last_matching_pattern_from_lists(dir,\n \t\t\t\t\t\t\t\t\tistate,\n \t\t\t\tdir->basebuf.buf, stk->baselen - 1,\n \t\t\t\tdir->basebuf.buf + current, &dt);\n@@ -1228,28 +1228,28 @@ static void prep_exclude(struct dir_struct *dir,\n \t\t\t * need fname to remain unchanged to ensure the src\n \t\t\t * member of each struct path_pattern correctly\n \t\t\t * back-references its source file.  Other invocations\n-\t\t\t * of add_exclude_list provide stable strings, so we\n+\t\t\t * of add_pattern_list provide stable strings, so we\n \t\t\t * strbuf_detach() and free() here in the caller.\n \t\t\t */\n \t\t\tstruct strbuf sb = STRBUF_INIT;\n \t\t\tstrbuf_addbuf(&sb, &dir->basebuf);\n \t\t\tstrbuf_addstr(&sb, dir->exclude_per_dir);\n \t\t\tpl->src = strbuf_detach(&sb, NULL);\n-\t\t\tadd_excludes(pl->src, pl->src, stk->baselen, pl, istate,\n+\t\t\tadd_patterns(pl->src, pl->src, stk->baselen, pl, istate,\n \t\t\t\t     untracked ? &oid_stat : NULL);\n \t\t}\n \t\t/*\n \t\t * NEEDSWORK: when untracked cache is enabled, prep_exclude()\n \t\t * will first be called in valid_cached_dir() then maybe many\n-\t\t * times more in last_exclude_matching(). When the cache is\n-\t\t * used, last_exclude_matching() will not be called and\n+\t\t * times more in last_matching_pattern(). When the cache is\n+\t\t * used, last_matching_pattern() will not be called and\n \t\t * reading .gitignore content will be a waste.\n \t\t *\n \t\t * So when it's called by valid_cached_dir() and we can get\n \t\t * .gitignore SHA-1 from the index (i.e. .gitignore is not\n \t\t * modified on work tree), we could delay reading the\n \t\t * .gitignore content until we absolutely need it in\n-\t\t * last_exclude_matching(). Be careful about ignore rule\n+\t\t * last_matching_pattern(). Be careful about ignore rule\n \t\t * order, though, if you do that.\n \t\t */\n \t\tif (untracked &&\n@@ -1269,7 +1269,7 @@ static void prep_exclude(struct dir_struct *dir,\n  * Returns the exclude_list element which matched, or NULL for\n  * undecided.\n  */\n-struct path_pattern *last_exclude_matching(struct dir_struct *dir,\n+struct path_pattern *last_matching_pattern(struct dir_struct *dir,\n \t\t\t\t      struct index_state *istate,\n \t\t\t\t      const char *pathname,\n \t\t\t\t      int *dtype_p)\n@@ -1283,7 +1283,7 @@ struct path_pattern *last_exclude_matching(struct dir_struct *dir,\n \tif (dir->pattern)\n \t\treturn dir->pattern;\n \n-\treturn last_exclude_matching_from_lists(dir, istate, pathname, pathlen,\n+\treturn last_matching_pattern_from_lists(dir, istate, pathname, pathlen,\n \t\t\tbasename, dtype_p);\n }\n \n@@ -1296,7 +1296,7 @@ int is_excluded(struct dir_struct *dir, struct index_state *istate,\n \t\tconst char *pathname, int *dtype_p)\n {\n \tstruct path_pattern *pattern =\n-\t\tlast_exclude_matching(dir, istate, pathname, dtype_p);\n+\t\tlast_matching_pattern(dir, istate, pathname, dtype_p);\n \tif (pattern)\n \t\treturn pattern->flags & PATTERN_FLAG_NEGATIVE ? 0 : 1;\n \treturn 0;\n@@ -1811,7 +1811,7 @@ static int valid_cached_dir(struct dir_struct *dir,\n \n \t/*\n \t * prep_exclude will be called eventually on this directory,\n-\t * but it's called much later in last_exclude_matching(). We\n+\t * but it's called much later in last_matching_pattern(). We\n \t * need it now to determine the validity of the cache for this\n \t * path. The next calls will be nearly no-op, the way\n \t * prep_exclude() is designed.\n@@ -2491,14 +2491,14 @@ void setup_standard_excludes(struct dir_struct *dir)\n \tif (!excludes_file)\n \t\texcludes_file = xdg_config_home(\"ignore\");\n \tif (excludes_file && !access_or_warn(excludes_file, R_OK, 0))\n-\t\tadd_excludes_from_file_1(dir, excludes_file,\n+\t\tadd_patterns_from_file_1(dir, excludes_file,\n \t\t\t\t\t dir->untracked ? &dir->ss_excludes_file : NULL);\n \n \t/* per repository user preference */\n \tif (startup_info->have_repository) {\n \t\tconst char *path = git_path_info_exclude();\n \t\tif (!access_or_warn(path, R_OK, 0))\n-\t\t\tadd_excludes_from_file_1(dir, path,\n+\t\t\tadd_patterns_from_file_1(dir, path,\n \t\t\t\t\t\t dir->untracked ? &dir->ss_info_exclude : NULL);\n \t}\n }\n@@ -2539,7 +2539,7 @@ void clear_directory(struct dir_struct *dir)\n \t\t\tpl = &group->pl[j];\n \t\t\tif (i == EXC_DIRS)\n \t\t\t\tfree((char *)pl->src);\n-\t\t\tclear_exclude_list(pl);\n+\t\t\tclear_pattern_list(pl);\n \t\t}\n \t\tfree(group->pl);\n \t}\ndiff --git a/dir.h b/dir.h\nindex 87eb10662f..7babf31d88 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -18,7 +18,7 @@ struct dir_entry {\n \n struct path_pattern {\n \t/*\n-\t * This allows callers of last_exclude_matching() etc.\n+\t * This allows callers of last_matching_pattern() etc.\n \t * to determine the origin of the matching pattern.\n \t */\n \tstruct pattern_list *pl;\n@@ -248,26 +248,26 @@ int match_pathname(const char *, int,\n \t\t   const char *, int,\n \t\t   const char *, int, int, unsigned);\n \n-struct path_pattern *last_exclude_matching(struct dir_struct *dir,\n-\t\t\t\t      struct index_state *istate,\n-\t\t\t\t      const char *name, int *dtype);\n+struct path_pattern *last_matching_pattern(struct dir_struct *dir,\n+\t\t\t\t\t   struct index_state *istate,\n+\t\t\t\t\t   const char *name, int *dtype);\n \n int is_excluded(struct dir_struct *dir,\n \t\tstruct index_state *istate,\n \t\tconst char *name, int *dtype);\n \n-struct pattern_list *add_exclude_list(struct dir_struct *dir,\n+struct pattern_list *add_pattern_list(struct dir_struct *dir,\n \t\t\t\t      int group_type, const char *src);\n-int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,\n+int add_patterns_from_file_to_list(const char *fname, const char *base, int baselen,\n \t\t\t\t   struct pattern_list *pl, struct  index_state *istate);\n-void add_excludes_from_file(struct dir_struct *, const char *fname);\n-int add_excludes_from_blob_to_list(struct object_id *oid,\n+void add_patterns_from_file(struct dir_struct *, const char *fname);\n+int add_patterns_from_blob_to_list(struct object_id *oid,\n \t\t\t\t   const char *base, int baselen,\n \t\t\t\t   struct pattern_list *pl);\n-void parse_exclude_pattern(const char **string, int *patternlen, unsigned *flags, int *nowildcardlen);\n-void add_exclude(const char *string, const char *base,\n+void parse_path_pattern(const char **string, int *patternlen, unsigned *flags, int *nowildcardlen);\n+void add_pattern(const char *string, const char *base,\n \t\t int baselen, struct pattern_list *pl, int srcpos);\n-void clear_exclude_list(struct pattern_list *pl);\n+void clear_pattern_list(struct pattern_list *pl);\n void clear_directory(struct dir_struct *dir);\n \n int repo_file_exists(struct repository *repo, const char *path);\ndiff --git a/list-objects-filter.c b/list-objects-filter.c\nindex a1fedf8bd8..ccd58e61c3 100644\n--- a/list-objects-filter.c\n+++ b/list-objects-filter.c\n@@ -482,7 +482,7 @@ static void filter_sparse_oid__init(\n \tstruct filter *filter)\n {\n \tstruct filter_sparse_data *d = xcalloc(1, sizeof(*d));\n-\tif (add_excludes_from_blob_to_list(filter_options->sparse_oid_value,\n+\tif (add_patterns_from_blob_to_list(filter_options->sparse_oid_value,\n \t\t\t\t\t   NULL, 0, &d->pl) < 0)\n \t\tdie(\"could not load filter specification\");\n \ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex c4dc21affb..902a799aeb 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -1464,7 +1464,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options\n \t\to->skip_sparse_checkout = 1;\n \tif (!o->skip_sparse_checkout) {\n \t\tchar *sparse = git_pathdup(\"info/sparse-checkout\");\n-\t\tif (add_excludes_from_file_to_list(sparse, \"\", 0, &pl, NULL) < 0)\n+\t\tif (add_patterns_from_file_to_list(sparse, \"\", 0, &pl, NULL) < 0)\n \t\t\to->skip_sparse_checkout = 1;\n \t\telse\n \t\t\to->pl = &pl;\n@@ -1631,7 +1631,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options\n \n done:\n \ttrace_performance_leave(\"unpack_trees\");\n-\tclear_exclude_list(&pl);\n+\tclear_pattern_list(&pl);\n \treturn ret;\n \n return_failed:\n-- \ngitgitgadget\n\n"},{"id":"381822","messageId":"CABPp-BFsOynr0skVAgxuhjrdXoZknU86+m2ecnN3BN+fFEiDoA@mail.gmail.com","threadId":"51795","inReplyTo":"d9a62c76339b64325a13d5f483f673450aa90c2b.1567533893.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 5/5] unpack-trees: rename 'is_excluded_from_list()'","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2019-09-04T20:25:54Z","receivedAt":"2019-09-04T20:26:08Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Tue, Sep 3, 2019 at 11:04 AM Derrick Stolee via GitGitGadget\n<gitgitgadget@gmail.com> wrote:\n>\n> From: Derrick Stolee <dstolee@microsoft.com>\n>\n> The first consumer of pattern-matching filenames was the\n> .gitignore feature. In that context, storing a list of patterns\n> as a 'struct exclude_list'  makes sense. However, the\n> sparse-checkout feature then adopted these structures and methods,\n> but with the opposite meaning: these patterns match the files\n> that should be included!\n>\n> Now that this library is renamed to use 'struct pattern_list'\n> and 'struct pattern', we can now rename the method used by\n> the sparse-checkout feature to determine which paths should\n> appear in the working directory.\n>\n> The method is_excluded_from_list() is only used by the\n> sparse-checkout logic in unpack-trees and list-objects-filter.\n> The confusing part is that it returned 1 for \"excluded\" (i.e.\n> it matches the list of exclusions) but that really manes that\n\ns/manes/means/\n\n> the path matched the list of patterns for _inclusion_ in the\n> working directory.\n>\n> Rename the method to be path_matches_pattern_list() and have\n> it return an explicit 'enum pattern_match_result'. Here, the\n> values MATCHED = 1, UNMATCHED = 0, and UNDECIDED = -1 agree\n> with the previous integer values. This shift allows future\n> consumers to better understand what the retur values mean,\n\ns/retur/return/\n\n> and provides more type checking for handling those values.\n>\n> Signed-off-by: Derrick Stolee <dstolee@microsoft.com>\n> ---\n>  dir.c                 | 25 +++++++++++++++++--------\n>  dir.h                 | 21 +++++++++++++++++----\n>  list-objects-filter.c | 29 +++++++++++++++--------------\n>  unpack-trees.c        | 39 +++++++++++++++++++++++----------------\n>  4 files changed, 72 insertions(+), 42 deletions(-)\n>\n> diff --git a/dir.c b/dir.c\n> index b057bd3d95..34972abdaf 100644\n> --- a/dir.c\n> +++ b/dir.c\n> @@ -1072,19 +1072,28 @@ static struct path_pattern *last_matching_pattern_from_list(const char *pathname\n>  }\n>\n>  /*\n> - * Scan the list and let the last match determine the fate.\n> - * Return 1 for exclude, 0 for include and -1 for undecided.\n> + * Scan the list of patterns to determine if the ordered list\n> + * of patterns matches on 'pathname'.\n> + *\n> + * Return 1 for a match, 0 for not matched and -1 for undecided.\n\nMaybe drop this last sentence since it's misleading, and since the\nfunction signature already specifies that it returns an enum and the\nenums have obvious meanings already?\n\n>   */\n> -int is_excluded_from_list(const char *pathname,\n> -                         int pathlen, const char *basename, int *dtype,\n> -                         struct pattern_list *pl, struct index_state *istate)\n> +enum pattern_match_result path_matches_pattern_list(\n> +                               const char *pathname, int pathlen,\n> +                               const char *basename, int *dtype,\n> +                               struct pattern_list *pl,\n> +                               struct index_state *istate)\n>  {\n>         struct path_pattern *pattern;\n>         pattern = last_matching_pattern_from_list(pathname, pathlen, basename,\n>                                                   dtype, pl, istate);\n> -       if (pattern)\n> -               return pattern->flags & PATTERN_FLAG_NEGATIVE ? 0 : 1;\n> -       return -1; /* undecided */\n> +       if (pattern) {\n> +               if (pattern->flags & PATTERN_FLAG_NEGATIVE)\n> +                       return NOT_MATCHED;\n> +               else\n> +                       return MATCHED;\n> +       }\n> +\n> +       return UNDECIDED;\n>  }\n>\n>  static struct path_pattern *last_matching_pattern_from_lists(\n> diff --git a/dir.h b/dir.h\n> index 7babf31d88..608696c958 100644\n> --- a/dir.h\n> +++ b/dir.h\n> @@ -230,10 +230,23 @@ int read_directory(struct dir_struct *, struct index_state *istate,\n>                    const char *path, int len,\n>                    const struct pathspec *pathspec);\n>\n> -int is_excluded_from_list(const char *pathname, int pathlen,\n> -                         const char *basename, int *dtype,\n> -                         struct pattern_list *pl,\n> -                         struct index_state *istate);\n> +enum pattern_match_result {\n> +       UNDECIDED = -1,\n> +       NOT_MATCHED = 0,\n> +       MATCHED = 1,\n\nAre we worried about preventing e.g. grep from using these names or\nclashing with another lib (block-sha1?) that might choose to define\nthese?\n\n> +};\n> +\n> +/*\n> + * Scan the list of patterns to determine if the ordered list\n> + * of patterns matches on 'pathname'.\n> + *\n> + * Return 1 for a match, 0 for not matched and -1 for undecided.\n\nAgain, I'd drop the last sentence.\n\n> + */\n> +enum pattern_match_result path_matches_pattern_list(const char *pathname,\n> +                               int pathlen,\n> +                               const char *basename, int *dtype,\n> +                               struct pattern_list *pl,\n> +                               struct index_state *istate);\n>  struct dir_entry *dir_add_ignored(struct dir_struct *dir,\n>                                   struct index_state *istate,\n>                                   const char *pathname, int len);\n> diff --git a/list-objects-filter.c b/list-objects-filter.c\n> index ccd58e61c3..d624f1c898 100644\n> --- a/list-objects-filter.c\n> +++ b/list-objects-filter.c\n> @@ -328,12 +328,12 @@ static void filter_blobs_limit__init(\n>   */\n>  struct frame {\n>         /*\n> -        * defval is the usual default include/exclude value that\n> +        * default_match is the usual default include/exclude value that\n>          * should be inherited as we recurse into directories based\n>          * upon pattern matching of the directory itself or of a\n>          * containing directory.\n>          */\n> -       int defval;\n> +       enum pattern_match_result default_match;\n>\n>         /*\n>          * 1 if the directory (recursively) contains any provisionally\n> @@ -363,8 +363,9 @@ static enum list_objects_filter_result filter_sparse(\n>         void *filter_data_)\n>  {\n>         struct filter_sparse_data *filter_data = filter_data_;\n> -       int val, dtype;\n> +       int dtype;\n>         struct frame *frame;\n> +       enum pattern_match_result match;\n>\n>         switch (filter_situation) {\n>         default:\n> @@ -373,15 +374,15 @@ static enum list_objects_filter_result filter_sparse(\n>         case LOFS_BEGIN_TREE:\n>                 assert(obj->type == OBJ_TREE);\n>                 dtype = DT_DIR;\n> -               val = is_excluded_from_list(pathname, strlen(pathname),\n> -                                           filename, &dtype, &filter_data->pl,\n> -                                           r->index);\n> -               if (val < 0)\n> -                       val = filter_data->array_frame[filter_data->nr - 1].defval;\n> +               match = path_matches_pattern_list(pathname, strlen(pathname),\n> +                                                 filename, &dtype, &filter_data->pl,\n> +                                                 r->index);\n> +               if (match == UNDECIDED)\n> +                       match = filter_data->array_frame[filter_data->nr - 1].default_match;\n>\n>                 ALLOC_GROW(filter_data->array_frame, filter_data->nr + 1,\n>                            filter_data->alloc);\n> -               filter_data->array_frame[filter_data->nr].defval = val;\n> +               filter_data->array_frame[filter_data->nr].default_match = match;\n>                 filter_data->array_frame[filter_data->nr].child_prov_omit = 0;\n>                 filter_data->nr++;\n>\n> @@ -435,12 +436,12 @@ static enum list_objects_filter_result filter_sparse(\n>                 frame = &filter_data->array_frame[filter_data->nr - 1];\n>\n>                 dtype = DT_REG;\n> -               val = is_excluded_from_list(pathname, strlen(pathname),\n> +               match = path_matches_pattern_list(pathname, strlen(pathname),\n>                                             filename, &dtype, &filter_data->pl,\n>                                             r->index);\n> -               if (val < 0)\n> -                       val = frame->defval;\n> -               if (val > 0) {\n> +               if (match == UNDECIDED)\n> +                       match = frame->default_match;\n> +               if (match == MATCHED) {\n>                         if (omits)\n>                                 oidset_remove(omits, &obj->oid);\n>                         return LOFR_MARK_SEEN | LOFR_DO_SHOW;\n> @@ -487,7 +488,7 @@ static void filter_sparse_oid__init(\n>                 die(\"could not load filter specification\");\n>\n>         ALLOC_GROW(d->array_frame, d->nr + 1, d->alloc);\n> -       d->array_frame[d->nr].defval = 0; /* default to include */\n> +       d->array_frame[d->nr].default_match = 0; /* default to include */\n\ns/0/MATCHED/ ?\n\n>         d->array_frame[d->nr].child_prov_omit = 0;\n>         d->nr++;\n>\n> diff --git a/unpack-trees.c b/unpack-trees.c\n> index 902a799aeb..cd548f4fa2 100644\n> --- a/unpack-trees.c\n> +++ b/unpack-trees.c\n> @@ -1265,7 +1265,8 @@ static int clear_ce_flags_1(struct index_state *istate,\n>                             struct cache_entry **cache, int nr,\n>                             struct strbuf *prefix,\n>                             int select_mask, int clear_mask,\n> -                           struct pattern_list *pl, int defval);\n> +                           struct pattern_list *pl,\n> +                           enum pattern_match_result default_match);\n>\n>  /* Whole directory matching */\n>  static int clear_ce_flags_dir(struct index_state *istate,\n> @@ -1273,19 +1274,21 @@ static int clear_ce_flags_dir(struct index_state *istate,\n>                               struct strbuf *prefix,\n>                               char *basename,\n>                               int select_mask, int clear_mask,\n> -                             struct pattern_list *pl, int defval)\n> +                             struct pattern_list *pl,\n> +                             enum pattern_match_result default_match)\n>  {\n>         struct cache_entry **cache_end;\n>         int dtype = DT_DIR;\n> -       int ret = is_excluded_from_list(prefix->buf, prefix->len,\n> -                                       basename, &dtype, pl, istate);\n>         int rc;\n> +       enum pattern_match_result ret;\n> +       ret = path_matches_pattern_list(prefix->buf, prefix->len,\n> +                                       basename, &dtype, pl, istate);\n>\n>         strbuf_addch(prefix, '/');\n>\n>         /* If undecided, use matching result of parent dir in defval */\n> -       if (ret < 0)\n> -               ret = defval;\n> +       if (ret == UNDECIDED)\n> +               ret = default_match;\n>\n>         for (cache_end = cache; cache_end != cache + nr; cache_end++) {\n>                 struct cache_entry *ce = *cache_end;\n> @@ -1298,7 +1301,7 @@ static int clear_ce_flags_dir(struct index_state *istate,\n>          * with ret (iow, we know in advance the incl/excl\n>          * decision for the entire directory), clear flag here without\n>          * calling clear_ce_flags_1(). That function will call\n> -        * the expensive is_excluded_from_list() on every entry.\n> +        * the expensive path_matches_pattern_list() on every entry.\n>          */\n>         rc = clear_ce_flags_1(istate, cache, cache_end - cache,\n>                               prefix,\n> @@ -1327,7 +1330,8 @@ static int clear_ce_flags_1(struct index_state *istate,\n>                             struct cache_entry **cache, int nr,\n>                             struct strbuf *prefix,\n>                             int select_mask, int clear_mask,\n> -                           struct pattern_list *pl, int defval)\n> +                           struct pattern_list *pl,\n> +                           enum pattern_match_result default_match)\n>  {\n>         struct cache_entry **cache_end = cache + nr;\n>\n> @@ -1338,7 +1342,8 @@ static int clear_ce_flags_1(struct index_state *istate,\n>         while(cache != cache_end) {\n>                 struct cache_entry *ce = *cache;\n>                 const char *name, *slash;\n> -               int len, dtype, ret;\n> +               int len, dtype;\n> +               enum pattern_match_result ret;\n>\n>                 if (select_mask && !(ce->ce_flags & select_mask)) {\n>                         cache++;\n> @@ -1362,7 +1367,7 @@ static int clear_ce_flags_1(struct index_state *istate,\n>                                                        prefix,\n>                                                        prefix->buf + prefix->len - len,\n>                                                        select_mask, clear_mask,\n> -                                                      pl, defval);\n> +                                                      pl, default_match);\n>\n>                         /* clear_c_f_dir eats a whole dir already? */\n>                         if (processed) {\n> @@ -1374,18 +1379,20 @@ static int clear_ce_flags_1(struct index_state *istate,\n>                         strbuf_addch(prefix, '/');\n>                         cache += clear_ce_flags_1(istate, cache, cache_end - cache,\n>                                                   prefix,\n> -                                                 select_mask, clear_mask, pl, defval);\n> +                                                 select_mask, clear_mask, pl,\n> +                                                 default_match);\n>                         strbuf_setlen(prefix, prefix->len - len - 1);\n>                         continue;\n>                 }\n>\n>                 /* Non-directory */\n>                 dtype = ce_to_dtype(ce);\n> -               ret = is_excluded_from_list(ce->name, ce_namelen(ce),\n> -                                           name, &dtype, pl, istate);\n> -               if (ret < 0)\n> -                       ret = defval;\n> -               if (ret > 0)\n> +               ret = path_matches_pattern_list(ce->name,\n> +                                               ce_namelen(ce),\n> +                                               name, &dtype, pl, istate);\n> +               if (ret == UNDECIDED)\n> +                       ret = default_match;\n> +               if (ret == MATCHED)\n>                         ce->ce_flags &= ~clear_mask;\n>                 cache++;\n>         }\n> --\n> gitgitgadget\n\nThe rest looks good.\n"},{"id":"381823","messageId":"CABPp-BH2LoP=f0ZD1uegP3-CKTgZ9MExamyYQw8YLkdmtTVpkg@mail.gmail.com","threadId":"51795","inReplyTo":"pull.329.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 0/5] Refactor excludes library","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2019-09-04T20:28:48Z","receivedAt":"2019-09-04T20:29:02Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Tue, Sep 3, 2019 at 11:04 AM Derrick Stolee via GitGitGadget\n<gitgitgadget@gmail.com> wrote:\n>\n> The exclude library defined in dir.h was originally written for the\n> .gitignore feature, but has since been used for .gitattributes and\n> sparse-checkout. In the later applications, these patterns are used for\n> inclusion rather than exclusion, so the name is confusing. This gets\n> particularly bad when looking at how the sparse-checkout feature uses\n> is_excluded_from_list() to really mean \"should be included in the working\n> directory\".\n>\n> This series performs several renames of structs and methods to generalize\n> the exclude library to be a \"pattern matching\" library. Instead of a list of\n> excludes, we have a list of path patterns. It is up to the consumer to\n> decide what to do with a match. The .gitignore logic will still treat the\n> patterns as a list of exclusions, the sparse-checkout logic treats the\n> patterns as a list of inclusions.\n\nWahoo!  Thanks for going through and cleaning these up.  The\npossibility of negated patterns (or negated logic or both) on top of\nusing \"exclude\" when \"include\" was _sometimes_ meant was just too much\nfor me to keep track of.  This series will make it much easier.\n\n> For this reason, some methods and structs in dir.h retain \"exclude\" in their\n> name. These are limited to things consumed only by the .gitignore feature\n> (as far as I can tell).\n>\n> Most of these changes are mechanical find-and-replaces, with the exception\n> of some variable names and the last patch.\n\nI looked through the first four patches with --color-words=. to spot\ncheck them; as you say, looks like straightforward mechanical changes.\n\nI did notice that the first two paragraphs were shared between the\ncommit messages; it does make sense to help provide the context, but\nit seemed a little duplicative.  I'm not sure what to suggest; it may\nbe fine as it is.  Just thought I'd flag it.\n\n> The last patch, \"unpack-trees: rename 'is_excluded_from_list()'\", performs a\n> more meaningful refactor. The method is_excluded_from_list() was only used\n> by sparse-checkout (inside the clear_ce_flags() methods) to see if a path\n> should be included in the working directory. The return value of \"1 for\n> excluded\" was confusing. Instead, use a new enum value. This required\n> changing several method prototypes inside unpack-trees.c.\n>\n> This refactor was inspired by Elijah Newren's feedback [1] on my\n> sparse-checkout builtin RFC. I am working on a few other orthogonal changes\n> to make to the existing sparse-checkout behavior before I resubmit that RFC.\n>\n> I had started working on v2.23.0, but found adjacent-diff conflicts with\n> md/list-objects-filter-combo [2] and js/partial-clone-sparse-blob [3]. Those\n> branches are independent, but the conflicts with\n> md/list-objects-filter-combo were more severe (and that branch seems closer\n> to merging) so this is based on md/list-object-filter-combo. Hopefully the\n> conflicts with js/partial-clone-sparse-blob are clear enough to resolve\n> easily.\n\nI posted some comments on patch 5; otherwise, the series looks good to me.\n"},{"id":"381859","messageId":"20190905065518.GD21450@sigill.intra.peff.net","threadId":"51795","inReplyTo":"8cdffbd1c82c34a7dbdb18cb396e5e422889aad6.1567533893.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 1/5] treewide: rename 'struct exclude' to 'struct path_pattern'","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-09-05T06:55:18Z","receivedAt":"2019-09-05T06:55:20Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Sep 03, 2019 at 11:04:55AM -0700, Derrick Stolee via GitGitGadget wrote:\n\n> From: Derrick Stolee <dstolee@microsoft.com>\n> \n> The first consumer of pattern-matching filenames was the\n> .gitignore feature. In that context, storing a list of patterns\n> as a list of 'struct exclude' items makes sense. However, the\n> sparse-checkout feature then adopted these structures and methods,\n> but with the opposite meaning: these patterns match the files\n> that should be included!\n> \n> It would be clearer to rename this entire library as a \"pattern\n> matching\" library, and the callers apply exclusion/inclusion\n> logic accordingly based on their needs.\n> \n> This commit renames 'struct exclude' to 'struct path_pattern'\n> and renames several variable names to match. 'struct pattern'\n> was already taken by attr.c, and this more completely describes\n> that the patterns are specific to file paths.\n\nI agree that the current name is overly restrictive, and this is a step\nin the right direction. However, when I see path_pattern that makes me\nthink of our command-line pathspecs.\n\nI wonder if there's a name that could more clearly distinguish the two.\nOr if it's sufficient to just become Git jargon that \"pathspec\" is the\ncommand-line one and \"path_pattern\" is the file-based one (we're at\nleast pretty consistent about the former already).\n\nI think one could also make an argument that the name collision is a\nsign that these two things should actually share both syntax and\nimplementation, since we're exposing too similar-but-not-quite versions\nof the same idea to users. But given the compatibility issues, it's\nprobably not worth changing the user facing parts at this point (and I\nalso haven't thought too hard about it; there may be reasons why the two\n_should_ differ).\n\n-Peff\n"},{"id":"381916","messageId":"xmqq4l1qpiaw.fsf@gitster-ct.c.googlers.com","threadId":"51795","inReplyTo":"20190905065518.GD21450@sigill.intra.peff.net","subject":"Re: [PATCH 1/5] treewide: rename 'struct exclude' to 'struct path_pattern'","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-09-05T21:03:19Z","receivedAt":"2019-09-05T21:03:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> I wonder if there's a name that could more clearly distinguish the two.\n> Or if it's sufficient to just become Git jargon that \"pathspec\" is the\n> command-line one and \"path_pattern\" is the file-based one (we're at\n> least pretty consistent about the former already).\n>\n> I think one could also make an argument that the name collision is a\n> sign that these two things should actually share both syntax and\n> implementation, since we're exposing too similar-but-not-quite versions\n> of the same idea to users. But given the compatibility issues, it's\n> probably not worth changing the user facing parts at this point (and I\n> also haven't thought too hard about it; there may be reasons why the two\n> _should_ differ).\n\nHmph.  I did not realize there are so many differences X-<.  \n\nA pathspec is relative to $CWD, and there is a syntax, i.e.\nprefixing with \":(top)\", to make it relative to the root level.  An\nentry in a .gitignore file will never affect paths outside the\ndirectory the file appears in.  And there should never be such a\nmechanism to allow it.\n\nAn entry without slash in .gitignore is a basename match, and there\nis a syntax i.e. prefixing with \"/\", to anchor it to a single\ndirectory.  A pathspec without slash also can be a basename match\n(e.g. \"*.c\" matches \"a/b.c\" as well as \"d.c\").  A pathspec with a\nslash can be made to tail-match (e.g. \"**/*.c\" matches \"a/b.c\",\n\"a/b/c.c\", etc.) but I do not think of a way to make an entry with a\nslash in a .gitignore file a tail-match the same way.  I do not think\nthis is intended but merely a missing feature.\n\nSo, yes, eventually we may want to make them more similar, but I\nsuspect that there are some things that should be in one but never\nbe in the other.\n"},{"id":"381984","messageId":"xmqqtv9pmaf7.fsf@gitster-ct.c.googlers.com","threadId":"51795","inReplyTo":"pull.329.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 0/5] Refactor excludes library","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-09-06T20:34:04Z","receivedAt":"2019-09-06T20:34:10Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> I had started working on v2.23.0, but found adjacent-diff conflicts with\n> md/list-objects-filter-combo [2] and js/partial-clone-sparse-blob [3]. Those\n> branches are independent, but the conflicts with\n> md/list-objects-filter-combo were more severe (and that branch seems closer\n> to merging) so this is based on md/list-object-filter-combo. Hopefully the\n> conflicts with js/partial-clone-sparse-blob are clear enough to resolve\n> easily.\n\nThanks.\n\nI did screw the resolution up in previous integration, but I think\nwhat we have today is in a good shape.\n"}]}