static char *
gen_merge_description (SeafRepo *repo,
                       const char *merged_root,
                       const char *p1_root,
                       const char *p2_root)
{
    GList *p;
    GList *results = NULL;
    char *desc;
    
    diff_merge_roots (repo->store_id, repo->version,
                      merged_root, p1_root, p2_root, &results, TRUE);

    desc = diff_results_to_description (results);

    for (p = results; p; p = p->next) {
        DiffEntry *de = p->data;
        diff_entry_free (de);
    }
    g_list_free (results);

    return desc;
}
Esempio n. 2
0
/*
 * If the missing virtual repo is renamed, update database entry;
 * otherwise delete the virtual repo.
 */
static void
handle_missing_virtual_repo (SeafRepoManager *mgr,
                             SeafRepo *repo, SeafCommit *head, SeafVirtRepo *vinfo)
{
    SeafCommit *parent = NULL;
    char *old_dir_id = NULL;
    GList *diff_res = NULL, *ptr;
    DiffEntry *de;

    parent = seaf_commit_manager_get_commit (seaf->commit_mgr,
                                             head->repo_id, head->version,
                                             head->parent_id);
    if (!parent) {
        seaf_warning ("Failed to find commit %s:%s.\n", head->repo_id, head->parent_id);
        return;
    }

    int rc = diff_commits (parent, head, &diff_res, TRUE);
    if (rc < 0) {
        seaf_warning ("Failed to diff commit %s to %s.\n",
                      parent->commit_id, head->commit_id);
        seaf_commit_unref (parent);
        return;
    }

    char *path = vinfo->path, *sub_path, *p, *par_path;
    gboolean is_renamed = FALSE;
    p = &path[strlen(path)];
    par_path = g_strdup(path);
    sub_path = NULL;

    while (1) {
        GError *error = NULL;
        old_dir_id = seaf_fs_manager_get_seafdir_id_by_path (seaf->fs_mgr,
                                                             repo->store_id,
                                                             repo->version,
                                                             parent->root_id,
                                                             par_path, &error);
        if (!old_dir_id) {
            if (error && error->code == SEAF_ERR_PATH_NO_EXIST) {
                seaf_warning ("Failed to find %s under commit %s in repo %s.\n",
                              par_path, parent->commit_id, repo->store_id);
                seaf_debug ("Delete virtual repo %.10s.\n", vinfo->repo_id);
                seaf_repo_manager_del_virtual_repo (mgr, vinfo->repo_id);
                g_clear_error (&error);
            }
            goto out;
        }

        char de_id[41];
        char *new_path;

        for (ptr = diff_res; ptr; ptr = ptr->next) {
            de = ptr->data;
            if (de->status == DIFF_STATUS_DIR_RENAMED) {
                rawdata_to_hex (de->sha1, de_id, 20);
                if (strcmp (de_id, old_dir_id) == 0) {
                    if (sub_path != NULL)
                        new_path = g_strconcat ("/", de->new_name, "/", sub_path, NULL);
                    else
                        new_path = g_strconcat ("/", de->new_name, NULL);
                    seaf_debug ("Updating path of virtual repo %s to %s.\n",
                                vinfo->repo_id, new_path);
                    set_virtual_repo_base_commit_path (vinfo->repo_id,
                                                       head->commit_id, new_path);
                    is_renamed = TRUE;
                    break;
                }
            }
        }
        g_free (old_dir_id);

        if (is_renamed)
            break;

        while (--p != path && *p != '/');

        if (p == path)
            break;

        g_free (par_path);
        g_free (sub_path);
        par_path = g_strndup (path, p - path);
        sub_path = g_strdup (p + 1);
    }

    if (!is_renamed) {
        seaf_debug ("Delete virtual repo %.10s.\n", vinfo->repo_id);
        seaf_repo_manager_del_virtual_repo (mgr, vinfo->repo_id);
    }

out:
    g_free (par_path);
    g_free (sub_path);

    for (ptr = diff_res; ptr; ptr = ptr->next)
        diff_entry_free ((DiffEntry *)ptr->data);
    g_list_free (diff_res);

    seaf_commit_unref (parent);
}