# HG changeset patch # User Olaf Wintermann # Date 1527617709 -7200 # Node ID 8a0c727aa4092d8d4a19d0883c590f6a2ee74f6d # Parent cdaf5a3d3a50379bf47a192f2f17f6f46209fbdc adds tag filter for dav-sync pull diff -r cdaf5a3d3a50 -r 8a0c727aa409 dav/db.h --- a/dav/db.h Sun May 27 19:45:28 2018 +0200 +++ b/dav/db.h Tue May 29 20:15:09 2018 +0200 @@ -54,6 +54,8 @@ DavBool tags_updated; UcxBuffer *cached_tags; char *tags_hash; + + DavBool keep; }; struct SyncDatabase { diff -r cdaf5a3d3a50 -r 8a0c727aa409 dav/main.c --- a/dav/main.c Sun May 27 19:45:28 2018 +0200 +++ b/dav/main.c Tue May 29 20:15:09 2018 +0200 @@ -197,6 +197,9 @@ } void print_usage(char *cmd) { + fprintf(stderr, "Usage: %s command [options] arguments...\n\n", cmd); + + fprintf(stderr, "Commands:\n"); for(int i=0;;i++) { char *str = cmdusageinfo[i]; if(!str) { @@ -226,7 +229,6 @@ fprintf(stderr, " -d order by last modified date\n"); fprintf(stderr, " -e show extended flags\n"); fprintf(stderr, " -O override resources\n"); - fprintf(stderr, " -A tar import/export\n"); fprintf(stderr, " -L specificy lock token\n"); fprintf(stderr, " -T timeout in seconds\n"); fprintf(stderr, " -n specify namespace uri\n"); diff -r cdaf5a3d3a50 -r 8a0c727aa409 dav/sopt.c --- a/dav/sopt.c Sun May 27 19:45:28 2018 +0200 +++ b/dav/sopt.c Tue May 29 20:15:09 2018 +0200 @@ -49,7 +49,7 @@ const char *NOARG = ""; char *option = NULL; - //char optchar = 0; + char optchar = 0; for(int i=0;ioptions, "read", NOARG); + ucx_map_cstr_put(a->options, "remove", NOARG); break; } case 'v': { @@ -101,6 +101,11 @@ ucx_map_cstr_put(a->options, "syncdir", NOARG); break; } + case 't': { + option = "tags"; + optchar = 't'; + break; + } } } } else if(option) { diff -r cdaf5a3d3a50 -r 8a0c727aa409 dav/sync.c --- a/dav/sync.c Sun May 27 19:45:28 2018 +0200 +++ b/dav/sync.c Tue May 29 20:15:09 2018 +0200 @@ -132,8 +132,8 @@ ret = cmd_add_tag(args); } else if(!strcmp(cmd, "remove-tag")) { ret = cmd_remove_tag(args); - } else if(!strcmp(cmd, "update-tags")) { - ret = cmd_update_tags(args); + } else if(!strcmp(cmd, "set-tags")) { + ret = cmd_set_tags(args); } else if(!strcmp(cmd, "list-tags")) { ret = cmd_list_tags(args); } else if(!strcmp(cmd, "add-dir") @@ -167,8 +167,8 @@ fprintf(stderr, "Usage: %s command [options] arguments...\n\n", cmd); fprintf(stderr, "Commands:\n"); - fprintf(stderr, " pull [-cld] \n"); - fprintf(stderr, " push [-cld] \n"); + fprintf(stderr, " pull [-cld] [-t ] \n"); + fprintf(stderr, " push [-cld] [-t ] \n"); fprintf(stderr, " archive [-cld] \n"); fprintf(stderr, " resolve-conflicts \n"); fprintf(stderr, " delete-conflicts \n"); @@ -176,14 +176,17 @@ fprintf(stderr, " empty-trash \n"); fprintf(stderr, " add-tag [-s ] \n"); fprintf(stderr, " remove-tag [-s ] \n"); - fprintf(stderr, " update-tags [-s ] [tags]\n"); + fprintf(stderr, " set-tags [-s ] [tags]\n"); fprintf(stderr, " list-tags [-s ] \n\n"); fprintf(stderr, "Options:\n"); fprintf(stderr, " -c Disable conflict detection\n"); fprintf(stderr, " -l Lock the repository before access\n"); fprintf(stderr, " -d Don't lock the repository\n"); - //fprintf(stderr, " -r Read changes from stdin\n\n"); + fprintf(stderr, " -t " + "Only sync files which have the specified tags\n"); + fprintf(stderr, " -r " + "Remove resources not matching the tag filter\n"); fprintf(stderr, " -v verbose output (all commands)\n\n"); fprintf(stderr, "Config commands:\n"); @@ -252,6 +255,55 @@ return 1; } +static int matches_tags(UcxList *resource_tags, UcxList *tags) { + if(!tags) { + return 1; + } + if(!resource_tags) { + return 0; + } + + UcxMap *res_tagmap = ucx_map_new(32); + UCX_FOREACH(elm, resource_tags) { + DavTag *t = elm->data; + // the value actually doesn't matter + ucx_map_cstr_put(res_tagmap, t->name, t); + } + + int ret = 1; + + // TODO: replace FOREACH with new tag expression evaluation + UCX_FOREACH(elm, tags) { + DavTag *matches_tag = elm->data; + if(!ucx_map_cstr_get(res_tagmap, matches_tag->name)) { + ret = 0; + break; + } + } + + ucx_map_free(res_tagmap); + return ret; +} + +static int res_matches_tags(DavResource *res, UcxList *tags) { + if(!tags) { + return 1; + } + + DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_NS, "tags"); + UcxList *res_tags = parse_dav_xml_taglist(tagsprop); + + int ret = matches_tags(res_tags, tags); + // TODO: free list content + ucx_list_free(res_tags); + return ret; +} + +static int localres_matches_tags(LocalResource *res, UcxList *tags) { + // TODO: implement + return 1; +} + static DavSession* create_session(DavContext *ctx, Repository *repo, char *url) { DavSession *sn = dav_session_new_auth( ctx, @@ -289,6 +341,14 @@ fprintf(stderr, "\n"); } +static void localres_keep(SyncDatabase *db, const char *path) { + LocalResource *local = ucx_map_cstr_remove(db->resources, path); + if(local) { + local->keep = TRUE; + } + +} + int cmd_pull(CmdArgs *a) { if(a->argc != 1) { fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many"); @@ -394,6 +454,13 @@ return -1; } + UcxList *tags = NULL; + char *tags_str = cmd_getoption(a, "tags"); + if(tags_str) { + tags = parse_csv_taglist(tags_str, strlen(tags_str)); + } + DavBool rm_tagmismatch = cmd_getoption(a, "remove") ? 1 : 0; + int sync_success = 0; int sync_delete = 0; int sync_error = 0; @@ -413,9 +480,18 @@ continue; } + if (!res_matches_tags(res, tags)) { + if(!rm_tagmismatch) { + localres_keep(db, res->path); + } + res = res->next; + continue; + } + char *status = dav_get_string_property(res, "idav:status"); if(status && !strcmp(status, "broken")) { res = res->next; + localres_keep(db, res->path); continue; } @@ -466,7 +542,7 @@ continue; } - if(sync_shutdown) { + if(sync_shutdown || local->keep) { ucx_map_cstr_put(svrres, local->path, local_resource_copy(local)); } else { // sync_remove_resource does all necessary tests @@ -1234,6 +1310,10 @@ newres->size = res->size; newres->last_modified = res->last_modified; newres->isdirectory = res->isdirectory; + if(res->tags_hash) { + newres->tags_hash = strdup(res->tags_hash); + } + newres->tags_updated = res->tags_updated; return newres; } @@ -2121,7 +2201,7 @@ #define CMD_TAG_ADD 0 #define CMD_TAG_REMOVE 1 -#define CMD_TAG_UPDATE 2 +#define CMD_TAG_SET 2 #define CMD_TAG_LIST 3 int cmd_add_tag(CmdArgs *args) { if(args->argc != 2) { @@ -2139,12 +2219,12 @@ return cmd_tagopt(args, CMD_TAG_REMOVE); } -int cmd_update_tags(CmdArgs *args) { +int cmd_set_tags(CmdArgs *args) { if(args->argc < 1 || args->argc > 2) { fprintf(stderr, "Too %s arguments\n", args->argc < 1 ? "few" : "many"); return -1; } - return cmd_tagopt(args, CMD_TAG_UPDATE); + return cmd_tagopt(args, CMD_TAG_SET); } int cmd_list_tags(CmdArgs *args) { @@ -2181,7 +2261,7 @@ UcxList *tags = NULL; DavBool store_tags = FALSE; - if(cmd != CMD_TAG_UPDATE) { + if(cmd != CMD_TAG_SET) { char *tag = args->argv[1]; char *tagcolor = NULL; // TODO: get color diff -r cdaf5a3d3a50 -r 8a0c727aa409 dav/sync.h --- a/dav/sync.h Sun May 27 19:45:28 2018 +0200 +++ b/dav/sync.h Tue May 29 20:15:09 2018 +0200 @@ -113,7 +113,7 @@ int cmd_add_tag(CmdArgs *args); int cmd_remove_tag(CmdArgs *args); -int cmd_update_tags(CmdArgs *args); +int cmd_set_tags(CmdArgs *args); int cmd_list_tags(CmdArgs *args); int cmd_tagopt(CmdArgs *args, int cmd);