Add search files RPC (#417)

* Add search files RPC

* Not case sensitive when searching files
This commit is contained in:
feiniks 2020-10-27 18:06:37 +08:00 committed by GitHub
parent 50ab9a8ffe
commit be8231ffc2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 202 additions and 1 deletions

1
.gitignore vendored
View file

@ -71,6 +71,7 @@ lib/commit.c
lib/crypt.c
lib/repo.c
lib/copy-task.c
lib/search-result.c
seaf-server
seafserv-gc
seaf-migrate

View file

@ -1,5 +1,10 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#ifndef _GNU_SOURECE
#define _GNU_SOURCE
char *strcasestr (const char *haystack, const char *needle);
#undef _GNU_SOURCE
#endif
#include "common.h"
#include <sys/stat.h>
@ -3115,3 +3120,85 @@ out:
return (GObject *)info;
}
static int
search_files_recursive (SeafFSManager *mgr,
const char *repo_id,
const char *path,
const char *id,
const char *str,
int version,
GList **file_list)
{
SeafDir *dir;
GList *p;
SeafDirent *seaf_dent;
int ret = 0;
char *full_path = NULL;
dir = seaf_fs_manager_get_seafdir (mgr, repo_id, version, id);
if (!dir) {
seaf_warning ("[fs-mgr]get seafdir %s failed\n", id);
return -1;
}
for (p = dir->entries; p; p = p->next) {
seaf_dent = (SeafDirent *)p->data;
full_path = g_strconcat (path, "/", seaf_dent->name, NULL);
if (seaf_dent->name && strcasestr (seaf_dent->name, str) != NULL) {
SearchResult *sr = g_new0(SearchResult, 1);
sr->path = g_strdup (full_path);
sr->size = seaf_dent->size;
sr->mtime = seaf_dent->mtime;
*file_list = g_list_prepend (*file_list, sr);
if (S_ISDIR(seaf_dent->mode)) {
sr->is_dir = TRUE;
}
}
if (S_ISDIR(seaf_dent->mode)) {
if (search_files_recursive (mgr, repo_id, full_path,
seaf_dent->id, str,
version, file_list) < 0) {
g_free (full_path);
ret = -1;
break;
}
}
g_free (full_path);
}
seaf_dir_free (dir);
return ret;
}
GList *
seaf_fs_manager_search_files (SeafFSManager *mgr,
const char *repo_id,
const char *str)
{
GList *file_list = NULL;
SeafCommit *head = NULL;
SeafRepo *repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
if (!repo) {
seaf_warning ("Failed to find repo %s\n", repo_id);
goto out;
}
head = seaf_commit_manager_get_commit (seaf->commit_mgr,repo->id, repo->version, repo->head->commit_id);
if (!head) {
seaf_warning ("Failed to find commit %s\n", repo->head->commit_id);
goto out;
}
search_files_recursive (mgr, repo_id, "", head->root_id,
str, repo->version, &file_list);
out:
seaf_repo_unref (repo);
seaf_commit_unref (head);
return file_list;
}

View file

@ -43,6 +43,13 @@ struct _Seafile {
int ref_count;
};
typedef struct SearchResult {
char *path;
gint64 size;
gint64 mtime;
gboolean is_dir;
} SearchResult;
void
seafile_ref (Seafile *seafile);
@ -429,4 +436,9 @@ seaf_fs_manager_get_file_count_info_by_path (SeafFSManager *mgr,
const char *path,
GError **error);
GList *
seaf_fs_manager_search_files (SeafFSManager *mgr,
const char *repo_id,
const char *str);
#endif

View file

