static int diff_file_content_load_workdir_file( git_diff_file_content *fc, git_buf *path) { int error = 0; git_vector filters = GIT_VECTOR_INIT; git_buf raw = GIT_BUF_INIT, filtered = GIT_BUF_INIT; git_file fd = git_futils_open_ro(git_buf_cstr(path)); if (fd < 0) return fd; if (!fc->file->size && !(fc->file->size = git_futils_filesize(fd))) goto cleanup; if (diff_file_content_binary_by_size(fc)) goto cleanup; if ((error = git_filters_load( &filters, fc->repo, fc->file->path, GIT_FILTER_TO_ODB)) < 0) goto cleanup; /* error >= is a filter count */ if (error == 0) { if (!(error = git_futils_mmap_ro( &fc->map, fd, 0, (size_t)fc->file->size))) fc->flags |= GIT_DIFF_FLAG__UNMAP_DATA; else /* fall through to try readbuffer below */ giterr_clear(); } if (error != 0) { error = git_futils_readbuffer_fd(&raw, fd, (size_t)fc->file->size); if (error < 0) goto cleanup; if (!filters.length) git_buf_swap(&filtered, &raw); else error = git_filters_apply(&filtered, &raw, &filters); if (!error) { fc->map.len = git_buf_len(&filtered); fc->map.data = git_buf_detach(&filtered); fc->flags |= GIT_DIFF_FLAG__FREE_DATA; } git_buf_free(&raw); git_buf_free(&filtered); } cleanup: git_filters_free(&filters); p_close(fd); return error; }
static int expandPerCentF(git_buf *buf, const char *replaceWith) { ssize_t foundPercentage = git_buf_find(buf, '%'); if (foundPercentage) { git_buf expanded = GIT_BUF_INIT; const char *end = buf->ptr + buf->size; const char *lastPercentage = buf->ptr; const char *idx = buf->ptr + foundPercentage; while (idx < end) { if (*idx == '%') { if (idx + 1 == end || (idx + 1 < end && *(idx + 1) == '%')) { // one '%' is at the end of the string OR "%%" is in the string git_buf_putc(&expanded, '%'); ++idx; ++idx; lastPercentage = idx; continue; } // now we know, that we're not at the end of the string and that the next char is not '%' git_buf_put(&expanded, lastPercentage, idx - lastPercentage); ++idx; if (*idx == 'f') git_buf_printf(&expanded, "\"%s\"", replaceWith); ++idx; lastPercentage = idx; continue; } ++idx; } if (lastPercentage) git_buf_put(&expanded, lastPercentage, idx - lastPercentage); if (git_buf_oom(&expanded)) { giterr_set_oom(); return -1; } git_buf_swap(buf, &expanded); git_buf_free(&expanded); } return 0; }
/* test swap */ void test_core_buffer__6(void) { git_buf a = GIT_BUF_INIT; git_buf b = GIT_BUF_INIT; git_buf_sets(&a, "foo"); cl_assert(git_buf_oom(&a) == 0); git_buf_sets(&b, "bar"); cl_assert(git_buf_oom(&b) == 0); cl_assert_equal_s("foo", git_buf_cstr(&a)); cl_assert_equal_s("bar", git_buf_cstr(&b)); git_buf_swap(&a, &b); cl_assert_equal_s("bar", git_buf_cstr(&a)); cl_assert_equal_s("foo", git_buf_cstr(&b)); git_buf_free(&a); git_buf_free(&b); }
int git_futils_dirs_set(git_futils_dir_t which, const char *search_path) { const char *expand_path = NULL; git_buf merge = GIT_BUF_INIT; GITERR_CHECK_ERROR(git_futils_check_selector(which)); if (search_path != NULL) expand_path = strstr(search_path, PATH_MAGIC); /* init with default if not yet done and needed (ignoring error) */ if ((!search_path || expand_path) && !git_buf_len(&git_futils__dirs[which])) git_futils__dir_guess[which](&git_futils__dirs[which]); /* if $PATH is not referenced, then just set the path */ if (!expand_path) return git_buf_sets(&git_futils__dirs[which], search_path); /* otherwise set to join(before $PATH, old value, after $PATH) */ if (expand_path > search_path) git_buf_set(&merge, search_path, expand_path - search_path); if (git_buf_len(&git_futils__dirs[which])) git_buf_join(&merge, GIT_PATH_LIST_SEPARATOR, merge.ptr, git_futils__dirs[which].ptr); expand_path += strlen(PATH_MAGIC); if (*expand_path) git_buf_join(&merge, GIT_PATH_LIST_SEPARATOR, merge.ptr, expand_path); git_buf_swap(&git_futils__dirs[which], &merge); git_buf_free(&merge); return git_buf_oom(&git_futils__dirs[which]) ? -1 : 0; }
static int filter_apply( git_filter *self, void **payload, /* may be read and/or set */ git_buf *to, const git_buf *from, const git_filter_source *src) { struct filter_filter *ffs = (struct filter_filter *)self; git_config *config; git_buf configKey = GIT_BUF_INIT; int isRequired = FALSE; int error; const char *cmd = NULL; git_buf cmdBuf = GIT_BUF_INIT; wchar_t *wide_cmd; COMMAND_HANDLE commandHandle = COMMAND_HANDLE_INIT; git_buf errBuf = GIT_BUF_INIT; DWORD exitCode; if (!*payload) return GIT_PASSTHROUGH; if (git_repository_config__weakptr(&config, git_filter_source_repo(src))) return -1; git_buf_join3(&configKey, '.', "filter", *payload, "required"); if (git_buf_oom(&configKey)) { giterr_set_oom(); return -1; } error = git_config_get_bool(&isRequired, config, configKey.ptr); git_buf_free(&configKey); if (error && error != GIT_ENOTFOUND) return -1; git_buf_join(&configKey, '.', "filter", *payload); if (git_filter_source_mode(src) == GIT_FILTER_SMUDGE) { git_buf_puts(&configKey, ".smudge"); } else { git_buf_puts(&configKey, ".clean"); } if (git_buf_oom(&configKey)) { giterr_set_oom(); return -1; } error = git_config_get_string(&cmd, config, configKey.ptr); git_buf_free(&configKey); if (error && error != GIT_ENOTFOUND) return -1; if (error == GIT_ENOTFOUND) { if (isRequired) return -1; return GIT_PASSTHROUGH; } git_buf_puts(&cmdBuf, cmd); if (git_buf_oom(&cmdBuf)) { giterr_set_oom(); return -1; } if (expandPerCentF(&cmdBuf, git_filter_source_path(src))) return -1; if (ffs->shexepath) { // build params for sh.exe git_buf shParams = GIT_BUF_INIT; git_buf_puts(&shParams, " -c \""); git_buf_text_puts_escaped(&shParams, cmdBuf.ptr, "\"\\", "\\"); git_buf_puts(&shParams, "\""); if (git_buf_oom(&shParams)) { git_buf_free(&cmdBuf); giterr_set_oom(); return -1; } git_buf_swap(&shParams, &cmdBuf); git_buf_free(&shParams); } if (git__utf8_to_16_alloc(&wide_cmd, cmdBuf.ptr) < 0) { git_buf_free(&cmdBuf); giterr_set_oom(); return -1; } git_buf_free(&cmdBuf); if (ffs->shexepath) { // build cmd, i.e. shexepath + params size_t len = wcslen(ffs->shexepath) + wcslen(wide_cmd) + 1; wchar_t *tmp = git__calloc(len, sizeof(wchar_t)); if (!tmp) { git__free(wide_cmd); giterr_set_oom(); return -1; } wcscat_s(tmp, len, ffs->shexepath); wcscat_s(tmp, len, wide_cmd); git__free(wide_cmd); wide_cmd = tmp; } commandHandle.errBuf = &errBuf; if (command_start(wide_cmd, &commandHandle, ffs->pEnv)) { git__free(wide_cmd); if (isRequired) return -1; return GIT_PASSTHROUGH; } git__free(wide_cmd); if (commmand_start_stdout_reading_thread(&commandHandle, to)) { command_close(&commandHandle); return -1; } if (command_write_gitbuf(&commandHandle, from)) { DWORD exitCode = command_close(&commandHandle); if (exitCode) setProcessError(exitCode, &errBuf); git_buf_free(&errBuf); if (isRequired) return -1; return GIT_PASSTHROUGH; } command_close_stdin(&commandHandle); if (command_wait_stdout_reading_thread(&commandHandle)) { DWORD exitCode = command_close(&commandHandle); if (exitCode) setProcessError(exitCode, &errBuf); git_buf_free(&errBuf); if (isRequired) return -1; return GIT_PASSTHROUGH; } exitCode = command_close(&commandHandle); if (exitCode) { if (isRequired) { setProcessError(exitCode, &errBuf); git_buf_free(&errBuf); return -1; } git_buf_free(&errBuf); return GIT_PASSTHROUGH; } git_buf_free(&errBuf); return 0; }
int git_futils_readbuffer_updated( git_buf *out, const char *path, git_oid *checksum, int *updated) { int error; git_file fd; struct stat st; git_buf buf = GIT_BUF_INIT; git_oid checksum_new; assert(out && path && *path); if (updated != NULL) *updated = 0; if (p_stat(path, &st) < 0) return git_path_set_error(errno, path, "stat"); if (S_ISDIR(st.st_mode)) { giterr_set(GITERR_INVALID, "requested file is a directory"); return GIT_ENOTFOUND; } if (!git__is_sizet(st.st_size+1)) { giterr_set(GITERR_OS, "invalid regular file stat for '%s'", path); return -1; } if ((fd = git_futils_open_ro(path)) < 0) return fd; if (git_futils_readbuffer_fd(&buf, fd, (size_t)st.st_size) < 0) { p_close(fd); return -1; } p_close(fd); if (checksum) { if ((error = git_hash_buf(&checksum_new, buf.ptr, buf.size)) < 0) { git_buf_free(&buf); return error; } /* * If we were given a checksum, we only want to use it if it's different */ if (!git_oid__cmp(checksum, &checksum_new)) { git_buf_free(&buf); if (updated) *updated = 0; return 0; } git_oid_cpy(checksum, &checksum_new); } /* * If we're here, the file did change, or the user didn't have an old version */ if (updated != NULL) *updated = 1; git_buf_swap(out, &buf); git_buf_free(&buf); return 0; }
static int find_repo( git_buf *repo_path, git_buf *parent_path, const char *start_path, uint32_t flags, const char *ceiling_dirs) { int error; git_buf path = GIT_BUF_INIT; struct stat st; dev_t initial_device = 0; bool try_with_dot_git = ((flags & GIT_REPOSITORY_OPEN_BARE) != 0); int ceiling_offset; git_buf_free(repo_path); if ((error = git_path_prettify(&path, start_path, NULL)) < 0) return error; ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs); if (!try_with_dot_git && (error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0) return error; while (!error && !git_buf_len(repo_path)) { if (p_stat(path.ptr, &st) == 0) { /* check that we have not crossed device boundaries */ if (initial_device == 0) initial_device = st.st_dev; else if (st.st_dev != initial_device && (flags & GIT_REPOSITORY_OPEN_CROSS_FS) == 0) break; if (S_ISDIR(st.st_mode)) { if (valid_repository_path(&path)) { git_path_to_dir(&path); git_buf_set(repo_path, path.ptr, path.size); break; } } else if (S_ISREG(st.st_mode)) { git_buf repo_link = GIT_BUF_INIT; if (!(error = read_gitfile(&repo_link, path.ptr))) { if (valid_repository_path(&repo_link)) git_buf_swap(repo_path, &repo_link); git_buf_free(&repo_link); break; } git_buf_free(&repo_link); } } /* move up one directory level */ if (git_path_dirname_r(&path, path.ptr) < 0) { error = -1; break; } if (try_with_dot_git) { /* if we tried original dir with and without .git AND either hit * directory ceiling or NO_SEARCH was requested, then be done. */ if (path.ptr[ceiling_offset] == '\0' || (flags & GIT_REPOSITORY_OPEN_NO_SEARCH) != 0) break; /* otherwise look first for .git item */ error = git_buf_joinpath(&path, path.ptr, DOT_GIT); } try_with_dot_git = !try_with_dot_git; } if (!error && parent_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) { if (!git_buf_len(repo_path)) git_buf_clear(parent_path); else { git_path_dirname_r(parent_path, path.ptr); git_path_to_dir(parent_path); } if (git_buf_oom(parent_path)) return -1; } git_buf_free(&path); if (!git_buf_len(repo_path) && !error) { giterr_set(GITERR_REPOSITORY, "Could not find repository from '%s'", start_path); error = GIT_ENOTFOUND; } return error; }