vendor/libgit2/src/checkout.c in rugged-1.0.1 vs vendor/libgit2/src/checkout.c in rugged-1.1.0

- old
+ new

@@ -42,11 +42,10 @@ CHECKOUT_ACTION__UPDATE_SUBMODULE = 4, CHECKOUT_ACTION__CONFLICT = 8, CHECKOUT_ACTION__REMOVE_CONFLICT = 16, CHECKOUT_ACTION__UPDATE_CONFLICT = 32, CHECKOUT_ACTION__MAX = 32, - CHECKOUT_ACTION__DEFER_REMOVE = 64, CHECKOUT_ACTION__REMOVE_AND_UPDATE = (CHECKOUT_ACTION__UPDATE_BLOB | CHECKOUT_ACTION__REMOVE), }; typedef struct { @@ -194,11 +193,11 @@ git_error_clear(); return true; } if (git_submodule_status(&sm_status, data->repo, wditem->path, GIT_SUBMODULE_IGNORE_UNSPECIFIED) < 0 || - GIT_SUBMODULE_STATUS_IS_WD_DIRTY(sm_status)) + GIT_SUBMODULE_STATUS_IS_WD_DIRTY(sm_status)) rval = true; else if ((sm_oid = git_submodule_wd_id(sm)) == NULL) rval = false; else rval = (git_oid__cmp(&baseitem->id, sm_oid) != 0); @@ -215,13 +214,14 @@ * us to avoid touching the disk. */ ie = git_index_get_bypath(data->index, wditem->path, 0); if (ie != NULL && - git_index_time_eq(&wditem->mtime, &ie->mtime) && - wditem->file_size == ie->file_size && - !is_filemode_changed(wditem->mode, ie->mode, data->respect_filemode)) { + !git_index_entry_newer_than_index(ie, data->index) && + git_index_time_eq(&wditem->mtime, &ie->mtime) && + wditem->file_size == ie->file_size && + !is_filemode_changed(wditem->mode, ie->mode, data->respect_filemode)) { /* The workdir is modified iff the index entry is modified */ return !is_workdir_base_or_new(&ie->id, baseitem, newitem) || is_filemode_changed(baseitem->mode, ie->mode, data->respect_filemode); } @@ -271,13 +271,12 @@ if (delta->new_file.mode == GIT_FILEMODE_LINK && wd != NULL) *action |= CHECKOUT_ACTION__REMOVE; /* if the file is on disk and doesn't match our mode, force update */ if (wd && - GIT_PERMS_IS_EXEC(wd->mode) != - GIT_PERMS_IS_EXEC(delta->new_file.mode)) - *action |= CHECKOUT_ACTION__REMOVE; + GIT_PERMS_IS_EXEC(wd->mode) != GIT_PERMS_IS_EXEC(delta->new_file.mode)) + *action |= CHECKOUT_ACTION__REMOVE; notify = GIT_CHECKOUT_NOTIFY_UPDATED; } if ((*action & CHECKOUT_ACTION__CONFLICT) != 0) @@ -369,13 +368,18 @@ const git_index_entry *wd = *wditem; if (!git_pathspec__match( pathspec, wd->path, (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0, - git_iterator_ignore_case(workdir), NULL, NULL)) - return git_iterator_advance(wditem, workdir); + git_iterator_ignore_case(workdir), NULL, NULL)) { + if (wd->mode == GIT_FILEMODE_TREE) + return git_iterator_advance_into(wditem, workdir); + else + return git_iterator_advance(wditem, workdir); + } + /* check if item is tracked in the index but not in the checkout diff */ if (data->index != NULL) { size_t pos; error = git_index__find_pos( @@ -792,17 +796,17 @@ const checkout_conflictdata *ca = a; const checkout_conflictdata *cb = b; int diff; if ((diff = checkout_idxentry_cmp(ca->ancestor, cb->ancestor)) == 0 && - (diff = checkout_idxentry_cmp(ca->ours, cb->theirs)) == 0) + (diff = checkout_idxentry_cmp(ca->ours, cb->theirs)) == 0) diff = checkout_idxentry_cmp(ca->theirs, cb->theirs); return diff; } -int checkout_conflictdata_empty( +static int checkout_conflictdata_empty( const git_vector *conflicts, size_t idx, void *payload) { checkout_conflictdata *conflict; GIT_UNUSED(payload); @@ -1171,11 +1175,11 @@ len = git_index_entrycount(index); /* Find d/f conflicts */ git_vector_foreach(&data->update_conflicts, i, conflict) { if ((conflict->ours && conflict->theirs) || - (!conflict->ours && !conflict->theirs)) + (!conflict->ours && !conflict->theirs)) continue; path = conflict->ours ? conflict->ours->path : conflict->theirs->path; @@ -1220,12 +1224,12 @@ if (data->strategy & GIT_CHECKOUT_SKIP_UNMERGED) return 0; if ((error = checkout_conflicts_load(data, workdir, pathspec)) < 0 || - (error = checkout_conflicts_coalesce_renames(data)) < 0 || - (error = checkout_conflicts_mark_directoryfile(data)) < 0) + (error = checkout_conflicts_coalesce_renames(data)) < 0 || + (error = checkout_conflicts_mark_directoryfile(data)) < 0) goto done; done: return error; } @@ -1302,18 +1306,19 @@ git_pool pathpool; git_diff_delta *delta; size_t i, *counts = NULL; uint32_t *actions = NULL; - git_pool_init(&pathpool, 1); + if (git_pool_init(&pathpool, 1) < 0) + return -1; if (data->opts.paths.count > 0 && - git_pathspec__vinit(&pathspec, &data->opts.paths, &pathpool) < 0) + git_pathspec__vinit(&pathspec, &data->opts.paths, &pathpool) < 0) return -1; if ((error = git_iterator_current(&wditem, workdir)) < 0 && - error != GIT_ITEROVER) + error != GIT_ITEROVER) goto fail; deltas = &data->diff->deltas; *counts_ptr = counts = git__calloc(CHECKOUT_ACTION__MAX+1, sizeof(size_t)); @@ -1348,23 +1353,22 @@ goto fail; counts[CHECKOUT_ACTION__REMOVE] += data->removes.length; if (counts[CHECKOUT_ACTION__CONFLICT] > 0 && - (data->strategy & GIT_CHECKOUT_ALLOW_CONFLICTS) == 0) - { + (data->strategy & GIT_CHECKOUT_ALLOW_CONFLICTS) == 0) { git_error_set(GIT_ERROR_CHECKOUT, "%"PRIuZ" %s checkout", counts[CHECKOUT_ACTION__CONFLICT], counts[CHECKOUT_ACTION__CONFLICT] == 1 ? "conflict prevents" : "conflicts prevent"); error = GIT_ECONFLICT; goto fail; } if ((error = checkout_get_remove_conflicts(data, workdir, &pathspec)) < 0 || - (error = checkout_get_update_conflicts(data, workdir, &pathspec)) < 0) + (error = checkout_get_update_conflicts(data, workdir, &pathspec)) < 0) goto fail; counts[CHECKOUT_ACTION__REMOVE_CONFLICT] = git_vector_length(&data->remove_conflicts); counts[CHECKOUT_ACTION__UPDATE_CONFLICT] = git_vector_length(&data->update_conflicts); @@ -1851,48 +1855,19 @@ } return 0; } -static int checkout_deferred_remove(git_repository *repo, const char *path) -{ -#if 0 - int error = git_futils_rmdir_r( - path, data->opts.target_directory, GIT_RMDIR_EMPTY_PARENTS); - - if (error == GIT_ENOTFOUND) { - error = 0; - git_error_clear(); - } - - return error; -#else - GIT_UNUSED(repo); - GIT_UNUSED(path); - assert(false); - return 0; -#endif -} - static int checkout_create_the_new( unsigned int *actions, checkout_data *data) { int error = 0; git_diff_delta *delta; size_t i; git_vector_foreach(&data->diff->deltas, i, delta) { - if (actions[i] & CHECKOUT_ACTION__DEFER_REMOVE) { - /* this had a blocker directory that should only be removed iff - * all of the contents of the directory were safely removed - */ - if ((error = checkout_deferred_remove( - data->repo, delta->old_file.path)) < 0) - return error; - } - if (actions[i] & CHECKOUT_ACTION__UPDATE_BLOB && !S_ISLNK(delta->new_file.mode)) { if ((error = checkout_blob(data, &delta->new_file)) < 0) return error; data->completed_steps++; report_progress(data, delta->new_file.path); @@ -1913,24 +1888,14 @@ static int checkout_create_submodules( unsigned int *actions, checkout_data *data) { - int error = 0; git_diff_delta *delta; size_t i; git_vector_foreach(&data->diff->deltas, i, delta) { - if (actions[i] & CHECKOUT_ACTION__DEFER_REMOVE) { - /* this has a blocker directory that should only be removed iff - * all of the contents of the directory were safely removed - */ - if ((error = checkout_deferred_remove( - data->repo, delta->old_file.path)) < 0) - return error; - } - if (actions[i] & CHECKOUT_ACTION__UPDATE_SUBMODULE) { int error = checkout_submodule(data, &delta->new_file); if (error < 0) return error; @@ -2518,13 +2483,12 @@ goto cleanup; } git_config_entry_free(conflict_style); } - git_pool_init(&data->pool, 1); - - if ((error = git_vector_init(&data->removes, 0, git__strcmp_cb)) < 0 || + if ((error = git_pool_init(&data->pool, 1)) < 0 || + (error = git_vector_init(&data->removes, 0, git__strcmp_cb)) < 0 || (error = git_vector_init(&data->remove_conflicts, 0, NULL)) < 0 || (error = git_vector_init(&data->update_conflicts, 0, NULL)) < 0 || (error = git_buf_puts(&data->target_path, data->opts.target_directory)) < 0 || (error = git_path_to_dir(&data->target_path)) < 0 || (error = git_strmap_new(&data->mkdir_map)) < 0) @@ -2542,10 +2506,21 @@ } #define CHECKOUT_INDEX_DONT_WRITE_MASK \ (GIT_CHECKOUT_DONT_UPDATE_INDEX | GIT_CHECKOUT_DONT_WRITE_INDEX) +GIT_INLINE(void) setup_pathspecs( + git_iterator_options *iter_opts, + const git_checkout_options *checkout_opts) +{ + if (checkout_opts && + (checkout_opts->checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)) { + iter_opts->pathlist.count = checkout_opts->paths.count; + iter_opts->pathlist.strings = checkout_opts->paths.strings; + } +} + int git_checkout_iterator( git_iterator *target, git_index *index, const git_checkout_options *opts) { @@ -2584,25 +2559,25 @@ GIT_ITERATOR_IGNORE_CASE : GIT_ITERATOR_DONT_IGNORE_CASE; workdir_opts.flags |= GIT_ITERATOR_DONT_AUTOEXPAND; workdir_opts.start = data.pfx; workdir_opts.end = data.pfx; + setup_pathspecs(&workdir_opts, opts); + if ((error = git_iterator_reset_range(target, data.pfx, data.pfx)) < 0 || (error = git_iterator_for_workdir_ext( &workdir, data.repo, data.opts.target_directory, index, NULL, &workdir_opts)) < 0) goto cleanup; baseline_opts.flags = git_iterator_ignore_case(target) ? GIT_ITERATOR_IGNORE_CASE : GIT_ITERATOR_DONT_IGNORE_CASE; baseline_opts.start = data.pfx; baseline_opts.end = data.pfx; - if (opts && (opts->checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)) { - baseline_opts.pathlist.count = opts->paths.count; - baseline_opts.pathlist.strings = opts->paths.strings; - } + setup_pathspecs(&baseline_opts, opts); + if (data.opts.baseline_index) { if ((error = git_iterator_for_index( &baseline, git_index_owner(data.opts.baseline_index), data.opts.baseline_index, &baseline_opts)) < 0) goto cleanup; @@ -2687,10 +2662,11 @@ int git_checkout_index( git_repository *repo, git_index *index, const git_checkout_options *opts) { + git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT; int error, owned = 0; git_iterator *index_i; if (!index && !repo) { git_error_set(GIT_ERROR_CHECKOUT, @@ -2714,11 +2690,13 @@ if (!index && (error = git_repository_index__weakptr(&index, repo)) < 0) return error; GIT_REFCOUNT_INC(index); - if (!(error = git_iterator_for_index(&index_i, repo, index, NULL))) + setup_pathspecs(&iter_opts, opts); + + if (!(error = git_iterator_for_index(&index_i, repo, index, &iter_opts))) error = git_checkout_iterator(index_i, index, opts); if (owned) GIT_REFCOUNT_OWN(index, NULL); @@ -2771,14 +2749,11 @@ } if ((error = git_repository_index(&index, repo)) < 0) return error; - if (opts && (opts->checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)) { - iter_opts.pathlist.count = opts->paths.count; - iter_opts.pathlist.strings = opts->paths.strings; - } + setup_pathspecs(&iter_opts, opts); if (!(error = git_iterator_for_tree(&tree_i, tree, &iter_opts))) error = git_checkout_iterator(tree_i, index, opts); git_iterator_free(tree_i); @@ -2801,9 +2776,11 @@ GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_checkout_options, GIT_CHECKOUT_OPTIONS_INIT); return 0; } +#ifndef GIT_DEPRECATE_HARD int git_checkout_init_options(git_checkout_options *opts, unsigned int version) { return git_checkout_options_init(opts, version); } +#endif