{"thread":{"id":"25155","subject":"[PATCH 0/6] Introduce pathspec struct","startedAt":"2010-09-19T23:21:48Z","lastAt":"2010-09-29T06:11:18Z","messageCount":22,"participants":["Nguyễn Thái Ngọc Duy","Elijah Newren","Nguyen Thai Ngoc Duy","Junio C Hamano","Bo Yang","David Ripton","yj2133011"],"isPatch":true,"patchVersion":1,"patchTotal":6},"messages":[{"id":"151015","messageId":"1284938514-16663-1-git-send-email-pclouds@gmail.com","threadId":"25155","inReplyTo":null,"subject":"[PATCH 0/6] Introduce pathspec struct","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-09-19T23:21:48Z","receivedAt":"2010-09-19T23:21:48Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This is base series for en/object-list-with-pathspec, the upcoming\nwildcard support in diff family (i.e. tree_entry_interesting()) and\nnegative pathspec farther in future.\n\nNguyễn Thái Ngọc Duy (6):\n  Add struct pathspec\n  diff-no-index: use diff_tree_setup_paths()\n  pathspec: cache string length when initialize pathspec\n  Convert struct diff_options to use struct pathspec\n  tree_entry_interesting(): remove dependency on struct diff_options\n  Move tree_entry_interesting() to tree-walk.c and export it\n\n builtin/diff-files.c |    2 +-\n builtin/diff.c       |    4 +-\n builtin/log.c        |    2 +-\n cache.h              |   10 +++\n diff-lib.c           |    2 +-\n diff-no-index.c      |   13 ++--\n diff.h               |    4 +-\n dir.c                |   27 +++++++++\n revision.c           |    6 +--\n tree-diff.c          |  157 +++-----------------------------------------------\n tree-walk.c          |  111 +++++++++++++++++++++++++++++++++++\n tree-walk.h          |    2 +\n 12 files changed, 173 insertions(+), 167 deletions(-)\n"},{"id":"151017","messageId":"1284938514-16663-2-git-send-email-pclouds@gmail.com","threadId":"25155","inReplyTo":"1284938514-16663-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 1/6] Add struct pathspec","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-09-19T23:21:49Z","receivedAt":"2010-09-19T23:21:49Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This struct for now is just a wrapper for the current pathspec form:\nconst char **. It is intended to be extended with more useful\npathspec-related information over time.\n\nThe data structure for passing pathspec around remains const char **,\nstruct pathspec will be initialized locally to be used and destroyed.\nHopefully all pathspec related code will be gradually migrated to pass\nthis struct instead.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n cache.h |    7 +++++++\n dir.c   |   18 ++++++++++++++++++\n 2 files changed, 25 insertions(+), 0 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex eb77e1d..6227ddb 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -492,6 +492,13 @@ extern int index_name_is_other(const struct index_state *, const char *, int);\n extern int ie_match_stat(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);\n extern int ie_modified(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);\n \n+struct pathspec {\n+\tconst char **raw;\n+\tint nr;\n+};\n+\n+extern int init_pathspec(struct pathspec *,const char **);\n+extern void free_pathspec(struct pathspec *);\n extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);\n extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path);\n extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);\ndiff --git a/dir.c b/dir.c\nindex 133f472..5815b64 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -1071,3 +1071,21 @@ int remove_path(const char *name)\n \treturn 0;\n }\n \n+int init_pathspec(struct pathspec *pathspec, const char **paths)\n+{\n+\tconst char **p = paths;\n+\n+\tmemset(pathspec, 0, sizeof(*pathspec));\n+\tif (!p)\n+\t\treturn 0;\n+\twhile (*p)\n+\t\tp++;\n+\tpathspec->raw = paths;\n+\tpathspec->nr = p - paths;\n+\treturn 0;\n+}\n+\n+void free_pathspec(struct pathspec *pathspec)\n+{\n+\t/* do nothing */\n+}\n-- \n1.7.1.rc1.70.g788ca\n"},{"id":"151018","messageId":"1284938514-16663-3-git-send-email-pclouds@gmail.com","threadId":"25155","inReplyTo":"1284938514-16663-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 2/6] diff-no-index: use diff_tree_setup_paths()","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-09-19T23:21:50Z","receivedAt":"2010-09-19T23:21:50Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"diff_options.{paths,nr_paths} will be removed later. Do not\nmodify them directly.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n diff-no-index.c |    9 +++++----\n 1 files changed, 5 insertions(+), 4 deletions(-)\n\ndiff --git a/diff-no-index.c b/diff-no-index.c\nindex ce9e783..e48ab92 100644\n--- a/diff-no-index.c\n+++ b/diff-no-index.c\n@@ -231,8 +231,9 @@ void diff_no_index(struct rev_info *revs,\n \n \tif (prefix) {\n \t\tint len = strlen(prefix);\n+\t\tconst char *paths[3];\n+\t\tmemset(paths, 0, sizeof(paths));\n \n-\t\trevs->diffopt.paths = xcalloc(2, sizeof(char *));\n \t\tfor (i = 0; i < 2; i++) {\n \t\t\tconst char *p = argv[argc - 2 + i];\n \t\t\t/*\n@@ -242,12 +243,12 @@ void diff_no_index(struct rev_info *revs,\n \t\t\tp = (strcmp(p, \"-\")\n \t\t\t     ? xstrdup(prefix_filename(prefix, len, p))\n \t\t\t     : p);\n-\t\t\trevs->diffopt.paths[i] = p;\n+\t\t\tpaths[i] = p;\n \t\t}\n+\t\tdiff_tree_setup_paths(paths, &revs->diffopt);\n \t}\n \telse\n-\t\trevs->diffopt.paths = argv + argc - 2;\n-\trevs->diffopt.nr_paths = 2;\n+\t\tdiff_tree_setup_paths(argv + argc - 2, &revs->diffopt);\n \trevs->diffopt.skip_stat_unmatch = 1;\n \tif (!revs->diffopt.output_format)\n \t\trevs->diffopt.output_format = DIFF_FORMAT_PATCH;\n-- \n1.7.1.rc1.70.g788ca\n"},{"id":"151016","messageId":"1284938514-16663-4-git-send-email-pclouds@gmail.com","threadId":"25155","inReplyTo":"1284938514-16663-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 3/6] pathspec: cache string length when initialize pathspec","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-09-19T23:21:51Z","receivedAt":"2010-09-19T23:21:51Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This field will be used when tree_entry_interesting() is converted to\nuse struct pathspec. Currently it uses pathlens[] in struct\ndiff_options to avoid calculating string over and over again.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n cache.h |    3 +++\n dir.c   |   11 ++++++++++-\n 2 files changed, 13 insertions(+), 1 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 6227ddb..045c9fc 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -495,6 +495,9 @@ extern int ie_modified(const struct index_state *, struct cache_entry *, struct\n struct pathspec {\n \tconst char **raw;\n \tint nr;\n+\tstruct pathspec_item {\n+\t\tint len;\n+\t} *items;\n };\n \n extern int init_pathspec(struct pathspec *,const char **);\ndiff --git a/dir.c b/dir.c\nindex 5815b64..80b2df2 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -1074,6 +1074,7 @@ int remove_path(const char *name)\n int init_pathspec(struct pathspec *pathspec, const char **paths)\n {\n \tconst char **p = paths;\n+\tint i;\n \n \tmemset(pathspec, 0, sizeof(*pathspec));\n \tif (!p)\n@@ -1082,10 +1083,18 @@ int init_pathspec(struct pathspec *pathspec, const char **paths)\n \t\tp++;\n \tpathspec->raw = paths;\n \tpathspec->nr = p - paths;\n+\tif (!pathspec->nr)\n+\t\treturn 0;\n+\n+\tpathspec->items = xmalloc(sizeof(struct pathspec_item)*pathspec->nr);\n+\tfor (i = 0; i < pathspec->nr; i++) {\n+\t\tpathspec->items[i].len = strlen(paths[i]);\n+\t}\n \treturn 0;\n }\n \n void free_pathspec(struct pathspec *pathspec)\n {\n-\t/* do nothing */\n+\tfree(pathspec->items);\n+\tpathspec->items = NULL;\n }\n-- \n1.7.1.rc1.70.g788ca\n"},{"id":"151019","messageId":"1284938514-16663-5-git-send-email-pclouds@gmail.com","threadId":"25155","inReplyTo":"1284938514-16663-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 4/6] Convert struct diff_options to use struct pathspec","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-09-19T23:21:52Z","receivedAt":"2010-09-19T23:21:52Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/diff-files.c |    2 +-\n builtin/diff.c       |    4 ++--\n builtin/log.c        |    2 +-\n diff-lib.c           |    2 +-\n diff-no-index.c      |    4 ++--\n diff.h               |    4 +---\n revision.c           |    6 +-----\n tree-diff.c          |   46 +++++++++++-----------------------------------\n 8 files changed, 20 insertions(+), 50 deletions(-)\n\ndiff --git a/builtin/diff-files.c b/builtin/diff-files.c\nindex 951c7c8..46085f8 100644\n--- a/builtin/diff-files.c\n+++ b/builtin/diff-files.c\n@@ -61,7 +61,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)\n \t    (rev.diffopt.output_format & DIFF_FORMAT_PATCH))\n \t\trev.combine_merges = rev.dense_combined_merges = 1;\n \n-\tif (read_cache_preload(rev.diffopt.paths) < 0) {\n+\tif (read_cache_preload(rev.diffopt.pathspec.raw) < 0) {\n \t\tperror(\"read_cache_preload\");\n \t\treturn -1;\n \t}\ndiff --git a/builtin/diff.c b/builtin/diff.c\nindex a43d326..76c42d8 100644\n--- a/builtin/diff.c\n+++ b/builtin/diff.c\n@@ -135,7 +135,7 @@ static int builtin_diff_index(struct rev_info *revs,\n \t    revs->max_count != -1 || revs->min_age != -1 ||\n \t    revs->max_age != -1)\n \t\tusage(builtin_diff_usage);\n-\tif (read_cache_preload(revs->diffopt.paths) < 0) {\n+\tif (read_cache_preload(revs->diffopt.pathspec.raw) < 0) {\n \t\tperror(\"read_cache_preload\");\n \t\treturn -1;\n \t}\n@@ -237,7 +237,7 @@ static int builtin_diff_files(struct rev_info *revs, int argc, const char **argv\n \t\trevs->combine_merges = revs->dense_combined_merges = 1;\n \n \tsetup_work_tree();\n-\tif (read_cache_preload(revs->diffopt.paths) < 0) {\n+\tif (read_cache_preload(revs->diffopt.pathspec.raw) < 0) {\n \t\tperror(\"read_cache_preload\");\n \t\treturn -1;\n \t}\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 08b8722..d78744f 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -89,7 +89,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,\n \t\trev->always_show_header = 0;\n \tif (DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES)) {\n \t\trev->always_show_header = 0;\n-\t\tif (rev->diffopt.nr_paths != 1)\n+\t\tif (rev->diffopt.pathspec.nr != 1)\n \t\t\tusage(\"git logs can only follow renames on one pathname at a time\");\n \t}\n \tfor (i = 1; i < argc; i++) {\ndiff --git a/diff-lib.c b/diff-lib.c\nindex 392ce2b..3b809f2 100644\n--- a/diff-lib.c\n+++ b/diff-lib.c\n@@ -501,7 +501,7 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)\n \tactive_nr = dst - active_cache;\n \n \tinit_revisions(&revs, NULL);\n-\trevs.prune_data = opt->paths;\n+\trevs.prune_data = opt->pathspec.raw;\n \ttree = parse_tree_indirect(tree_sha1);\n \tif (!tree)\n \t\tdie(\"bad tree object %s\", sha1_to_hex(tree_sha1));\ndiff --git a/diff-no-index.c b/diff-no-index.c\nindex e48ab92..3a36144 100644\n--- a/diff-no-index.c\n+++ b/diff-no-index.c\n@@ -260,8 +260,8 @@ void diff_no_index(struct rev_info *revs,\n \tif (diff_setup_done(&revs->diffopt) < 0)\n \t\tdie(\"diff_setup_done failed\");\n \n-\tif (queue_diff(&revs->diffopt, revs->diffopt.paths[0],\n-\t\t       revs->diffopt.paths[1]))\n+\tif (queue_diff(&revs->diffopt, revs->diffopt.pathspec.raw[0],\n+\t\t       revs->diffopt.pathspec.raw[1]))\n \t\texit(1);\n \tdiff_set_mnemonic_prefix(&revs->diffopt, \"1/\", \"2/\");\n \tdiffcore_std(&revs->diffopt);\ndiff --git a/diff.h b/diff.h\nindex bf2f44d..6497b71 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -133,9 +133,7 @@ struct diff_options {\n \tFILE *file;\n \tint close_file;\n \n-\tint nr_paths;\n-\tconst char **paths;\n-\tint *pathlens;\n+\tstruct pathspec pathspec;\n \tchange_fn_t change;\n \tadd_remove_fn_t add_remove;\n \tdiff_format_fn_t format_callback;\ndiff --git a/revision.c b/revision.c\nindex b1c1890..b2a5867 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -553,11 +553,7 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)\n \n \tleft_first = left_count < right_count;\n \tinit_patch_ids(&ids);\n-\tif (revs->diffopt.nr_paths) {\n-\t\tids.diffopts.nr_paths = revs->diffopt.nr_paths;\n-\t\tids.diffopts.paths = revs->diffopt.paths;\n-\t\tids.diffopts.pathlens = revs->diffopt.pathlens;\n-\t}\n+\tids.diffopts.pathspec = revs->diffopt.pathspec;\n \n \t/* Compute patch-ids for one side */\n \tfor (p = list; p; p = p->next) {\ndiff --git a/tree-diff.c b/tree-diff.c\nindex cd659c6..986c0f4 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -100,16 +100,16 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int\n \tint pathlen;\n \tint never_interesting = -1;\n \n-\tif (!opt->nr_paths)\n+\tif (!opt->pathspec.nr)\n \t\treturn 1;\n \n \tsha1 = tree_entry_extract(desc, &path, &mode);\n \n \tpathlen = tree_entry_len(path, sha1);\n \n-\tfor (i = 0; i < opt->nr_paths; i++) {\n-\t\tconst char *match = opt->paths[i];\n-\t\tint matchlen = opt->pathlens[i];\n+\tfor (i = 0; i < opt->pathspec.nr; i++) {\n+\t\tconst char *match = opt->pathspec.raw[i];\n+\t\tint matchlen = opt->pathspec.items[i].len;\n \t\tint m = -1; /* signals that we haven't called strncmp() */\n \n \t\tif (baselen >= matchlen) {\n@@ -289,7 +289,7 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, stru\n \t\tif (DIFF_OPT_TST(opt, QUICK) &&\n \t\t    DIFF_OPT_TST(opt, HAS_CHANGES))\n \t\t\tbreak;\n-\t\tif (opt->nr_paths) {\n+\t\tif (opt->pathspec.nr) {\n \t\t\tskip_uninteresting(t1, base, baselen, opt);\n \t\t\tskip_uninteresting(t2, base, baselen, opt);\n \t\t}\n@@ -348,7 +348,7 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co\n \tDIFF_OPT_SET(&diff_opts, RECURSIVE);\n \tDIFF_OPT_SET(&diff_opts, FIND_COPIES_HARDER);\n \tdiff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;\n-\tdiff_opts.single_follow = opt->paths[0];\n+\tdiff_opts.single_follow = opt->pathspec.raw[0];\n \tdiff_opts.break_opt = opt->break_opt;\n \tpaths[0] = NULL;\n \tdiff_tree_setup_paths(paths, &diff_opts);\n@@ -368,15 +368,15 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co\n \t\t * diff_queued_diff, we will also use that as the path in\n \t\t * the future!\n \t\t */\n-\t\tif ((p->status == 'R' || p->status == 'C') && !strcmp(p->two->path, opt->paths[0])) {\n+\t\tif ((p->status == 'R' || p->status == 'C') && !strcmp(p->two->path, opt->pathspec.raw[0])) {\n \t\t\t/* Switch the file-pairs around */\n \t\t\tq->queue[i] = choice;\n \t\t\tchoice = p;\n \n \t\t\t/* Update the path we use from now on.. */\n \t\t\tdiff_tree_release_paths(opt);\n-\t\t\topt->paths[0] = xstrdup(p->one->path);\n-\t\t\tdiff_tree_setup_paths(opt->paths, opt);\n+\t\t\topt->pathspec.raw[0] = xstrdup(p->one->path);\n+\t\t\tdiff_tree_setup_paths(opt->pathspec.raw, opt);\n \n \t\t\t/*\n \t\t\t * The caller expects us to return a set of vanilla\n@@ -451,36 +451,12 @@ int diff_root_tree_sha1(const unsigned char *new, const char *base, struct diff_\n \treturn retval;\n }\n \n-static int count_paths(const char **paths)\n-{\n-\tint i = 0;\n-\twhile (*paths++)\n-\t\ti++;\n-\treturn i;\n-}\n-\n void diff_tree_release_paths(struct diff_options *opt)\n {\n-\tfree(opt->pathlens);\n+\tfree_pathspec(&opt->pathspec);\n }\n \n void diff_tree_setup_paths(const char **p, struct diff_options *opt)\n {\n-\topt->nr_paths = 0;\n-\topt->pathlens = NULL;\n-\topt->paths = NULL;\n-\n-\tif (p) {\n-\t\tint i;\n-\n-\t\topt->paths = p;\n-\t\topt->nr_paths = count_paths(p);\n-\t\tif (opt->nr_paths == 0) {\n-\t\t\topt->pathlens = NULL;\n-\t\t\treturn;\n-\t\t}\n-\t\topt->pathlens = xmalloc(opt->nr_paths * sizeof(int));\n-\t\tfor (i=0; i < opt->nr_paths; i++)\n-\t\t\topt->pathlens[i] = strlen(p[i]);\n-\t}\n+\tinit_pathspec(&opt->pathspec, p);\n }\n-- \n1.7.1.rc1.70.g788ca\n"},{"id":"151020","messageId":"1284938514-16663-6-git-send-email-pclouds@gmail.com","threadId":"25155","inReplyTo":"1284938514-16663-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 5/6] tree_entry_interesting(): remove dependency on struct diff_options","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-09-19T23:21:53Z","receivedAt":"2010-09-19T23:21:53Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This function can be potentially used in more places than just\ntree-diff.c. \"struct diff_options\" does not make much sense outside\ndiff_tree_sha1().\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n tree-diff.c |   28 +++++++++++-----------------\n 1 files changed, 11 insertions(+), 17 deletions(-)\n\ndiff --git a/tree-diff.c b/tree-diff.c\nindex 986c0f4..822d45e 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -91,25 +91,20 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const\n  *  - zero for no\n  *  - negative for \"no, and no subsequent entries will be either\"\n  */\n-static int tree_entry_interesting(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt)\n+static int tree_entry_interesting(const struct name_entry *entry, const char *base, int baselen, const struct pathspec *ps)\n {\n-\tconst char *path;\n-\tconst unsigned char *sha1;\n-\tunsigned mode;\n \tint i;\n \tint pathlen;\n \tint never_interesting = -1;\n \n-\tif (!opt->pathspec.nr)\n+\tif (!ps || !ps->nr)\n \t\treturn 1;\n \n-\tsha1 = tree_entry_extract(desc, &path, &mode);\n-\n-\tpathlen = tree_entry_len(path, sha1);\n+\tpathlen = tree_entry_len(entry->path, entry->sha1);\n \n-\tfor (i = 0; i < opt->pathspec.nr; i++) {\n-\t\tconst char *match = opt->pathspec.raw[i];\n-\t\tint matchlen = opt->pathspec.items[i].len;\n+\tfor (i = 0; i < ps->nr; i++) {\n+\t\tconst char *match = ps->raw[i];\n+\t\tint matchlen = ps->items[i].len;\n \t\tint m = -1; /* signals that we haven't called strncmp() */\n \n \t\tif (baselen >= matchlen) {\n@@ -147,7 +142,7 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int\n \t\t\t * Does match sort strictly earlier than path\n \t\t\t * with their common parts?\n \t\t\t */\n-\t\t\tm = strncmp(match, path,\n+\t\t\tm = strncmp(match, entry->path,\n \t\t\t\t    (matchlen < pathlen) ? matchlen : pathlen);\n \t\t\tif (m < 0)\n \t\t\t\tcontinue;\n@@ -174,7 +169,7 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int\n \t\tif (matchlen > pathlen) {\n \t\t\tif (match[pathlen] != '/')\n \t\t\t\tcontinue;\n-\t\t\tif (!S_ISDIR(mode))\n+\t\t\tif (!S_ISDIR(entry->mode))\n \t\t\t\tcontinue;\n \t\t}\n \n@@ -183,7 +178,7 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int\n \t\t\t * we cheated and did not do strncmp(), so we do\n \t\t\t * that here.\n \t\t\t */\n-\t\t\tm = strncmp(match, path, pathlen);\n+\t\t\tm = strncmp(match, entry->path, pathlen);\n \n \t\t/*\n \t\t * If common part matched earlier then it is a hit,\n@@ -206,8 +201,7 @@ static void show_tree(struct diff_options *opt, const char *prefix, struct tree_\n \t\tif (all_interesting)\n \t\t\tshow = 1;\n \t\telse {\n-\t\t\tshow = tree_entry_interesting(desc, base, baselen,\n-\t\t\t\t\t\t      opt);\n+\t\t\tshow = tree_entry_interesting(&desc->entry, base, baselen, &opt->pathspec);\n \t\t\tif (show == 2)\n \t\t\t\tall_interesting = 1;\n \t\t}\n@@ -266,7 +260,7 @@ static void skip_uninteresting(struct tree_desc *t, const char *base, int basele\n \t\tif (all_interesting)\n \t\t\tshow = 1;\n \t\telse {\n-\t\t\tshow = tree_entry_interesting(t, base, baselen, opt);\n+\t\t\tshow = tree_entry_interesting(&t->entry, base, baselen, &opt->pathspec);\n \t\t\tif (show == 2)\n \t\t\t\tall_interesting = 1;\n \t\t}\n-- \n1.7.1.rc1.70.g788ca\n"},{"id":"151021","messageId":"1284938514-16663-7-git-send-email-pclouds@gmail.com","threadId":"25155","inReplyTo":"1284938514-16663-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 6/6] Move tree_entry_interesting() to tree-walk.c and export it","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-09-19T23:21:54Z","receivedAt":"2010-09-19T23:21:54Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n tree-diff.c |  109 ---------------------------------------------------------\n tree-walk.c |  111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n tree-walk.h |    2 +\n 3 files changed, 113 insertions(+), 109 deletions(-)\n\ndiff --git a/tree-diff.c b/tree-diff.c\nindex 822d45e..50d7e6d 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -82,115 +82,6 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const\n \treturn 0;\n }\n \n-/*\n- * Is a tree entry interesting given the pathspec we have?\n- *\n- * Return:\n- *  - 2 for \"yes, and all subsequent entries will be\"\n- *  - 1 for yes\n- *  - zero for no\n- *  - negative for \"no, and no subsequent entries will be either\"\n- */\n-static int tree_entry_interesting(const struct name_entry *entry, const char *base, int baselen, const struct pathspec *ps)\n-{\n-\tint i;\n-\tint pathlen;\n-\tint never_interesting = -1;\n-\n-\tif (!ps || !ps->nr)\n-\t\treturn 1;\n-\n-\tpathlen = tree_entry_len(entry->path, entry->sha1);\n-\n-\tfor (i = 0; i < ps->nr; i++) {\n-\t\tconst char *match = ps->raw[i];\n-\t\tint matchlen = ps->items[i].len;\n-\t\tint m = -1; /* signals that we haven't called strncmp() */\n-\n-\t\tif (baselen >= matchlen) {\n-\t\t\t/* If it doesn't match, move along... */\n-\t\t\tif (strncmp(base, match, matchlen))\n-\t\t\t\tcontinue;\n-\n-\t\t\t/*\n-\t\t\t * If the base is a subdirectory of a path which\n-\t\t\t * was specified, all of them are interesting.\n-\t\t\t */\n-\t\t\tif (!matchlen ||\n-\t\t\t    base[matchlen] == '/' ||\n-\t\t\t    match[matchlen - 1] == '/')\n-\t\t\t\treturn 2;\n-\n-\t\t\t/* Just a random prefix match */\n-\t\t\tcontinue;\n-\t\t}\n-\n-\t\t/* Does the base match? */\n-\t\tif (strncmp(base, match, baselen))\n-\t\t\tcontinue;\n-\n-\t\tmatch += baselen;\n-\t\tmatchlen -= baselen;\n-\n-\t\tif (never_interesting) {\n-\t\t\t/*\n-\t\t\t * We have not seen any match that sorts later\n-\t\t\t * than the current path.\n-\t\t\t */\n-\n-\t\t\t/*\n-\t\t\t * Does match sort strictly earlier than path\n-\t\t\t * with their common parts?\n-\t\t\t */\n-\t\t\tm = strncmp(match, entry->path,\n-\t\t\t\t    (matchlen < pathlen) ? matchlen : pathlen);\n-\t\t\tif (m < 0)\n-\t\t\t\tcontinue;\n-\n-\t\t\t/*\n-\t\t\t * If we come here even once, that means there is at\n-\t\t\t * least one pathspec that would sort equal to or\n-\t\t\t * later than the path we are currently looking at.\n-\t\t\t * In other words, if we have never reached this point\n-\t\t\t * after iterating all pathspecs, it means all\n-\t\t\t * pathspecs are either outside of base, or inside the\n-\t\t\t * base but sorts strictly earlier than the current\n-\t\t\t * one.  In either case, they will never match the\n-\t\t\t * subsequent entries.  In such a case, we initialized\n-\t\t\t * the variable to -1 and that is what will be\n-\t\t\t * returned, allowing the caller to terminate early.\n-\t\t\t */\n-\t\t\tnever_interesting = 0;\n-\t\t}\n-\n-\t\tif (pathlen > matchlen)\n-\t\t\tcontinue;\n-\n-\t\tif (matchlen > pathlen) {\n-\t\t\tif (match[pathlen] != '/')\n-\t\t\t\tcontinue;\n-\t\t\tif (!S_ISDIR(entry->mode))\n-\t\t\t\tcontinue;\n-\t\t}\n-\n-\t\tif (m == -1)\n-\t\t\t/*\n-\t\t\t * we cheated and did not do strncmp(), so we do\n-\t\t\t * that here.\n-\t\t\t */\n-\t\t\tm = strncmp(match, entry->path, pathlen);\n-\n-\t\t/*\n-\t\t * If common part matched earlier then it is a hit,\n-\t\t * because we rejected the case where path is not a\n-\t\t * leading directory and is shorter than match.\n-\t\t */\n-\t\tif (!m)\n-\t\t\treturn 1;\n-\t}\n-\treturn never_interesting; /* No matches */\n-}\n-\n /* A whole sub-tree went away or appeared */\n static void show_tree(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base, int baselen)\n {\ndiff --git a/tree-walk.c b/tree-walk.c\nindex a9bbf4e..01168ea 100644\n--- a/tree-walk.c\n+++ b/tree-walk.c\n@@ -455,3 +455,114 @@ int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned ch\n \tfree(tree);\n \treturn retval;\n }\n+\n+/*\n+ * Is a tree entry interesting given the pathspec we have?\n+ *\n+ * Return:\n+ *  - 2 for \"yes, and all subsequent entries will be\"\n+ *  - 1 for yes\n+ *  - zero for no\n+ *  - negative for \"no, and no subsequent entries will be either\"\n+ */\n+int tree_entry_interesting(const struct name_entry *entry,\n+\t\t\t   const char *base, int baselen,\n+\t\t\t   const struct pathspec *ps)\n+{\n+\tint i;\n+\tint pathlen;\n+\tint never_interesting = -1;\n+\n+\tif (!ps || !ps->nr)\n+\t\treturn 1;\n+\n+\tpathlen = tree_entry_len(entry->path, entry->sha1);\n+\n+\tfor (i = 0; i < ps->nr; i++) {\n+\t\tconst char *match = ps->raw[i];\n+\t\tint matchlen = ps->items[i].len;\n+\t\tint m = -1; /* signals that we haven't called strncmp() */\n+\n+\t\tif (baselen >= matchlen) {\n+\t\t\t/* If it doesn't match, move along... */\n+\t\t\tif (strncmp(base, match, matchlen))\n+\t\t\t\tcontinue;\n+\n+\t\t\t/*\n+\t\t\t * If the base is a subdirectory of a path which\n+\t\t\t * was specified, all of them are interesting.\n+\t\t\t */\n+\t\t\tif (!matchlen ||\n+\t\t\t    base[matchlen] == '/' ||\n+\t\t\t    match[matchlen - 1] == '/')\n+\t\t\t\treturn 2;\n+\n+\t\t\t/* Just a random prefix match */\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* Does the base match? */\n+\t\tif (strncmp(base, match, baselen))\n+\t\t\tcontinue;\n+\n+\t\tmatch += baselen;\n+\t\tmatchlen -= baselen;\n+\n+\t\tif (never_interesting) {\n+\t\t\t/*\n+\t\t\t * We have not seen any match that sorts later\n+\t\t\t * than the current path.\n+\t\t\t */\n+\n+\t\t\t/*\n+\t\t\t * Does match sort strictly earlier than path\n+\t\t\t * with their common parts?\n+\t\t\t */\n+\t\t\tm = strncmp(match, entry->path,\n+\t\t\t\t    (matchlen < pathlen) ? matchlen : pathlen);\n+\t\t\tif (m < 0)\n+\t\t\t\tcontinue;\n+\n+\t\t\t/*\n+\t\t\t * If we come here even once, that means there is at\n+\t\t\t * least one pathspec that would sort equal to or\n+\t\t\t * later than the path we are currently looking at.\n+\t\t\t * In other words, if we have never reached this point\n+\t\t\t * after iterating all pathspecs, it means all\n+\t\t\t * pathspecs are either outside of base, or inside the\n+\t\t\t * base but sorts strictly earlier than the current\n+\t\t\t * one.  In either case, they will never match the\n+\t\t\t * subsequent entries.  In such a case, we initialized\n+\t\t\t * the variable to -1 and that is what will be\n+\t\t\t * returned, allowing the caller to terminate early.\n+\t\t\t */\n+\t\t\tnever_interesting = 0;\n+\t\t}\n+\n+\t\tif (pathlen > matchlen)\n+\t\t\tcontinue;\n+\n+\t\tif (matchlen > pathlen) {\n+\t\t\tif (match[pathlen] != '/')\n+\t\t\t\tcontinue;\n+\t\t\tif (!S_ISDIR(entry->mode))\n+\t\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (m == -1)\n+\t\t\t/*\n+\t\t\t * we cheated and did not do strncmp(), so we do\n+\t\t\t * that here.\n+\t\t\t */\n+\t\t\tm = strncmp(match, entry->path, pathlen);\n+\n+\t\t/*\n+\t\t * If common part matched earlier then it is a hit,\n+\t\t * because we rejected the case where path is not a\n+\t\t * leading directory and is shorter than match.\n+\t\t */\n+\t\tif (!m)\n+\t\t\treturn 1;\n+\t}\n+\treturn never_interesting; /* No matches */\n+}\ndiff --git a/tree-walk.h b/tree-walk.h\nindex 88ea7e9..c3d0684 100644\n--- a/tree-walk.h\n+++ b/tree-walk.h\n@@ -57,4 +57,6 @@ static inline int traverse_path_len(const struct traverse_info *info, const stru\n \treturn info->pathlen + tree_entry_len(n->path, n->sha1);\n }\n \n+extern int tree_entry_interesting(const struct name_entry *, const char *, int, const struct pathspec *ps);\n+\n #endif\n-- \n1.7.1.rc1.70.g788ca\n"},{"id":"151092","messageId":"AANLkTimR=mgjFYwdzqUF7_0j33ha4AJcrJbuL7VJunPK@mail.gmail.com","threadId":"25155","inReplyTo":"1284938514-16663-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 0/6] Introduce pathspec struct","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2010-09-20T08:31:51Z","receivedAt":"2010-09-20T08:31:51Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"2010/9/19 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>:\n> This is base series for en/object-list-with-pathspec, the upcoming\n> wildcard support in diff family (i.e. tree_entry_interesting()) and\n> negative pathspec farther in future.\n\nI briefly looked over the series.  If I understand correctly, it's\npretty much the same as your previous series, except that it uses a\nnew data structure instead of exclude_list, and doesn't include my\ntwo-patch series anymore or negated pathspecs.  Is that correct?  If\nso, it looks good to me.\n\nI'll try to test it soon, and resubmit my \"Nuke match_tree_entry()\"\n(which duplicates code from tree_entry_interesting()) patch on top of\nit.\n\n\nThanks,\nElijah\n"},{"id":"151165","messageId":"AANLkTikYpt75f7yGgzTwKj9fMUAytxkN+jHPRY=8W9hE@mail.gmail.com","threadId":"25155","inReplyTo":"AANLkTimR=mgjFYwdzqUF7_0j33ha4AJcrJbuL7VJunPK@mail.gmail.com","subject":"Re: [PATCH 0/6] Introduce pathspec struct","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-09-20T22:15:20Z","receivedAt":"2010-09-20T22:15:20Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2010/9/20 Elijah Newren <newren@gmail.com>:\n> 2010/9/19 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>:\n>> This is base series for en/object-list-with-pathspec, the upcoming\n>> wildcard support in diff family (i.e. tree_entry_interesting()) and\n>> negative pathspec farther in future.\n>\n> I briefly looked over the series.  If I understand correctly, it's\n> pretty much the same as your previous series, except that it uses a\n> new data structure instead of exclude_list, and doesn't include my\n> two-patch series anymore or negated pathspecs.  Is that correct?  If\n> so, it looks good to me.\n\nCorrect. The globbing series is in place of negated pathspecs now.\nYour two patch series are also resent elsewhere.\n-- \nDuy\n"},{"id":"151860","messageId":"7vbp7ix20u.fsf@alter.siamese.dyndns.org","threadId":"25155","inReplyTo":"1284938514-16663-2-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 1/6] Add struct pathspec","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-09-27T22:19:45Z","receivedAt":"2010-09-27T22:19:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> This struct for now is just a wrapper for the current pathspec form:\n> const char **. It is intended to be extended with more useful\n> pathspec-related information over time.\n>\n> The data structure for passing pathspec around remains const char **,\n> struct pathspec will be initialized locally to be used and destroyed.\n> Hopefully all pathspec related code will be gradually migrated to pass\n> this struct instead.\n>\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  cache.h |    7 +++++++\n>  dir.c   |   18 ++++++++++++++++++\n>  2 files changed, 25 insertions(+), 0 deletions(-)\n>\n> diff --git a/cache.h b/cache.h\n> index eb77e1d..6227ddb 100644\n> --- a/cache.h\n> +++ b/cache.h\n> @@ -492,6 +492,13 @@ extern int index_name_is_oth\n> ...\n> +struct pathspec {\n> +\tconst char **raw;\n> +\tint nr;\n> +};\n> +\n> +extern int init_pathspec(struct pathspec *,const char **);\n\ns/,/, /;\n\n> +extern void free_pathspec(struct pathspec *);\n>  extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);\n>  extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path);\n>  extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);\n> diff --git a/dir.c b/dir.c\n> index 133f472..5815b64 100644\n> --- a/dir.c\n> +++ b/dir.c\n> @@ -1071,3 +1071,21 @@ int remove_path(const char *name)\n> ...\n> +void free_pathspec(struct pathspec *pathspec)\n> +{\n> +\t/* do nothing */\n> +}\n\nI'd prefer making this more explicit by saying\n\n\t{\n        \t; /* do nothing */\n\t}\n"},{"id":"151861","messageId":"7v62xqx20o.fsf@alter.siamese.dyndns.org","threadId":"25155","inReplyTo":"1284938514-16663-4-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 3/6] pathspec: cache string length when initialize pathspec","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-09-27T22:19:51Z","receivedAt":"2010-09-27T22:19:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> Subject: Re: [PATCH 3/6] pathspec: cache string length when initialize pathspec\n\ns/initialize/initializing/;\n\n> This field will be used when tree_entry_interesting() is converted to\n> use struct pathspec. Currently it uses pathlens[] in struct\n> diff_options to avoid calculating string over and over again.\n>\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  cache.h |    3 +++\n>  dir.c   |   11 ++++++++++-\n>  2 files changed, 13 insertions(+), 1 deletions(-)\n>\n> diff --git a/cache.h b/cache.h\n> index 6227ddb..045c9fc 100644\n> --- a/cache.h\n> +++ b/cache.h\n> @@ -495,6 +495,9 @@ extern int ie_modified(const struct index_state *, struct cache_entry *, struct\n>  struct pathspec {\n>  \tconst char **raw;\n>  \tint nr;\n> +\tstruct pathspec_item {\n> +\t\tint len;\n> +\t} *items;\n\nHmm... I would have expected to see\n\n        struct pathspec_item {\n                const char *pattern;\n                int len;\n        };\n\tstruct pathspec {\n        \tstruct pathspec_item *items;\n\t\tint nr;\n\t};\n\nas you would be allocating a structure anyway, but persumably many places\ntake their input as a NULL terminated \"char **\" array, and keeping such an\narray around as the \"raw\" field may be easier in refactoring.\n"},{"id":"151862","messageId":"7vzkv2vng3.fsf@alter.siamese.dyndns.org","threadId":"25155","inReplyTo":"1284938514-16663-5-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 4/6] Convert struct diff_options to use struct pathspec","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-09-27T22:19:56Z","receivedAt":"2010-09-27T22:19:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> diff --git a/revision.c b/revision.c\n> index b1c1890..b2a5867 100644\n> --- a/revision.c\n> +++ b/revision.c\n> @@ -553,11 +553,7 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)\n>  \n>  \tleft_first = left_count < right_count;\n>  \tinit_patch_ids(&ids);\n> -\tif (revs->diffopt.nr_paths) {\n> -\t\tids.diffopts.nr_paths = revs->diffopt.nr_paths;\n> -\t\tids.diffopts.paths = revs->diffopt.paths;\n> -\t\tids.diffopts.pathlens = revs->diffopt.pathlens;\n> -\t}\n> +\tids.diffopts.pathspec = revs->diffopt.pathspec;\n\nJust a mental note; we need to be careful not to destroy this structure\n(i.e. freeing ids.diffopts.pathspec.items) when we are done with ids.\n\nNice code reduction ;-)\n"},{"id":"151864","messageId":"7vtylavnfx.fsf@alter.siamese.dyndns.org","threadId":"25155","inReplyTo":"1284938514-16663-6-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 5/6] tree_entry_interesting(): remove dependency on struct diff_options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-09-27T22:20:02Z","receivedAt":"2010-09-27T22:20:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> This function can be potentially used in more places than just\n> tree-diff.c. \"struct diff_options\" does not make much sense outside\n> diff_tree_sha1().\n\nThis does a bit more than that; it does not call tree_entry_extract()\nanymore, and instead uses the knowledge of its underlying implementation.\nThe mode of the entry that is passed to S_ISDIR() check is not cleansed\nwith canon_mode() anymore.\n\nI do not think these are necessarily bad changes, but they should be\ndocumented.\n"},{"id":"151872","messageId":"AANLkTinu5msupME4efxLLRcDPvM3gFd2q+k3RLw6tYuV@mail.gmail.com","threadId":"25155","inReplyTo":"7v62xqx20o.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 3/6] pathspec: cache string length when initialize pathspec","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-09-28T01:08:09Z","receivedAt":"2010-09-28T01:08:09Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2010/9/28 Junio C Hamano <gitster@pobox.com>:\n> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n>\n>> Subject: Re: [PATCH 3/6] pathspec: cache string length when initialize pathspec\n>\n> s/initialize/initializing/;\n>\n>> This field will be used when tree_entry_interesting() is converted to\n>> use struct pathspec. Currently it uses pathlens[] in struct\n>> diff_options to avoid calculating string over and over again.\n>>\n>> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n>> ---\n>>  cache.h |    3 +++\n>>  dir.c   |   11 ++++++++++-\n>>  2 files changed, 13 insertions(+), 1 deletions(-)\n>>\n>> diff --git a/cache.h b/cache.h\n>> index 6227ddb..045c9fc 100644\n>> --- a/cache.h\n>> +++ b/cache.h\n>> @@ -495,6 +495,9 @@ extern int ie_modified(const struct index_state *, struct cache_entry *, struct\n>>  struct pathspec {\n>>       const char **raw;\n>>       int nr;\n>> +     struct pathspec_item {\n>> +             int len;\n>> +     } *items;\n>\n> Hmm... I would have expected to see\n>\n>        struct pathspec_item {\n>                const char *pattern;\n>                int len;\n>        };\n>        struct pathspec {\n>                struct pathspec_item *items;\n>                int nr;\n>        };\n>\n> as you would be allocating a structure anyway, but persumably many places\n> take their input as a NULL terminated \"char **\" array, and keeping such an\n> array around as the \"raw\" field may be easier in refactoring.\n\npathspec_item.pattern is added later on when I implement negative\npathspec so it's not too different from your expectation. \"raw\"\nhowever is kept. The reason (again in my WIP negative pathspec) is\nthat I use \"!\" alone to denote a negative pathspec. So if user gives {\n\"foo\", \"!\", \"foo/bar\", NULL }, \"raw\" will contain exactly that, but\nthere are only two pathspec_item for \"foo\" and \"foo/bar\" (with\nnegative flag set).\n-- \nDuy\n"},{"id":"151885","messageId":"7v7hi6us35.fsf@alter.siamese.dyndns.org","threadId":"25155","inReplyTo":"1284938514-16663-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 0/6] Introduce pathspec struct","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-09-28T09:37:18Z","receivedAt":"2010-09-28T09:37:18Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Just a couple of quick notes.\n\n - I had to eject Bo's \"log -L range path\" series in order to push this\n   out on 'pu' as the range stuff adds new callsites to the old pathspec\n   API.\n\n   This is tentative and does not mean Bo's series is getting rejected;\n   I'd want to get its command line parsing around the pathnames fixed\n   anyway but I suspect the affected codepath would overlap between the\n   two series.  Help is appreciated.\n\n - I do not think either !pattern nor ^pattern is particularly a good way\n   to express negative pathspecs.  My gut feeling is (I have not thought\n   this through nor clearly enough; note the time of this message) that it\n   would be the cleanest at the UI level to introduce negative patterns as\n   arguments to a separate command line flag, e.g.\n\n   $ git log --exclude \"Doc*\" master..pu -- '*.txt'\n   $ git grep --exclude \"t/\" -e 'test .*-L' -- '*.sh'\n\n - David's \"git grep --exclude-dir D\" topic should be able to internally\n   use the same negative pathspec mechanism.  At the command line level,\n   it allows (and needs to allow) only the leading prefix (which is how\n   GNU grep's --exclude-dir works), but it makes tons of sense for us to\n   allow \"--exclude $pattern\" from the command line, and share the\n   mechanism internally between the two.\n"},{"id":"151913","messageId":"AANLkTinrOxDvzm2-zG+huNp=00+o4XqYwnsfhjOFEEoH@mail.gmail.com","threadId":"25155","inReplyTo":"7v7hi6us35.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 0/6] Introduce pathspec struct","fromName":"Bo Yang","fromEmail":"struggleyb.nku@gmail.com","sentAt":"2010-09-28T13:56:45Z","receivedAt":"2010-09-28T13:56:45Z","isPatch":true,"sender":{"key":"struggleyb.nku@gmail.com","avatar":"https://avatars.githubusercontent.com/u/233030?v=4"},"body":"2010/9/28 Junio C Hamano <gitster@pobox.com>:\n> Just a couple of quick notes.\n>\n>  - I had to eject Bo's \"log -L range path\" series in order to push this\n>   out on 'pu' as the range stuff adds new callsites to the old pathspec\n>   API.\n>\n>   This is tentative and does not mean Bo's series is getting rejected;\n>   I'd want to get its command line parsing around the pathnames fixed\n>   anyway but I suspect the affected codepath would overlap between the\n>   two series.  Help is appreciated.\n\nAh, it is not very astonished to see this series put into 'pu' since I\nam not active these days. :)\n\nHmm, let me make a summary about the requirement for the pathname\ncommand line options:\n1. The syntax now 'git log <rev> -L l:m path1 -L l:m path2' got clash\nwith current git command line style 'git subcommand dash-option <rev>\npath'. Since we support multiple paths with multiple ranges, I think\nthe best way to comply with git command line style is to change it to\n'git log -L l:m path1 -L l:m path2 <rev>'.\n\n2. The way I parse the command line should make a little change, that\nin '-L' in callback to parse both range and path arguments.\n\nThat's it?\n\n-- \nRegards!\nBo\n----------------------------\nMy blog: http://blog.morebits.org\nWhy Git: http://www.whygitisbetterthanx.com/\n"},{"id":"151970","messageId":"AANLkTikso2O5M_ZBr1pvr8jqg=h7jhd+U+fBGossdU0W@mail.gmail.com","threadId":"25155","inReplyTo":"7vtylavnfx.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 5/6] tree_entry_interesting(): remove dependency on struct diff_options","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-09-28T22:00:46Z","receivedAt":"2010-09-28T22:00:46Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Tue, Sep 28, 2010 at 8:20 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n>\n>> This function can be potentially used in more places than just\n>> tree-diff.c. \"struct diff_options\" does not make much sense outside\n>> diff_tree_sha1().\n>\n> This does a bit more than that; it does not call tree_entry_extract()\n> anymore, and instead uses the knowledge of its underlying implementation.\n> The mode of the entry that is passed to S_ISDIR() check is not cleansed\n> with canon_mode() anymore.\n\nHmm.. missed that. Thanks for catching.\n-- \nDuy\n"},{"id":"151973","messageId":"AANLkTinZ=dx1nBXTw0E=nLOmncsgNb7wv1-+ddWzPU+e@mail.gmail.com","threadId":"25155","inReplyTo":"7v7hi6us35.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 0/6] Introduce pathspec struct","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-09-28T22:31:08Z","receivedAt":"2010-09-28T22:31:08Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2010/9/28 Junio C Hamano <gitster@pobox.com>:\n> Just a couple of quick notes.\n>\n>  - I had to eject Bo's \"log -L range path\" series in order to push this\n>   out on 'pu' as the range stuff adds new callsites to the old pathspec\n>   API.\n>\n>   This is tentative and does not mean Bo's series is getting rejected;\n>   I'd want to get its command line parsing around the pathnames fixed\n>   anyway but I suspect the affected codepath would overlap between the\n>   two series.  Help is appreciated.\n\nI'll have a look.\n\n>  - I do not think either !pattern nor ^pattern is particularly a good way\n>   to express negative pathspecs.  My gut feeling is (I have not thought\n>   this through nor clearly enough; note the time of this message) that it\n>   would be the cleanest at the UI level to introduce negative patterns as\n>   arguments to a separate command line flag, e.g.\n>\n>   $ git log --exclude \"Doc*\" master..pu -- '*.txt'\n>   $ git grep --exclude \"t/\" -e 'test .*-L' -- '*.sh'\n\nI was writing \"but you would lose the ability to mix negative and\npositive pathspecs together, something like 'exclude Documentation\nexcept Documentation/technical'\", but then we can have negative\nexcludes too:\n\n$ git log --exclude Documentation --exclude \"!Documentation/technical\"\nmaster..pu -- '*.txt'\n\ndoes not sound too twisted to understand (I hope).\n\n>  - David's \"git grep --exclude-dir D\" topic should be able to internally\n>   use the same negative pathspec mechanism.  At the command line level,\n>   it allows (and needs to allow) only the leading prefix (which is how\n>   GNU grep's --exclude-dir works), but it makes tons of sense for us to\n>   allow \"--exclude $pattern\" from the command line, and share the\n>   mechanism internally between the two.\n\nYes, eventually. But\n - tree_entry_interesting() needs (a bit complex) rework to have\nwildcard matching capability\n - then I am still not sure how negative pathspecs should be done properly\n\nBoth may take me weeks to come up with something sensible. If David\nneeds \"git grep --exclude-dir\" now, he should keep working on\nbuiltin/grep.c as he's doing now (maybe change --exclude-dir to\n--exclude). If my work on negative pathspec has a result, sure I will\nremove pathspec_matches() from builtin/grep.c, but his work on the\ncommand line interface _and tests_ won't be wasted.\n-- \nDuy\n"},{"id":"151983","messageId":"4CA2789A.7090306@ripton.net","threadId":"25155","inReplyTo":"7v7hi6us35.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 0/6] Introduce pathspec struct","fromName":"David Ripton","fromEmail":"dripton@ripton.net","sentAt":"2010-09-28T23:22:02Z","receivedAt":"2010-09-28T23:22:02Z","isPatch":true,"sender":{"key":"dripton@ripton.net","avatar":"https://avatars.githubusercontent.com/u/153528?v=4"},"body":"On 09/28/10 04:37, Junio C Hamano wrote:\n\n>   - David's \"git grep --exclude-dir D\" topic should be able to internally\n>     use the same negative pathspec mechanism.  At the command line level,\n>     it allows (and needs to allow) only the leading prefix (which is how\n>     GNU grep's --exclude-dir works), but it makes tons of sense for us to\n>     allow \"--exclude $pattern\" from the command line, and share the\n>     mechanism internally between the two.\n\nI don't think GNU grep's --exclude-dir only allows the leading prefix. \nHere the data directory is a level below the top, but --exclude-dir=data \neffectively excludes it:\n\n$ grep -R behemoth_green *\nBinary file slugathon/util/colors.pyc matches\nslugathon/util/colors.py:    \"behemoth_green\": (2, 129, 2),\nBinary file slugathon/data/creaturedata.pyc matches\nslugathon/data/creaturedata.py:\"Behemoth\": (\"Behemoths\", 8, 3, 0, 0, \n\"creature\", 0, 0, 18, \"behemoth_green\"),\nslugathon/data/creaturedata.py:\"Cyclops\": (\"Cyclopes\", 9, 2, 0, 0, \n\"creature\", 0, 0, 28, \"behemoth_green\"),\n\ngrep -R --exclude-dir=data behemoth_green *\nBinary file slugathon/util/colors.pyc matches\nslugathon/util/colors.py:    \"behemoth_green\": (2, 129, 2),\n\nIMO it's useful to allow excluding directories below the top like it \ncurrently does, because some projects might have a bunch of noise \ndirectories with the same name, and having --exclude-dir exclude them \nall would be handy.\n\nThat said, if consistency with other exclude patterns is more important \nthan this use case, fine with me.\n\n-- \nDavid Ripton    dripton@ripton.net\n"},{"id":"152014","messageId":"7vzkv1qinx.fsf@alter.siamese.dyndns.org","threadId":"25155","inReplyTo":"AANLkTinZ=dx1nBXTw0E=nLOmncsgNb7wv1-+ddWzPU+e@mail.gmail.com","subject":"Re: [PATCH 0/6] Introduce pathspec struct","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-09-29T04:26:42Z","receivedAt":"2010-09-29T04:26:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyen Thai Ngoc Duy <pclouds@gmail.com> writes:\n\n>>  $ git log --exclude \"Doc*\" master..pu -- '*.txt'\n>>  $ git grep --exclude \"t/\" -e 'test .*-L' -- '*.sh'\n>\n> I was writing \"but you would lose the ability to mix negative and\n> positive pathspecs together, something like 'exclude Documentation\n> except Documentation/technical'\",...\n\nI think that is way overengineered.  We _could_ make the expressions\narbitrarily complex and hard to use by using irregular syntax tricks, but\nlet's not go there.  Let's just keep things simple and usable instead.\n\n * Without pathspec, everything is included;\n * pathspecs will filter everything that do not match;\n * --exclude also filters what matches them from the remainder.\n\nSo...\n\n> $ git log --exclude Documentation --exclude \"!Documentation/technical\"\n> master..pu -- '*.txt'\n>\n> does not sound too twisted to understand (I hope).\n\n...I would not vote for this.\n\n> ... If David\n> needs \"git grep --exclude-dir\" now, he should keep working on\n> builtin/grep.c as he's doing now (maybe change --exclude-dir to\n> --exclude).\n\nThat's not what I am saying.\n\nBecause --exclude-dir is a special case of --exclude, it would be an\nefficient solution _if_ we can externally keep the command line option\ncompatible with GNU grep as a syntax sugar, and turn it into something\nelse internally that can be passed to your \"pathspec with negative\"\nengine.\n\n\n> ..., but his work on the\n> command line interface _and tests_ won't be wasted.\n\nYup.\n"},{"id":"152015","messageId":"7vvd5pqik2.fsf@alter.siamese.dyndns.org","threadId":"25155","inReplyTo":"4CA2789A.7090306@ripton.net","subject":"Re: [PATCH 0/6] Introduce pathspec struct","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-09-29T04:29:01Z","receivedAt":"2010-09-29T04:29:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"David Ripton <dripton@ripton.net> writes:\n\n> On 09/28/10 04:37, Junio C Hamano wrote:\n>\n>>   - David's \"git grep --exclude-dir D\" topic should be able to internally\n>>     use the same negative pathspec mechanism.  At the command line level,\n>>     it allows (and needs to allow) only the leading prefix (which is how\n>>     GNU grep's --exclude-dir works), but it makes tons of sense for us to\n>>     allow \"--exclude $pattern\" from the command line, and share the\n>>     mechanism internally between the two.\n>\n> I don't think GNU grep's --exclude-dir only allows the leading\n> prefix.\n\nHeh, I was half expecting to hear that after I wrote it ;-) What I meant\nwas \"pattern matches against the leading path, excluding the basename\npart\" (as the option is exclude-DIR, that is more or less by definition).\n"},{"id":"152020","messageId":"1285740678928-5582619.post@n2.nabble.com","threadId":"25155","inReplyTo":"1284938514-16663-2-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 1/6] Add struct pathspec","fromName":"yj2133011","fromEmail":"274040551@qq.com","sentAt":"2010-09-29T06:11:18Z","receivedAt":"2010-09-29T06:11:18Z","isPatch":true,"sender":{"key":"274040551@qq.com","avatar":null},"body":"\nThis struct for now is just a wrapper for the current pathspec form:\nconst char **. It is intended to be extended with more useful\npathspec-related information over time.\n\nThe data structure for passing pathspec around remains const char **,\nstruct pathspec will be initialized locally to be used and destroyed.\nHopefully all pathspec related code will be gradually migrated to pass\nthis struct instead.\n\n\n-----\nThe voice input and output is very good in this \nhttp://www.tomtop.com/black-ps3-wireless-bluetooth-headset-for-playstation-3.html?aid=z\nWireless PS3 Headset . It is compatible with all PS3 games.Buy from Reliable \nhttp://www.tomtop.com/google-android-7-notebook-3g-tablet-pc-umpc-wifi-mid-pda.html?aid=z\nGoogle Android PC  apad Wholesalers.\n-- \nView this message in context: http://git.661346.n2.nabble.com/PATCH-0-6-Introduce-pathspec-struct-tp5548679p5582619.html\nSent from the git mailing list archive at Nabble.com.\n"}]}