dav/sync.c

changeset 650
14e7101d7604
parent 649
0f4c59ac8c74
child 659
51206020cfbe
--- a/dav/sync.c	Thu Oct 03 12:00:25 2019 +0200
+++ b/dav/sync.c	Sun Oct 06 13:27:24 2019 +0200
@@ -1039,6 +1039,8 @@
      
     // if hashing is enabled we can compare the hash of the remote file
     // with the local file to test if a file is really modified
+    DavBool update_db = FALSE;
+    char *update_hash = NULL;
     if (!iscollection &&
         !link &&
         (ret == REMOTE_CHANGE_MODIFIED || ret == REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED) &&
@@ -1052,9 +1054,23 @@
         if(local_hash) {
             if(!strcmp(hash, local_hash)) {
                 ret = REMOTE_NO_CHANGE;
+                update_db = TRUE;
+                update_hash = local_hash;
+                
+                // if local already exists, update the hash here
+                // because it is possible that there are metadata updates
+                // and in this case the db will updated later and needs
+                // the current hash
+                if(local) {
+                    if(local->hash) {
+                        free(local->hash);
+                    }
+                    local->hash = local_hash;
+                }
+            } else {
+                free(local_hash);
             }
         }
-        free(local_hash);
     }
     
     // if a file is not modified, check if the metadata has changed
@@ -1104,6 +1120,29 @@
         break;
     }
     
+    // if update_db is set, a file was modified on the server, but we already
+    // have the file content, but we need to update the db
+    if(ret == REMOTE_NO_CHANGE && update_db) {
+        if(!local) {
+            local = calloc(1, sizeof(LocalResource));
+            local->path = strdup(res->path);
+            
+            ucx_map_cstr_put(db->resources, local->path, local);
+        }
+        
+        // update local res
+        SYS_STAT s;
+        if(!sys_stat(local_path, &s)) {
+            sync_set_metadata_from_stat(local, &s);
+        } else {
+            fprintf(stderr, "stat failed for file: %s : %s", local_path, strerror(errno));
+        }
+        local_resource_set_etag(local, etag);
+        if(!local->hash) {
+            local->hash = update_hash;
+        } // else: hash already updated
+    }
+        
     free(local_path);
     return ret;
 }
@@ -2151,8 +2190,15 @@
             DavBool equal = FALSE;
             int changed = remote_resource_is_changed(sn, dir, db, res, local_res, &equal);
             if(equal) {
+                char *etag = dav_get_string_property(res, "D:getetag");
                 if(local_res->metadata_updated) {
                     ls_update = ucx_list_prepend(ls_update, local_res);
+                } else if(etag) {
+                    // update etag in db
+                    if(local_res->etag) {
+                        free(local_res->etag);
+                    }
+                    local_res->etag = strdup(etag);
                 }
             } else if(cdt && changed) {
                 printf("conflict: %s\n", local_res->path);
@@ -2256,9 +2302,6 @@
         remove(locktokenfile);
     }
     
-    //ucx_map_free_content(db->resources, (ucx_destructor)local_resource_free);
-    //ucx_map_free(db->resources);
-    
     dav_session_destroy(sn);
     
     // Report
@@ -2866,15 +2909,14 @@
             {
                 // mtime and size unchanged, content also likely unchanged
                 return 0;
-            } else if(SYNC_HASHING(dir) && db_res->hash) {
-                // in case of activated hashing, we check if the content
-                // has really changed
-                
+            } else if(SYNC_HASHING(dir)) {
                 // res->hash missing (see above)
                 char *local_path = util_concat_path(dir->path, local_resource_path(res));
                 res->hash = util_file_hash(local_path);
                 free(local_path);
-                if(res->hash && !strcmp(res->hash, db_res->hash)) {
+                
+                // check if the content has really changed
+                if(res->hash && db_res->hash && !strcmp(res->hash, db_res->hash)) {
                     return 0;
                 }
             }

mercurial