diff --git a/server/http-server.c b/server/http-server.c index ce3286d..1710d5b 100644 --- a/server/http-server.c +++ b/server/http-server.c @@ -1105,7 +1105,6 @@ put_update_branch_cb (evhtp_request_t *req, void *arg) goto out; } - seaf_repo_manager_cleanup_virtual_repos (seaf->repo_mgr, repo_id); seaf_repo_manager_merge_virtual_repo (seaf->repo_mgr, repo_id, NULL); schedule_repo_size_computation (seaf->size_sched, repo_id); diff --git a/server/processors/recvbranch-proc.c b/server/processors/recvbranch-proc.c index 1c55078..1171b88 100644 --- a/server/processors/recvbranch-proc.c +++ b/server/processors/recvbranch-proc.c @@ -204,7 +204,6 @@ update_repo (void *vprocessor) goto out; } - seaf_repo_manager_cleanup_virtual_repos (seaf->repo_mgr, repo_id); seaf_repo_manager_merge_virtual_repo (seaf->repo_mgr, repo_id, NULL); out: diff --git a/server/processors/recvbranch-v2-proc.c b/server/processors/recvbranch-v2-proc.c index 3990536..d46d1df 100644 --- a/server/processors/recvbranch-v2-proc.c +++ b/server/processors/recvbranch-v2-proc.c @@ -337,7 +337,6 @@ update_repo (void *vprocessor) goto out; } - seaf_repo_manager_cleanup_virtual_repos (seaf->repo_mgr, repo_id); seaf_repo_manager_merge_virtual_repo (seaf->repo_mgr, repo_id, NULL); out: diff --git a/server/repo-op.c b/server/repo-op.c index 262f2a9..ce8a7ed 100644 --- a/server/repo-op.c +++ b/server/repo-op.c @@ -1490,7 +1490,8 @@ static char * del_file_recursive(SeafRepo *repo, const char *dir_id, const char *to_path, - const char *filename) + const char *filename, + int *mode, int *deleted_num, char **desc_file) { SeafDir *olddir, *newdir; SeafDirent *dent; @@ -1523,6 +1524,12 @@ del_file_recursive(SeafRepo *repo, for (i = 0; i < file_num; i++) { if (strcmp(old->name, file_names[i]) == 0) { found_flag = 1; + if (deleted_num) + (*deleted_num)++; + if (mode) + *mode = old->mode; + if (desc_file && *desc_file==NULL) + *desc_file = g_strdup(old->name); break; } } @@ -1538,6 +1545,13 @@ del_file_recursive(SeafRepo *repo, if (strcmp(old->name, filename) != 0) { new = seaf_dirent_dup (old); newentries = g_list_prepend (newentries, new); + } else { + if (deleted_num) + (*deleted_num)++; + if (mode) + *mode = old->mode; + if (desc_file && *desc_file==NULL) + *desc_file = g_strdup(old->name); } } } @@ -1567,7 +1581,8 @@ del_file_recursive(SeafRepo *repo, if (strcmp(dent->name, to_path_dup) != 0) continue; - id = del_file_recursive(repo, dent->id, remain, filename); + id = del_file_recursive(repo, dent->id, remain, filename, + mode, deleted_num, desc_file); if (id != NULL) { memcpy(dent->id, id, 40); dent->id[40] = '\0'; @@ -1599,13 +1614,15 @@ static char * do_del_file(SeafRepo *repo, const char *root_id, const char *parent_dir, - const char *file_name) + const char *file_name, + int *mode, int *deleted_num, char **desc_file) { /* if parent_dir is a absolutely path, we will remove the first '/' */ if (*parent_dir == '/') parent_dir = parent_dir + 1; - return del_file_recursive(repo, root_id, parent_dir, file_name); + return del_file_recursive(repo, root_id, parent_dir, file_name, + mode, deleted_num, desc_file); } int @@ -1618,15 +1635,14 @@ seaf_repo_manager_del_file (SeafRepoManager *mgr, { SeafRepo *repo = NULL; SeafCommit *head_commit = NULL; + SeafDir *dir = NULL; char *canon_path = NULL; - char **file_names; char buf[SEAF_PATH_MAX]; char *root_id = NULL; - char *desc_file; - int i = 0; + char *desc_file = NULL; int mode = 0; int ret = 0; - int file_num = 0, empty_num = 0; + int deleted_num = 0; GET_REPO_OR_FAIL(repo, repo_id); GET_COMMIT_OR_FAIL(head_commit, repo->id, repo->version, repo->head->commit_id); @@ -1634,39 +1650,19 @@ seaf_repo_manager_del_file (SeafRepoManager *mgr, if (!canon_path) canon_path = get_canonical_path (parent_dir); - if (strchr(file_name, '\t')) { - file_names = g_strsplit (file_name, "\t", -1); - file_num = g_strv_length (file_names); - - for (i = 0; i < file_num; i++) { - if (strcmp(file_names[i], "") == 0) { - empty_num++; - continue; - } - if (!check_file_exists(repo->store_id, repo->version, - head_commit->root_id, canon_path, file_names[i], &mode)) { - char *tmp_path; - if (strcmp(canon_path, "") == 0) - tmp_path = "/"; - else - tmp_path = canon_path; - seaf_warning ("[del file] File \'%s\' dosen't exist in %s in repo %s.\n", - file_names[i], tmp_path, repo->id); - empty_num++; - continue; - } - desc_file = file_names[i]; - } - file_num -= empty_num; - if (file_num <= 0) - goto out; - } else if (!check_file_exists(repo->store_id, repo->version, - head_commit->root_id, canon_path, file_name, &mode)) { + dir = seaf_fs_manager_get_seafdir_by_path (seaf->fs_mgr, + repo->store_id, repo->version, + head_commit->root_id, canon_path, NULL); + if (!dir) { + seaf_warning ("parent_dir %s doesn't exist in repo %s.\n", + canon_path, repo->store_id); + ret = -1; goto out; } root_id = do_del_file (repo, - head_commit->root_id, canon_path, file_name); + head_commit->root_id, canon_path, file_name, &mode, + &deleted_num, &desc_file); if (!root_id) { seaf_warning ("[del file] Failed to del file from %s in repo %s.\n", canon_path, repo->id); @@ -1675,15 +1671,23 @@ seaf_repo_manager_del_file (SeafRepoManager *mgr, ret = -1; goto out; } + if (deleted_num == 0) { + seaf_warning ("[del file] Nothing to be deleted in dir %s in repo %.8s.\n ", + parent_dir, repo->id); + g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, + "File doesn't exist"); + ret = -1; + goto out; + } /* Commit. */ - if (file_num > 1) { + if (deleted_num > 1) { snprintf(buf, SEAF_PATH_MAX, "Deleted \"%s\" and %d more files", - desc_file, file_num - 1); + desc_file, deleted_num - 1); } else if (S_ISDIR(mode)) { - snprintf(buf, SEAF_PATH_MAX, "Removed directory \"%s\"", file_name); + snprintf(buf, SEAF_PATH_MAX, "Removed directory \"%s\"", desc_file); } else { - snprintf(buf, SEAF_PATH_MAX, "Deleted \"%s\"", file_name); + snprintf(buf, SEAF_PATH_MAX, "Deleted \"%s\"", desc_file); } if (gen_new_commit (repo_id, head_commit, root_id, @@ -1692,8 +1696,6 @@ seaf_repo_manager_del_file (SeafRepoManager *mgr, goto out; } - seaf_repo_manager_cleanup_virtual_repos (mgr, repo_id); - seaf_repo_manager_merge_virtual_repo (mgr, repo_id, NULL); out: @@ -1701,10 +1703,11 @@ out: seaf_repo_unref (repo); if (head_commit) seaf_commit_unref(head_commit); - if (file_num) - g_strfreev (file_names); + if (dir) + seaf_dir_free (dir); g_free (root_id); g_free (canon_path); + g_free (desc_file); if (ret == 0) { update_repo_size (repo_id); @@ -2600,7 +2603,8 @@ move_file_same_repo (const char *repo_id, ret = -1; goto out; } - root_id = do_del_file (repo, root_id_after_put, src_path, filenames_str->str); + root_id = do_del_file (repo, root_id_after_put, src_path, filenames_str->str, + NULL, NULL, NULL); if (!root_id) { g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "move file failed"); @@ -2855,7 +2859,6 @@ seaf_repo_manager_move_file (SeafRepoManager *mgr, goto out; } - seaf_repo_manager_cleanup_virtual_repos (mgr, src_repo_id); seaf_repo_manager_merge_virtual_repo (mgr, src_repo_id, NULL); update_repo_size (dst_repo_id); @@ -3086,7 +3089,6 @@ seaf_repo_manager_move_multiple_files (SeafRepoManager *mgr, ret = -1; goto out; } - seaf_repo_manager_cleanup_virtual_repos (mgr, src_repo_id); seaf_repo_manager_merge_virtual_repo (mgr, src_repo_id, NULL); update_repo_size (dst_repo_id); @@ -3704,7 +3706,6 @@ seaf_repo_manager_rename_file (SeafRepoManager *mgr, goto out; } - seaf_repo_manager_cleanup_virtual_repos (mgr, repo_id); seaf_repo_manager_merge_virtual_repo (mgr, repo_id, NULL); out: diff --git a/server/virtual-repo.c b/server/virtual-repo.c index c53a9e3..5cbe8f2 100644 --- a/server/virtual-repo.c +++ b/server/virtual-repo.c @@ -521,7 +521,8 @@ seaf_repo_manager_merge_virtual_repo (SeafRepoManager *mgr, */ static void handle_missing_virtual_repo (SeafRepoManager *mgr, - SeafRepo *repo, SeafCommit *head, SeafVirtRepo *vinfo) + SeafRepo *repo, SeafCommit *head, SeafVirtRepo *vinfo, + char **return_new_path) { SeafCommit *parent = NULL; char *old_dir_id = NULL; @@ -569,9 +570,7 @@ handle_missing_virtual_repo (SeafRepoManager *mgr, } char de_id[41]; - char *new_path; - char *new_name; - char **parts = NULL; + char *new_path, *new_name; for (ptr = diff_res; ptr; ptr = ptr->next) { de = ptr->data; @@ -586,17 +585,23 @@ handle_missing_virtual_repo (SeafRepoManager *mgr, vinfo->repo_id, new_path); set_virtual_repo_base_commit_path (vinfo->repo_id, head->commit_id, new_path); - parts = g_strsplit(new_path, "/", 0); - new_name = parts[g_strv_length(parts) - 1]; - - seaf_repo_manager_edit_repo (vinfo->repo_id, - new_name, - "Changed library name", - NULL, - &error); - if (error) { - seaf_warning ("Failed to rename repo %s", de->new_name); - g_clear_error (&error); + if (return_new_path) + *return_new_path = g_strdup(new_path); + /* 'sub_path = NUll' means the virtual dir itself has been renamed, + * we need to make a new commit for the virtual repo + */ + if (sub_path == NULL) { + new_name = g_path_get_basename(new_path); + seaf_repo_manager_edit_repo (vinfo->repo_id, + new_name, + "Changed library name", + NULL, + &error); + if (error) { + seaf_warning ("Failed to rename repo %s", new_name); + g_clear_error (&error); + } + g_free(new_name); } is_renamed = TRUE; g_free (new_path); @@ -605,7 +610,6 @@ handle_missing_virtual_repo (SeafRepoManager *mgr, } } g_free (old_dir_id); - g_strfreev (parts); if (is_renamed) break; @@ -676,7 +680,7 @@ seaf_repo_manager_cleanup_virtual_repos (SeafRepoManager *mgr, &error); if (error) { if (error->code == SEAF_ERR_PATH_NO_EXIST) { - handle_missing_virtual_repo (mgr, repo, head, vinfo); + handle_missing_virtual_repo (mgr, repo, head, vinfo, NULL); } g_clear_error (&error); } else @@ -740,6 +744,31 @@ static void *merge_virtual_repo (void *vtask) goto out; } + orig_root = seaf_fs_manager_get_seafdir_id_by_path (seaf->fs_mgr, + orig_repo->store_id, + orig_repo->version, + orig_head->root_id, + vinfo->path, + NULL); + if (!orig_root) { + seaf_debug("Path %s not found in origin repo %.8s, delete or rename virtual repo %.8s\n", + vinfo->path, vinfo->origin_repo_id, repo_id); + + char *new_path = NULL; + handle_missing_virtual_repo (mgr, orig_repo, orig_head, vinfo, &new_path); + if (new_path != NULL) { + orig_root = seaf_fs_manager_get_seafdir_id_by_path (seaf->fs_mgr, + orig_repo->store_id, + orig_repo->version, + orig_head->root_id, + new_path, + NULL); + g_free (new_path); + } + if (!orig_root) + goto out; + } + base = seaf_commit_manager_get_commit (seaf->commit_mgr, orig_repo->id, orig_repo->version, vinfo->base_commit); @@ -766,19 +795,6 @@ static void *merge_virtual_repo (void *vtask) goto out; } - orig_root = seaf_fs_manager_get_seafdir_id_by_path (seaf->fs_mgr, - orig_repo->store_id, - orig_repo->version, - orig_head->root_id, - vinfo->path, - NULL); - if (!orig_root) { - seaf_warning ("Cannot find seafdir for repo %.10s path %s.\n", - vinfo->origin_repo_id, vinfo->path); - ret = -1; - goto out; - } - if (strcmp (root, orig_root) == 0) { /* Nothing to merge. */ seaf_debug ("Nothing to merge.\n"); diff --git a/tests/test_share_and_perm/test_shared_repo_perm.py b/tests/test_share_and_perm/test_shared_repo_perm.py index 85b5400..5088b85 100644 --- a/tests/test_share_and_perm/test_shared_repo_perm.py +++ b/tests/test_share_and_perm/test_shared_repo_perm.py @@ -1,4 +1,5 @@ import pytest +import time from seaserv import seafile_api as api from seaserv import ccnet_api @@ -114,6 +115,8 @@ def test_share_dir_to_user(repo, permission): assert api.del_file(repo.id, '/', 'dir1', USER) == 0 assert api.unshare_subdir_for_user(repo.id, '/dir2', USER, USER2) == 0 + time.sleep(1) + assert api.get_shared_repo_by_path(repo.id, '/dir1', USER2) is None assert api.get_shared_repo_by_path(repo.id, '/dir2', USER2) is None @@ -135,6 +138,8 @@ def test_share_dir_to_group(repo, group, permission): assert api.del_file(repo.id, '/', 'dir1', USER) == 0 assert api.unshare_subdir_for_group(repo.id, '/dir2', USER, group.id) == 0 + time.sleep(1) + assert api.check_permission(v_repo_id_1, USER2) is None assert api.check_permission(v_repo_id_2, USER2) is None