@ -4528,6 +4528,31 @@ seafile_get_repo_status(const char *repo_id, GError **error)
return (status == -1) ? 0 : status;
}
GList *
seafile_search_files (const char *repo_id, const char *str, GError **error)
{
if (!is_uuid_valid (repo_id)) {
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
return NULL;
}
GList *file_list = seaf_fs_manager_search_files (seaf->fs_mgr, repo_id, str);
GList *ret = NULL, *ptr;
for (ptr = file_list; ptr; ptr=ptr->next) {
SearchResult *sr = ptr->data;
SeafileSearchResult *search_result = seafile_search_result_new ();
g_object_set (search_result, "path", sr->path, "size", sr->size,
"mtime", sr->mtime, "is_dir", sr->is_dir, NULL);
ret = g_list_prepend (ret, search_result);
g_free (sr->path);
g_free (sr);
}
return g_list_reverse (ret);
}
/*RPC functions merged from ccnet-server*/
int
ccnet_rpc_add_emailuser (const char *email, const char *passwd,

View file

@ -1134,6 +1134,9 @@ seafile_publish_event(const char *channel, const char *content, GError **error);
json_t *
seafile_pop_event(const char *channel, GError **error);
GList *
seafile_search_files (const char *repo_id, const char *str, GError **error);
/*Following is ccnet rpc*/
int
ccnet_rpc_add_emailuser (const char *email, const char *passwd,

View file

@ -13,7 +13,7 @@ BUILT_SOURCES = gensource
## source file rules
seafile_object_define = repo.vala commit.vala dirent.vala dir.vala \
task.vala branch.vala crypt.vala webaccess.vala copy-task.vala ccnetobj.vala
task.vala branch.vala crypt.vala webaccess.vala copy-task.vala ccnetobj.vala search-result.vala
seafile_object_gen = $(seafile_object_define:.vala=.c)

18
lib/search-result.vala Normal file
View file

@ -0,0 +1,18 @@
// compile this file with `valac --pkg posix repo.vala -C -H repo.h`
namespace Seafile {
public class SearchResult: Object {
public string _path;
public string path {
get { return _path; }
set { _path = value; }
}
public int64 size { get; set; }
public int64 mtime { get; set; }
public bool is_dir { set; get; }
}
} // namespace

View file

@ -808,6 +808,10 @@ class SeafServerThreadedRpcClient(NamedPipeClient):
def pop_event(channel):
pass
@searpc_func("objlist", ["string", "string"])
def search_files(self, repo_id, search_str):
pass
#user management
@searpc_func("int", ["string", "string", "int", "int"])
def add_emailuser(self, email, passwd, is_staff, is_active):

View file

@ -838,6 +838,9 @@ class SeafileAPI(object):
def pop_event(self, channel):
return seafserv_threaded_rpc.pop_event(channel)
def search_files(self, repo_id, search_str):
return seafserv_threaded_rpc.search_files(repo_id, search_str)
seafile_api = SeafileAPI()

View file

@ -333,6 +333,11 @@ static void start_rpc_service (const char *seafile_dir,
"convert_repo_path",
searpc_signature_string__string_string_string_int());
searpc_server_register_function ("seafserv-threaded-rpcserver",
seafile_search_files,
"search_files",
searpc_signature_objlist__string_string());
/* share repo to user */
searpc_server_register_function ("seafserv-threaded-rpcserver",
seafile_add_share,

View file

@ -0,0 +1,43 @@
import pytest
import os
import time
from tests.config import USER
from seaserv import seafile_api as api
file_name = 'test.txt'
file_content = 'test file content'
file_path = os.getcwd() + '/' + file_name
dir_name = "test_dir"
def create_the_file ():
with open(file_path, 'w') as fp:
fp.write(file_content)
def test_file_operation():
t_repo_version = 1
t_repo_id1 = api.create_repo('test_file_operation1', '', USER, passwd = None)
create_the_file()
assert api.post_file(t_repo_id1, file_path, '/', file_name, USER) == 0
assert api.post_dir(t_repo_id1, '/', dir_name, USER) == 0
#test search files
file_list = api.search_files (t_repo_id1, "test")
assert len(file_list) == 2
assert file_list[0].path == "/test.txt"
assert file_list[0].is_dir == False
assert file_list[1].path == "/test_dir"
assert file_list[1].is_dir == True
file_list = api.search_files (t_repo_id1, "dir")
assert len(file_list) == 1
assert file_list[0].path == "/test_dir"
assert file_list[0].is_dir == True
file_list = api.search_files (t_repo_id1, "DiR")
assert len(file_list) == 1
assert file_list[0].path == "/test_dir"
assert file_list[0].is_dir == True
api.remove_repo(t_repo_id1)