dav/sync.c

changeset 368
11797f33bc24
parent 367
4a6a59f89f9f
child 369
4322b8953bd5
--- 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);

mercurial