added conflict detection

Thu, 10 Jul 2014 13:50:00 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Thu, 10 Jul 2014 13:50:00 +0200
changeset 52
91517b874a86
parent 51
e94bf8530d56
child 53
ddc4efc9b0f8

added conflict detection

dav/sync.c file | annotate | diff | comparison | revisions
dav/sync.h file | annotate | diff | comparison | revisions
--- a/dav/sync.c	Fri Jul 04 12:09:48 2014 +0200
+++ b/dav/sync.c	Thu Jul 10 13:50:00 2014 +0200
@@ -35,6 +35,7 @@
 #include <libxml/xmlerror.h>
 #include <sys/types.h>
 #include <ucx/string.h>
+#include <ucx/utils.h>
 #include <dirent.h>
 
 #include <libidav/webdav.h>
@@ -192,19 +193,19 @@
     if(local) {
         if(stat(local_path, &s)) {
             if(errno == ENOENT) {
-                printf("removed %s\n", res->path);
+                printf("removed: %s\n", res->path);
                 // the file is in the database, but doesn't exists
                 // mark the file as removed to delete it on next push
                 ucx_map_cstr_remove(db->resources, local->path);
                 ucx_map_cstr_put(db->remove, local->path, local);
                 return 0;
             } else {
-                fprintf(stderr, "stat failed: %s\n", local_path);
+                fprintf(stderr, "Cannot stat file: %s\n", local_path);
                 free(local_path);
                 return -1;
             }
         }
-        
+              
         if(local->etag) {
             sstr_t e = sstr(etag);
             if(sstrprefix(e, S("W/"))) {
@@ -215,8 +216,21 @@
                 return 0;
             }
         }
+        
+        if(s.st_mtim.tv_sec != local->last_modified) {
+            // file modified on the server and on the client
+            rename_local_file(dir, db, local->path);
+        }
+    } else {
+        if(stat(local_path, &s)) {
+            if(errno != ENOENT) {
+                fprintf(stderr, "Cannot stat file: %s\n", local_path);
+            }
+        } else if(!S_ISDIR(s.st_mode)) {
+            rename_local_file(dir, db, res->path);
+        }
     }
-    
+      
     int ret = 0;
     if(res->iscollection) {
         mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
@@ -227,16 +241,20 @@
     } else {
         FILE *out = fopen(local_path, "w");
         if(!out) {
-            fprintf(stderr, "cannot open output file: %s\n", local_path);
+            fprintf(stderr, "Cannot open output file: %s\n", local_path);
             free(local_path);
             return -1;
         }
-        printf("get %s\n", res->path);
+        printf("get: %s\n", res->path);
         if(dav_get_content(res, out, (dav_write_func)fwrite)) {
             ret = -1;
         }
         fclose(out);
         
+        if(stat(local_path, &s)) {
+            fprintf(stderr, "Cannot stat file: %s\n", local_path);
+        }
+        
         if(ret == 0) {
             if(!local) {
                 // new local resource
@@ -279,6 +297,42 @@
     free(local_path);
 }
 
+void rename_local_file(SyncDirectory *dir, SyncDatabase *db, char *path) {
+    char *local_path = util_concat_path(dir->path, path);
+    char *parent = util_parent_path(local_path);
+    
+    int rev = 0;
+    struct stat s;
+    int loop = 1;
+    do {
+        sstr_t new_path = ucx_asprintf(
+        ucx_default_allocator(),
+            "%sorig.%d.%s",
+            parent,
+            rev,
+            util_resource_name(path));
+        
+        
+        if(stat(new_path.ptr, &s)) {
+            if(errno == ENOENT) {
+                loop = 0;
+                printf("conflict: %s\n", local_path);
+                if(rename(local_path, new_path.ptr)) {
+                    printf("errno: %d\n", errno);
+                    fprintf(
+                            stderr,
+                            "Cannot rename file %s to %s\n",
+                            local_path,
+                            new_path.ptr);
+                }
+            }
+        }
+        rev++;
+        free(new_path.ptr);
+    } while(loop);
+    free(parent);
+}
+
 int cmd_push(CmdArgs *a) {
     if(a->argc != 1) {
         fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many");
--- a/dav/sync.h	Fri Jul 04 12:09:48 2014 +0200
+++ b/dav/sync.h	Thu Jul 10 13:50:00 2014 +0200
@@ -47,7 +47,7 @@
 
 int sync_get_resource(SyncDirectory *dir, DavResource *res, SyncDatabase *db);
 void sync_remove_resource(SyncDirectory *dir, LocalResource *res);
-
+void rename_local_file(SyncDirectory *dir, SyncDatabase *db, char *path);
 UcxList* local_scan(SyncDirectory *dir, SyncDatabase *db);
 
 int sync_put_resource(SyncDirectory *dir, DavResource *res, SyncDatabase *db);

mercurial