static int submodules_from_index(git_strmap *map, git_index *idx) { int error; git_iterator *i; const git_index_entry *entry; if ((error = git_iterator_for_index(&i, idx, 0, NULL, NULL)) < 0) return error; while (!(error = git_iterator_advance(&entry, i))) { khiter_t pos = git_strmap_lookup_index(map, entry->path); git_submodule *sm; if (git_strmap_valid_index(map, pos)) { sm = git_strmap_value_at(map, pos); if (S_ISGITLINK(entry->mode)) submodule_update_from_index_entry(sm, entry); else sm->flags |= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE; } else if (S_ISGITLINK(entry->mode)) { if (!submodule_get_or_create(&sm, git_index_owner(idx), map, entry->path)) { submodule_update_from_index_entry(sm, entry); git_submodule_free(sm); } } } if (error == GIT_ITEROVER) error = 0; git_iterator_free(i); return error; }
static int build_tree_from_index(git_tree **out, git_index *index) { int error; git_oid i_tree_oid; if ((error = git_index_write_tree(&i_tree_oid, index)) < 0) return -1; return git_tree_lookup(out, git_index_owner(index), &i_tree_oid); }
static int commit_untracked( git_commit **u_commit, git_index *index, const git_signature *stasher, const char *message, git_commit *i_commit, uint32_t flags) { git_tree *u_tree = NULL; git_oid u_commit_oid; git_buf msg = GIT_BUF_INIT; int error; if ((error = build_untracked_tree(&u_tree, index, i_commit, flags)) < 0) goto cleanup; if ((error = git_buf_printf(&msg, "untracked files on %s\n", message)) < 0) goto cleanup; if ((error = git_commit_create( &u_commit_oid, git_index_owner(index), NULL, stasher, stasher, NULL, git_buf_cstr(&msg), u_tree, 0, NULL)) < 0) goto cleanup; error = git_commit_lookup(u_commit, git_index_owner(index), &u_commit_oid); cleanup: git_tree_free(u_tree); git_buf_free(&msg); return error; }
static int commit_index( git_commit **i_commit, git_index *index, const git_signature *stasher, const char *message, const git_commit *parent) { git_tree *i_tree = NULL; git_oid i_commit_oid; git_buf msg = GIT_BUF_INIT; int error; if ((error = build_tree_from_index(&i_tree, index)) < 0) goto cleanup; if ((error = git_buf_printf(&msg, "index on %s\n", message)) < 0) goto cleanup; if ((error = git_commit_create( &i_commit_oid, git_index_owner(index), NULL, stasher, stasher, NULL, git_buf_cstr(&msg), i_tree, 1, &parent)) < 0) goto cleanup; error = git_commit_lookup(i_commit, git_index_owner(index), &i_commit_oid); cleanup: git_tree_free(i_tree); git_buf_free(&msg); return error; }
static int build_untracked_tree( git_tree **tree_out, git_index *index, git_commit *i_commit, uint32_t flags) { git_tree *i_tree = NULL; git_diff_list *diff = NULL; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; struct cb_data 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; data.include_untracked = true; } if (flags & GIT_STASH_INCLUDE_IGNORED) { opts.flags |= GIT_DIFF_INCLUDE_IGNORED; data.include_ignored = true; } if ((error = git_commit_tree(&i_tree, i_commit)) < 0) goto cleanup; if ((error = git_diff_tree_to_workdir( &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; goto cleanup; } error = build_tree_from_index(tree_out, index); cleanup: git_diff_list_free(diff); git_tree_free(i_tree); return error; }
static int build_workdir_tree( git_tree **tree_out, git_index *index, git_commit *b_commit) { git_repository *repo = git_index_owner(index); git_tree *b_tree = NULL; git_diff_list *diff = NULL, *diff2 = NULL; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; struct cb_data data = {0}; int error; 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) 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; goto cleanup; } if ((error = build_tree_from_index(tree_out, index)) < 0) goto cleanup; cleanup: git_diff_list_free(diff); git_diff_list_free(diff2); git_tree_free(b_tree); return error; }
static int commit_worktree( git_oid *w_commit_oid, git_index *index, const git_signature *stasher, const char *message, git_commit *i_commit, git_commit *b_commit, git_commit *u_commit) { int error = 0; git_tree *w_tree = NULL, *i_tree = NULL; const git_commit *parents[] = { NULL, NULL, NULL }; parents[0] = b_commit; parents[1] = i_commit; parents[2] = u_commit; if ((error = git_commit_tree(&i_tree, i_commit)) < 0) goto cleanup; if ((error = git_index_read_tree(index, i_tree)) < 0) goto cleanup; if ((error = build_workdir_tree(&w_tree, index, b_commit)) < 0) goto cleanup; error = git_commit_create( w_commit_oid, git_index_owner(index), NULL, stasher, stasher, NULL, message, w_tree, u_commit ? 3 : 2, parents); cleanup: git_tree_free(i_tree); git_tree_free(w_tree); return error; }