dav/sync.c

changeset 65
d4077e8175f3
parent 64
112dbf7ba8b0
child 66
f8c1f685e08e
--- a/dav/sync.c	Sat Nov 08 20:27:10 2014 +0100
+++ b/dav/sync.c	Sun Nov 09 11:30:24 2014 +0100
@@ -87,8 +87,6 @@
         ret = cmd_pull(args);
     } else if(!strcmp(cmd, "push")) {
         ret = cmd_push(args);
-    } else if(!strcmp(cmd, "sync")) {
-        ret = cmd_sync(args);
     }
     
     // TODO: cleanup sync config (don't forget to call regfree for regex)
@@ -109,6 +107,17 @@
 }
 
 static int res_matches_filter(SyncDirectory *dir, char *res_path) {
+    // trash filter
+    if (dir->trash) {
+        sstr_t rpath = sstr(util_concat_path(dir->path, res_path));
+        if (sstrprefix(rpath, sstr(dir->trash))) {
+            free(rpath.ptr);
+            return 1;
+        }
+        free(rpath.ptr);
+    }
+    
+    // include/exclude filter
     UCX_FOREACH(inc, dir->include) {
         regex_t* pattern = (regex_t*) inc->data;
         if (regexec(pattern, res_path, 0, NULL, 0) == 0) {
@@ -215,7 +224,7 @@
             continue;
         }
         // sync_remove_resource does all necessary tests
-        sync_remove_resource(dir, local);
+        sync_remove_local_resource(dir, local);
     }
     ucx_map_free(db->resources);
     db->resources = svrres;
@@ -232,10 +241,6 @@
 }
 
 int sync_get_resource(CmdArgs *a, SyncDirectory *dir, DavResource *res, SyncDatabase *db) {
-    LocalResource *removed = ucx_map_cstr_get(db->remove, res->path);
-    if(removed) {
-        return 0;
-    }
     int cdt = cmd_getoption(a, "conflict") ? 0 : 1; // conflict detection
     
     LocalResource *local = ucx_map_cstr_get(db->resources, res->path);
@@ -243,7 +248,8 @@
     
     char *etag = dav_get_property(res, "D:getetag");
     struct stat s;
-    if(local) { 
+    if(local) {
+        int exists = 1;
         if(stat(local_path, &s)) {
             // Ignore the fact, that the file is locally removed. If the
             // server has an updated version, we readd the file or the
@@ -252,6 +258,8 @@
                 fprintf(stderr, "Cannot stat file: %s\n", local_path);
                 free(local_path);
                 return -1;
+            } else {
+                exists = 0;
             }
         }
               
@@ -266,7 +274,7 @@
             }
         }
         
-        if(cdt && s.st_mtime != local->last_modified) {
+        if(cdt && exists && s.st_mtime != local->last_modified) {
             // file modified on the server and on the client
             rename_local_file(dir, db, local->path);
         }
@@ -328,7 +336,7 @@
     return ret;
 }
 
-void sync_remove_resource(SyncDirectory *dir, LocalResource *res) {
+void sync_remove_local_resource(SyncDirectory *dir, LocalResource *res) {
     char *local_path = util_concat_path(dir->path, res->path);
     struct stat s;
     if(stat(local_path, &s)) {
@@ -342,7 +350,10 @@
     }
     
     printf("delete: %s\n", res->path);
-    if(unlink(local_path)) {
+    
+    if(dir->trash) {
+        move_to_trash(dir, local_path);
+    } else if(unlink(local_path)) {
         fprintf(stderr, "Cannot remove file %s\n", local_path);
     }
     free(local_path);
@@ -369,7 +380,7 @@
                 loop = 0;
                 printf("conflict: %s\n", local_path);
                 if(rename(local_path, new_path.ptr)) {
-                    printf("errno: %d\n", errno);
+                    //printf("errno: %d\n", errno);
                     fprintf(
                             stderr,
                             "Cannot rename file %s to %s\n",
@@ -384,6 +395,43 @@
     free(parent);
 }
 
+void move_to_trash(SyncDirectory *dir, char *path) {
+    char *new_path = NULL;
+    for (int i=0;;i++) {
+        sstr_t np = ucx_asprintf(
+        ucx_default_allocator(),
+            "%s%d-%s",
+            dir->trash,
+            i,
+            util_resource_name(path));
+        
+        struct stat s;
+        if(stat(np.ptr, &s)) {
+            if(errno == ENOENT) {
+                new_path = np.ptr;
+            }
+            break;
+        }
+        free(np.ptr);
+    };
+    
+    if(!new_path) {
+        fprintf(stderr, "Cannot move file %s to trash.\n", path);
+        return;
+    }
+    
+    if(rename(path, new_path)) {
+        //printf("errno: %d\n", errno);
+        fprintf(
+                stderr,
+                "Cannot rename file %s to %s\n",
+                path,
+                new_path);
+    }
+    
+    free(new_path);
+}
+
 int cmd_push(CmdArgs *a) {
     if(a->argc != 1) {
         fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many");
@@ -453,18 +501,9 @@
     UcxMapIterator i = ucx_map_iterator(db->resources);
     LocalResource *local;
     UCX_MAP_FOREACH(key, local, i) {
-        // TODO: save deletion: check for remote changes
-        
-        DavResource *res = dav_resource_new(sn, local->path);
-        printf("delete: %s\n", res->path);
-        if(dav_delete(res)) {
-            if(sn->error != DAV_NOT_FOUND) {
-                fprintf(stderr, "Cannot delete resource %s\n", res->path);
-            }
+        if(sync_delete_remote_resource(sn, local)) {
+            ucx_map_cstr_put(lclres, local->path, local);
         }
-        dav_resource_free(res);
-        // TODO: free local resource
-        ucx_map_remove(db->remove, key);
     }
     ucx_map_free(db->resources);
     db->resources = lclres;
@@ -667,9 +706,38 @@
     return ret;
 }
 
+int sync_delete_remote_resource(DavSession *sn, LocalResource *local_res) {
+    DavResource *res = dav_get(sn, local_res->path, "D:getetag");
+    if(!res) {
+        return sn->error == DAV_NOT_FOUND ? 0 : 1;
+    }
+    
+    char *etag = dav_get_property(res, "D:getetag");
+    if(etag) {
+        if(strlen(etag) > 2 && etag[0] == 'W' && etag[1] == '/') {
+            etag = etag + 2;
+        } 
+    }
+    
+    int ret = 0;
+    if(!strcmp(etag, local_res->etag)) {
+        // local resource metadata == remote resource metadata
+        // resource can be deleted
+        printf("delete: %s\n", res->path);
+        if(dav_delete(res)) {
+            if(sn->error != DAV_NOT_FOUND) {
+                fprintf(stderr, "Cannot delete resource %s\n", res->path);
+            }
+        }
+    } else {
+        ret = 1;
+    }
+    
+    // cleanup
+    dav_resource_free(res);
+    
+    return ret;
+}
 
 
-int cmd_sync(CmdArgs *a) {
-    return 0;
-}
 

mercurial