diff -r 4a6a59f89f9f -r 11797f33bc24 dav/sync.c --- a/dav/sync.c Fri Feb 02 18:57:21 2018 +0100 +++ b/dav/sync.c Sat Feb 03 15:59:53 2018 +0100 @@ -974,7 +974,7 @@ if(dir->tagconfig && local_res->tags_updated && !abort) { // get tags from tagstore (xattr or something else) // and store it in resource property - UcxList *tags = sync_get_file_tags(dir, local_res); + UcxList *tags = sync_get_file_tags(dir, local_res, NULL); DavXmlNode *prop = create_xml_taglist(tags); if(prop) { dav_set_property_ns(res, DAV_NS, "tags", prop); @@ -1248,7 +1248,7 @@ res->etag = strdup(db_res->etag); } - if(dir->tagconfig && dir->tagconfig->scan && !res->tags_updated) { + if(dir->tagconfig && dir->tagconfig->detect_changes && !res->tags_updated) { UcxBuffer *tags = sync_get_file_tag_data(dir, res); if(tags) { if(db_res->tags_hash) { @@ -1330,34 +1330,94 @@ } } - if(!tags) { + 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_KEEP_LOCAL: { + store_empty_tags = TRUE; + tags = local_tags; + // TODO: free tags + break; + } + case TAG_KEEP_REMOTE: break; + case TAG_MERGE: { + // this map is used to check the existence of tags + UcxMap *tag_map = ucx_map_new(32); + // merged taglist + UcxList *new_tags = NULL; + + // add all local tags + UCX_FOREACH(elm, local_tags) { + DavTag *t = elm->data; + ucx_map_cstr_put(tag_map, t->name, t); + DavTag *newt = calloc(1, sizeof(DavTag)); + newt->color = t->color ? strdup(t->color) : NULL; + newt->name = strdup(t->name); + new_tags = ucx_list_append(new_tags, newt); + } + // check if a remote tag is already in the map + // and if not add it to the new taglist + UCX_FOREACH(elm, tags) { + DavTag *t = elm->data; + if(!ucx_map_cstr_get(tag_map, t->name)) { + DavTag *newt = calloc(1, sizeof(DavTag)); + newt->color = t->color ? strdup(t->color) : NULL; + newt->name = strdup(t->name); + new_tags = ucx_list_append(new_tags, newt); + } + } + + ucx_map_free(tag_map); + // TODO: free tags and local_tags + + tags = new_tags; + + store_empty_tags = TRUE; + + break; + } + } + } else { + // TODO: free local_tags + } + } + + if(!tags && !store_empty_tags) { return 0; } int ret = 0; if(dir->tagconfig->store == TAG_STORE_XATTR) { UcxBuffer *data = NULL; - switch(dir->tagconfig->local_format) { - default: break; - case TAG_FORMAT_TEXT: { - data = create_text_taglist(tags); - break; - } - case TAG_FORMAT_CSV: { - data = create_csv_taglist(tags); - break; + if(tags) { + switch(dir->tagconfig->local_format) { + default: break; + case TAG_FORMAT_TEXT: { + data = create_text_taglist(tags); + break; + } + case TAG_FORMAT_CSV: { + data = create_csv_taglist(tags); + break; + } + case TAG_FORMAT_MACOS: { + data = create_macos_taglist(tags); + break; + } } - case TAG_FORMAT_MACOS: { - data = create_macos_taglist(tags); - break; + + if(data) { + ret = xattr_set(path, dir->tagconfig->xattr_name, data->space, data->pos); + ucx_buffer_free(data); + } else { + ret = -1; } - } - - if(data) { - ret = xattr_set(path, "tags", data->space, data->pos); - ucx_buffer_free(data); } else { - ret = -1; + // TODO: relete xattr + //ret = xattr_remove(path, dir->tagconfig->xattr_name); } } @@ -1376,7 +1436,7 @@ char *local_path = util_concat_path(dir->path, res->path); char* tag_data = xattr_get( local_path, - dir->tagconfig->local_format == TAG_FORMAT_MACOS ? MACOS_TAG_XATTR : "tags", + dir->tagconfig->xattr_name, &tag_length); free(local_path); @@ -1388,7 +1448,9 @@ return buf; } -UcxList* sync_get_file_tags(SyncDirectory *dir, LocalResource *res) { +UcxList* sync_get_file_tags(SyncDirectory *dir, LocalResource *res, DavBool *changed) { + if(changed) *changed = FALSE; + UcxList *tags = NULL; if(!dir->tagconfig) { @@ -1400,7 +1462,16 @@ sync_get_file_tag_data(dir, res); if(tag_buf) { - res->tags_hash = dav_create_hash(tag_buf->space, tag_buf->size); + char *newhash = dav_create_hash(tag_buf->space, tag_buf->size); + if(res->tags_hash) { + if(changed && strcmp(res->tags_hash, newhash)) { + *changed = TRUE; + } + free(res->tags_hash); + } else { + if(changed) *changed = TRUE; + } + res->tags_hash = newhash; switch(dir->tagconfig->local_format) { default: break; @@ -1421,6 +1492,8 @@ // we created the buffer therefore we destroy it ucx_buffer_free(tag_buf); } + } else if(res->tags_hash) { + if(changed) *changed = TRUE; } } @@ -1453,7 +1526,7 @@ dav_set_content(res, in, (dav_read_func)fread); if(dir->tagconfig) { - UcxList *tags = sync_get_file_tags(dir, local); + UcxList *tags = sync_get_file_tags(dir, local, NULL); // TODO: check remote tags DavXmlNode *prop = create_xml_taglist(tags); if(prop) { dav_set_property_ns(res, DAV_NS, "tags", prop);