diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/checkout.c | 4 | ||||
-rw-r--r-- | src/diff.c | 132 | ||||
-rw-r--r-- | src/diff.h | 10 | ||||
-rw-r--r-- | src/diff_file.c | 4 | ||||
-rw-r--r-- | src/diff_file.h | 2 | ||||
-rw-r--r-- | src/diff_patch.c | 284 | ||||
-rw-r--r-- | src/diff_patch.h | 19 | ||||
-rw-r--r-- | src/diff_print.c | 241 | ||||
-rw-r--r-- | src/diff_tform.c | 81 | ||||
-rw-r--r-- | src/diff_xdiff.c | 122 | ||||
-rw-r--r-- | src/pathspec.c | 2 | ||||
-rw-r--r-- | src/reset.c | 11 | ||||
-rw-r--r-- | src/stash.c | 139 | ||||
-rw-r--r-- | src/status.c | 6 | ||||
-rw-r--r-- | src/status.h | 4 | ||||
-rw-r--r-- | src/submodule.c | 6 |
16 files changed, 549 insertions, 518 deletions
diff --git a/src/checkout.c b/src/checkout.c index 85a817608..662803725 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -46,7 +46,7 @@ enum { typedef struct { git_repository *repo; - git_diff_list *diff; + git_diff *diff; git_checkout_opts opts; bool opts_free_baseline; char *pfx; @@ -2006,7 +2006,7 @@ cleanup: (data.strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0) error = git_index_write(data.index); - git_diff_list_free(data.diff); + git_diff_free(data.diff); git_iterator_free(workdir); git_iterator_free(baseline); git__free(actions); diff --git a/src/diff.c b/src/diff.c index 39facce60..37bc737d6 100644 --- a/src/diff.c +++ b/src/diff.c @@ -21,7 +21,7 @@ (VAL) ? ((DIFF)->opts.flags | (FLAG)) : ((DIFF)->opts.flags & ~(VAL)) static git_diff_delta *diff_delta__alloc( - git_diff_list *diff, + git_diff *diff, git_delta_t status, const char *path) { @@ -50,7 +50,7 @@ static git_diff_delta *diff_delta__alloc( } static int diff_notify( - const git_diff_list *diff, + const git_diff *diff, const git_diff_delta *delta, const char *matched_pathspec) { @@ -62,7 +62,7 @@ static int diff_notify( } static int diff_delta__from_one( - git_diff_list *diff, + git_diff *diff, git_delta_t status, const git_index_entry *entry) { @@ -81,7 +81,7 @@ static int diff_delta__from_one( if (!git_pathspec__match( &diff->pathspec, entry->path, DIFF_FLAG_IS_SET(diff, GIT_DIFF_DISABLE_PATHSPEC_MATCH), - DIFF_FLAG_IS_SET(diff, GIT_DIFF_DELTAS_ARE_ICASE), + DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_CASE), &matched_pathspec, NULL)) return 0; @@ -90,6 +90,7 @@ static int diff_delta__from_one( /* This fn is just for single-sided diffs */ assert(status != GIT_DELTA_MODIFIED); + delta->nfiles = 1; if (delta->status == GIT_DELTA_DELETED) { delta->old_file.mode = entry->mode; @@ -120,7 +121,7 @@ static int diff_delta__from_one( } static int diff_delta__from_two( - git_diff_list *diff, + git_diff *diff, git_delta_t status, const git_index_entry *old_entry, uint32_t old_mode, @@ -148,6 +149,7 @@ static int diff_delta__from_two( delta = diff_delta__alloc(diff, status, canonical_path); GITERR_CHECK_ALLOC(delta); + delta->nfiles = 2; git_oid_cpy(&delta->old_file.oid, &old_entry->oid); delta->old_file.size = old_entry->file_size; @@ -181,7 +183,7 @@ static int diff_delta__from_two( } static git_diff_delta *diff_delta__last_for_item( - git_diff_list *diff, + git_diff *diff, const git_index_entry *item) { git_diff_delta *delta = git_vector_last(&diff->deltas); @@ -340,13 +342,13 @@ static const char *diff_mnemonic_prefix( return pfx; } -static git_diff_list *diff_list_alloc( +static git_diff *diff_list_alloc( git_repository *repo, git_iterator *old_iter, git_iterator *new_iter) { git_diff_options dflt = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = git__calloc(1, sizeof(git_diff_list)); + git_diff *diff = git__calloc(1, sizeof(git_diff)); if (!diff) return NULL; @@ -360,7 +362,7 @@ static git_diff_list *diff_list_alloc( if (git_vector_init(&diff->deltas, 0, git_diff_delta__cmp) < 0 || git_pool_init(&diff->pool, 1, 0) < 0) { - git_diff_list_free(diff); + git_diff_free(diff); return NULL; } @@ -368,14 +370,14 @@ static git_diff_list *diff_list_alloc( * the ignore_case bit set */ if (!git_iterator_ignore_case(old_iter) && !git_iterator_ignore_case(new_iter)) { - diff->opts.flags &= ~GIT_DIFF_DELTAS_ARE_ICASE; + diff->opts.flags &= ~GIT_DIFF_IGNORE_CASE; diff->strcomp = git__strcmp; diff->strncomp = git__strncmp; diff->pfxcomp = git__prefixcmp; diff->entrycomp = git_index_entry__cmp; } else { - diff->opts.flags |= GIT_DIFF_DELTAS_ARE_ICASE; + diff->opts.flags |= GIT_DIFF_IGNORE_CASE; diff->strcomp = git__strcasecmp; diff->strncomp = git__strncasecmp; @@ -389,7 +391,7 @@ static git_diff_list *diff_list_alloc( } static int diff_list_apply_options( - git_diff_list *diff, + git_diff *diff, const git_diff_options *opts) { git_config *cfg; @@ -399,9 +401,9 @@ static int diff_list_apply_options( if (opts) { /* copy user options (except case sensitivity info from iterators) */ - bool icase = DIFF_FLAG_IS_SET(diff, GIT_DIFF_DELTAS_ARE_ICASE); + bool icase = DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_CASE); memcpy(&diff->opts, opts, sizeof(diff->opts)); - DIFF_FLAG_SET(diff, GIT_DIFF_DELTAS_ARE_ICASE, icase); + DIFF_FLAG_SET(diff, GIT_DIFF_IGNORE_CASE, icase); /* initialize pathspec from options */ if (git_pathspec__vinit(&diff->pathspec, &opts->pathspec, pool) < 0) @@ -413,7 +415,7 @@ static int diff_list_apply_options( diff->opts.flags |= GIT_DIFF_INCLUDE_TYPECHANGE; /* flag INCLUDE_UNTRACKED_CONTENT implies INCLUDE_UNTRACKED */ - if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_UNTRACKED_CONTENT)) + if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_SHOW_UNTRACKED_CONTENT)) diff->opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED; /* load config values that affect diff behavior */ @@ -490,7 +492,7 @@ static int diff_list_apply_options( return 0; } -static void diff_list_free(git_diff_list *diff) +static void diff_list_free(git_diff *diff) { git_diff_delta *delta; unsigned int i; @@ -508,7 +510,7 @@ static void diff_list_free(git_diff_list *diff) git__free(diff); } -void git_diff_list_free(git_diff_list *diff) +void git_diff_free(git_diff *diff) { if (!diff) return; @@ -516,7 +518,7 @@ void git_diff_list_free(git_diff_list *diff) GIT_REFCOUNT_DEC(diff, diff_list_free); } -void git_diff_list_addref(git_diff_list *diff) +void git_diff_addref(git_diff *diff) { GIT_REFCOUNT_INC(diff); } @@ -612,7 +614,7 @@ typedef struct { static int maybe_modified_submodule( git_delta_t *status, git_oid *found_oid, - git_diff_list *diff, + git_diff *diff, diff_in_progress *info) { int error = 0; @@ -659,7 +661,7 @@ static int maybe_modified_submodule( } static int maybe_modified( - git_diff_list *diff, + git_diff *diff, diff_in_progress *info) { git_oid noid; @@ -674,7 +676,7 @@ static int maybe_modified( if (!git_pathspec__match( &diff->pathspec, oitem->path, DIFF_FLAG_IS_SET(diff, GIT_DIFF_DISABLE_PATHSPEC_MATCH), - DIFF_FLAG_IS_SET(diff, GIT_DIFF_DELTAS_ARE_ICASE), + DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_CASE), &matched_pathspec, NULL)) return 0; @@ -778,7 +780,7 @@ static int maybe_modified( } static bool entry_is_prefixed( - git_diff_list *diff, + git_diff *diff, const git_index_entry *item, const git_index_entry *prefix_item) { @@ -795,7 +797,7 @@ static bool entry_is_prefixed( } static int diff_scan_inside_untracked_dir( - git_diff_list *diff, diff_in_progress *info, git_delta_t *delta_type) + git_diff *diff, diff_in_progress *info, git_delta_t *delta_type) { int error = 0; git_buf base = GIT_BUF_INIT; @@ -861,7 +863,7 @@ done: } static int handle_unmatched_new_item( - git_diff_list *diff, diff_in_progress *info) + git_diff *diff, diff_in_progress *info) { int error = 0; const git_index_entry *nitem = info->nitem; @@ -910,7 +912,7 @@ static int handle_unmatched_new_item( */ if (!recurse_into_dir && delta_type == GIT_DELTA_UNTRACKED && - DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_FAST_UNTRACKED_DIRS)) + DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS)) { git_diff_delta *last; @@ -1016,7 +1018,7 @@ static int handle_unmatched_new_item( } static int handle_unmatched_old_item( - git_diff_list *diff, diff_in_progress *info) + git_diff *diff, diff_in_progress *info) { int error = diff_delta__from_one(diff, GIT_DELTA_DELETED, info->oitem); if (error < 0) @@ -1048,7 +1050,7 @@ static int handle_unmatched_old_item( } static int handle_matched_item( - git_diff_list *diff, diff_in_progress *info) + git_diff *diff, diff_in_progress *info) { int error = 0; @@ -1063,7 +1065,7 @@ static int handle_matched_item( } int git_diff__from_iterators( - git_diff_list **diff_ptr, + git_diff **diff_ptr, git_repository *repo, git_iterator *old_iter, git_iterator *new_iter, @@ -1071,7 +1073,7 @@ int git_diff__from_iterators( { int error = 0; diff_in_progress info; - git_diff_list *diff; + git_diff *diff; *diff_ptr = NULL; @@ -1084,7 +1086,7 @@ int git_diff__from_iterators( git_buf_init(&info.ignore_prefix, 0); /* make iterators have matching icase behavior */ - if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_DELTAS_ARE_ICASE)) { + if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_CASE)) { if ((error = git_iterator_set_ignore_case(old_iter, true)) < 0 || (error = git_iterator_set_ignore_case(new_iter, true)) < 0) goto cleanup; @@ -1132,7 +1134,7 @@ cleanup: if (!error) *diff_ptr = diff; else - git_diff_list_free(diff); + git_diff_free(diff); git_buf_free(&info.ignore_prefix); @@ -1149,7 +1151,7 @@ cleanup: } while (0) int git_diff_tree_to_tree( - git_diff_list **diff, + git_diff **diff, git_repository *repo, git_tree *old_tree, git_tree *new_tree, @@ -1164,7 +1166,7 @@ int git_diff_tree_to_tree( * currently case insensitive, unless the user explicitly asked * for case insensitivity */ - if (opts && (opts->flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0) + if (opts && (opts->flags & GIT_DIFF_IGNORE_CASE) != 0) iflag = GIT_ITERATOR_IGNORE_CASE; DIFF_FROM_ITERATORS( @@ -1176,7 +1178,7 @@ int git_diff_tree_to_tree( } int git_diff_tree_to_index( - git_diff_list **diff, + git_diff **diff, git_repository *repo, git_tree *old_tree, git_index *index, @@ -1204,9 +1206,9 @@ int git_diff_tree_to_index( git_index__set_ignore_case(index, true); if (!error) { - git_diff_list *d = *diff; + git_diff *d = *diff; - d->opts.flags |= GIT_DIFF_DELTAS_ARE_ICASE; + d->opts.flags |= GIT_DIFF_IGNORE_CASE; d->strcomp = git__strcasecmp; d->strncomp = git__strncasecmp; d->pfxcomp = git__prefixcmp_icase; @@ -1221,7 +1223,7 @@ int git_diff_tree_to_index( } int git_diff_index_to_workdir( - git_diff_list **diff, + git_diff **diff, git_repository *repo, git_index *index, const git_diff_options *opts) @@ -1242,9 +1244,8 @@ int git_diff_index_to_workdir( return error; } - int git_diff_tree_to_workdir( - git_diff_list **diff, + git_diff **diff, git_repository *repo, git_tree *old_tree, const git_diff_options *opts) @@ -1262,16 +1263,43 @@ int git_diff_tree_to_workdir( return error; } -size_t git_diff_num_deltas(git_diff_list *diff) +int git_diff_tree_to_workdir_with_index( + git_diff **diff, + git_repository *repo, + git_tree *old_tree, + const git_diff_options *opts) +{ + int error = 0; + git_diff *d1 = NULL, *d2 = NULL; + + assert(diff && repo); + + if (!(error = git_diff_tree_to_index(&d1, repo, old_tree, NULL, opts)) && + !(error = git_diff_index_to_workdir(&d2, repo, NULL, opts))) + error = git_diff_merge(d1, d2); + + git_diff_free(d2); + + if (error) { + git_diff_free(d1); + d1 = NULL; + } + + *diff = d1; + return error; +} + + +size_t git_diff_num_deltas(const git_diff *diff) { assert(diff); - return (size_t)diff->deltas.length; + return diff->deltas.length; } -size_t git_diff_num_deltas_of_type(git_diff_list *diff, git_delta_t type) +size_t git_diff_num_deltas_of_type(const git_diff *diff, git_delta_t type) { size_t i, count = 0; - git_diff_delta *delta; + const git_diff_delta *delta; assert(diff); @@ -1282,14 +1310,20 @@ size_t git_diff_num_deltas_of_type(git_diff_list *diff, git_delta_t type) return count; } -int git_diff_is_sorted_icase(const git_diff_list *diff) +const git_diff_delta *git_diff_get_delta(const git_diff *diff, size_t idx) +{ + assert(diff); + return git_vector_get(&diff->deltas, idx); +} + +int git_diff_is_sorted_icase(const git_diff *diff) { - return (diff->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0; + return (diff->opts.flags & GIT_DIFF_IGNORE_CASE) != 0; } int git_diff__paired_foreach( - git_diff_list *head2idx, - git_diff_list *idx2wd, + git_diff *head2idx, + git_diff *idx2wd, int (*cb)(git_diff_delta *h2i, git_diff_delta *i2w, void *payload), void *payload) { @@ -1318,10 +1352,10 @@ int git_diff__paired_foreach( * always sort by the old name in the i2w list. */ h2i_icase = head2idx != NULL && - (head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0; + (head2idx->opts.flags & GIT_DIFF_IGNORE_CASE) != 0; i2w_icase = idx2wd != NULL && - (idx2wd->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0; + (idx2wd->opts.flags & GIT_DIFF_IGNORE_CASE) != 0; icase_mismatch = (head2idx != NULL && idx2wd != NULL && h2i_icase != i2w_icase); diff --git a/src/diff.h b/src/diff.h index bec7e27d7..270bea071 100644 --- a/src/diff.h +++ b/src/diff.h @@ -52,7 +52,7 @@ enum { #define GIT_DIFF__VERBOSE (1 << 30) -struct git_diff_list { +struct git_diff { git_refcount rc; git_repository *repo; git_diff_options opts; @@ -72,7 +72,7 @@ struct git_diff_list { extern void git_diff__cleanup_modes( uint32_t diffcaps, uint32_t *omode, uint32_t *nmode); -extern void git_diff_list_addref(git_diff_list *diff); +extern void git_diff_addref(git_diff *diff); extern int git_diff_delta__cmp(const void *a, const void *b); extern int git_diff_delta__casecmp(const void *a, const void *b); @@ -93,15 +93,15 @@ extern int git_diff__oid_for_file( git_repository *, const char *, uint16_t, git_off_t, git_oid *); extern int git_diff__from_iterators( - git_diff_list **diff_ptr, + git_diff **diff_ptr, git_repository *repo, git_iterator *old_iter, git_iterator *new_iter, const git_diff_options *opts); extern int git_diff__paired_foreach( - git_diff_list *idx2head, - git_diff_list *wd2idx, + git_diff *idx2head, + git_diff *wd2idx, int (*cb)(git_diff_delta *i2h, git_diff_delta *w2i, void *payload), void *payload); diff --git a/src/diff_file.c b/src/diff_file.c index 5939ee8b8..a4c8641bc 100644 --- a/src/diff_file.c +++ b/src/diff_file.c @@ -88,7 +88,7 @@ static int diff_file_content_init_common( int git_diff_file_content__init_from_diff( git_diff_file_content *fc, - git_diff_list *diff, + git_diff *diff, size_t delta_index, bool use_old) { @@ -110,7 +110,7 @@ int git_diff_file_content__init_from_diff( has_data = use_old; break; case GIT_DELTA_UNTRACKED: has_data = !use_old && - (diff->opts.flags & GIT_DIFF_INCLUDE_UNTRACKED_CONTENT) != 0; + (diff->opts.flags & GIT_DIFF_SHOW_UNTRACKED_CONTENT) != 0; break; case GIT_DELTA_MODIFIED: case GIT_DELTA_COPIED: diff --git a/src/diff_file.h b/src/diff_file.h index fb08cca6a..84bf255aa 100644 --- a/src/diff_file.h +++ b/src/diff_file.h @@ -27,7 +27,7 @@ typedef struct { extern int git_diff_file_content__init_from_diff( git_diff_file_content *fc, - git_diff_list *diff, + git_diff *diff, size_t delta_index, bool use_old); diff --git a/src/diff_patch.c b/src/diff_patch.c index cc45b6ddb..cc49d68eb 100644 --- a/src/diff_patch.c +++ b/src/diff_patch.c @@ -12,36 +12,24 @@ #include "diff_xdiff.h" #include "fileops.h" -/* cached information about a single span in a diff */ -typedef struct diff_patch_line diff_patch_line; -struct diff_patch_line { - const char *ptr; - size_t len; - size_t lines, oldno, newno; - char origin; -}; - /* cached information about a hunk in a diff */ typedef struct diff_patch_hunk diff_patch_hunk; struct diff_patch_hunk { - git_diff_range range; - char header[128]; - size_t header_len; + git_diff_hunk hunk; size_t line_start; size_t line_count; }; -struct git_diff_patch { +struct git_patch { git_refcount rc; - git_diff_list *diff; /* for refcount purposes, maybe NULL for blob diffs */ + git_diff *diff; /* for refcount purposes, maybe NULL for blob diffs */ git_diff_delta *delta; size_t delta_index; git_diff_file_content ofile; git_diff_file_content nfile; uint32_t flags; git_array_t(diff_patch_hunk) hunks; - git_array_t(diff_patch_line) lines; - size_t oldno, newno; + git_array_t(git_diff_line) lines; size_t content_size, context_size, header_size; git_pool flattened; }; @@ -55,12 +43,13 @@ enum { GIT_DIFF_PATCH_FLATTENED = (1 << 5), }; -static void diff_output_init(git_diff_output*, const git_diff_options*, - git_diff_file_cb, git_diff_hunk_cb, git_diff_data_cb, void*); +static void diff_output_init( + git_diff_output*, const git_diff_options*, + git_diff_file_cb, git_diff_hunk_cb, git_diff_line_cb, void*); -static void diff_output_to_patch(git_diff_output *, git_diff_patch *); +static void diff_output_to_patch(git_diff_output *, git_patch *); -static void diff_patch_update_binary(git_diff_patch *patch) +static void diff_patch_update_binary(git_patch *patch) { if ((patch->delta->flags & DIFF_FLAGS_KNOWN_BINARY) != 0) return; @@ -74,21 +63,21 @@ static void diff_patch_update_binary(git_diff_patch *patch) patch->delta->flags |= GIT_DIFF_FLAG_NOT_BINARY; } -static void diff_patch_init_common(git_diff_patch *patch) +static void diff_patch_init_common(git_patch *patch) { diff_patch_update_binary(patch); if ((patch->delta->flags & GIT_DIFF_FLAG_BINARY) != 0) - patch->flags |= GIT_DIFF_PATCH_LOADED; /* set LOADED but not DIFFABLE */ + patch->flags |= GIT_DIFF_PATCH_LOADED; /* LOADED but not DIFFABLE */ patch->flags |= GIT_DIFF_PATCH_INITIALIZED; if (patch->diff) - git_diff_list_addref(patch->diff); + git_diff_addref(patch->diff); } static int diff_patch_init_from_diff( - git_diff_patch *patch, git_diff_list *diff, size_t delta_index) + git_patch *patch, git_diff *diff, size_t delta_index) { int error = 0; @@ -109,12 +98,10 @@ static int diff_patch_init_from_diff( } static int diff_patch_alloc_from_diff( - git_diff_patch **out, - git_diff_list *diff, - size_t delta_index) + git_patch **out, git_diff *diff, size_t delta_index) { int error; - git_diff_patch *patch = git__calloc(1, sizeof(git_diff_patch)); + git_patch *patch = git__calloc(1, sizeof(git_patch)); GITERR_CHECK_ALLOC(patch); if (!(error = diff_patch_init_from_diff(patch, diff, delta_index))) { @@ -129,7 +116,7 @@ static int diff_patch_alloc_from_diff( return error; } -static int diff_patch_load(git_diff_patch *patch, git_diff_output *output) +static int diff_patch_load(git_patch *patch, git_diff_output *output) { int error = 0; bool incomplete_data; @@ -207,7 +194,7 @@ cleanup: } static int diff_patch_file_callback( - git_diff_patch *patch, git_diff_output *output) + git_patch *patch, git_diff_output *output) { float progress; @@ -223,7 +210,7 @@ static int diff_patch_file_callback( return output->error; } -static int diff_patch_generate(git_diff_patch *patch, git_diff_output *output) +static int diff_patch_generate(git_patch *patch, git_diff_output *output) { int error = 0; @@ -248,7 +235,7 @@ static int diff_patch_generate(git_diff_patch *patch, git_diff_output *output) return error; } -static void diff_patch_free(git_diff_patch *patch) +static void diff_patch_free(git_patch *patch) { git_diff_file_content__clear(&patch->ofile); git_diff_file_content__clear(&patch->nfile); @@ -256,7 +243,7 @@ static void diff_patch_free(git_diff_patch *patch) git_array_clear(patch->lines); git_array_clear(patch->hunks); - git_diff_list_free(patch->diff); /* decrements refcount */ + git_diff_free(patch->diff); /* decrements refcount */ patch->diff = NULL; git_pool_clear(&patch->flattened); @@ -265,7 +252,7 @@ static void diff_patch_free(git_diff_patch *patch) git__free(patch); } -static int diff_required(git_diff_list *diff, const char *action) +static int diff_required(git_diff *diff, const char *action) { if (diff) return 0; @@ -274,16 +261,16 @@ static int diff_required(git_diff_list *diff, const char *action) } int git_diff_foreach( - git_diff_list *diff, + git_diff *diff, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb data_cb, + git_diff_line_cb data_cb, void *payload) { int error = 0; git_xdiff_output xo; size_t idx; - git_diff_patch patch; + git_patch patch; if (diff_required(diff, "git_diff_foreach") < 0) return -1; @@ -305,7 +292,7 @@ int git_diff_foreach( if (!error) error = diff_patch_generate(&patch, &xo.output); - git_diff_patch_free(&patch); + git_patch_free(&patch); } if (error < 0) @@ -318,7 +305,7 @@ int git_diff_foreach( } typedef struct { - git_diff_patch patch; + git_patch patch; git_diff_delta delta; char paths[GIT_FLEX_ARRAY]; } diff_patch_with_delta; @@ -326,7 +313,7 @@ typedef struct { static int diff_single_generate(diff_patch_with_delta *pd, git_xdiff_output *xo) { int error = 0; - git_diff_patch *patch = &pd->patch; + git_patch *patch = &pd->patch; bool has_old = ((patch->ofile.flags & GIT_DIFF_FLAG__NO_DATA) == 0); bool has_new = ((patch->nfile.flags & GIT_DIFF_FLAG__NO_DATA) == 0); @@ -430,7 +417,7 @@ int git_diff_blobs( const git_diff_options *opts, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb data_cb, + git_diff_line_cb data_cb, void *payload) { int error = 0; @@ -452,13 +439,13 @@ int git_diff_blobs( error = diff_patch_from_blobs( &pd, &xo, old_blob, old_path, new_blob, new_path, opts); - git_diff_patch_free(&pd.patch); + git_patch_free(&pd.patch); return error; } -int git_diff_patch_from_blobs( - git_diff_patch **out, +int git_patch_from_blobs( + git_patch **out, const git_blob *old_blob, const char *old_path, const git_blob *new_blob, @@ -484,9 +471,9 @@ int git_diff_patch_from_blobs( pd, &xo, old_blob, old_path, new_blob, new_path, opts); if (!error) - *out = (git_diff_patch *)pd; + *out = (git_patch *)pd; else - git_diff_patch_free((git_diff_patch *)pd); + git_patch_free((git_patch *)pd); return error; } @@ -542,7 +529,7 @@ int git_diff_blob_to_buffer( const git_diff_options *opts, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb data_cb, + git_diff_line_cb data_cb, void *payload) { int error = 0; @@ -564,13 +551,13 @@ int git_diff_blob_to_buffer( error = diff_patch_from_blob_and_buffer( &pd, &xo, old_blob, old_path, buf, buflen, buf_path, opts); - git_diff_patch_free(&pd.patch); + git_patch_free(&pd.patch); return error; } -int git_diff_patch_from_blob_and_buffer( - git_diff_patch **out, +int git_patch_from_blob_and_buffer( + git_patch **out, const git_blob *old_blob, const char *old_path, const char *buf, @@ -597,28 +584,24 @@ int git_diff_patch_from_blob_and_buffer( pd, &xo, old_blob, old_path, buf, buflen, buf_path, opts); if (!error) - *out = (git_diff_patch *)pd; + *out = (git_patch *)pd; else - git_diff_patch_free((git_diff_patch *)pd); + git_patch_free((git_patch *)pd); return error; } -int git_diff_get_patch( - git_diff_patch **patch_ptr, - const git_diff_delta **delta_ptr, - git_diff_list *diff, - size_t idx) +int git_patch_from_diff( + git_patch **patch_ptr, git_diff *diff, size_t idx) { int error = 0; git_xdiff_output xo; git_diff_delta *delta = NULL; - git_diff_patch *patch = NULL; + git_patch *patch = NULL; if (patch_ptr) *patch_ptr = NULL; - if (delta_ptr) *delta_ptr = NULL; - if (diff_required(diff, "git_diff_get_patch") < 0) + if (diff_required(diff, "git_patch_from_diff") < 0) return -1; delta = git_vector_get(&diff->deltas, idx); @@ -627,9 +610,6 @@ int git_diff_get_patch( return GIT_ENOTFOUND; } - if (delta_ptr) - *delta_ptr = delta; - if (git_diff_delta__should_skip(&diff->opts, delta)) return 0; @@ -656,7 +636,7 @@ int git_diff_get_patch( } if (error || !patch_ptr) - git_diff_patch_free(patch); + git_patch_free(patch); else *patch_ptr = patch; @@ -665,36 +645,36 @@ int git_diff_get_patch( return error; } -void git_diff_patch_free(git_diff_patch *patch) +void git_patch_free(git_patch *patch) { if (patch) GIT_REFCOUNT_DEC(patch, diff_patch_free); } -const git_diff_delta *git_diff_patch_delta(git_diff_patch *patch) +const git_diff_delta *git_patch_get_delta(git_patch *patch) { assert(patch); return patch->delta; } -size_t git_diff_patch_num_hunks(git_diff_patch *patch) +size_t git_patch_num_hunks(git_patch *patch) { assert(patch); return git_array_size(patch->hunks); } -int git_diff_patch_line_stats( +int git_patch_line_stats( size_t *total_ctxt, size_t *total_adds, size_t *total_dels, - const git_diff_patch *patch) + const git_patch *patch) { size_t totals[3], idx; memset(totals, 0, sizeof(totals)); for (idx = 0; idx < git_array_size(patch->lines); ++idx) { - diff_patch_line *line = git_array_get(patch->lines, idx); + git_diff_line *line = git_array_get(patch->lines, idx); if (!line) continue; @@ -726,12 +706,10 @@ static int diff_error_outofrange(const char *thing) return GIT_ENOTFOUND; } -int git_diff_patch_get_hunk( - const git_diff_range **range, - const char **header, - size_t *header_len, +int git_patch_get_hunk( + const git_diff_hunk **out, size_t *lines_in_hunk, - git_diff_patch *patch, + git_patch *patch, size_t hunk_idx) { diff_patch_hunk *hunk; @@ -740,21 +718,17 @@ int git_diff_patch_get_hunk( hunk = git_array_get(patch->hunks, hunk_idx); if (!hunk) { - if (range) *range = NULL; - if (header) *header = NULL; - if (header_len) *header_len = 0; + if (out) *out = NULL; if (lines_in_hunk) *lines_in_hunk = 0; return diff_error_outofrange("hunk"); } - if (range) *range = &hunk->range; - if (header) *header = hunk->header; - if (header_len) *header_len = hunk->header_len; + if (out) *out = &hunk->hunk; if (lines_in_hunk) *lines_in_hunk = hunk->line_count; return 0; } -int git_diff_patch_num_lines_in_hunk(git_diff_patch *patch, size_t hunk_idx) +int git_patch_num_lines_in_hunk(git_patch *patch, size_t hunk_idx) { diff_patch_hunk *hunk; assert(patch); @@ -764,54 +738,35 @@ int git_diff_patch_num_lines_in_hunk(git_diff_patch *patch, size_t hunk_idx) return (int)hunk->line_count; } -int git_diff_patch_get_line_in_hunk( - char *line_origin, - const char **content, - size_t *content_len, - int *old_lineno, - int *new_lineno, - git_diff_patch *patch, +int git_patch_get_line_in_hunk( + const git_diff_line **out, + git_patch *patch, size_t hunk_idx, size_t line_of_hunk) { diff_patch_hunk *hunk; - diff_patch_line *line; - const char *thing; + git_diff_line *line; assert(patch); if (!(hunk = git_array_get(patch->hunks, hunk_idx))) { - thing = "hunk"; - goto notfound; + if (out) *out = NULL; + return diff_error_outofrange("hunk"); } if (line_of_hunk >= hunk->line_count || !(line = git_array_get( patch->lines, hunk->line_start + line_of_hunk))) { - thing = "line"; - goto notfound; + if (out) *out = NULL; + return diff_error_outofrange("line"); } - if (line_origin) *line_origin = line->origin; - if (content) *content = line->ptr; - if (content_len) *content_len = line->len; - if (old_lineno) *old_lineno = (int)line->oldno; - if (new_lineno) *new_lineno = (int)line->newno; - + if (out) *out = line; return 0; - -notfound: - if (line_origin) *line_origin = GIT_DIFF_LINE_CONTEXT; - if (content) *content = NULL; - if (content_len) *content_len = 0; - if (old_lineno) *old_lineno = -1; - if (new_lineno) *new_lineno = -1; - - return diff_error_outofrange(thing); } -size_t git_diff_patch_size( - git_diff_patch *patch, +size_t git_patch_size( + git_patch *patch, int include_context, int include_hunk_headers, int include_file_headers) @@ -843,36 +798,36 @@ size_t git_diff_patch_size( return out; } -git_diff_list *git_diff_patch__diff(git_diff_patch *patch) +git_diff *git_patch__diff(git_patch *patch) { return patch->diff; } -git_diff_driver *git_diff_patch__driver(git_diff_patch *patch) +git_diff_driver *git_patch__driver(git_patch *patch) { /* ofile driver is representative for whole patch */ return patch->ofile.driver; } -void git_diff_patch__old_data( - char **ptr, size_t *len, git_diff_patch *patch) +void git_patch__old_data( + char **ptr, size_t *len, git_patch *patch) { *ptr = patch->ofile.map.data; *len = patch->ofile.map.len; } -void git_diff_patch__new_data( - char **ptr, size_t *len, git_diff_patch *patch) +void git_patch__new_data( + char **ptr, size_t *len, git_patch *patch) { *ptr = patch->nfile.map.data; *len = patch->nfile.map.len; } -int git_diff_patch__invoke_callbacks( - git_diff_patch *patch, +int git_patch__invoke_callbacks( + git_patch *patch, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb line_cb, + git_diff_line_cb line_cb, void *payload) { int error = 0; @@ -887,18 +842,16 @@ int git_diff_patch__invoke_callbacks( for (i = 0; !error && i < git_array_size(patch->hunks); ++i) { diff_patch_hunk *h = git_array_get(patch->hunks, i); - error = hunk_cb( - patch->delta, &h->range, h->header, h->header_len, payload); + error = hunk_cb(patch->delta, &h->hunk, payload); if (!line_cb) continue; for (j = 0; !error && j < h->line_count; ++j) { - diff_patch_line *l = + git_diff_line *l = git_array_get(patch->lines, h->line_start + j); - error = line_cb( - patch->delta, &h->range, l->origin, l->ptr, l->len, payload); + error = line_cb(patch->delta, &h->hunk, l, payload); } } @@ -917,12 +870,10 @@ static int diff_patch_file_cb( static int diff_patch_hunk_cb( const git_diff_delta *delta, - const git_diff_range *range, - const char *header, - size_t header_len, + const git_diff_hunk *hunk_, void *payload) { - git_diff_patch *patch = payload; + git_patch *patch = payload; diff_patch_hunk *hunk; GIT_UNUSED(delta); @@ -930,39 +881,28 @@ static int diff_patch_hunk_cb( hunk = git_array_alloc(patch->hunks); GITERR_CHECK_ALLOC(hunk); - memcpy(&hunk->range, range, sizeof(hunk->range)); - - assert(header_len + 1 < sizeof(hunk->header)); - memcpy(&hunk->header, header, header_len); - hunk->header[header_len] = '\0'; - hunk->header_len = header_len; + memcpy(&hunk->hunk, hunk_, sizeof(hunk->hunk)); - patch->header_size += header_len; + patch->header_size += hunk_->header_len; hunk->line_start = git_array_size(patch->lines); hunk->line_count = 0; - patch->oldno = range->old_start; - patch->newno = range->new_start; - return 0; } static int diff_patch_line_cb( const git_diff_delta *delta, - const git_diff_range *range, - char line_origin, - const char *content, - size_t content_len, + const git_diff_hunk *hunk_, + const git_diff_line *line_, void *payload) { - git_diff_patch *patch = payload; + git_patch *patch = payload; diff_patch_hunk *hunk; - diff_patch_line *line; - const char *content_end = content + content_len; + git_diff_line *line; GIT_UNUSED(delta); - GIT_UNUSED(range); + GIT_UNUSED(hunk_); hunk = git_array_last(patch->hunks); GITERR_CHECK_ALLOC(hunk); @@ -970,48 +910,20 @@ static int diff_patch_line_cb( line = git_array_alloc(patch->lines); GITERR_CHECK_ALLOC(line); - line->ptr = content; - line->len = content_len; - line->origin = line_origin; + memcpy(line, line_, sizeof(*line)); /* do some bookkeeping so we can provide old/new line numbers */ - line->lines = 0; - while (content < content_end) - if (*content++ == '\n') - ++line->lines; + patch->content_size += line->content_len; - patch->content_size += content_len; - - switch (line_origin) { - case GIT_DIFF_LINE_ADDITION: - patch->content_size += 1; - case GIT_DIFF_LINE_DEL_EOFNL: - line->oldno = -1; - line->newno = patch->newno; - patch->newno += line->lines; - break; - case GIT_DIFF_LINE_DELETION: + if (line->origin == GIT_DIFF_LINE_ADDITION || + line->origin == GIT_DIFF_LINE_DELETION) patch->content_size += 1; - case GIT_DIFF_LINE_ADD_EOFNL: - line->oldno = patch->oldno; - line->newno = -1; - patch->oldno += line->lines; - break; - case GIT_DIFF_LINE_CONTEXT: + else if (line->origin == GIT_DIFF_LINE_CONTEXT) { patch->content_size += 1; - patch->context_size += 1; - case GIT_DIFF_LINE_CONTEXT_EOFNL: - patch->context_size += content_len; - line->oldno = patch->oldno; - line->newno = patch->newno; - patch->oldno += line->lines; - patch->newno += line->lines; - break; - default: - assert(false); - break; - } + patch->context_size += line->content_len + 1; + } else if (line->origin == GIT_DIFF_LINE_CONTEXT_EOFNL) + patch->context_size += line->content_len; hunk->line_count++; @@ -1023,7 +935,7 @@ static void diff_output_init( const git_diff_options *opts, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb data_cb, + git_diff_line_cb data_cb, void *payload) { GIT_UNUSED(opts); @@ -1036,7 +948,7 @@ static void diff_output_init( out->payload = payload; } -static void diff_output_to_patch(git_diff_output *out, git_diff_patch *patch) +static void diff_output_to_patch(git_diff_output *out, git_patch *patch) { diff_output_init( out, NULL, diff --git a/src/diff_patch.h b/src/diff_patch.h index 56af14600..df2ba4c31 100644 --- a/src/diff_patch.h +++ b/src/diff_patch.h @@ -11,19 +11,20 @@ #include "diff.h" #include "diff_file.h" #include "array.h" +#include "git2/patch.h" -extern git_diff_list *git_diff_patch__diff(git_diff_patch *); +extern git_diff *git_patch__diff(git_patch *); -extern git_diff_driver *git_diff_patch__driver(git_diff_patch *); +extern git_diff_driver *git_patch__driver(git_patch *); -extern void git_diff_patch__old_data(char **, size_t *, git_diff_patch *); -extern void git_diff_patch__new_data(char **, size_t *, git_diff_patch *); +extern void git_patch__old_data(char **, size_t *, git_patch *); +extern void git_patch__new_data(char **, size_t *, git_patch *); -extern int git_diff_patch__invoke_callbacks( - git_diff_patch *patch, +extern int git_patch__invoke_callbacks( + git_patch *patch, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb line_cb, + git_diff_line_cb line_cb, void *payload); typedef struct git_diff_output git_diff_output; @@ -31,7 +32,7 @@ struct git_diff_output { /* these callbacks are issued with the diff data */ git_diff_file_cb file_cb; git_diff_hunk_cb hunk_cb; - git_diff_data_cb data_cb; + git_diff_line_cb data_cb; void *payload; /* this records the actual error in cases where it may be obscured */ @@ -40,7 +41,7 @@ struct git_diff_output { /* this callback is used to do the diff and drive the other callbacks. * see diff_xdiff.h for how to use this in practice for now. */ - int (*diff_cb)(git_diff_output *output, git_diff_patch *patch); + int (*diff_cb)(git_diff_output *output, git_patch *patch); }; #endif diff --git a/src/diff_print.c b/src/diff_print.c index fd18b67e3..b04b11515 100644 --- a/src/diff_print.c +++ b/src/diff_print.c @@ -10,23 +10,36 @@ #include "fileops.h" typedef struct { - git_diff_list *diff; - git_diff_data_cb print_cb; + git_diff *diff; + git_diff_format_t format; + git_diff_line_cb print_cb; void *payload; git_buf *buf; + uint32_t flags; int oid_strlen; + git_diff_line line; } diff_print_info; static int diff_print_info_init( diff_print_info *pi, - git_buf *out, git_diff_list *diff, git_diff_data_cb cb, void *payload) + git_buf *out, + git_diff *diff, + git_diff_format_t format, + git_diff_line_cb cb, + void *payload) { pi->diff = diff; + pi->format = format; pi->print_cb = cb; pi->payload = payload; pi->buf = out; - if (!diff || !diff->repo) + if (diff) + pi->flags = diff->opts.flags; + + if (diff && diff->opts.oid_abbrev != 0) + pi->oid_strlen = diff->opts.oid_abbrev; + else if (!diff || !diff->repo) pi->oid_strlen = GIT_ABBREV_DEFAULT; else if (git_repository__cvar( &pi->oid_strlen, diff->repo, GIT_CVAR_ABBREV) < 0) @@ -39,6 +52,11 @@ static int diff_print_info_init( else if (pi->oid_strlen > GIT_OID_HEXSZ + 1) pi->oid_strlen = GIT_OID_HEXSZ + 1; + memset(&pi->line, 0, sizeof(pi->line)); + pi->line.old_lineno = -1; + pi->line.new_lineno = -1; + pi->line.num_lines = 1; + return 0; } @@ -77,7 +95,35 @@ static int callback_error(void) return GIT_EUSER; } -static int diff_print_one_compact( +static int diff_print_one_name_only( + const git_diff_delta *delta, float progress, void *data) +{ + diff_print_info *pi = data; + git_buf *out = pi->buf; + + GIT_UNUSED(progress); + + if ((pi->flags & GIT_DIFF_SHOW_UNMODIFIED) == 0 && + delta->status == GIT_DELTA_UNMODIFIED) + return 0; + + git_buf_clear(out); + + if (git_buf_puts(out, delta->new_file.path) < 0 || + git_buf_putc(out, '\n')) + return -1; + + pi->line.origin = GIT_DIFF_LINE_FILE_HDR; + pi->line.content = git_buf_cstr(out); + pi->line.content_len = git_buf_len(out); + + if (pi->print_cb(delta, NULL, &pi->line, pi->payload)) + return callback_error(); + + return 0; +} + +static int diff_print_one_name_status( const git_diff_delta *delta, float progress, void *data) { diff_print_info *pi = data; @@ -88,7 +134,7 @@ static int diff_print_one_compact( GIT_UNUSED(progress); - if (code == ' ') + if ((pi->flags & GIT_DIFF_SHOW_UNMODIFIED) == 0 && code == ' ') return 0; old_suffix = diff_pick_suffix(delta->old_file.mode); @@ -112,31 +158,16 @@ static int diff_print_one_compact( if (git_buf_oom(out)) return -1; - if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR, - git_buf_cstr(out), git_buf_len(out), pi->payload)) + pi->line.origin = GIT_DIFF_LINE_FILE_HDR; + pi->line.content = git_buf_cstr(out); + pi->line.content_len = git_buf_len(out); + + if (pi->print_cb(delta, NULL, &pi->line, pi->payload)) return callback_error(); return 0; } -/* print a git_diff_list to a print callback in compact format */ -int git_diff_print_compact( - git_diff_list *diff, - git_diff_data_cb print_cb, - void *payload) -{ - int error; - git_buf buf = GIT_BUF_INIT; - diff_print_info pi; - - if (!(error = diff_print_info_init(&pi, &buf, diff, print_cb, payload))) - error = git_diff_foreach(diff, diff_print_one_compact, NULL, NULL, &pi); - - git_buf_free(&buf); - - return error; -} - static int diff_print_one_raw( const git_diff_delta *delta, float progress, void *data) { @@ -147,7 +178,7 @@ static int diff_print_one_raw( GIT_UNUSED(progress); - if (code == ' ') + if ((pi->flags & GIT_DIFF_SHOW_UNMODIFIED) == 0 && code == ' ') return 0; git_buf_clear(out); @@ -173,31 +204,16 @@ static int diff_print_one_raw( if (git_buf_oom(out)) return -1; - if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR, - git_buf_cstr(out), git_buf_len(out), pi->payload)) + pi->line.origin = GIT_DIFF_LINE_FILE_HDR; + pi->line.content = git_buf_cstr(out); + pi->line.content_len = git_buf_len(out); + + if (pi->print_cb(delta, NULL, &pi->line, pi->payload)) return callback_error(); return 0; } -/* print a git_diff_list to a print callback in raw output format */ -int git_diff_print_raw( - git_diff_list *diff, - git_diff_data_cb print_cb, - void *payload) -{ - int error; - git_buf buf = GIT_BUF_INIT; - diff_print_info pi; - - if (!(error = diff_print_info_init(&pi, &buf, diff, print_cb, payload))) - error = git_diff_foreach(diff, diff_print_one_raw, NULL, NULL, &pi); - - git_buf_free(&buf); - - return error; -} - static int diff_print_oid_range( git_buf *out, const git_diff_delta *delta, int oid_strlen) { @@ -287,7 +303,6 @@ static int diff_print_patch_file( pi->diff ? pi->diff->opts.old_prefix : DIFF_OLD_PREFIX_DEFAULT; const char *newpfx = pi->diff ? pi->diff->opts.new_prefix : DIFF_NEW_PREFIX_DEFAULT; - uint32_t opts_flags = pi->diff ? pi->diff->opts.flags : GIT_DIFF_NORMAL; GIT_UNUSED(progress); @@ -295,15 +310,18 @@ static int diff_print_patch_file( delta->status == GIT_DELTA_UNMODIFIED || delta->status == GIT_DELTA_IGNORED || (delta->status == GIT_DELTA_UNTRACKED && - (opts_flags & GIT_DIFF_INCLUDE_UNTRACKED_CONTENT) == 0)) + (pi->flags & GIT_DIFF_SHOW_UNTRACKED_CONTENT) == 0)) return 0; if (git_diff_delta__format_file_header( pi->buf, delta, oldpfx, newpfx, pi->oid_strlen) < 0) return -1; - if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR, - git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload)) + pi->line.origin = GIT_DIFF_LINE_FILE_HDR; + pi->line.content = git_buf_cstr(pi->buf); + pi->line.content_len = git_buf_len(pi->buf); + + if (pi->print_cb(delta, NULL, &pi->line, pi->payload)) return callback_error(); if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0) @@ -316,8 +334,12 @@ static int diff_print_patch_file( "Binary files %s%s and %s%s differ\n") < 0) return -1; - if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_BINARY, - git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload)) + pi->line.origin = GIT_DIFF_LINE_BINARY; + pi->line.content = git_buf_cstr(pi->buf); + pi->line.content_len = git_buf_len(pi->buf); + pi->line.num_lines = 1; + + if (pi->print_cb(delta, NULL, &pi->line, pi->payload)) return callback_error(); return 0; @@ -325,9 +347,7 @@ static int diff_print_patch_file( static int diff_print_patch_hunk( const git_diff_delta *d, - const git_diff_range *r, - const char *header, - size_t header_len, + const git_diff_hunk *h, void *data) { diff_print_info *pi = data; @@ -335,12 +355,11 @@ static int diff_print_patch_hunk( if (S_ISDIR(d->new_file.mode)) return 0; - git_buf_clear(pi->buf); - if (git_buf_put(pi->buf, header, header_len) < 0) - return -1; + pi->line.origin = GIT_DIFF_LINE_HUNK_HDR; + pi->line.content = h->header; + pi->line.content_len = h->header_len; - if (pi->print_cb(d, r, GIT_DIFF_LINE_HUNK_HDR, - git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload)) + if (pi->print_cb(d, h, &pi->line, pi->payload)) return callback_error(); return 0; @@ -348,10 +367,8 @@ static int diff_print_patch_hunk( static int diff_print_patch_line( const git_diff_delta *delta, - const git_diff_range *range, - char line_origin, /* GIT_DIFF_LINE value from above */ - const char *content, - size_t content_len, + const git_diff_hunk *hunk, + const git_diff_line *line, void *data) { diff_print_info *pi = data; @@ -359,50 +376,63 @@ static int diff_print_patch_line( if (S_ISDIR(delta->new_file.mode)) return 0; - git_buf_clear(pi->buf); - git_buf_grow(pi->buf, content_len + 2); - - if (line_origin == GIT_DIFF_LINE_ADDITION || - line_origin == GIT_DIFF_LINE_DELETION || - line_origin == GIT_DIFF_LINE_CONTEXT) - git_buf_putc(pi->buf, line_origin); - - git_buf_put(pi->buf, content, content_len); - - if (git_buf_oom(pi->buf)) - return -1; - - if (pi->print_cb(delta, range, line_origin, - git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload)) + if (pi->print_cb(delta, hunk, line, pi->payload)) return callback_error(); return 0; } -/* print a git_diff_list to an output callback in patch format */ -int git_diff_print_patch( - git_diff_list *diff, - git_diff_data_cb print_cb, +/* print a git_diff to an output callback */ +int git_diff_print( + git_diff *diff, + git_diff_format_t format, + git_diff_line_cb print_cb, void *payload) { int error; git_buf buf = GIT_BUF_INIT; diff_print_info pi; + git_diff_file_cb print_file = NULL; + git_diff_hunk_cb print_hunk = NULL; + git_diff_line_cb print_line = NULL; + + switch (format) { + case GIT_DIFF_FORMAT_PATCH: + print_file = diff_print_patch_file; + print_hunk = diff_print_patch_hunk; + print_line = diff_print_patch_line; + break; + case GIT_DIFF_FORMAT_PATCH_HEADER: + print_file = diff_print_patch_file; + break; + case GIT_DIFF_FORMAT_RAW: + print_file = diff_print_one_raw; + break; + case GIT_DIFF_FORMAT_NAME_ONLY: + print_file = diff_print_one_name_only; + break; + case GIT_DIFF_FORMAT_NAME_STATUS: + print_file = diff_print_one_name_status; + break; + default: + giterr_set(GITERR_INVALID, "Unknown diff output format (%d)", format); + return -1; + } - if (!(error = diff_print_info_init(&pi, &buf, diff, print_cb, payload))) + if (!(error = diff_print_info_init( + &pi, &buf, diff, format, print_cb, payload))) error = git_diff_foreach( - diff, diff_print_patch_file, diff_print_patch_hunk, - diff_print_patch_line, &pi); + diff, print_file, print_hunk, print_line, &pi); git_buf_free(&buf); return error; } -/* print a git_diff_patch to an output callback */ -int git_diff_patch_print( - git_diff_patch *patch, - git_diff_data_cb print_cb, +/* print a git_patch to an output callback */ +int git_patch_print( + git_patch *patch, + git_diff_line_cb print_cb, void *payload) { int error; @@ -412,8 +442,9 @@ int git_diff_patch_print( assert(patch && print_cb); if (!(error = diff_print_info_init( - &pi, &temp, git_diff_patch__diff(patch), print_cb, payload))) - error = git_diff_patch__invoke_callbacks( + &pi, &temp, git_patch__diff(patch), + GIT_DIFF_FORMAT_PATCH, print_cb, payload))) + error = git_patch__invoke_callbacks( patch, diff_print_patch_file, diff_print_patch_hunk, diff_print_patch_line, &pi); @@ -424,26 +455,30 @@ int git_diff_patch_print( static int diff_print_to_buffer_cb( const git_diff_delta *delta, - const git_diff_range *range, - char line_origin, - const char *content, - size_t content_len, + const git_diff_hunk *hunk, + const git_diff_line *line, void *payload) { git_buf *output = payload; - GIT_UNUSED(delta); GIT_UNUSED(range); GIT_UNUSED(line_origin); - return git_buf_put(output, content, content_len); + GIT_UNUSED(delta); GIT_UNUSED(hunk); + + if (line->origin == GIT_DIFF_LINE_ADDITION || + line->origin == GIT_DIFF_LINE_DELETION || + line->origin == GIT_DIFF_LINE_CONTEXT) + git_buf_putc(output, line->origin); + + return git_buf_put(output, line->content, line->content_len); } -/* print a git_diff_patch to a string buffer */ -int git_diff_patch_to_str( +/* print a git_patch to a string buffer */ +int git_patch_to_str( char **string, - git_diff_patch *patch) + git_patch *patch) { int error; git_buf output = GIT_BUF_INIT; - error = git_diff_patch_print(patch, diff_print_to_buffer_cb, &output); + error = git_patch_print(patch, diff_print_to_buffer_cb, &output); /* GIT_EUSER means git_buf_put in print_to_buffer_cb returned -1, * meaning a memory allocation failure, so just map to -1... diff --git a/src/diff_tform.c b/src/diff_tform.c index cbe8bafbd..9461ca2c8 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -97,8 +97,8 @@ static git_diff_delta *diff_delta__merge_like_cgit( } int git_diff_merge( - git_diff_list *onto, - const git_diff_list *from) + git_diff *onto, + const git_diff *from) { int error = 0; git_pool onto_pool; @@ -117,15 +117,15 @@ int git_diff_merge( git_pool_init(&onto_pool, 1, 0) < 0) return -1; - if ((onto->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0 || - (from->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0) + if ((onto->opts.flags & GIT_DIFF_IGNORE_CASE) != 0 || + (from->opts.flags & GIT_DIFF_IGNORE_CASE) != 0) { ignore_case = true; /* This function currently only supports merging diff lists that * are sorted identically. */ - assert((onto->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0 && - (from->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0); + assert((onto->opts.flags & GIT_DIFF_IGNORE_CASE) != 0 && + (from->opts.flags & GIT_DIFF_IGNORE_CASE) != 0); } for (i = 0, j = 0; i < onto->deltas.length || j < from->deltas.length; ) { @@ -230,9 +230,9 @@ int git_diff_find_similar__calc_similarity( #define DEFAULT_RENAME_LIMIT 200 static int normalize_find_opts( - git_diff_list *diff, + git_diff *diff, git_diff_find_options *opts, - git_diff_find_options *given) + const git_diff_find_options *given) { git_config *cfg = NULL; @@ -328,7 +328,7 @@ static int normalize_find_opts( } static int apply_splits_and_deletes( - git_diff_list *diff, size_t expected_size, bool actually_split) + git_diff *diff, size_t expected_size, bool actually_split) { git_vector onto = GIT_VECTOR_INIT; size_t i; @@ -350,6 +350,7 @@ static int apply_splits_and_deletes( goto on_error; deleted->status = GIT_DELTA_DELETED; + deleted->nfiles = 1; memset(&deleted->new_file, 0, sizeof(deleted->new_file)); deleted->new_file.path = deleted->old_file.path; deleted->new_file.flags |= GIT_DIFF_FLAG_VALID_OID; @@ -361,6 +362,7 @@ static int apply_splits_and_deletes( delta->status = GIT_DELTA_UNTRACKED; else delta->status = GIT_DELTA_ADDED; + delta->nfiles = 1; memset(&delta->old_file, 0, sizeof(delta->old_file)); delta->old_file.path = delta->new_file.path; delta->old_file.flags |= GIT_DIFF_FLAG_VALID_OID; @@ -402,7 +404,7 @@ on_error: return -1; } -GIT_INLINE(git_diff_file *) similarity_get_file(git_diff_list *diff, size_t idx) +GIT_INLINE(git_diff_file *) similarity_get_file(git_diff *diff, size_t idx) { git_diff_delta *delta = git_vector_get(&diff->deltas, idx / 2); return (idx & 1) ? &delta->new_file : &delta->old_file; @@ -419,7 +421,7 @@ typedef struct { } similarity_info; static int similarity_init( - similarity_info *info, git_diff_list *diff, size_t file_idx) + similarity_info *info, git_diff *diff, size_t file_idx) { info->idx = file_idx; info->src = (file_idx & 1) ? diff->new_src : diff->old_src; @@ -509,7 +511,7 @@ static void similarity_unload(similarity_info *info) */ static int similarity_measure( int *score, - git_diff_list *diff, + git_diff *diff, const git_diff_find_options *opts, void **cache, size_t a_idx, @@ -595,7 +597,7 @@ cleanup: } static int calc_self_similarity( - git_diff_list *diff, + git_diff *diff, const git_diff_find_options *opts, size_t delta_idx, void **cache) @@ -612,7 +614,7 @@ static int calc_self_similarity( return error; if (similarity >= 0) { - delta->similarity = (uint32_t)similarity; + delta->similarity = (uint16_t)similarity; delta->flags |= GIT_DIFF_FLAG__HAS_SELF_SIMILARITY; } @@ -620,7 +622,7 @@ static int calc_self_similarity( } static bool is_rename_target( - git_diff_list *diff, + git_diff *diff, const git_diff_find_options *opts, size_t delta_idx, void **cache) @@ -675,7 +677,7 @@ static bool is_rename_target( } static bool is_rename_source( - git_diff_list *diff, + git_diff *diff, const git_diff_find_options *opts, size_t delta_idx, void **cache) @@ -745,25 +747,27 @@ GIT_INLINE(bool) delta_is_new_only(git_diff_delta *delta) } GIT_INLINE(void) delta_make_rename( - git_diff_delta *to, const git_diff_delta *from, uint32_t similarity) + git_diff_delta *to, const git_diff_delta *from, uint16_t similarity) { to->status = GIT_DELTA_RENAMED; to->similarity = similarity; + to->nfiles = 2; memcpy(&to->old_file, &from->old_file, sizeof(to->old_file)); to->flags &= ~GIT_DIFF_FLAG__TO_SPLIT; } typedef struct { - uint32_t idx; - uint32_t similarity; + size_t idx; + uint16_t similarity; } diff_find_match; int git_diff_find_similar( - git_diff_list *diff, - git_diff_find_options *given_opts) + git_diff *diff, + const git_diff_find_options *given_opts) { size_t s, t; - int error = 0, similarity; + int error = 0, result; + uint16_t similarity; git_diff_delta *src, *tgt; git_diff_find_options opts; size_t num_deltas, num_srcs = 0, num_tgts = 0; @@ -839,17 +843,18 @@ find_best_matches: /* calculate similarity for this pair and find best match */ if (s == t) - similarity = -1; /* don't measure self-similarity here */ + result = -1; /* don't measure self-similarity here */ else if ((error = similarity_measure( - &similarity, diff, &opts, sigcache, 2 * s, 2 * t + 1)) < 0) + &result, diff, &opts, sigcache, 2 * s, 2 * t + 1)) < 0) goto cleanup; - if (similarity < 0) + if (result < 0) continue; + similarity = (uint16_t)result; /* is this a better rename? */ - if (tgt2src[t].similarity < (uint32_t)similarity && - src2tgt[s].similarity < (uint32_t)similarity) + if (tgt2src[t].similarity < similarity && + src2tgt[s].similarity < similarity) { /* eject old mapping */ if (src2tgt[s].similarity > 0) { @@ -862,18 +867,18 @@ find_best_matches: } /* write new mapping */ - tgt2src[t].idx = (uint32_t)s; - tgt2src[t].similarity = (uint32_t)similarity; - src2tgt[s].idx = (uint32_t)t; - src2tgt[s].similarity = (uint32_t)similarity; + tgt2src[t].idx = s; + tgt2src[t].similarity = similarity; + src2tgt[s].idx = t; + src2tgt[s].similarity = similarity; } /* keep best absolute match for copies */ if (tgt2src_copy != NULL && - tgt2src_copy[t].similarity < (uint32_t)similarity) + tgt2src_copy[t].similarity < similarity) { - tgt2src_copy[t].idx = (uint32_t)s; - tgt2src_copy[t].similarity = (uint32_t)similarity; + tgt2src_copy[t].idx = s; + tgt2src_copy[t].similarity = similarity; } if (++tried_srcs >= num_srcs) @@ -943,7 +948,7 @@ find_best_matches: delta_make_rename(tgt, src, best_match->similarity); num_rewrites--; - src->status = GIT_DELTA_DELETED; + assert(src->status == GIT_DELTA_DELETED); memcpy(&src->old_file, &swap, sizeof(src->old_file)); memset(&src->new_file, 0, sizeof(src->new_file)); src->new_file.path = src->old_file.path; @@ -953,7 +958,7 @@ find_best_matches: if (src2tgt[t].similarity > 0 && src2tgt[t].idx > t) { /* what used to be at src t is now at src s */ - tgt2src[src2tgt[t].idx].idx = (uint32_t)s; + tgt2src[src2tgt[t].idx].idx = s; } } } @@ -969,6 +974,7 @@ find_best_matches: src->status = (diff->new_src == GIT_ITERATOR_TYPE_WORKDIR) ? GIT_DELTA_UNTRACKED : GIT_DELTA_ADDED; + src->nfiles = 1; memset(&src->old_file, 0, sizeof(src->old_file)); src->old_file.path = src->new_file.path; src->old_file.flags |= GIT_DIFF_FLAG_VALID_OID; @@ -1006,7 +1012,7 @@ find_best_matches: /* otherwise, if we just overwrote a source, update mapping */ else if (src2tgt[t].similarity > 0 && src2tgt[t].idx > t) { /* what used to be at src t is now at src s */ - tgt2src[src2tgt[t].idx].idx = (uint32_t)s; + tgt2src[src2tgt[t].idx].idx = s; } num_updates++; @@ -1026,6 +1032,7 @@ find_best_matches: tgt->status = GIT_DELTA_COPIED; tgt->similarity = best_match->similarity; + tgt->nfiles = 2; memcpy(&tgt->old_file, &src->old_file, sizeof(tgt->old_file)); num_updates++; diff --git a/src/diff_xdiff.c b/src/diff_xdiff.c index 7694fb996..2aca76f87 100644 --- a/src/diff_xdiff.c +++ b/src/diff_xdiff.c @@ -24,26 +24,26 @@ static int git_xdiff_scan_int(const char **str, int *value) return (digits > 0) ? 0 : -1; } -static int git_xdiff_parse_hunk(git_diff_range *range, const char *header) +static int git_xdiff_parse_hunk(git_diff_hunk *hunk, const char *header) { /* expect something of the form "@@ -%d[,%d] +%d[,%d] @@" */ if (*header != '@') return -1; - if (git_xdiff_scan_int(&header, &range->old_start) < 0) + if (git_xdiff_scan_int(&header, &hunk->old_start) < 0) return -1; if (*header == ',') { - if (git_xdiff_scan_int(&header, &range->old_lines) < 0) + if (git_xdiff_scan_int(&header, &hunk->old_lines) < 0) return -1; } else - range->old_lines = 1; - if (git_xdiff_scan_int(&header, &range->new_start) < 0) + hunk->old_lines = 1; + if (git_xdiff_scan_int(&header, &hunk->new_start) < 0) return -1; if (*header == ',') { - if (git_xdiff_scan_int(&header, &range->new_lines) < 0) + if (git_xdiff_scan_int(&header, &hunk->new_lines) < 0) return -1; } else - range->new_lines = 1; - if (range->old_start < 0 || range->new_start < 0) + hunk->new_lines = 1; + if (hunk->old_start < 0 || hunk->new_start < 0) return -1; return 0; @@ -51,38 +51,96 @@ static int git_xdiff_parse_hunk(git_diff_range *range, const char *header) typedef struct { git_xdiff_output *xo; - git_diff_patch *patch; - git_diff_range range; + git_patch *patch; + git_diff_hunk hunk; + int old_lineno, new_lineno; } git_xdiff_info; +static int diff_update_lines( + git_xdiff_info *info, + git_diff_line *line, + const char *content, + size_t content_len) +{ + const char *scan = content, *scan_end = content + content_len; + + for (line->num_lines = 0; scan < scan_end; ++scan) + if (*scan == '\n') + ++line->num_lines; + + line->content = content; + line->content_len = content_len; + + /* expect " "/"-"/"+", then data */ + switch (line->origin) { + case GIT_DIFF_LINE_ADDITION: + case GIT_DIFF_LINE_DEL_EOFNL: + line->old_lineno = -1; + line->new_lineno = info->new_lineno; + info->new_lineno += (int)line->num_lines; + break; + case GIT_DIFF_LINE_DELETION: + case GIT_DIFF_LINE_ADD_EOFNL: + line->old_lineno = info->old_lineno; + line->new_lineno = -1; + info->old_lineno += (int)line->num_lines; + break; + case GIT_DIFF_LINE_CONTEXT: + case GIT_DIFF_LINE_CONTEXT_EOFNL: + line->old_lineno = info->old_lineno; + line->new_lineno = info->new_lineno; + info->old_lineno += (int)line->num_lines; + info->new_lineno += (int)line->num_lines; + break; + default: + giterr_set(GITERR_INVALID, "Unknown diff line origin %02x", + (unsigned int)line->origin); + return -1; + } + + return 0; +} + static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len) { git_xdiff_info *info = priv; - git_diff_patch *patch = info->patch; - const git_diff_delta *delta = git_diff_patch_delta(patch); + git_patch *patch = info->patch; + const git_diff_delta *delta = git_patch_get_delta(patch); git_diff_output *output = &info->xo->output; + git_diff_line line; if (len == 1) { - output->error = git_xdiff_parse_hunk(&info->range, bufs[0].ptr); + output->error = git_xdiff_parse_hunk(&info->hunk, bufs[0].ptr); if (output->error < 0) return output->error; + info->hunk.header_len = bufs[0].size; + if (info->hunk.header_len >= sizeof(info->hunk.header)) + info->hunk.header_len = sizeof(info->hunk.header) - 1; + memcpy(info->hunk.header, bufs[0].ptr, info->hunk.header_len); + info->hunk.header[info->hunk.header_len] = '\0'; + if (output->hunk_cb != NULL && - output->hunk_cb(delta, &info->range, - bufs[0].ptr, bufs[0].size, output->payload)) + output->hunk_cb(delta, &info->hunk, output->payload)) output->error = GIT_EUSER; + + info->old_lineno = info->hunk.old_start; + info->new_lineno = info->hunk.new_start; } if (len == 2 || len == 3) { /* expect " "/"-"/"+", then data */ - char origin = + line.origin = (*bufs[0].ptr == '+') ? GIT_DIFF_LINE_ADDITION : (*bufs[0].ptr == '-') ? GIT_DIFF_LINE_DELETION : GIT_DIFF_LINE_CONTEXT; - if (output->data_cb != NULL && - output->data_cb(delta, &info->range, - origin, bufs[1].ptr, bufs[1].size, output->payload)) + output->error = diff_update_lines( + info, &line, bufs[1].ptr, bufs[1].size); + + if (!output->error && + output->data_cb != NULL && + output->data_cb(delta, &info->hunk, &line, output->payload)) output->error = GIT_EUSER; } @@ -92,21 +150,24 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len) * If we have a '-' and a third buf, then we have removed a line * with out a newline but added a blank line, so ADD_EOFNL. */ - char origin = + line.origin = (*bufs[0].ptr == '+') ? GIT_DIFF_LINE_DEL_EOFNL : (*bufs[0].ptr == '-') ? GIT_DIFF_LINE_ADD_EOFNL : GIT_DIFF_LINE_CONTEXT_EOFNL; - if (output->data_cb != NULL && - output->data_cb(delta, &info->range, - origin, bufs[2].ptr, bufs[2].size, output->payload)) + output->error = diff_update_lines( + info, &line, bufs[2].ptr, bufs[2].size); + + if (!output->error && + output->data_cb != NULL && + output->data_cb(delta, &info->hunk, &line, output->payload)) output->error = GIT_EUSER; } return output->error; } -static int git_xdiff(git_diff_output *output, git_diff_patch *patch) +static int git_xdiff(git_diff_output *output, git_patch *patch) { git_xdiff_output *xo = (git_xdiff_output *)output; git_xdiff_info info; @@ -120,7 +181,7 @@ static int git_xdiff(git_diff_output *output, git_diff_patch *patch) xo->callback.priv = &info; git_diff_find_context_init( - &xo->config.find_func, &findctxt, git_diff_patch__driver(patch)); + &xo->config.find_func, &findctxt, git_patch__driver(patch)); xo->config.find_func_priv = &findctxt; if (xo->config.find_func != NULL) @@ -132,8 +193,8 @@ static int git_xdiff(git_diff_output *output, git_diff_patch *patch) * updates are needed to xo->params.flags */ - git_diff_patch__old_data(&xd_old_data.ptr, &xd_old_data.size, patch); - git_diff_patch__new_data(&xd_new_data.ptr, &xd_new_data.size, patch); + git_patch__old_data(&xd_old_data.ptr, &xd_old_data.size, patch); + git_patch__new_data(&xd_new_data.ptr, &xd_new_data.size, patch); xdl_diff(&xd_old_data, &xd_new_data, &xo->params, &xo->config, &xo->callback); @@ -145,7 +206,7 @@ static int git_xdiff(git_diff_output *output, git_diff_patch *patch) void git_xdiff_init(git_xdiff_output *xo, const git_diff_options *opts) { - uint32_t flags = opts ? opts->flags : GIT_DIFF_NORMAL; + uint32_t flags = opts ? opts->flags : 0; xo->output.diff_cb = git_xdiff; @@ -161,6 +222,11 @@ void git_xdiff_init(git_xdiff_output *xo, const git_diff_options *opts) if (flags & GIT_DIFF_IGNORE_WHITESPACE_EOL) xo->params.flags |= XDF_IGNORE_WHITESPACE_AT_EOL; + if (flags & GIT_DIFF_PATIENCE) + xo->params.flags |= XDF_PATIENCE_DIFF; + if (flags & GIT_DIFF_MINIMAL) + xo->params.flags |= XDF_NEED_MINIMAL; + memset(&xo->callback, 0, sizeof(xo->callback)); xo->callback.outf = git_xdiff_cb; } diff --git a/src/pathspec.c b/src/pathspec.c index d56d03918..1e7e65e90 100644 --- a/src/pathspec.c +++ b/src/pathspec.c @@ -585,7 +585,7 @@ int git_pathspec_match_tree( int git_pathspec_match_diff( git_pathspec_match_list **out, - git_diff_list *diff, + git_diff *diff, uint32_t flags, git_pathspec *ps) { diff --git a/src/reset.c b/src/reset.c index 87dc45a3f..a9780bfbc 100644 --- a/src/reset.c +++ b/src/reset.c @@ -24,10 +24,9 @@ int git_reset_default( { git_object *commit = NULL; git_tree *tree = NULL; - git_diff_list *diff = NULL; + git_diff *diff = NULL; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - size_t i; - git_diff_delta *delta; + size_t i, max_i; git_index_entry entry; int error; git_index *index = NULL; @@ -58,7 +57,9 @@ int git_reset_default( &diff, repo, tree, index, &opts)) < 0) goto cleanup; - git_vector_foreach(&diff->deltas, i, delta) { + for (i = 0, max_i = git_diff_num_deltas(diff); i < max_i; ++i) { + const git_diff_delta *delta = git_diff_get_delta(diff, i); + if ((error = git_index_conflict_remove(index, delta->old_file.path)) < 0) goto cleanup; @@ -85,7 +86,7 @@ cleanup: git_object_free(commit); git_tree_free(tree); git_index_free(index); - git_diff_list_free(diff); + git_diff_free(diff); return error; } diff --git a/src/stash.c b/src/stash.c index 7742eee19..6fa74ac0a 100644 --- a/src/stash.c +++ b/src/stash.c @@ -153,65 +153,61 @@ cleanup: return error; } -struct cb_data { - git_index *index; - - int error; - +struct stash_update_rules { bool include_changed; bool include_untracked; bool include_ignored; }; -static int update_index_cb( - const git_diff_delta *delta, - float progress, - void *payload) +static int stash_update_index_from_diff( + git_index *index, + const git_diff *diff, + struct stash_update_rules *data) { - struct cb_data *data = (struct cb_data *)payload; - const char *add_path = NULL; - - GIT_UNUSED(progress); - - switch (delta->status) { - case GIT_DELTA_IGNORED: - if (data->include_ignored) - add_path = delta->new_file.path; - break; - - case GIT_DELTA_UNTRACKED: - if (data->include_untracked) - add_path = delta->new_file.path; - break; - - case GIT_DELTA_ADDED: - case GIT_DELTA_MODIFIED: - if (data->include_changed) - add_path = delta->new_file.path; - break; - - case GIT_DELTA_DELETED: - if (!data->include_changed) + int error = 0; + size_t d, max_d = git_diff_num_deltas(diff); + + for (d = 0; !error && d < max_d; ++d) { + const char *add_path = NULL; + const git_diff_delta *delta = git_diff_get_delta(diff, d); + + switch (delta->status) { + case GIT_DELTA_IGNORED: + if (data->include_ignored) + add_path = delta->new_file.path; + break; + + case GIT_DELTA_UNTRACKED: + if (data->include_untracked) + add_path = delta->new_file.path; break; - if (git_index_find(NULL, data->index, delta->old_file.path) == 0) - data->error = git_index_remove( - data->index, delta->old_file.path, 0); - break; - - default: - /* Unimplemented */ - giterr_set( - GITERR_INVALID, - "Cannot update index. Unimplemented status (%d)", - delta->status); - data->error = -1; - break; - } - if (add_path != NULL) - data->error = git_index_add_bypath(data->index, add_path); + case GIT_DELTA_ADDED: + case GIT_DELTA_MODIFIED: + if (data->include_changed) + add_path = delta->new_file.path; + break; - return data->error; + case GIT_DELTA_DELETED: + if (data->include_changed && + !git_index_find(NULL, index, delta->old_file.path)) + error = git_index_remove(index, delta->old_file.path, 0); + break; + + default: + /* Unimplemented */ + giterr_set( + GITERR_INVALID, + "Cannot update index. Unimplemented status (%d)", + delta->status); + return -1; + } + + if (add_path != NULL) + error = git_index_add_bypath(index, add_path); + } + + return error; } static int build_untracked_tree( @@ -221,15 +217,13 @@ static int build_untracked_tree( uint32_t flags) { git_tree *i_tree = NULL; - git_diff_list *diff = NULL; + git_diff *diff = NULL; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - struct cb_data data = {0}; + struct stash_update_rules data = {0}; int error; git_index_clear(index); - data.index = index; - if (flags & GIT_STASH_INCLUDE_UNTRACKED) { opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_RECURSE_UNTRACKED_DIRS; @@ -248,18 +242,13 @@ static int build_untracked_tree( &diff, git_index_owner(index), i_tree, &opts)) < 0) goto cleanup; - if ((error = git_diff_foreach( - diff, update_index_cb, NULL, NULL, &data)) < 0) - { - if (error == GIT_EUSER) - error = data.error; + if ((error = stash_update_index_from_diff(index, diff, &data)) < 0) goto cleanup; - } error = build_tree_from_index(tree_out, index); cleanup: - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(i_tree); return error; } @@ -311,9 +300,9 @@ static int build_workdir_tree( { git_repository *repo = git_index_owner(index); git_tree *b_tree = NULL; - git_diff_list *diff = NULL, *diff2 = NULL; + git_diff *diff = NULL; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - struct cb_data data = {0}; + struct stash_update_rules data = {0}; int error; opts.flags = GIT_DIFF_IGNORE_SUBMODULES; @@ -321,33 +310,19 @@ static int build_workdir_tree( if ((error = git_commit_tree(&b_tree, b_commit)) < 0) goto cleanup; - if ((error = git_diff_tree_to_index(&diff, repo, b_tree, NULL, &opts)) < 0) - goto cleanup; - - if ((error = git_diff_index_to_workdir(&diff2, repo, NULL, &opts)) < 0) - goto cleanup; - - if ((error = git_diff_merge(diff, diff2)) < 0) + if ((error = git_diff_tree_to_workdir_with_index( + &diff, repo, b_tree, &opts)) < 0) goto cleanup; - data.index = index; data.include_changed = true; - if ((error = git_diff_foreach( - diff, update_index_cb, NULL, NULL, &data)) < 0) - { - if (error == GIT_EUSER) - error = data.error; + if ((error = stash_update_index_from_diff(index, diff, &data)) < 0) goto cleanup; - } - - if ((error = build_tree_from_index(tree_out, index)) < 0) - goto cleanup; + error = build_tree_from_index(tree_out, index); cleanup: - git_diff_list_free(diff); - git_diff_list_free(diff2); + git_diff_free(diff); git_tree_free(b_tree); return error; diff --git a/src/status.c b/src/status.c index be40b9f83..2b84794b5 100644 --- a/src/status.c +++ b/src/status.c @@ -52,7 +52,7 @@ static unsigned int index_delta2status(const git_diff_delta *head2idx) } static unsigned int workdir_delta2status( - git_diff_list *diff, git_diff_delta *idx2wd) + git_diff *diff, git_diff_delta *idx2wd) { git_status_t st = GIT_STATUS_CURRENT; @@ -361,8 +361,8 @@ void git_status_list_free(git_status_list *status) if (status == NULL) return; - git_diff_list_free(status->head2idx); - git_diff_list_free(status->idx2wd); + git_diff_free(status->head2idx); + git_diff_free(status->idx2wd); git_vector_foreach(&status->paired, i, status_entry) git__free(status_entry); diff --git a/src/status.h b/src/status.h index b58e0ebd6..33008b89c 100644 --- a/src/status.h +++ b/src/status.h @@ -14,8 +14,8 @@ struct git_status_list { git_status_options opts; - git_diff_list *head2idx; - git_diff_list *idx2wd; + git_diff *head2idx; + git_diff *idx2wd; git_vector paired; }; diff --git a/src/submodule.c b/src/submodule.c index 12ade83fe..18d80f0a9 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -1528,7 +1528,7 @@ static void submodule_get_wd_status( (sm->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID) ? &sm->wd_oid : NULL; git_tree *sm_head = NULL; git_diff_options opt = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff; + git_diff *diff; *status = *status & ~GIT_SUBMODULE_STATUS__WD_FLAGS; @@ -1568,7 +1568,7 @@ static void submodule_get_wd_status( else { if (git_diff_num_deltas(diff) > 0) *status |= GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED; - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; } @@ -1588,7 +1588,7 @@ static void submodule_get_wd_status( if (git_diff_num_deltas(diff) != untracked) *status |= GIT_SUBMODULE_STATUS_WD_WD_MODIFIED; - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; } } |