int diff_merge (SeafCommit *merge, GList **results) { SeafCommit *parent1, *parent2; struct tree_desc t[3]; struct unpack_trees_options opts; struct index_state istate; g_assert (*results == NULL); g_assert (merge->parent_id != NULL && merge->second_parent_id != NULL); parent1 = seaf_commit_manager_get_commit (seaf->commit_mgr, merge->parent_id); if (!parent1) { seaf_warning ("failed to find commit %s.\n", merge->parent_id); return -1; } parent2 = seaf_commit_manager_get_commit (seaf->commit_mgr, merge->second_parent_id); if (!parent2) { seaf_warning ("failed to find commit %s.\n", merge->second_parent_id); seaf_commit_unref (parent1); return -1; } fill_tree_descriptor(&t[0], merge->root_id); fill_tree_descriptor(&t[1], parent1->root_id); fill_tree_descriptor(&t[2], parent2->root_id); seaf_commit_unref (parent1); seaf_commit_unref (parent2); /* Empty index */ memset(&istate, 0, sizeof(istate)); memset(&opts, 0, sizeof(opts)); opts.head_idx = -1; opts.index_only = 1; opts.merge = 1; opts.fn = threeway_diff; opts.unpack_data = results; opts.src_index = &istate; opts.dst_index = NULL; if (unpack_trees(3, t, &opts) < 0) { seaf_warning ("failed to unpack trees.\n"); return -1; } if (*results != NULL) diff_resolve_renames (results); tree_desc_free (&t[0]); tree_desc_free (&t[1]); tree_desc_free (&t[2]); return 0; }
int diff_commits (SeafCommit *commit1, SeafCommit *commit2, GList **results) { struct tree_desc t[2]; struct unpack_trees_options opts; struct index_state istate; g_assert (*results == NULL); if (strcmp (commit1->commit_id, commit2->commit_id) == 0) return 0; if (strcmp (commit1->root_id, EMPTY_SHA1) != 0) { fill_tree_descriptor(&t[0], commit1->root_id); } else { fill_tree_descriptor(&t[0], NULL); } if (strcmp (commit2->root_id, EMPTY_SHA1) != 0) { fill_tree_descriptor(&t[1], commit2->root_id); } else { fill_tree_descriptor(&t[1], NULL); } /* Empty index */ memset(&istate, 0, sizeof(istate)); memset(&opts, 0, sizeof(opts)); opts.head_idx = -1; opts.index_only = 1; opts.merge = 1; opts.fn = twoway_diff; opts.unpack_data = results; opts.src_index = &istate; opts.dst_index = NULL; if (unpack_trees(2, t, &opts) < 0) { seaf_warning ("failed to unpack trees.\n"); return -1; } if (results != NULL) diff_resolve_empty_dirs (results); if (*results != NULL) diff_resolve_renames (results); tree_desc_free (&t[0]); tree_desc_free (&t[1]); return 0; }
/* * Get the new blocks that need to be checked out if we ff to @remote. */ static int get_new_blocks_ff (SeafRepo *repo, SeafCommit *head, SeafCommit *remote, BlockList **bl) { SeafRepoManager *mgr = repo->manager; char index_path[SEAF_PATH_MAX]; struct tree_desc trees[2]; struct unpack_trees_options topts; struct index_state istate; int ret = 0; memset (&istate, 0, sizeof(istate)); snprintf (index_path, SEAF_PATH_MAX, "%s/%s", mgr->index_dir, repo->id); if (read_index_from (&istate, index_path) < 0) { g_warning ("Failed to load index.\n"); return -1; } fill_tree_descriptor (&trees[0], head->root_id); fill_tree_descriptor (&trees[1], remote->root_id); memset(&topts, 0, sizeof(topts)); topts.base = repo->worktree; topts.head_idx = -1; topts.src_index = &istate; topts.update = 1; topts.merge = 1; topts.fn = twoway_merge; /* unpack_trees() doesn't update index or worktree. */ if (unpack_trees (2, trees, &topts) < 0) { g_warning ("Failed to ff to commit %s.\n", remote->commit_id); ret = -1; goto out; } *bl = block_list_new (); collect_new_blocks_from_index (&topts.result, *bl); out: tree_desc_free (&trees[0]); tree_desc_free (&trees[1]); discard_index (&istate); discard_index (&topts.result); return ret; }
static int seafile_merge_trees(struct merge_options *o, struct unpack_trees_options *opts, SeafDir *common, SeafDir *head, SeafDir *merge, char **error) { int rc; struct tree_desc t[3]; memset(opts, 0, sizeof(*opts)); if (o->call_depth) opts->index_only = 1; else opts->update = 1; opts->merge = 1; opts->head_idx = 2; opts->base = o->worktree; opts->fn = threeway_merge; opts->src_index = o->index; opts->dst_index = o->index; if (o->crypt) opts->crypt = o->crypt; fill_tree_descriptor(t+0, common->dir_id); fill_tree_descriptor(t+1, head->dir_id); fill_tree_descriptor(t+2, merge->dir_id); rc = unpack_trees(3, t, opts); if (rc == 0) { discard_index(o->index); *(o->index) = opts->result; if (o->collect_blocks_only) collect_new_blocks_from_index (o->index, o->bl); } tree_desc_free (t); tree_desc_free (t+1); tree_desc_free (t+2); return rc; }
int diff_index(struct index_state *istate, SeafDir *root, GList **results) { struct tree_desc t; struct unpack_trees_options opts; memset(&opts, 0, sizeof(opts)); opts.head_idx = 1; opts.index_only = 1; /* Unmerged entries are handled in diff worktree. */ opts.skip_unmerged = 1; opts.merge = 1; opts.fn = oneway_diff; opts.unpack_data = results; opts.src_index = istate; opts.dst_index = NULL; fill_tree_descriptor(&t, root->dir_id); int ret = unpack_trees(1, &t, &opts); tree_desc_free (&t); return ret; }
static int fast_forward_checkout (SeafRepo *repo, SeafCommit *head, CloneTask *task) { SeafRepoManager *mgr = repo->manager; char index_path[SEAF_PATH_MAX]; struct tree_desc trees[2]; struct unpack_trees_options topts; struct index_state istate; int ret = 0; if (strcmp (head->root_id, task->root_id) == 0) return 0; memset (&istate, 0, sizeof(istate)); snprintf (index_path, SEAF_PATH_MAX, "%s/%s", mgr->index_dir, repo->id); if (read_index_from (&istate, index_path) < 0) { seaf_warning ("Failed to load index.\n"); return -1; } repo->index_corrupted = FALSE; fill_tree_descriptor (&trees[0], task->root_id); fill_tree_descriptor (&trees[1], head->root_id); memset(&topts, 0, sizeof(topts)); topts.base = task->worktree; topts.head_idx = -1; topts.src_index = &istate; topts.update = 1; topts.merge = 1; topts.fn = twoway_merge; if (repo->encrypted) { topts.crypt = seafile_crypt_new (repo->enc_version, repo->enc_key, repo->enc_iv); } if (unpack_trees (2, trees, &topts) < 0) { seaf_warning ("Failed to merge commit %s with work tree.\n", head->commit_id); ret = -1; goto out; } if (update_worktree (&topts, FALSE, head->commit_id, head->creator_name, NULL) < 0) { seaf_warning ("Failed to update worktree.\n"); ret = -1; goto out; } discard_index (&istate); istate = topts.result; if (update_index (&istate, index_path) < 0) { seaf_warning ("Failed to update index.\n"); } out: tree_desc_free (&trees[0]); tree_desc_free (&trees[1]); g_free (topts.crypt); discard_index (&istate); return ret; }