Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 34 additions & 58 deletions src/path.c
Original file line number Diff line number Diff line change
Expand Up @@ -1766,14 +1766,14 @@ static bool verify_component(
if (flags & GIT_PATH_REJECT_DOT_GIT_HFS) {
if (!verify_dotgit_hfs(component, len))
return false;
if (S_ISLNK(mode) && git_path_is_hfs_dotgit_modules(component, len))
if (S_ISLNK(mode) && git_path_is_gitfile(component, len, GIT_PATH_GITFILE_GITMODULES, GIT_PATH_FS_HFS))
return false;
}

if (flags & GIT_PATH_REJECT_DOT_GIT_NTFS) {
if (!verify_dotgit_ntfs(repo, component, len))
return false;
if (S_ISLNK(mode) && git_path_is_ntfs_dotgit_modules(component, len))
if (S_ISLNK(mode) && git_path_is_gitfile(component, len, GIT_PATH_GITFILE_GITMODULES, GIT_PATH_FS_NTFS))
return false;
}

Expand Down Expand Up @@ -1872,64 +1872,40 @@ int git_path_normalize_slashes(git_buf *out, const char *path)
return 0;
}

static int verify_dotgit_generic(const char *name, size_t len, const char *dotgit_name, size_t dotgit_len, const char *shortname_pfix)
{
if (!verify_dotgit_ntfs_generic(name, len, dotgit_name, dotgit_len, shortname_pfix))
return false;

return verify_dotgit_hfs_generic(name, len, dotgit_name, dotgit_len);
}

int git_path_is_ntfs_dotgit_modules(const char *name, size_t len)
{
return !verify_dotgit_ntfs_generic(name, len, "gitmodules", CONST_STRLEN("gitmodules"), "gi7eba");
}

int git_path_is_hfs_dotgit_modules(const char *name, size_t len)
{
return !verify_dotgit_hfs_generic(name, len, "gitmodules", CONST_STRLEN("gitmodules"));
}

int git_path_is_dotgit_modules(const char *name, size_t len)
{
if (git_path_is_hfs_dotgit_modules(name, len))
return 1;

return git_path_is_ntfs_dotgit_modules(name, len);
}

int git_path_is_ntfs_dotgit_ignore(const char *name, size_t len)
{
return !verify_dotgit_ntfs_generic(name, len, "gitignore", CONST_STRLEN("gitignore"), "gi250a");
}
static const struct {
const char *file;
const char *hash;
size_t filelen;
} gitfiles[] = {
{ "gitignore", "gi250a", CONST_STRLEN("gitignore") },
{ "gitmodules", "gi7eba", CONST_STRLEN("gitmodules") },
{ "gitattributes", "gi7d29", CONST_STRLEN("gitattributes") }
};

int git_path_is_hfs_dotgit_ignore(const char *name, size_t len)
extern int git_path_is_gitfile(const char *path, size_t pathlen, git_path_gitfile gitfile, git_path_fs fs)
{
return !verify_dotgit_hfs_generic(name, len, "gitignore", CONST_STRLEN("gitignore"));
}

int git_path_is_dotgit_ignore(const char *name, size_t len)
{
if (git_path_is_hfs_dotgit_ignore(name, len))
return 1;

return git_path_is_ntfs_dotgit_ignore(name, len);
}
const char *file, *hash;
size_t filelen;

int git_path_is_hfs_dotgit_attributes(const char *name, size_t len)
{
return !verify_dotgit_hfs_generic(name, len, "gitattributes", CONST_STRLEN("gitattributes"));
}

int git_path_is_ntfs_dotgit_attributes(const char *name, size_t len)
{
return !verify_dotgit_ntfs_generic(name, len, "gitattributes", CONST_STRLEN("gitattributes"), "gi7d29");
}

