Beispiel #1
0
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;
}
Beispiel #2
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;
}
Beispiel #3
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}