fixes tag syncing

Sun, 27 May 2018 19:45:28 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 27 May 2018 19:45:28 +0200
changeset 379
cdaf5a3d3a50
parent 378
d64ecd8d6969
child 380
8a0c727aa409

fixes tag syncing

dav/libxattr.c file | annotate | diff | comparison | revisions
dav/libxattr.h file | annotate | diff | comparison | revisions
dav/sync.c file | annotate | diff | comparison | revisions
dav/sync.h file | annotate | diff | comparison | revisions
--- 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) {
--- 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
--- 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 <syncdir>] <file> <tag>\n");
     fprintf(stderr, "        remove-tag [-s <syncdir>] <file> <tag>\n");
     fprintf(stderr, "        update-tags [-s <syncdir>] <file> [tags]\n");
-    fprintf(stderr, "        update-tags [-s <syncdir>] <file>\n\n");
+    fprintf(stderr, "        list-tags [-s <syncdir>] <file>\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;
+            }
         }
     }
     
--- 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(

mercurial