int git_path_is_dotgit_attributes(const char *name, size_t len)
{
if (git_path_is_hfs_dotgit_attributes(name, len))
return 1;
if (gitfile < 0 && gitfile >= ARRAY_SIZE(gitfiles)) {
giterr_set(GITERR_OS, "invalid gitfile for path validation");
return -1;
}

return git_path_is_ntfs_dotgit_attributes(name, len);
file = gitfiles[gitfile].file;
filelen = gitfiles[gitfile].filelen;
hash = gitfiles[gitfile].hash;

switch (fs) {
case GIT_PATH_FS_GENERIC:
return !verify_dotgit_ntfs_generic(path, pathlen, file, filelen, hash) ||
!verify_dotgit_hfs_generic(path, pathlen, file, filelen);
case GIT_PATH_FS_NTFS:
return !verify_dotgit_ntfs_generic(path, pathlen, file, filelen, hash);
case GIT_PATH_FS_HFS:
return !verify_dotgit_hfs_generic(path, pathlen, file, filelen);
default:
giterr_set(GITERR_OS, "invalid filesystem for path validation");
return -1;
}
}
108 changes: 37 additions & 71 deletions src/path.h
Original file line number Diff line number Diff line change
Expand Up @@ -645,76 +645,42 @@ extern bool git_path_isvalid(
*/
int git_path_normalize_slashes(git_buf *out, const char *path);

/**
* Check whether a path component corresponds to a .gitmodules file
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_dotgit_modules(const char *name, size_t len);

/**
* Check whether a path component corresponds to a .gitmodules file in NTFS
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_ntfs_dotgit_modules(const char *name, size_t len);

/**
* Check whether a path component corresponds to a .gitmodules file in HFS+
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_hfs_dotgit_modules(const char *name, size_t len);

/**
* Check whether a path component corresponds to a .gitignore file
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_dotgit_ignore(const char *name, size_t len);

/**
* Check whether a path component corresponds to a .gitignore file in NTFS
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_ntfs_dotgit_ignore(const char *name, size_t len);

/**
* Check whether a path component corresponds to a .gitignore file in HFS+
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_hfs_dotgit_ignore(const char *name, size_t len);

/**
* Check whether a path component corresponds to a .gitignore file
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_dotgit_attributes(const char *name, size_t len);

/**
* Check whether a path component corresponds to a .gitattributes file in NTFS
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_ntfs_dotgit_attributes(const char *name, size_t len);

/**
* Check whether a path component corresponds to a .gitattributes file in HFS+
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_hfs_dotgit_attributes(const char *name, size_t len);
/*
* The order needs to stay the same to not break the `gitfiles`
* array in path.c
*/
typedef enum {
GIT_PATH_GITFILE_GITIGNORE,
GIT_PATH_GITFILE_GITMODULES,
GIT_PATH_GITFILE_GITATTRIBUTES
} git_path_gitfile;

typedef enum {
/* Do both NTFS- and HFS-specific checks */
GIT_PATH_FS_GENERIC,
/* Do NTFS-specific checks only */
GIT_PATH_FS_NTFS,
/* Do HFS-specific checks only */
GIT_PATH_FS_HFS
} git_path_fs;

/**
* Check whether a path component corresponds to a .git$SUFFIX
* file.
*
* As some filesystems do special things to filenames when
* writing files to disk, you cannot always do a plain string
* comparison to verify whether a file name matches an expected
* path or not. This function can do the comparison for you,
* depending on the filesystem you're on.
*
* @param path the path component to check
* @param pathlen the length of `path` that is to be checked
* @param gitfile which file to check against
* @param fs which filesystem-specific checks to use
* @return 0 in case the file does not match, a positive value if
* it does; -1 in case of an error
*/
extern int git_path_is_gitfile(const char *path, size_t pathlen, git_path_gitfile gitfile, git_path_fs fs);

#endif
10 changes: 5 additions & 5 deletions tests/path/dotgit.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,21 +94,21 @@ static char *gitmodules_not_altnames[] = {
void test_path_dotgit__dotgit_modules(void)
{
size_t i;
cl_assert_equal_i(1, git_path_is_dotgit_modules(".gitmodules", strlen(".gitmodules")));
cl_assert_equal_i(1, git_path_is_dotgit_modules(".git\xe2\x80\x8cmodules", strlen(".git\xe2\x80\x8cmodules")));

cl_assert_equal_i(1, git_path_is_gitfile(".gitmodules", strlen(".gitmodules"), GIT_PATH_GITFILE_GITMODULES, GIT_PATH_FS_GENERIC));
cl_assert_equal_i(1, git_path_is_gitfile(".git\xe2\x80\x8cmodules", strlen(".git\xe2\x80\x8cmodules"), GIT_PATH_GITFILE_GITMODULES, GIT_PATH_FS_GENERIC));

for (i = 0; i < ARRAY_SIZE(gitmodules_altnames); i++) {
const char *name = gitmodules_altnames[i];
if (!git_path_is_dotgit_modules(name, strlen(name)))
if (!git_path_is_gitfile(name, strlen(name), GIT_PATH_GITFILE_GITMODULES, GIT_PATH_FS_GENERIC))
cl_fail(name);
}

for (i = 0; i < ARRAY_SIZE(gitmodules_not_altnames); i++) {
const char *name = gitmodules_not_altnames[i];
if (git_path_is_dotgit_modules(name, strlen(name)))
if (git_path_is_gitfile(name, strlen(name), GIT_PATH_GITFILE_GITMODULES, GIT_PATH_FS_GENERIC))
cl_fail(name);
}

}

void test_path_dotgit__dotgit_modules_symlink(void)
Expand Down