示例#1
0
static int
get_commit_start (CcnetProcessor *processor, int argc, char **argv)
{
    USE_PRIV;
    GString *buf = g_string_new (NULL);
    TransferTask *task = ((SeafileGetcommitV3Proc *)processor)->tx_task;
    SeafBranch *master = NULL;

    g_return_val_if_fail (task->session_token, -1);

    /* fs_roots can be non-NULL if transfer is resumed from NET_DOWN. */
    if (task->fs_roots != NULL)
        object_list_free (task->fs_roots);
    task->fs_roots = object_list_new ();

    priv->writer_id = seaf_obj_store_register_async_write (seaf->commit_mgr->obj_store,
                                                           task->repo_id,
                                                           task->repo_version,
                                                           commit_write_cb, processor);

    g_string_printf (buf, "remote %s seafile-putcommit-v3 %s %s",
                     processor->peer_id, 
                     task->head, task->session_token);

    ccnet_processor_send_request (processor, buf->str);
    g_string_free (buf, TRUE);

    seaf_branch_unref (master);

    return 0;
}
示例#2
0
static int
verify_repo (SeafRepo *repo)
{
    GList *branches, *ptr;
    SeafBranch *branch;
    int ret = 0;
    VerifyData data = {0};

    data.truncate_time = seaf_repo_manager_get_repo_truncate_time (repo->manager,
                                                                   repo->id);

    branches = seaf_branch_manager_get_branch_list (seaf->branch_mgr, repo->id);
    if (branches == NULL) {
        seaf_warning ("[GC] Failed to get branch list of repo %s.\n", repo->id);
        return -1;
    }

    for (ptr = branches; ptr != NULL; ptr = ptr->next) {
        branch = ptr->data;
        gboolean res = seaf_commit_manager_traverse_commit_tree (seaf->commit_mgr,
                                                                 branch->commit_id,
                                                                 traverse_commit,
                                                                 &data);
        seaf_branch_unref (branch);
        if (!res) {
            ret = -1;
            break;
        }
    }

    g_list_free (branches);

    return ret;
}
示例#3
0
static void *
merge_job (void *data)
{
    MergeAux *aux = data;
    CloneTask *task = aux->task;
    SeafRepo *repo = aux->repo;
    SeafBranch *local = NULL;
    SeafCommit *head = NULL;

    /* If we haven't indexed files in the worktree, index them now. */
    if (task->root_id[0] == 0) {
        if (seaf_repo_index_worktree_files (task->repo_id,
                                            task->worktree,
                                            task->passwd,
                                            task->root_id) < 0)
            return aux;
    }

    local = seaf_branch_manager_get_branch (seaf->branch_mgr, repo->id, "local");
    if (!local) {
        aux->success = FALSE;
        goto out;
    }

    head = seaf_commit_manager_get_commit (seaf->commit_mgr, local->commit_id);
    if (!head) {
        aux->success = FALSE;
        goto out;
    }

    if (check_fast_forward (head, task->root_id)) {
        seaf_debug ("[clone mgr] Fast forward.\n");
        if (fast_forward_checkout (repo, head, task) < 0)
            goto out;
    } else {
        if (real_merge (repo, head, task) < 0)
            goto out;

        /* Commit the result of merge. */
        GError *error = NULL;
        /* XXX: the commit code assumes repo->head is set. */
        repo->head = local;
        seaf_repo_index_commit (repo, "", &error);
        if (error) {
            seaf_warning ("Failed to commit after merge.\n");
            goto out;
        }
        repo->head = NULL;
    }

    /* Set repo head to mark checkout done. */
    seaf_repo_set_head (repo, local);

    aux->success = TRUE;

out:
    seaf_branch_unref (local);
    seaf_commit_unref (head);
    return aux;
}
示例#4
0
static int
send_repo_branch_info (CcnetProcessor *processor, const char *repo_id,
                       const char *branch)
                       
