Add search files RPC (#417)
* Add search files RPC * Not case sensitive when searching files
This commit is contained in:
parent
50ab9a8ffe
commit
be8231ffc2
11 changed files with 202 additions and 1 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
18
lib/search-result.vala
Normal 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
|
|
@ -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):
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
43
tests/test_file_operation/test_search_files.py
Normal file
43
tests/test_file_operation/test_search_files.py
Normal 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)
|
Loading…
Add table
Add a link
Reference in a new issue