From: Jeff King Date: Tue, 15 May 2018 14:15:18 +0000 (-0400) Subject: Merge branch 'jk/submodule-name-verify-fix' into jk/submodule-name-verify-fsck X-Git-Tag: v2.17.1~1^2~10 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/eedd5949f5a6b1bb86726051d0916421cdbb5dcd Merge branch 'jk/submodule-name-verify-fix' into jk/submodule-name-verify-fsck * jk/submodule-name-verify-fix: verify_path: disallow symlinks in .gitmodules update-index: stat updated files earlier verify_path: drop clever fallthrough skip_prefix: add icase-insensitive variant is_{hfs,ntfs}_dotgitmodules: add tests path: match NTFS short names for more .git files is_hfs_dotgit: match other .git files is_ntfs_dotgit: use a size_t for traversing string submodule-config: verify submodule names as paths Note that this includes two bits of evil-merge: - there's a new call to verify_path() that doesn't actually have a mode available. It should be OK to pass "0" here, since we're just manipulating the untracked cache, not an actual index entry. - the lstat() in builtin/update-index.c:update_one() needs to be updated to handle the fsmonitor case (without this it still behaves correctly, but does an unnecessary lstat). --- eedd5949f5a6b1bb86726051d0916421cdbb5dcd diff --cc builtin/submodule--helper.c index 6ba8587b6d,b4b4d29d82..4f35c98bb9 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@@ -1814,9 -1190,34 +1814,32 @@@ static int is_active(int argc, const ch if (argc != 2) die("submodule--helper is-active takes exactly 1 argument"); - gitmodules_config(); - - return !is_submodule_initialized(argv[1]); + return !is_submodule_active(the_repository, argv[1]); } + /* + * Exit non-zero if any of the submodule names given on the command line is + * invalid. If no names are given, filter stdin to print only valid names + * (which is primarily intended for testing). + */ + static int check_name(int argc, const char **argv, const char *prefix) + { + if (argc > 1) { + while (*++argv) { + if (check_submodule_name(*argv) < 0) + return 1; + } + } else { + struct strbuf buf = STRBUF_INIT; + while (strbuf_getline(&buf, stdin) != EOF) { + if (!check_submodule_name(buf.buf)) + printf("%s\n", buf.buf); + } + strbuf_release(&buf); + } + return 0; + } + #define SUPPORT_SUPER_PREFIX (1<<0) struct cmd_struct { diff --cc builtin/update-index.c index 58d1c2d282,19216595fb..1af8a00b88 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@@ -449,7 -442,17 +448,18 @@@ static void chmod_path(char flip, cons static void update_one(const char *path) { - if (!verify_path(path)) { + int stat_errno = 0; + struct stat st; + - if (mark_valid_only || mark_skip_worktree_only || force_remove) ++ if (mark_valid_only || mark_skip_worktree_only || force_remove || ++ mark_fsmonitor_only) + st.st_mode = 0; + else if (lstat(path, &st) < 0) { + st.st_mode = 0; + stat_errno = errno; + } /* else stat is valid */ + + if (!verify_path(path, st.st_mode)) { fprintf(stderr, "Ignoring path %s\n", path); return; } diff --cc cache.h index a61b2d3f0d,5a44f79e26..0323853c99 --- a/cache.h +++ b/cache.h @@@ -592,49 -590,15 +592,49 @@@ extern int read_index(struct index_stat extern int read_index_preload(struct index_state *, const struct pathspec *pathspec); extern int do_read_index(struct index_state *istate, const char *path, int must_exist); /* for testting only! */ -extern int read_index_from(struct index_state *, const char *path); +extern int read_index_from(struct index_state *, const char *path, + const char *gitdir); extern int is_index_unborn(struct index_state *); extern int read_index_unmerged(struct index_state *); + +/* For use with `write_locked_index()`. */ #define COMMIT_LOCK (1 << 0) -#define CLOSE_LOCK (1 << 1) +#define SKIP_IF_UNCHANGED (1 << 1) + +/* + * Write the index while holding an already-taken lock. Close the lock, + * and if `COMMIT_LOCK` is given, commit it. + * + * Unless a split index is in use, write the index into the lockfile. + * + * With a split index, write the shared index to a temporary file, + * adjust its permissions and rename it into place, then write the + * split index to the lockfile. If the temporary file for the shared + * index cannot be created, fall back to the behavior described in + * the previous paragraph. + * + * With `COMMIT_LOCK`, the lock is always committed or rolled back. + * Without it, the lock is closed, but neither committed nor rolled + * back. + * + * If `SKIP_IF_UNCHANGED` is given and the index is unchanged, nothing + * is written (and the lock is rolled back if `COMMIT_LOCK` is given). + */ extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags); + extern int discard_index(struct index_state *); +extern void move_index_extensions(struct index_state *dst, struct index_state *src); extern int unmerged_index(const struct index_state *); + +/** + * Returns 1 if the index differs from HEAD, 0 otherwise. When on an unborn + * branch, returns 1 if there are entries in the index, 0 otherwise. If an + * strbuf is provided, the space-separated list of files that differ will be + * appended to it. + */ +extern int index_has_changes(struct strbuf *sb); + - extern int verify_path(const char *path); + extern int verify_path(const char *path, unsigned mode); extern int strcmp_offset(const char *s1, const char *s2, size_t *first_change); extern int index_dir_exists(struct index_state *istate, const char *name, int namelen); extern void adjust_dirname_case(struct index_state *istate, char *name); diff --cc dir.c index dedbf5d476,31f9343f9f..41aac3b7b3 --- a/dir.c +++ b/dir.c @@@ -2992,8 -2781,6 +2992,8 @@@ void untracked_cache_invalidate_path(st { if (!istate->untracked || !istate->untracked->root) return; - if (!safe_path && !verify_path(path)) ++ if (!safe_path && !verify_path(path, 0)) + return; invalidate_one_component(istate->untracked, istate->untracked->root, path, strlen(path)); } diff --cc submodule-config.h index a5503a5d17,103cc79dd8..17e2970223 --- a/submodule-config.h +++ b/submodule-config.h @@@ -22,30 -22,24 +22,37 @@@ struct submodule int recommend_shallow; }; +#define SUBMODULE_INIT { NULL, NULL, NULL, RECURSE_SUBMODULES_NONE, \ + NULL, NULL, SUBMODULE_UPDATE_STRATEGY_INIT, {0}, -1 }; + +struct submodule_cache; +struct repository; + +extern void submodule_cache_free(struct submodule_cache *cache); + +extern int parse_submodule_fetchjobs(const char *var, const char *value); extern int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg); +struct option; +extern int option_fetch_parse_recurse_submodules(const struct option *opt, + const char *arg, int unset); extern int parse_update_recurse_submodules_arg(const char *opt, const char *arg); extern int parse_push_recurse_submodules_arg(const char *opt, const char *arg); -extern int parse_submodule_config_option(const char *var, const char *value); +extern void repo_read_gitmodules(struct repository *repo); +extern void gitmodules_config_oid(const struct object_id *commit_oid); extern const struct submodule *submodule_from_name( - const unsigned char *commit_or_tree, const char *name); + const struct object_id *commit_or_tree, const char *name); extern const struct submodule *submodule_from_path( - const unsigned char *commit_or_tree, const char *path); -extern int gitmodule_sha1_from_commit(const unsigned char *commit_sha1, - unsigned char *gitmodules_sha1, - struct strbuf *rev); + const struct object_id *commit_or_tree, const char *path); +extern const struct submodule *submodule_from_cache(struct repository *repo, + const struct object_id *treeish_name, + const char *key); extern void submodule_free(void); + /* + * Returns 0 if the name is syntactically acceptable as a submodule "name" + * (e.g., that may be found in the subsection of a .gitmodules file) and -1 + * otherwise. + */ + int check_submodule_name(const char *name); + #endif /* SUBMODULE_CONFIG_H */ diff --cc t/helper/test-path-utils.c index 2b3c5092a1,77517a43ed..94846550f7 --- a/t/helper/test-path-utils.c +++ b/t/helper/test-path-utils.c @@@ -265,11 -257,25 +271,25 @@@ int cmd_main(int argc, const char **arg } if (argc == 2 && !strcmp(argv[1], "basename")) - return test_function(basename_data, basename, argv[1]); + return test_function(basename_data, posix_basename, argv[1]); if (argc == 2 && !strcmp(argv[1], "dirname")) - return test_function(dirname_data, dirname, argv[1]); + return test_function(dirname_data, posix_dirname, argv[1]); + if (argc > 2 && !strcmp(argv[1], "is_dotgitmodules")) { + int res = 0, expect = 1, i; + for (i = 2; i < argc; i++) + if (!strcmp("--not", argv[i])) + expect = !expect; + else if (expect != is_dotgitmodules(argv[i])) + res = error("'%s' is %s.gitmodules", argv[i], + expect ? "not " : ""); + else + fprintf(stderr, "ok: '%s' is %s.gitmodules\n", + argv[i], expect ? "" : "not "); + return !!res; + } + fprintf(stderr, "%s: unknown function name: %s\n", argv[0], argv[1] ? argv[1] : "(there was none)"); return 1;