# HG changeset patch # User Olaf Wintermann # Date 1527443128 -7200 # Node ID cdaf5a3d3a50379bf47a192f2f17f6f46209fbdc # Parent d64ecd8d69695d1340d8b01961b24f423b48b04c fixes tag syncing diff -r d64ecd8d6969 -r cdaf5a3d3a50 dav/libxattr.c --- a/dav/libxattr.c Sun May 27 13:02:40 2018 +0200 +++ b/dav/libxattr.c Sun May 27 19:45:28 2018 +0200 @@ -163,6 +163,13 @@ return ret; } +int xattr_remove(const char *path, const char *name) { + char *attrname = name2nsname(name); + int ret = removexattr(path, attrname); + free(attrname); + return ret; +} + #endif /* Linux */ #ifdef __APPLE__ @@ -248,6 +255,10 @@ return ret; } +int xattr_remove(const char *path, const char *name) { + return removexattr(path, name, 0); +} + #endif /* Apple */ #ifdef __sun @@ -360,6 +371,17 @@ return remaining > 0 ? -1 : 0; } +int xattr_remove(const char *path, const char *name) { + int attrdir = open_attrfile(path, ".", O_RDONLY|O_XATTR); + if(attrdir == -1) { + return -1; + } + + int ret = unlinkat(attrdir, name, 0); + close(attrdir); + return ret; +} + #endif /* Sun */ @@ -441,6 +463,10 @@ return ret; } +int xattr_remove(const char *path, const char *name) { + return extattr_delete_file(path, EXTATTR_NAMESPACE_USER, name); +} + #endif /* FreeBSD */ @@ -460,6 +486,10 @@ return -1; } +int xattr_remove(const char *path, const char *name) { + return -1; +} + #endif /* unsupported platform */ void xattr_free_list(char **attrnames, ssize_t nelm) { diff -r d64ecd8d6969 -r cdaf5a3d3a50 dav/libxattr.h --- a/dav/libxattr.h Sun May 27 13:02:40 2018 +0200 +++ b/dav/libxattr.h Sun May 27 19:45:28 2018 +0200 @@ -42,6 +42,8 @@ int xattr_set(const char *path, const char *name, const void *value, size_t len); +int xattr_remove(const char *path, const char *name); + void xattr_free_list(char **attrnames, ssize_t nelm); #ifdef __cplusplus diff -r d64ecd8d6969 -r cdaf5a3d3a50 dav/sync.c --- a/dav/sync.c Sun May 27 13:02:40 2018 +0200 +++ b/dav/sync.c Sun May 27 19:45:28 2018 +0200 @@ -177,7 +177,7 @@ fprintf(stderr, " add-tag [-s ] \n"); fprintf(stderr, " remove-tag [-s ] \n"); fprintf(stderr, " update-tags [-s ] [tags]\n"); - fprintf(stderr, " update-tags [-s ] \n\n"); + fprintf(stderr, " list-tags [-s ] \n\n"); fprintf(stderr, "Options:\n"); fprintf(stderr, " -c Disable conflict detection\n"); @@ -1352,6 +1352,38 @@ return new_tags; } +int sync_tags_equal(UcxList *tags1, UcxList *tags2) { + if(!tags1) { + return tags2 ? 0 : 1; + } + if(!tags2) { + return tags1 ? 0 : 1; + } + + UcxMap *map1 = ucx_map_new(32); + UCX_FOREACH(elm, tags1) { + DavTag *t = elm->data; + ucx_map_cstr_put(map1, t->name, t); + } + + int equal = 1; + int i = 0; + UCX_FOREACH(elm, tags2) { + DavTag *t = elm->data; + if(!ucx_map_cstr_get(map1, t->name)) { + equal = 0; + break; + } + i++; + } + + if(i != map1->count) { + equal = 0; + } + ucx_map_free(map1); + return equal; +} + int sync_store_tags(SyncDirectory *dir, const char *path, LocalResource *local, DavResource *res) { if(!dir->tagconfig) { return 0; @@ -1366,36 +1398,38 @@ } } - DavBool store_empty_tags = FALSE; - if(dir->tagconfig->conflict != TAG_NO_CONFLICT) { - DavBool tags_changed = FALSE; - UcxList *local_tags = sync_get_file_tags(dir, local, &tags_changed); - if(tags_changed) { - switch(dir->tagconfig->conflict) { - case TAG_NO_CONFLICT: - case TAG_KEEP_LOCAL: { - store_empty_tags = TRUE; - tags = local_tags; - // TODO: free tags - break; - } - case TAG_KEEP_REMOTE: break; - case TAG_MERGE: { - UcxList *new_tags = sync_merge_tags(local_tags, tags); - // TODO: free tags and local_tags - tags = new_tags; - store_empty_tags = TRUE; - // make sure the merged tags will be pushed the next time - local->tags_updated = TRUE; - break; - } + DavBool store_tags = FALSE; + DavBool tags_changed = FALSE; + UcxList *local_tags = sync_get_file_tags(dir, local, &tags_changed); + if(tags_changed) { + switch(dir->tagconfig->conflict) { + case TAG_NO_CONFLICT: + case TAG_KEEP_LOCAL: { + store_tags = FALSE; + break; + } + case TAG_KEEP_REMOTE: { + store_tags = TRUE; + local->tags_updated = FALSE; } - } else { - // TODO: free local_tags + case TAG_MERGE: { + UcxList *new_tags = sync_merge_tags(local_tags, tags); + // TODO: free tags and local_tags + tags = new_tags; + store_tags = TRUE; + // make sure the merged tags will be pushed the next time + local->tags_updated = TRUE; + break; + } } + } else { + if(!sync_tags_equal(tags, local_tags)) { + store_tags = TRUE; + } + // TODO: free local_tags } - if(!tags && !store_empty_tags) { + if(!store_tags) { return 0; } @@ -1433,21 +1467,30 @@ if(local) { if(!local->tags_hash || strcmp(data_hash, local->tags_hash)) { printf("update: %s\n", local->path); - // TODO: update hash in localres?? } else { update = 0; } } if(update) { ret = xattr_set(path, dir->tagconfig->xattr_name, data->space, data->pos); + if(local) { + if(local->tags_hash) { + free(local->tags_hash); + } + local->tags_hash = data_hash; + } + } else { + free(data_hash); } ucx_buffer_free(data); } else { ret = -1; } } else { - // TODO: delete xattr - //ret = xattr_remove(path, dir->tagconfig->xattr_name); + if(local) { + printf("update: %s\n", local->path); + } + ret = xattr_remove(path, dir->tagconfig->xattr_name); } } @@ -1492,6 +1535,9 @@ if(!dir->tagconfig) { return NULL; } + if(changed && res->tags_updated) { + *changed = TRUE; + } if(dir->tagconfig->store == TAG_STORE_XATTR) { UcxBuffer *tag_buf = res->cached_tags ? res->cached_tags : @@ -2180,6 +2226,12 @@ } if(localres) { localres->tags_updated = TRUE; + if(!tags) { + if(localres->tags_hash) { + free(localres->tags_hash); + } + localres->tags_hash = NULL; + } } } diff -r d64ecd8d6969 -r cdaf5a3d3a50 dav/sync.h --- a/dav/sync.h Sun May 27 13:02:40 2018 +0200 +++ b/dav/sync.h Sun May 27 19:45:28 2018 +0200 @@ -91,6 +91,7 @@ UcxBuffer* sync_get_file_tag_data(SyncDirectory *dir, LocalResource *res); UcxList* sync_get_file_tags(SyncDirectory *dir, LocalResource *res, DavBool *changed); UcxList* sync_merge_tags(UcxList *tags1, UcxList *tags2); +int sync_tags_equal(UcxList *tags1, UcxList *tags2); int sync_store_tags(SyncDirectory *dir, const char *path, LocalResource *local, DavResource *res); int sync_store_tags_local(SyncDirectory *dir, LocalResource *local, const char *path, UcxList *tags); int sync_put_resource(