{
    SeafRepo *repo;
    SeafBranch *seaf_branch;
    
    repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
    if (!repo) {
         ccnet_processor_send_response (processor, SC_NO_REPO, SS_NO_REPO,
                                        NULL, 0);
         return 0;
    }

    seaf_branch = seaf_branch_manager_get_branch (seaf->branch_mgr,
                                                  repo_id, branch);
    if (seaf_branch == NULL) {
        ccnet_processor_send_response (processor, SC_NO_BRANCH, SS_NO_BRANCH,
                                       NULL, 0);
        return -1;
    }

    ccnet_processor_send_response (processor, SC_COMMIT_ID, SS_COMMIT_ID,
                                   seaf_branch->commit_id, 41);
    seaf_branch_unref (seaf_branch);

    return 0;

}
示例#5
0
static void
set_head_common (SeafRepo *repo, SeafBranch *branch)
{
    if (repo->head)
        seaf_branch_unref (repo->head);
    repo->head = branch;
    seaf_branch_ref(branch);
}
示例#6
0
void
seaf_repo_free (SeafRepo *repo)
{
    if (repo->name) g_free (repo->name);
    if (repo->desc) g_free (repo->desc);
    if (repo->category) g_free (repo->category);
    if (repo->head) seaf_branch_unref (repo->head);
    g_free (repo);
}
示例#7
0
void
seaf_branch_list_free (GList *blist)
{
    GList *ptr;

    for (ptr = blist; ptr; ptr = ptr->next) {
        seaf_branch_unref (ptr->data);
    }
    g_list_free (blist);
}
示例#8
0
static SeafRepo *
load_repo (SeafRepoManager *manager, const char *repo_id)
{
    SeafRepo *repo;
    SeafBranch *branch;
    SeafVirtRepo *vinfo = NULL;

    repo = seaf_repo_new(repo_id, NULL, NULL);
    if (!repo) {
        g_warning ("[repo mgr] failed to alloc repo.\n");
        return NULL;
    }

    repo->manager = manager;

    branch = seaf_branch_manager_get_branch (seaf->branch_mgr, repo_id, "master");
    if (!branch) {
        g_warning ("Failed to get master branch of repo %.8s.\n", repo_id);
        repo->is_corrupted = TRUE;
    } else {
        load_repo_commit (manager, repo, branch);
        seaf_branch_unref (branch);
    }

    if (repo->is_corrupted) {
        g_warning ("Repo %.8s is corrupted.\n", repo->id);
        seaf_repo_free (repo);
        return NULL;
    }

    vinfo = seaf_repo_manager_get_virtual_repo_info (manager, repo_id);
    if (vinfo) {
        repo->is_virtual = TRUE;
        memcpy (repo->store_id, vinfo->origin_repo_id, 36);
    } else {
        repo->is_virtual = FALSE;
        memcpy (repo->store_id, repo->id, 36);
    }
    seaf_virtual_repo_info_free (vinfo);

#if 0
    if (pthread_rwlock_wrlock (&manager->priv->lock) < 0) {
        g_warning ("[repo mgr] failed to lock repo cache.\n");
        seaf_repo_free (repo);
        return NULL;
    }
    avl_insert (manager->priv->repo_tree, repo);
    /* Don't need to increase ref count, since the ref count of
     * a new repo object is already 1.
     */
    pthread_rwlock_unlock (&manager->priv->lock);
#endif

    return repo;
}
示例#9
0
文件: repo-mgr.c 项目: Buzer/seafile
static SeafRepo *
load_repo (SeafRepoManager *manager, const char *repo_id, gboolean ret_corrupt)
{
    SeafRepo *repo;
    SeafBranch *branch;
    SeafVirtRepo *vinfo = NULL;

    repo = seaf_repo_new(repo_id, NULL, NULL);
    if (!repo) {
        seaf_warning ("[repo mgr] failed to alloc repo.\n");
        return NULL;
    }

    repo->manager = manager;

    branch = seaf_branch_manager_get_branch (seaf->branch_mgr, repo_id, "master");
    if (!branch) {
        g_warning ("Failed to get master branch of repo %.8s.\n", repo_id);
        repo->is_corrupted = TRUE;
    } else {
        load_repo_commit (manager, repo, branch);
        seaf_branch_unref (branch);
    }

    if (repo->is_corrupted) {
        if (!ret_corrupt) {
            seaf_repo_free (repo);
            return NULL;
        }
        return repo;
    }

    vinfo = seaf_repo_manager_get_virtual_repo_info (manager, repo_id);
    if (vinfo) {
        repo->is_virtual = TRUE;
        memcpy (repo->store_id, vinfo->origin_repo_id, 36);
    } else {
        repo->is_virtual = FALSE;
        memcpy (repo->store_id, repo->id, 36);
    }
    seaf_virtual_repo_info_free (vinfo);

    return repo;
}
示例#10
0
static int
start (CcnetProcessor *processor, int argc, char **argv)
{
    USE_PRIV;
    GString *buf;
    SeafileGetfsV2Proc *proc = (SeafileGetfsV2Proc *)processor;
    TransferTask *task = proc->tx_task;

    buf = g_string_new (NULL);
    if (!task->is_clone) {
        SeafBranch *master = seaf_branch_manager_get_branch (seaf->branch_mgr,
                                                             task->repo_id,
                                                             "master");
        if (!master) {
            seaf_warning ("Master branch not found for repo %s.\n", task->repo_id);
            g_string_free (buf, TRUE);
            ccnet_processor_done (processor, FALSE);
            return -1;
        }

        g_string_printf (buf, "remote %s seafile-putfs-v2 %s %s %s",
                         processor->peer_id, task->session_token,
                         task->head, master->commit_id);

        seaf_branch_unref (master);
    } else
        g_string_printf (buf, "remote %s seafile-putfs-v2 %s %s",
                         processor->peer_id, task->session_token,
                         task->head);

    ccnet_processor_send_request (processor, buf->str);
    g_string_free (buf, TRUE);

    priv->registered = TRUE;
    priv->writer_id = seaf_obj_store_register_async_write (seaf->fs_mgr->obj_store,
                                                           task->repo_id,
                                                           task->repo_version,
                                                           on_fs_write,
                                                           processor);
    return 0;
}
示例#11
0
static gboolean
load_branch_cb (SeafDBRow *row, void *vrepo)
{
    SeafRepo *repo = vrepo;
    SeafRepoManager *manager = repo->manager;

    const char *branch_name = seaf_db_row_get_column_text (row, 0);
    SeafBranch *branch =
        seaf_branch_manager_get_branch (manager->seaf->branch_mgr,
                                        repo->id, branch_name);
    if (branch == NULL) {
        g_warning ("Broken branch name for repo %s\n", repo->id); 
        repo->is_corrupted = TRUE;
        return FALSE;
    }
    load_repo_commit (manager, repo, branch);
    seaf_branch_unref (branch);

    /* Only one result. */
    return FALSE;
}
示例#12
0
GList *
seaf_repo_get_commits (SeafRepo *repo)
{
    GList *branches;
    GList *ptr;
    SeafBranch *branch;
    GList *commits = NULL;

    branches = seaf_branch_manager_get_branch_list (seaf->branch_mgr, repo->id);
    if (branches == NULL) {
        g_warning ("Failed to get branch list of repo %s.\n", repo->id);
        return NULL;
    }

    for (ptr = branches; ptr != NULL; ptr = ptr->next) {
        branch = ptr->data;
        gboolean res = seaf_commit_manager_traverse_commit_tree (seaf->commit_mgr,
                       repo->id,
                       repo->version,
                       branch->commit_id,
                       collect_commit,
                       &commits,
                       FALSE);
        if (!res) {
            for (ptr = commits; ptr != NULL; ptr = ptr->next)
                seaf_commit_unref ((SeafCommit *)(ptr->data));
            g_list_free (commits);
            goto out;
        }
    }

    commits = g_list_reverse (commits);

out:
    for (ptr = branches; ptr != NULL; ptr = ptr->next) {
        seaf_branch_unref ((SeafBranch *)ptr->data);
    }
    return commits;
}
示例#13
0
static void
handle_upload_ok (CcnetProcessor *processor, TransferTask *task,
                  char *content, int clen)
{
    if (clen == 0) {
        ccnet_processor_send_update (processor,
                                     SC_GET_TOKEN, SS_GET_TOKEN,
                                     NULL, 0);
        return;
    }

    if (clen != 41 || content[clen-1] != '\0') {
        seaf_warning ("Bad response content.\n");
        transfer_task_set_error (task, TASK_ERR_UNKNOWN);
        ccnet_processor_send_update (processor, SC_BAD_ARGS, SS_BAD_ARGS, NULL, 0);
        ccnet_processor_done (processor, FALSE);
        return;
    }

    /* Ignore the returned remote head id, just use the head of master branch.
     * For protocol version >= 6, the complete hitstory is not downloaded, so
     * there is no way to check fast forward on the client. For protocol version
     * < 6, the server will check fast forward anyway.
     */
    SeafBranch *master = seaf_branch_manager_get_branch (seaf->branch_mgr,
                                                         task->repo_id, "master");
    if (!master) {
        seaf_warning ("Cannot find branch master for repo %s.\n", task->repo_id);
        ccnet_processor_send_update (processor, SC_SHUTDOWN, SS_SHUTDOWN, NULL, 0);
        ccnet_processor_done (processor, FALSE);
        return;
    }
    memcpy (task->remote_head, master->commit_id, 40);
    seaf_branch_unref (master);

    ccnet_processor_send_update (processor,
                                 SC_GET_TOKEN, SS_GET_TOKEN,
                                 NULL, 0);
}
示例#14
0
static SeafRepo *
load_repo (SeafRepoManager *manager, const char *repo_id)
{
    SeafRepo *repo;
    SeafBranch *branch;

    repo = seaf_repo_new(repo_id, NULL, NULL);
    if (!repo) {
        seaf_warning ("[repo mgr] failed to alloc repo.\n");
        return NULL;
    }

    repo->manager = manager;

    branch = seaf_branch_manager_get_branch (seaf->branch_mgr, repo_id, "master");
    if (!branch) {
        seaf_warning ("Failed to get master branch of repo %.8s.\n", repo_id);
        repo->is_corrupted = TRUE;
    } else {
        load_repo_commit (manager, repo, branch);
        seaf_branch_unref (branch);
    }

    if (repo->is_corrupted) {
        seaf_warning ("Repo %.8s is corrupted.\n", repo->id);
        seaf_repo_free (repo);
        return NULL;
    }

    char *origin_repo_id = get_origin_repo_id (manager, repo->id);
    if (origin_repo_id)
        memcpy (repo->store_id, origin_repo_id, 36);
    else
        memcpy (repo->store_id, repo->id, 36);
    g_free (origin_repo_id);

    return repo;
}
示例#15
0
static int
get_commit_start (CcnetProcessor *processor, int argc, char **argv)
{
    GString *buf = g_string_new (NULL);
    TransferTask *task = ((SeafileGetcommitV2Proc *)processor)->tx_task;
    SeafBranch *master = NULL;
    char *end_commit_id = NULL;

    g_return_val_if_fail (task->session_token, -1);

    if (!task->is_clone) {
        master = seaf_branch_manager_get_branch (seaf->branch_mgr,
                                                 task->repo_id,
                                                 "master");
        if (master != NULL)
            end_commit_id = master->commit_id;
    }

    /* fs_roots can be non-NULL if transfer is resumed from NET_DOWN. */
    if (task->fs_roots != NULL)
        object_list_free (task->fs_roots);
    task->fs_roots = object_list_new ();

    if (end_commit_id != NULL)
        g_string_printf (buf, "remote %s seafile-putcommit-v2 %s %s %s",
                         processor->peer_id, 
                         task->head, end_commit_id, task->session_token);
    else
        g_string_printf (buf, "remote %s seafile-putcommit-v2 %s %s",
                         processor->peer_id, 
                         task->head, task->session_token);
    ccnet_processor_send_request (processor, buf->str);
    g_string_free (buf, TRUE);

    seaf_branch_unref (master);

    return 0;
}
示例#16
0
static void *
send_repo_branch_info (void *vprocessor)                       
{
    CcnetProcessor *processor = vprocessor;
    SeafRepo *repo;
    SeafBranch *seaf_branch;
    USE_PRIV;
    
    repo = seaf_repo_manager_get_repo_ex (seaf->repo_mgr, priv->repo_id);
    if (!repo) {
        priv->rsp_code = g_strdup (SC_NO_REPO);
        priv->rsp_msg = g_strdup (SS_NO_REPO);
        return vprocessor;
    } else if (repo->is_corrupted) {
        priv->rsp_code = g_strdup (SC_REPO_CORRUPT);
        priv->rsp_msg = g_strdup (SS_REPO_CORRUPT);
        return vprocessor;
    }

    seaf_branch = seaf_branch_manager_get_branch (seaf->branch_mgr,
                                                  priv->repo_id,
                                                  priv->branch_name);
    if (!seaf_branch) {
        seaf_repo_unref (repo);
        priv->rsp_code = g_strdup (SC_NO_BRANCH);
        priv->rsp_msg = g_strdup (SS_NO_BRANCH);
        return vprocessor;
    }

    priv->rsp_code = g_strdup (SC_COMMIT_ID);
    priv->rsp_msg = g_strdup (SS_COMMIT_ID);
    memcpy (priv->commit_id, seaf_branch->commit_id, 41);

    seaf_repo_unref (repo);
    seaf_branch_unref (seaf_branch);

    return vprocessor;
}
示例#17
0
static void
get_branch_head (CcnetProcessor *processor)
{
    SeafBranch *branch;
    USE_PRIV;

    branch = seaf_branch_manager_get_branch (seaf->branch_mgr, 
                                             priv->repo_id, priv->branch_name);
    if (branch != NULL) {
        priv->has_branch = 1;
        memcpy (priv->head_id, branch->commit_id, 41);
        seaf_branch_unref (branch);

        priv->rsp_code = g_strdup(SC_OK);
        priv->rsp_msg = g_strdup(SS_OK);
    } else if (priv->type == CHECK_TX_TYPE_UPLOAD) {
        priv->rsp_code = g_strdup(SC_OK);
        priv->rsp_msg = g_strdup(SS_OK);
    } else {
        priv->rsp_code = g_strdup(SC_NO_BRANCH);
        priv->rsp_msg = g_strdup(SS_NO_BRANCH);
    }
}
示例#18
0
文件: fsck.c 项目: Danath/seafile
static int
recover_corrupted_repo_head (char *repo_id)
{
    GList *commit_list = NULL;
    GList *temp_list = NULL;
    SeafCommit *temp_commit = NULL;
    SeafBranch *branch = NULL;
    SeafRepo *repo = NULL;
    SeafVirtRepo *vinfo = NULL;
    FsckRes res;
    int rc = -1;

    seaf_message ("Recovering corrupt head commit for repo %.8s.\n", repo_id);

    seaf_obj_store_foreach_obj (seaf->commit_mgr->obj_store, repo_id,
                                1, fsck_get_repo_commit, &commit_list);

    if (commit_list == NULL)
        return rc;

    commit_list = g_list_sort (commit_list, compare_commit_by_ctime);
    memset (&res, 0, sizeof(res));
    res.existing_blocks = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                 g_free, NULL);


    for (temp_list = commit_list; temp_list; temp_list = temp_list->next) {
        temp_commit = temp_list->data;

        branch = seaf_branch_new ("master", repo_id, temp_commit->commit_id);
        if (branch == NULL) {
            continue;
        }
        repo = seaf_repo_new (repo_id, NULL, NULL);
        if (repo == NULL) {
            seaf_branch_unref (branch);
            continue;
        }
        repo->head = branch;
        seaf_repo_from_commit (repo, temp_commit);
        vinfo = seaf_repo_manager_get_virtual_repo_info (seaf->repo_mgr, repo_id);
        if (vinfo) {
            repo->is_virtual = TRUE;
            memcpy (repo->store_id, vinfo->origin_repo_id, 36);
        } else {
            repo->is_virtual = FALSE;
            memcpy (repo->store_id, repo->id, 36);
        }
        seaf_virtual_repo_info_free (vinfo);

        res.repo = repo;
        rc = seaf_fs_manager_traverse_tree (seaf->fs_mgr,
                                            repo->store_id,
                                            repo->version,
                                            temp_commit->root_id,
                                            fs_callback,
                                            &res, FALSE);

        if (rc < 0) {
            seaf_repo_unref (repo);
        } else {
            break;
        }
    }

    if (rc < 0) {
        seaf_warning ("Failed to fix head commit of repo %.8s.\n", repo_id);
    } else {
        // create new head commit, and set it's parent commit as latest avaliable commit
        temp_commit = cre_commit_from_parent (repo_id, temp_commit);
        if (temp_commit) {
            seaf_branch_set_commit (repo->head, temp_commit->commit_id);
            // in case of branch col miss, using add_branch instead of update_branch
            if (seaf_branch_manager_add_branch (seaf->branch_mgr, repo->head) < 0) {
                seaf_warning ("Failed to fix head commit of repo %.8s.\n", repo_id);
                rc = -1;
            } else {
                seaf_commit_manager_add_commit (seaf->commit_mgr, temp_commit);
                seaf_message ("Head commit of repo %.8s has been fixed to commit %.8s.\n",
                              repo_id, temp_commit->commit_id);
            }
            seaf_commit_unref (temp_commit);
        } else {
            seaf_warning ("Failed to fix head commit of repo %.8s.\n", repo_id);
            rc = -1;
        }
    }

    g_hash_table_destroy (res.existing_blocks);
    seaf_repo_unref (repo);
    for (temp_list = commit_list; temp_list; temp_list = temp_list->next) {
        temp_commit = temp_list->data;
        seaf_commit_unref (temp_commit);
    }
    g_list_free (commit_list);

    return rc;
}
示例#19
0
static void *
update_repo (void *vprocessor)
{
    CcnetProcessor *processor = vprocessor;
    USE_PRIV;
    char *repo_id, *branch_name, *new_head;
    SeafRepo *repo = NULL;
    SeafBranch *branch = NULL;
    SeafCommit *commit = NULL;
    char old_commit_id[41];

    repo_id = priv->repo_id;
    branch_name = priv->branch_name;
    new_head = priv->new_head;

    /* Since this is the last step of upload procedure, commit should exist. */
    commit = seaf_commit_manager_get_commit (seaf->commit_mgr, new_head);
    if (!commit) {
        priv->rsp_code = g_strdup (SC_BAD_COMMIT);
        priv->rsp_msg = g_strdup (SS_BAD_COMMIT);
        goto out;
    }

    repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
    if (!repo) {
        /* repo is deleted on server */
        priv->rsp_code = g_strdup (SC_BAD_REPO);
        priv->rsp_msg = g_strdup (SC_BAD_REPO);
        goto out;

    }

    if (seaf_quota_manager_check_quota (seaf->quota_mgr, repo_id) < 0) {
        priv->rsp_code = g_strdup(SC_QUOTA_FULL);
        priv->rsp_msg = g_strdup(SS_QUOTA_FULL);
        goto out;
    }

    branch = seaf_branch_manager_get_branch (seaf->branch_mgr, repo_id, branch_name);
    if (!branch) {
        priv->rsp_code = g_strdup (SC_BAD_BRANCH);
        priv->rsp_msg = g_strdup (SS_BAD_BRANCH);
        goto out;
    }

    /* If branch exists, check fast forward. */
    if (strcmp (new_head, branch->commit_id) != 0 &&
        !is_fast_forward (new_head, branch->commit_id)) {
        g_warning ("Upload is not fast forward. Refusing.\n");

        seaf_repo_unref (repo);
        seaf_commit_unref (commit);
        seaf_branch_unref (branch);

        priv->rsp_code = g_strdup (SC_NOT_FF);
        priv->rsp_msg = g_strdup (SS_NOT_FF);
        return vprocessor;
    }

    /* Update branch. In case of concurrent update, we must ensure atomicity.
     */
    memcpy (old_commit_id, branch->commit_id, 41);
    seaf_branch_set_commit (branch, commit->commit_id);
    if (seaf_branch_manager_test_and_update_branch (seaf->branch_mgr,
                                                    branch, old_commit_id) < 0)
    {
        g_warning ("Upload is not fast forward, concurrent update.\n");
        priv->rsp_code = g_strdup (SC_NOT_FF);
        priv->rsp_msg = g_strdup (SS_NOT_FF);
        goto out;
    }

out:
    if (repo)   seaf_repo_unref (repo);
    if (commit) seaf_commit_unref (commit);
    if (branch) seaf_branch_unref (branch);

    if (!priv->rsp_code) {
        priv->rsp_code = g_strdup (SC_OK);
        priv->rsp_msg = g_strdup (SS_OK);
    }

    return vprocessor;
}
示例#20
0
static void
mark_clone_done_v2 (SeafRepo *repo, CloneTask *task)
{
    SeafBranch *local = NULL;

    seaf_repo_manager_set_repo_worktree (repo->manager,
                                         repo,
                                         task->worktree);

    local = seaf_branch_manager_get_branch (seaf->branch_mgr, repo->id, "local");
    if (!local) {
        seaf_warning ("Cannot get branch local for repo %s(%.10s).\n",
                      repo->name, repo->id);
        transition_to_error (task, CLONE_ERROR_INTERNAL);
        return;
    }
    /* Set repo head to mark checkout done. */
    seaf_repo_set_head (repo, local);
    seaf_branch_unref (local);

    if (repo->encrypted) {
        if (seaf_repo_manager_set_repo_passwd (seaf->repo_mgr,
                                               repo,
                                               task->passwd) < 0) {
            seaf_warning ("[Clone mgr] failed to set passwd for %s.\n", repo->id);
            transition_to_error (task, CLONE_ERROR_INTERNAL);
            return;
        }
    }

    if (task->is_readonly) {
        seaf_repo_set_readonly (repo);
    }

    if (task->sync_wt_name) {
        seaf_repo_manager_set_repo_property (seaf->repo_mgr,
                                             repo->id,
                                             REPO_SYNC_WORKTREE_NAME,
                                             "true");
    }

    if (task->server_url)
        repo->server_url = g_strdup(task->server_url);

    if (repo->auto_sync && (repo->sync_interval == 0)) {
        if (seaf_wt_monitor_watch_repo (seaf->wt_monitor,
                                        repo->id, repo->worktree) < 0) {
            seaf_warning ("failed to watch repo %s(%.10s).\n", repo->name, repo->id);
            transition_to_error (task, CLONE_ERROR_INTERNAL);
            return;
        }
    }

    /* For compatibility, still set these two properties.
     * So that if we downgrade to an old version, the syncing can still work.
     */
    seaf_repo_manager_set_repo_property (seaf->repo_mgr,
                                         repo->id,
                                         REPO_REMOTE_HEAD,
                                         repo->head->commit_id);
    seaf_repo_manager_set_repo_property (seaf->repo_mgr,
                                         repo->id,
                                         REPO_LOCAL_HEAD,
                                         repo->head->commit_id);

    transition_state (task, CLONE_STATE_DONE);
}
示例#21
0
static int
do_create_virtual_repo (SeafRepoManager *mgr,
                        SeafRepo *origin_repo,
                        const char *repo_id,
                        const char *repo_name,
                        const char *repo_desc,
                        const char *root_id,
                        const char *user,
                        const char *passwd,
                        GError **error)
{
    SeafRepo *repo = NULL;
    SeafCommit *commit = NULL;
    SeafBranch *master = NULL;
    int ret = 0;

    repo = seaf_repo_new (repo_id, repo_name, repo_desc);

    repo->no_local_history = TRUE;
    if (passwd != NULL && passwd[0] != '\0') {
        repo->encrypted = TRUE;
        repo->enc_version = origin_repo->enc_version;
        seafile_generate_magic (repo->enc_version, repo_id, passwd, repo->magic);
        if (repo->enc_version == 2)
            memcpy (repo->random_key, origin_repo->random_key, 96);
    }

    /* Virtual repos share fs and block store with origin repo and
     * have the same version as the origin.
     */
    repo->version = origin_repo->version;
    memcpy (repo->store_id, origin_repo->id, 36);

    commit = seaf_commit_new (NULL, repo->id,
                              root_id, /* root id */
                              user, /* creator */
                              EMPTY_SHA1, /* creator id */
                              repo_desc,  /* description */
                              0);         /* ctime */

    seaf_repo_to_commit (repo, commit);
    if (seaf_commit_manager_add_commit (seaf->commit_mgr, commit) < 0) {
        seaf_warning ("Failed to add commit.\n");
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                     "Failed to add commit");
        ret = -1;
        goto out;
    }

    master = seaf_branch_new ("master", repo->id, commit->commit_id);
    if (seaf_branch_manager_add_branch (seaf->branch_mgr, master) < 0) {
        seaf_warning ("Failed to add branch.\n");
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                     "Failed to add branch");
        ret = -1;
        goto out;
    }

    if (seaf_repo_set_head (repo, master) < 0) {
        seaf_warning ("Failed to set repo head.\n");
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                     "Failed to set repo head.");
        ret = -1;
        goto out;
    }

    if (seaf_repo_manager_add_repo (mgr, repo) < 0) {
        seaf_warning ("Failed to add repo.\n");
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                     "Failed to add repo.");
        ret = -1;
        goto out;
    }

out:
    if (repo)
        seaf_repo_unref (repo);
    if (commit)
        seaf_commit_unref (commit);
    if (master)
        seaf_branch_unref (master);
    
    return ret;    
}