diff options
Diffstat (limited to 'src/stash.c')
-rw-r--r-- | src/stash.c | 170 |
1 files changed, 75 insertions, 95 deletions
diff --git a/src/stash.c b/src/stash.c index 1222634d5..083c2a4cd 100644 --- a/src/stash.c +++ b/src/stash.c @@ -27,7 +27,7 @@ static int retrieve_head(git_reference **out, git_repository *repo) { int error = git_repository_head(out, repo); - if (error == GIT_EORPHANEDHEAD) + if (error == GIT_EUNBORNBRANCH) return create_error(error, "You do not have the initial commit yet."); return error; @@ -117,7 +117,7 @@ static int build_tree_from_index(git_tree **out, git_index *index) static int commit_index( git_commit **i_commit, git_index *index, - git_signature *stasher, + const git_signature *stasher, const char *message, const git_commit *parent) { @@ -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; - 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_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 && + !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 data->error; + 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; } @@ -267,7 +256,7 @@ cleanup: static int commit_untracked( git_commit **u_commit, git_index *index, - git_signature *stasher, + const git_signature *stasher, const char *message, git_commit *i_commit, uint32_t flags) @@ -311,41 +300,29 @@ 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; - if ((error = git_commit_tree(&b_tree, b_commit)) < 0) - goto cleanup; + opts.flags = GIT_DIFF_IGNORE_SUBMODULES; - 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) + if ((error = git_commit_tree(&b_tree, b_commit)) < 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; @@ -354,7 +331,7 @@ cleanup: static int commit_worktree( git_oid *w_commit_oid, git_index *index, - git_signature *stasher, + const git_signature *stasher, const char *message, git_commit *i_commit, git_commit *b_commit, @@ -431,17 +408,19 @@ cleanup: static int update_reflog( git_oid *w_commit_oid, git_repository *repo, - git_signature *stasher, + const git_signature *stasher, const char *message) { - git_reference *stash = NULL; + git_reference *stash; git_reflog *reflog = NULL; int error; if ((error = git_reference_create(&stash, repo, GIT_REFS_STASH_FILE, w_commit_oid, 1)) < 0) goto cleanup; - if ((error = git_reflog_read(&reflog, stash)) < 0) + git_reference_free(stash); + + if ((error = git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE) < 0)) goto cleanup; if ((error = git_reflog_append(reflog, w_commit_oid, stasher, message)) < 0) @@ -451,7 +430,6 @@ static int update_reflog( goto cleanup; cleanup: - git_reference_free(stash); git_reflog_free(reflog); return error; } @@ -474,12 +452,14 @@ static int ensure_there_are_changes_to_stash( git_status_options opts = GIT_STATUS_OPTIONS_INIT; opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; + opts.flags = GIT_STATUS_OPT_EXCLUDE_SUBMODULES; + if (include_untracked_files) - opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | + opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; if (include_ignored_files) - opts.flags = GIT_STATUS_OPT_INCLUDE_IGNORED; + opts.flags |= GIT_STATUS_OPT_INCLUDE_IGNORED; error = git_status_foreach_ext(repo, &opts, is_dirty_cb, NULL); @@ -510,7 +490,7 @@ static int reset_index_and_workdir( int git_stash_save( git_oid *out, git_repository *repo, - git_signature *stasher, + const git_signature *stasher, const char *message, uint32_t flags) { @@ -595,7 +575,7 @@ int git_stash_foreach( if (error < 0) goto cleanup; - if ((error = git_reflog_read(&reflog, stash)) < 0) + if ((error = git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)) < 0) goto cleanup; max = git_reflog_entrycount(reflog); @@ -629,7 +609,7 @@ int git_stash_drop( if ((error = git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE)) < 0) return error; - if ((error = git_reflog_read(&reflog, stash)) < 0) + if ((error = git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)) < 0) goto cleanup; max = git_reflog_entrycount(reflog); |