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; }
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; }
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); }