* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+
+#include "patch_generate.h"
+
#include "git2/blob.h"
#include "diff.h"
#include "diff_generate.h"
#include "diff_file.h"
#include "diff_driver.h"
-#include "patch_generate.h"
#include "diff_xdiff.h"
#include "delta.h"
#include "zstream.h"
-#include "fileops.h"
+#include "futils.h"
static void diff_output_init(
git_patch_generated_output *, const git_diff_options *, git_diff_file_cb,
const git_diff_options *opts)
{
if (opts) {
- GITERR_CHECK_VERSION(opts, GIT_DIFF_OPTIONS_VERSION, "git_diff_options");
+ GIT_ERROR_CHECK_VERSION(opts, GIT_DIFF_OPTIONS_VERSION, "git_diff_options");
memcpy(out, opts, sizeof(git_diff_options));
} else {
git_diff_options default_opts = GIT_DIFF_OPTIONS_INIT;
git__strdup(opts->new_prefix) :
git__strdup(DIFF_NEW_PREFIX_DEFAULT);
- GITERR_CHECK_ALLOC(out->old_prefix);
- GITERR_CHECK_ALLOC(out->new_prefix);
+ GIT_ERROR_CHECK_ALLOC(out->old_prefix);
+ GIT_ERROR_CHECK_ALLOC(out->new_prefix);
return 0;
}
{
int error;
git_patch_generated *patch = git__calloc(1, sizeof(git_patch_generated));
- GITERR_CHECK_ALLOC(patch);
+ GIT_ERROR_CHECK_ALLOC(patch);
if (!(error = patch_generated_init(patch, diff, delta_index))) {
patch->flags |= GIT_PATCH_GENERATED_ALLOCATED;
- GIT_REFCOUNT_INC(patch);
+ GIT_REFCOUNT_INC(&patch->base);
} else {
git__free(patch);
patch = NULL;
((patch->nfile.flags & GIT_DIFF_FLAG__NO_DATA) != 0 ||
(patch->nfile.file->flags & GIT_DIFF_FLAG_VALID_ID) != 0));
- /* always try to load workdir content first because filtering may
- * need 2x data size and this minimizes peak memory footprint
- */
- if (patch->ofile.src == GIT_ITERATOR_TYPE_WORKDIR) {
- if ((error = git_diff_file_content__load(
- &patch->ofile, &patch->base.diff_opts)) < 0 ||
- should_skip_binary(patch, patch->ofile.file))
- goto cleanup;
- }
- if (patch->nfile.src == GIT_ITERATOR_TYPE_WORKDIR) {
- if ((error = git_diff_file_content__load(
- &patch->nfile, &patch->base.diff_opts)) < 0 ||
- should_skip_binary(patch, patch->nfile.file))
- goto cleanup;
- }
-
- /* once workdir has been tried, load other data as needed */
- if (patch->ofile.src != GIT_ITERATOR_TYPE_WORKDIR) {
- if ((error = git_diff_file_content__load(
- &patch->ofile, &patch->base.diff_opts)) < 0 ||
- should_skip_binary(patch, patch->ofile.file))
- goto cleanup;
- }
- if (patch->nfile.src != GIT_ITERATOR_TYPE_WORKDIR) {
- if ((error = git_diff_file_content__load(
- &patch->nfile, &patch->base.diff_opts)) < 0 ||
- should_skip_binary(patch, patch->nfile.file))
- goto cleanup;
- }
+ if ((error = git_diff_file_content__load(
+ &patch->ofile, &patch->base.diff_opts)) < 0 ||
+ (error = git_diff_file_content__load(
+ &patch->nfile, &patch->base.diff_opts)) < 0 ||
+ should_skip_binary(patch, patch->nfile.file))
+ goto cleanup;
/* if previously missing an oid, and now that we have it the two sides
* are the same (and not submodules), update MODIFIED -> UNMODIFIED
if (!output->file_cb)
return 0;
- return giterr_set_after_callback_function(
+ return git_error_set_after_callback_function(
output->file_cb(patch->base.delta, progress, output->payload),
"git_patch");
}
const char *b_data,
size_t b_datalen)
{
- git_buf deflate = GIT_BUF_INIT, delta = GIT_BUF_INIT;
+ git_str deflate = GIT_STR_INIT, delta = GIT_STR_INIT;
size_t delta_data_len = 0;
int error;
if (delta.size && delta.size < deflate.size) {
*out_type = GIT_DIFF_BINARY_DELTA;
*out_datalen = delta.size;
- *out_data = git_buf_detach(&delta);
+ *out_data = git_str_detach(&delta);
*out_inflatedlen = delta_data_len;
} else {
*out_type = GIT_DIFF_BINARY_LITERAL;
*out_datalen = deflate.size;
- *out_data = git_buf_detach(&deflate);
+ *out_data = git_str_detach(&deflate);
*out_inflatedlen = b_datalen;
}
done:
- git_buf_free(&deflate);
- git_buf_free(&delta);
+ git_str_dispose(&deflate);
+ git_str_dispose(&delta);
return error;
}
return error;
}
- error = giterr_set_after_callback_function(
+ error = git_error_set_after_callback_function(
output->binary_cb(patch->base.delta, &binary, output->payload),
"git_patch");
{
if (diff)
return 0;
- giterr_set(GITERR_INVALID, "Must provide valid diff to %s", action);
+ git_error_set(GIT_ERROR_INVALID, "must provide valid diff to %s", action);
return -1;
}
-int git_diff_foreach(
- git_diff *diff,
- git_diff_file_cb file_cb,
- git_diff_binary_cb binary_cb,
- git_diff_hunk_cb hunk_cb,
- git_diff_line_cb data_cb,
- void *payload)
-{
- int error = 0;
- git_xdiff_output xo;
- size_t idx;
- git_patch_generated patch;
-
- if ((error = diff_required(diff, "git_diff_foreach")) < 0)
- return error;
-
- memset(&xo, 0, sizeof(xo));
- memset(&patch, 0, sizeof(patch));
- diff_output_init(
- &xo.output, &diff->opts, file_cb, binary_cb, hunk_cb, data_cb, payload);
- git_xdiff_init(&xo, &diff->opts);
-
- git_vector_foreach(&diff->deltas, idx, patch.base.delta) {
-
- /* check flags against patch status */
- if (git_diff_delta__should_skip(&diff->opts, patch.base.delta))
- continue;
-
- if (binary_cb || hunk_cb || data_cb) {
- if ((error = patch_generated_init(&patch, diff, idx)) != 0 ||
- (error = patch_generated_load(&patch, &xo.output)) != 0)
- return error;
- }
-
- if ((error = patch_generated_invoke_file_callback(&patch, &xo.output)) == 0) {
- if (binary_cb || hunk_cb || data_cb)
- error = patch_generated_create(&patch, &xo.output);
- }
-
- git_patch_free(&patch.base);
-
- if (error)
- break;
- }
-
- return error;
-}
-
typedef struct {
git_patch_generated patch;
git_diff_delta delta;
size_t new_len = *new_path ? strlen(*new_path) : 0;
size_t alloc_len;
- GITERR_CHECK_ALLOC_ADD(&alloc_len, sizeof(*pd), old_len);
- GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, new_len);
- GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
+ GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, sizeof(*pd), old_len);
+ GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, new_len);
+ GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
*out = pd = git__calloc(1, alloc_len);
- GITERR_CHECK_ALLOC(pd);
+ GIT_ERROR_CHECK_ALLOC(pd);
pd->patch.flags = GIT_PATCH_GENERATED_ALLOCATED;
patch_generated_with_delta *pd;
git_xdiff_output xo;
- assert(out);
+ GIT_ASSERT_ARG(out);
*out = NULL;
if ((error = patch_generated_with_delta_alloc(
git_patch **out,
const git_blob *old_blob,
const char *old_path,
- const char *buf,
+ const void *buf,
size_t buflen,
const char *buf_path,
const git_diff_options *opts)
const void *old_buf,
size_t old_len,
const char *old_path,
- const char *new_buf,
+ const void *new_buf,
size_t new_len,
const char *new_path,
const git_diff_options *opts)
delta = git_vector_get(&diff->deltas, idx);
if (!delta) {
- giterr_set(GITERR_INVALID, "Index out of range for delta in diff");
+ git_error_set(GIT_ERROR_INVALID, "index out of range for delta in diff");
return GIT_ENOTFOUND;
}
return patch->ofile.driver;
}
-void git_patch_generated_old_data(
- char **ptr, size_t *len, git_patch_generated *patch)
+int git_patch_generated_old_data(
+ char **ptr, long *len, git_patch_generated *patch)
{
+ if (patch->ofile.map.len > LONG_MAX ||
+ patch->ofile.map.len > GIT_XDIFF_MAX_SIZE) {
+ git_error_set(GIT_ERROR_INVALID, "files too large for diff");
+ return -1;
+ }
+
*ptr = patch->ofile.map.data;
- *len = patch->ofile.map.len;
+ *len = (long)patch->ofile.map.len;
+
+ return 0;
}
-void git_patch_generated_new_data(
- char **ptr, size_t *len, git_patch_generated *patch)
+int git_patch_generated_new_data(
+ char **ptr, long *len, git_patch_generated *patch)
{
+ if (patch->ofile.map.len > LONG_MAX ||
+ patch->ofile.map.len > GIT_XDIFF_MAX_SIZE) {
+ git_error_set(GIT_ERROR_INVALID, "files too large for diff");
+ return -1;
+ }
+
*ptr = patch->nfile.map.data;
- *len = patch->nfile.map.len;
+ *len = (long)patch->nfile.map.len;
+
+ return 0;
}
static int patch_generated_file_cb(
if (binary->old_file.data) {
patch->binary.old_file.data = git__malloc(binary->old_file.datalen);
- GITERR_CHECK_ALLOC(patch->binary.old_file.data);
+ GIT_ERROR_CHECK_ALLOC(patch->binary.old_file.data);
memcpy((char *)patch->binary.old_file.data,
binary->old_file.data, binary->old_file.datalen);
if (binary->new_file.data) {
patch->binary.new_file.data = git__malloc(binary->new_file.datalen);
- GITERR_CHECK_ALLOC(patch->binary.new_file.data);
+ GIT_ERROR_CHECK_ALLOC(patch->binary.new_file.data);
memcpy((char *)patch->binary.new_file.data,
binary->new_file.data, binary->new_file.datalen);
GIT_UNUSED(delta);
hunk = git_array_alloc(patch->base.hunks);
- GITERR_CHECK_ALLOC(hunk);
+ GIT_ERROR_CHECK_ALLOC(hunk);
memcpy(&hunk->hunk, hunk_, sizeof(hunk->hunk));
{
git_patch_generated *patch = payload;
git_patch_hunk *hunk;
- git_diff_line *line;
+ git_diff_line *line;
GIT_UNUSED(delta);
GIT_UNUSED(hunk_);
hunk = git_array_last(patch->base.hunks);
- assert(hunk); /* programmer error if no hunk is available */
+ GIT_ASSERT(hunk); /* programmer error if no hunk is available */
line = git_array_alloc(patch->base.lines);
- GITERR_CHECK_ALLOC(line);
+ GIT_ERROR_CHECK_ALLOC(line);
memcpy(line, line_, sizeof(*line));