dav/sync.c

changeset 552
e1a12762bf0a
parent 551
99ef8202cd82
child 553
891823d8dd7b
--- a/dav/sync.c	Sun Apr 07 10:44:29 2019 +0200
+++ b/dav/sync.c	Sun Apr 07 13:08:50 2019 +0200
@@ -1595,7 +1595,7 @@
             // check if a file with this hash already exists
             LocalResource *origin = ucx_map_cstr_get(db_hashes, hash);
             if(origin) {
-                local->origin = strdup(origin->path);
+                local->origin = local_resource_copy(origin, origin->path);
                 // the file is a copied/moved file
                 // check if the file is in the resources_map, because then
                 // it still exists
@@ -1732,39 +1732,50 @@
     DavBool copy = TRUE;
     for(UcxList *elm=ls_copy;elm && !sync_shutdown;elm=elm->next) {
         LocalResource *local = elm->data;
-        DavResource *res = dav_resource_new(sn, local->origin);
+        
         int err = 0;
-        if(copy) {
-            printf("copy: %s -> %s\n", local->origin, local->path);
-            err = dav_copy_o(res, local->path, FALSE);
-            
-            if(!elm->next) {
-                // finished copy, begin move
-                elm->next = ls_move;
-                copy = FALSE;
+        DavResource *res = dav_resource_new(sn, local->path);
+        if(dav_exists(res)) {
+            printf("conflict: %s\n", local->path);
+            sync_skipped++;
+        } else {
+            DavResource *origin_res = dav_resource_new(sn, local->origin->path);
+            int origin_changed = remote_resource_is_changed(
+                    sn,
+                    dir,
+                    db,
+                    origin_res,
+                    local->origin);
+            if(origin_changed) {
+                // upload with put
+                printf("put: %s\n", local->path);
+                err = sync_put_resource(dir, res, local, &sync_success);
+            } else {
+                printf("%s: %s -> %s\n", copy ? "copy":"move", local->origin->path, local->path);
+                err = sync_move_remote_resource(
+                        dir,
+                        origin_res,
+                        local,
+                        copy,
+                        &sync_success);
             }
-        } else {
-            printf("move: %s -> %s\n", local->origin, local->path);
-            err = dav_move_o(res, local->path, FALSE);
         }
         
         if(err) {
-            if(sn->error == DAV_PRECONDITION_FAILED) {
-                printf("conflict: %s\n", local->path);
-                local->last_modified = 0;
-                local->skipped = TRUE;
-                sync_skipped++;
-            } else {
-                sync_error++;
-                print_resource_error(sn, res->path);
-                ret = -1;
-                error = 1;
-            }
+            sync_error++;
+            print_resource_error(sn, res->path);
+            ret = -1;
+            error = 1;
         }
         
-        dav_resource_free(res);
         LocalResource *dbres = ucx_map_cstr_remove(db->resources, local->path);
         ucx_map_cstr_put(db->resources, local->path, local);
+        
+        if(copy && !elm->next) {
+            // finished copy, begin move
+            elm->next = ls_move;
+            copy = FALSE;
+        }
     }
     
     // metadata updates
@@ -2228,28 +2239,6 @@
     }
 }
 
-LocalResource* local_resource_copy(LocalResource *res) {
-    LocalResource *newres = calloc(1, sizeof(LocalResource));
-    if(res->name) {
-        newres->name = strdup(res->name);
-    }
-    if(res->path) {
-        newres->path = strdup(res->path);
-    }
-    if(res->etag) {
-        newres->etag = strdup(res->etag);
-    }
-    newres->skipped = res->skipped;
-    newres->size = res->size;
-    newres->last_modified = res->last_modified;
-    newres->isdirectory = res->isdirectory;
-    if(res->tags_hash) {
-       newres->tags_hash = strdup(res->tags_hash); 
-    }
-    newres->tags_updated = res->tags_updated;
-    return newres;
-}
-
 int local_resource_is_changed(
         SyncDirectory *dir,
         SyncDatabase *db,
@@ -3406,6 +3395,78 @@
     return ret;
 }
 
+int sync_move_remote_resource(
+        SyncDirectory *dir,
+        DavResource *origin,
+        LocalResource *local,
+        DavBool copy,
+        int *counter)
+{
+    char *local_path = create_local_path(dir, local->path);
+    
+    SYS_STAT s;
+    if(sys_stat(local_path, &s)) {
+        fprintf(stderr, "Cannot stat file: %s\n", local_path);
+        perror("");
+        free(local_path);
+        return -1;
+    }
+    free(local_path);
+    
+    int result = 0;
+    if(copy) {
+        result = dav_copy_o(origin, local->path, FALSE);
+    } else {
+        result = dav_move_o(origin, local->path, FALSE);
+    }
+    
+    if(result != 0) {
+        return result;
+    }
+    
+    // replace LocalResource with origin content
+    LocalResource *local_origin = local->origin;
+    local->origin = NULL;
+    char *path = strdup(local->path);
+    // TODO: free stuff before replacing it
+    memcpy(local, local_origin, sizeof(LocalResource));
+    local->path = path;
+    
+    free(local_origin); // only free origin pointer
+    
+    // get new etag
+    DavResource *up_res = dav_get(origin->session, origin->path, "D:getetag");
+    if(up_res) {
+        (*counter)++;
+        
+        // everything seems fine, we can update the local resource
+        char *etag = dav_get_string_property(up_res, "D:getetag");
+        if(etag) {
+            if(strlen(etag) > 2 && etag[0] == 'W' && etag[1] == '/') {
+                etag = etag + 2;
+            } 
+        }
+
+        if(local->etag) {
+            free(local->etag);
+        }
+
+        if(etag) {
+            local->etag = strdup(etag);
+        } else {
+            local->etag = NULL;
+        }
+        
+        local->last_modified = s.st_mtime;
+        
+        dav_resource_free(up_res);
+    } else {
+        result = 1;
+    }
+    
+    return result;
+}
+
 int sync_delete_remote_resource(
         SyncDirectory *dir,
         DavSession *sn,
@@ -3440,7 +3501,7 @@
             } 
         }
 
-        if(etag && !strcmp(etag, local_res->etag)) {
+        if(nullstrcmp(etag, local_res->etag)) {
             // local resource metadata == remote resource metadata
             // resource can be deleted
             printf("delete: %s\n", res->path);

mercurial