diff --git a/read-cache.c b/read-cache.c index a78b88a41bf..8a50ff66b30 100644 --- a/read-cache.c +++ b/read-cache.c @@ -849,6 +849,19 @@ struct cache_entry *make_empty_transient_cache_entry(size_t len, return xcalloc(1, cache_entry_size(len)); } +enum verify_path_result { + PATH_OK, + PATH_INVALID, + PATH_DIR_WITH_SEP, +}; + +static enum verify_path_result verify_path_internal(const char *, unsigned); + +int verify_path(const char *path, unsigned mode) +{ + return verify_path_internal(path, mode) == PATH_OK; +} + struct cache_entry *make_cache_entry(struct index_state *istate, unsigned int mode, const struct object_id *oid, @@ -859,7 +872,7 @@ struct cache_entry *make_cache_entry(struct index_state *istate, struct cache_entry *ce, *ret; int len; - if (!verify_path(path, mode)) { + if (verify_path_internal(path, mode) == PATH_INVALID) { error(_("invalid path '%s'"), path); return NULL; } @@ -993,60 +1006,62 @@ static int verify_dotfile(const char *rest, unsigned mode) return 1; } -int verify_path(const char *path, unsigned mode) +static enum verify_path_result verify_path_internal(const char *path, + unsigned mode) { char c = 0; if (has_dos_drive_prefix(path)) - return 0; + return PATH_INVALID; if (!is_valid_path(path)) - return 0; + return PATH_INVALID; goto inside; for (;;) { if (!c) - return 1; + return PATH_OK; if (is_dir_sep(c)) { inside: if (protect_hfs) { if (is_hfs_dotgit(path)) - return 0; + return PATH_INVALID; if (S_ISLNK(mode)) { if (is_hfs_dotgitmodules(path)) - return 0; + return PATH_INVALID; } } if (protect_ntfs) { #if defined GIT_WINDOWS_NATIVE || defined __CYGWIN__ if (c == '\\') - return 0; + return PATH_INVALID; #endif if (is_ntfs_dotgit(path)) - return 0; + return PATH_INVALID; if (S_ISLNK(mode)) { if (is_ntfs_dotgitmodules(path)) - return 0; + return PATH_INVALID; } } c = *path++; if ((c == '.' && !verify_dotfile(path, mode)) || is_dir_sep(c)) - return 0; + return PATH_INVALID; /* * allow terminating directory separators for * sparse directory entries. */ if (c == '\0') - return S_ISDIR(mode); + return S_ISDIR(mode) ? PATH_DIR_WITH_SEP : + PATH_INVALID; } else if (c == '\\' && protect_ntfs) { if (is_ntfs_dotgit(path)) - return 0; + return PATH_INVALID; if (S_ISLNK(mode)) { if (is_ntfs_dotgitmodules(path)) - return 0; + return PATH_INVALID; } } @@ -1349,7 +1364,7 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e if (!ok_to_add) return -1; - if (!verify_path(ce->name, ce->ce_mode)) + if (verify_path_internal(ce->name, ce->ce_mode) == PATH_INVALID) return error(_("invalid path '%s'"), ce->name); if (!skip_df_check && diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh index dd2cdcc1148..5390eec4e3b 100755 --- a/t/t3905-stash-include-untracked.sh +++ b/t/t3905-stash-include-untracked.sh @@ -422,4 +422,10 @@ test_expect_success 'stash show --{include,only}-untracked on stashes without un test_must_be_empty actual ' +test_expect_success 'stash -u ignores sub-repository' ' + test_when_finished "rm -rf sub-repo" && + git init sub-repo && + git stash -u +' + test_done