diff --git a/src/checkout.c b/src/checkout.c index c226f4342..85a817608 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -27,6 +27,7 @@ #include "pathspec.h" #include "buf_text.h" #include "merge_file.h" +#include "path.h" /* See docs/checkout-internals.md for more information */ @@ -887,29 +888,6 @@ done: return error; } -GIT_INLINE(void) path_equal_or_prefixed( - bool *path_eq, - bool *path_prefixed, - const char *parent, - const char *child) -{ - const char *p, *c; - - *path_eq = 0; - *path_prefixed = 0; - - for (p = parent, c = child; *p && *c; p++, c++) { - if (*p != *c) - return; - } - - if (!*p) - *path_prefixed = (*c == '/'); - - if (!*p && !*c) - *path_eq = 1; -} - static int checkout_conflicts_mark_directoryfile( checkout_data *data) { @@ -917,8 +895,7 @@ static int checkout_conflicts_mark_directoryfile( const git_index_entry *entry; size_t i, j, len; const char *path; - bool eq, prefixed; - int error = 0; + int prefixed, error = 0; len = git_index_entrycount(data->index); @@ -947,12 +924,12 @@ static int checkout_conflicts_mark_directoryfile( goto done; } - path_equal_or_prefixed(&eq, &prefixed, path, entry->path); + prefixed = git_path_equal_or_prefixed(path, entry->path); - if (eq) + if (prefixed == GIT_PATH_EQUAL) continue; - if (prefixed) + if (prefixed == GIT_PATH_PREFIX) conflict->directoryfile = 1; break; @@ -1055,8 +1032,6 @@ static int checkout_get_actions( counts[CHECKOUT_ACTION__UPDATE_CONFLICT] = git_vector_length(&data->conflicts); - /* HERE */ - git_pathspec__vfree(&pathspec); git_pool_clear(&pathpool); @@ -1257,7 +1232,7 @@ static int checkout_submodule( return checkout_submodule_update_index(data, file); } -void report_progress( +static void report_progress( checkout_data *data, const char *path) { @@ -1267,7 +1242,7 @@ void report_progress( data->opts.progress_payload); } -int git_checkout__safe_for_update_only(const char *path, mode_t expected_mode) +static int checkout_safe_for_update_only(const char *path, mode_t expected_mode) { struct stat st; @@ -1288,7 +1263,7 @@ int git_checkout__safe_for_update_only(const char *path, mode_t expected_mode) return 0; } -int git_checkout__write_content( +static int checkout_write_content( checkout_data *data, const git_oid *oid, const char *full_path, @@ -1337,13 +1312,13 @@ static int checkout_blob( return -1; if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0) { - int rval = git_checkout__safe_for_update_only( + int rval = checkout_safe_for_update_only( git_buf_cstr(&data->path), file->mode); if (rval <= 0) return rval; } - error = git_checkout__write_content( + error = checkout_write_content( data, &file->oid, git_buf_cstr(&data->path), NULL, file->mode, &st); /* update the index unless prevented */ @@ -1593,10 +1568,10 @@ static int checkout_write_entry( } if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 && - (error = git_checkout__safe_for_update_only(git_buf_cstr(&data->path), side->mode)) <= 0) + (error = checkout_safe_for_update_only(git_buf_cstr(&data->path), side->mode)) <= 0) return error; - return git_checkout__write_content(data, + return checkout_write_content(data, &side->oid, git_buf_cstr(&data->path), hint_path, side->mode, &st); } @@ -1694,7 +1669,7 @@ static int checkout_write_merge( goto done; if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 && - (error = git_checkout__safe_for_update_only(git_buf_cstr(&path_workdir), result.mode)) <= 0) + (error = checkout_safe_for_update_only(git_buf_cstr(&path_workdir), result.mode)) <= 0) goto done; if ((error = git_futils_mkpath2file(path_workdir.ptr, 0755)) < 0 || diff --git a/src/path.h b/src/path.h index eaf94d486..17f4f7726 100644 --- a/src/path.h +++ b/src/path.h @@ -358,6 +358,34 @@ extern int git_path_dirload_with_stat( const char *end_stat, git_vector *contents); +enum { GIT_PATH_NOTEQUAL = 0, GIT_PATH_EQUAL = 1, GIT_PATH_PREFIX = 2 }; + +/* + * Determines if a path is equal to or potentially a child of another. + * @param parent The possible parent + * @param child The possible child + */ +GIT_INLINE(int) git_path_equal_or_prefixed( + const char *parent, + const char *child) +{ + const char *p = parent, *c = child; + + while (*p && *c) { + if (*p++ != *c++) + return GIT_PATH_NOTEQUAL; + } + + if (*p != '\0') + return GIT_PATH_NOTEQUAL; + if (*c == '\0') + return GIT_PATH_EQUAL; + if (*c == '/') + return GIT_PATH_PREFIX; + + return GIT_PATH_NOTEQUAL; +} + /* translate errno to libgit2 error code and set error message */ extern int git_path_set_error( int errno_value, const char *path, const char *action);