dav/sync.c

changeset 380
8a0c727aa409
parent 379
cdaf5a3d3a50
child 381
17ccf828a2f2
equal deleted inserted replaced
379:cdaf5a3d3a50 380:8a0c727aa409
130 ret = cmd_empty_trash(args); 130 ret = cmd_empty_trash(args);
131 } else if(!strcmp(cmd, "add-tag")) { 131 } else if(!strcmp(cmd, "add-tag")) {
132 ret = cmd_add_tag(args); 132 ret = cmd_add_tag(args);
133 } else if(!strcmp(cmd, "remove-tag")) { 133 } else if(!strcmp(cmd, "remove-tag")) {
134 ret = cmd_remove_tag(args); 134 ret = cmd_remove_tag(args);
135 } else if(!strcmp(cmd, "update-tags")) { 135 } else if(!strcmp(cmd, "set-tags")) {
136 ret = cmd_update_tags(args); 136 ret = cmd_set_tags(args);
137 } else if(!strcmp(cmd, "list-tags")) { 137 } else if(!strcmp(cmd, "list-tags")) {
138 ret = cmd_list_tags(args); 138 ret = cmd_list_tags(args);
139 } else if(!strcmp(cmd, "add-dir") 139 } else if(!strcmp(cmd, "add-dir")
140 || !strcmp(cmd, "add-directory")) { 140 || !strcmp(cmd, "add-directory")) {
141 ret = cmd_add_directory(args); 141 ret = cmd_add_directory(args);
165 165
166 void print_usage(char *cmd) { 166 void print_usage(char *cmd) {
167 fprintf(stderr, "Usage: %s command [options] arguments...\n\n", cmd); 167 fprintf(stderr, "Usage: %s command [options] arguments...\n\n", cmd);
168 168
169 fprintf(stderr, "Commands:\n"); 169 fprintf(stderr, "Commands:\n");
170 fprintf(stderr, " pull [-cld] <directory>\n"); 170 fprintf(stderr, " pull [-cld] [-t <tags>] <directory>\n");
171 fprintf(stderr, " push [-cld] <directory>\n"); 171 fprintf(stderr, " push [-cld] [-t <tags>] <directory>\n");
172 fprintf(stderr, " archive [-cld] <directory>\n"); 172 fprintf(stderr, " archive [-cld] <directory>\n");
173 fprintf(stderr, " resolve-conflicts <directory>\n"); 173 fprintf(stderr, " resolve-conflicts <directory>\n");
174 fprintf(stderr, " delete-conflicts <directory>\n"); 174 fprintf(stderr, " delete-conflicts <directory>\n");
175 fprintf(stderr, " trash-info <directory>\n"); 175 fprintf(stderr, " trash-info <directory>\n");
176 fprintf(stderr, " empty-trash <directory>\n"); 176 fprintf(stderr, " empty-trash <directory>\n");
177 fprintf(stderr, " add-tag [-s <syncdir>] <file> <tag>\n"); 177 fprintf(stderr, " add-tag [-s <syncdir>] <file> <tag>\n");
178 fprintf(stderr, " remove-tag [-s <syncdir>] <file> <tag>\n"); 178 fprintf(stderr, " remove-tag [-s <syncdir>] <file> <tag>\n");
179 fprintf(stderr, " update-tags [-s <syncdir>] <file> [tags]\n"); 179 fprintf(stderr, " set-tags [-s <syncdir>] <file> [tags]\n");
180 fprintf(stderr, " list-tags [-s <syncdir>] <file>\n\n"); 180 fprintf(stderr, " list-tags [-s <syncdir>] <file>\n\n");
181 181
182 fprintf(stderr, "Options:\n"); 182 fprintf(stderr, "Options:\n");
183 fprintf(stderr, " -c Disable conflict detection\n"); 183 fprintf(stderr, " -c Disable conflict detection\n");
184 fprintf(stderr, " -l Lock the repository before access\n"); 184 fprintf(stderr, " -l Lock the repository before access\n");
185 fprintf(stderr, " -d Don't lock the repository\n"); 185 fprintf(stderr, " -d Don't lock the repository\n");
186 //fprintf(stderr, " -r Read changes from stdin\n\n"); 186 fprintf(stderr, " -t <tags> "
187 "Only sync files which have the specified tags\n");
188 fprintf(stderr, " -r "
189 "Remove resources not matching the tag filter\n");
187 fprintf(stderr, " -v verbose output (all commands)\n\n"); 190 fprintf(stderr, " -v verbose output (all commands)\n\n");
188 191
189 fprintf(stderr, "Config commands:\n"); 192 fprintf(stderr, "Config commands:\n");
190 fprintf(stderr, " add-directory\n"); 193 fprintf(stderr, " add-directory\n");
191 fprintf(stderr, " list-directories\n"); 194 fprintf(stderr, " list-directories\n");
247 } 250 }
248 } 251 }
249 return 0; 252 return 0;
250 } 253 }
251 } 254 }
255 return 1;
256 }
257
258 static int matches_tags(UcxList *resource_tags, UcxList *tags) {
259 if(!tags) {
260 return 1;
261 }
262 if(!resource_tags) {
263 return 0;
264 }
265
266 UcxMap *res_tagmap = ucx_map_new(32);
267 UCX_FOREACH(elm, resource_tags) {
268 DavTag *t = elm->data;
269 // the value actually doesn't matter
270 ucx_map_cstr_put(res_tagmap, t->name, t);
271 }
272
273 int ret = 1;
274
275 // TODO: replace FOREACH with new tag expression evaluation
276 UCX_FOREACH(elm, tags) {
277 DavTag *matches_tag = elm->data;
278 if(!ucx_map_cstr_get(res_tagmap, matches_tag->name)) {
279 ret = 0;
280 break;
281 }
282 }
283
284 ucx_map_free(res_tagmap);
285 return ret;
286 }
287
288 static int res_matches_tags(DavResource *res, UcxList *tags) {
289 if(!tags) {
290 return 1;
291 }
292
293 DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_NS, "tags");
294 UcxList *res_tags = parse_dav_xml_taglist(tagsprop);
295
296 int ret = matches_tags(res_tags, tags);
297 // TODO: free list content
298 ucx_list_free(res_tags);
299 return ret;
300 }
301
302 static int localres_matches_tags(LocalResource *res, UcxList *tags) {
303 // TODO: implement
252 return 1; 304 return 1;
253 } 305 }
254 306
255 static DavSession* create_session(DavContext *ctx, Repository *repo, char *url) { 307 static DavSession* create_session(DavContext *ctx, Repository *repo, char *url) {
256 DavSession *sn = dav_session_new_auth( 308 DavSession *sn = dav_session_new_auth(
287 fprintf(stderr, "%sarchive", sep); 339 fprintf(stderr, "%sarchive", sep);
288 } 340 }
289 fprintf(stderr, "\n"); 341 fprintf(stderr, "\n");
290 } 342 }
291 343
344 static void localres_keep(SyncDatabase *db, const char *path) {
345 LocalResource *local = ucx_map_cstr_remove(db->resources, path);
346 if(local) {
347 local->keep = TRUE;
348 }
349
350 }
351
292 int cmd_pull(CmdArgs *a) { 352 int cmd_pull(CmdArgs *a) {
293 if(a->argc != 1) { 353 if(a->argc != 1) {
294 fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many"); 354 fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many");
295 return -1; 355 return -1;
296 } 356 }
392 } 452 }
393 453
394 return -1; 454 return -1;
395 } 455 }
396 456
457 UcxList *tags = NULL;
458 char *tags_str = cmd_getoption(a, "tags");
459 if(tags_str) {
460 tags = parse_csv_taglist(tags_str, strlen(tags_str));
461 }
462 DavBool rm_tagmismatch = cmd_getoption(a, "remove") ? 1 : 0;
463
397 int sync_success = 0; 464 int sync_success = 0;
398 int sync_delete = 0; 465 int sync_delete = 0;
399 int sync_error = 0; 466 int sync_error = 0;
400 467
401 UcxMap *svrres = ucx_map_new(db->resources->count); 468 UcxMap *svrres = ucx_map_new(db->resources->count);
411 if (res_matches_filter(dir, res->path)) { 478 if (res_matches_filter(dir, res->path)) {
412 res = res->next; 479 res = res->next;
413 continue; 480 continue;
414 } 481 }
415 482
483 if (!res_matches_tags(res, tags)) {
484 if(!rm_tagmismatch) {
485 localres_keep(db, res->path);
486 }
487 res = res->next;
488 continue;
489 }
490
416 char *status = dav_get_string_property(res, "idav:status"); 491 char *status = dav_get_string_property(res, "idav:status");
417 if(status && !strcmp(status, "broken")) { 492 if(status && !strcmp(status, "broken")) {
418 res = res->next; 493 res = res->next;
494 localres_keep(db, res->path);
419 continue; 495 continue;
420 } 496 }
421 497
422 // download the resource 498 // download the resource
423 if(!sync_shutdown && sync_get_resource(a, dir, res, db, &sync_success)) { 499 if(!sync_shutdown && sync_get_resource(a, dir, res, db, &sync_success)) {
464 UCX_MAP_FOREACH(key, local, i) { 540 UCX_MAP_FOREACH(key, local, i) {
465 if (res_matches_filter(dir, local->path)) { 541 if (res_matches_filter(dir, local->path)) {
466 continue; 542 continue;
467 } 543 }
468 544
469 if(sync_shutdown) { 545 if(sync_shutdown || local->keep) {
470 ucx_map_cstr_put(svrres, local->path, local_resource_copy(local)); 546 ucx_map_cstr_put(svrres, local->path, local_resource_copy(local));
471 } else { 547 } else {
472 // sync_remove_resource does all necessary tests 548 // sync_remove_resource does all necessary tests
473 int ret = sync_remove_local_resource(dir, local); 549 int ret = sync_remove_local_resource(dir, local);
474 if(ret == -1) { 550 if(ret == -1) {
1232 } 1308 }
1233 newres->skipped = res->skipped; 1309 newres->skipped = res->skipped;
1234 newres->size = res->size; 1310 newres->size = res->size;
1235 newres->last_modified = res->last_modified; 1311 newres->last_modified = res->last_modified;
1236 newres->isdirectory = res->isdirectory; 1312 newres->isdirectory = res->isdirectory;
1313 if(res->tags_hash) {
1314 newres->tags_hash = strdup(res->tags_hash);
1315 }
1316 newres->tags_updated = res->tags_updated;
1237 return newres; 1317 return newres;
1238 } 1318 }
1239 1319
1240 int local_resource_is_changed(SyncDirectory *dir, SyncDatabase *db, LocalResource *res) { 1320 int local_resource_is_changed(SyncDirectory *dir, SyncDatabase *db, LocalResource *res) {
1241 LocalResource *db_res = ucx_map_cstr_get(db->resources, res->path); 1321 LocalResource *db_res = ucx_map_cstr_get(db->resources, res->path);
2119 return 0; 2199 return 0;
2120 } 2200 }
2121 2201
2122 #define CMD_TAG_ADD 0 2202 #define CMD_TAG_ADD 0
2123 #define CMD_TAG_REMOVE 1 2203 #define CMD_TAG_REMOVE 1
2124 #define CMD_TAG_UPDATE 2 2204 #define CMD_TAG_SET 2
2125 #define CMD_TAG_LIST 3 2205 #define CMD_TAG_LIST 3
2126 int cmd_add_tag(CmdArgs *args) { 2206 int cmd_add_tag(CmdArgs *args) {
2127 if(args->argc != 2) { 2207 if(args->argc != 2) {
2128 fprintf(stderr, "Too %s arguments\n", args->argc <= 1 ? "few" : "many"); 2208 fprintf(stderr, "Too %s arguments\n", args->argc <= 1 ? "few" : "many");
2129 return -1; 2209 return -1;
2137 return -1; 2217 return -1;
2138 } 2218 }
2139 return cmd_tagopt(args, CMD_TAG_REMOVE); 2219 return cmd_tagopt(args, CMD_TAG_REMOVE);
2140 } 2220 }
2141 2221
2142 int cmd_update_tags(CmdArgs *args) { 2222 int cmd_set_tags(CmdArgs *args) {
2143 if(args->argc < 1 || args->argc > 2) { 2223 if(args->argc < 1 || args->argc > 2) {
2144 fprintf(stderr, "Too %s arguments\n", args->argc < 1 ? "few" : "many"); 2224 fprintf(stderr, "Too %s arguments\n", args->argc < 1 ? "few" : "many");
2145 return -1; 2225 return -1;
2146 } 2226 }
2147 return cmd_tagopt(args, CMD_TAG_UPDATE); 2227 return cmd_tagopt(args, CMD_TAG_SET);
2148 } 2228 }
2149 2229
2150 int cmd_list_tags(CmdArgs *args) { 2230 int cmd_list_tags(CmdArgs *args) {
2151 if(args->argc != 1) { 2231 if(args->argc != 1) {
2152 fprintf(stderr, "Too %s arguments\n", args->argc <= 1 ? "few" : "many"); 2232 fprintf(stderr, "Too %s arguments\n", args->argc <= 1 ? "few" : "many");
2179 2259
2180 LocalResource *localres = ucx_map_cstr_get(db->resources, file.path); 2260 LocalResource *localres = ucx_map_cstr_get(db->resources, file.path);
2181 UcxList *tags = NULL; 2261 UcxList *tags = NULL;
2182 DavBool store_tags = FALSE; 2262 DavBool store_tags = FALSE;
2183 2263
2184 if(cmd != CMD_TAG_UPDATE) { 2264 if(cmd != CMD_TAG_SET) {
2185 char *tag = args->argv[1]; 2265 char *tag = args->argv[1];
2186 char *tagcolor = NULL; // TODO: get color 2266 char *tagcolor = NULL; // TODO: get color
2187 2267
2188 tags = sync_get_file_tags(file.dir, localres, NULL); 2268 tags = sync_get_file_tags(file.dir, localres, NULL);
2189 UcxList *x = NULL; 2269 UcxList *x = NULL;

mercurial