adds dav-sync options for restoring deleted or modified files

Wed, 11 Jul 2018 16:40:07 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Wed, 11 Jul 2018 16:40:07 +0200
changeset 444
761dc4867208
parent 443
2f019a4bc78a
child 445
c525f049c8b7

adds dav-sync options for restoring deleted or modified files

dav/db.h file | annotate | diff | comparison | revisions
dav/sopt.c file | annotate | diff | comparison | revisions
dav/sync.c file | annotate | diff | comparison | revisions
dav/sync.h file | annotate | diff | comparison | revisions
--- a/dav/db.h	Wed Jul 11 15:46:15 2018 +0200
+++ b/dav/db.h	Wed Jul 11 16:40:07 2018 +0200
@@ -56,6 +56,7 @@
     char *tags_hash;
     
     DavBool keep;
+    DavBool restore;
 };
 
 struct SyncDatabase {
--- a/dav/sopt.c	Wed Jul 11 15:46:15 2018 +0200
+++ b/dav/sopt.c	Wed Jul 11 16:40:07 2018 +0200
@@ -81,7 +81,7 @@
                         ucx_map_cstr_put(a->options, "verbose", NOARG);
                         break;
                     }
-                    case 's': {;
+                    case 's': {
                         option = "syncdir";
                         optchar = 's';
                         break;
@@ -91,6 +91,14 @@
                         optchar = 't';
                         break;
                     }
+                    case 'D': {
+                        ucx_map_cstr_put(a->options, "restore-deleted", NOARG);
+                        break;
+                    }
+                    case 'M': {
+                        ucx_map_cstr_put(a->options, "restore-modified", NOARG);
+                        break;
+                    }
                 }
             }
         } else if(option) {
--- a/dav/sync.c	Wed Jul 11 15:46:15 2018 +0200
+++ b/dav/sync.c	Wed Jul 11 16:40:07 2018 +0200
@@ -171,8 +171,8 @@
     
     fprintf(stderr, "Commands:\n");
     fprintf(stderr, "        pull [-cldr] [-t <tags>] <directory>\n");
-    fprintf(stderr, "        push [-cldr] [-t <tags>] <directory>\n");
-    fprintf(stderr, "        archive [-cld] [-t <tags>] <directory>\n");
+    fprintf(stderr, "        push [-cldrDM] [-t <tags>] <directory>\n");
+    fprintf(stderr, "        archive [-cldDM] [-t <tags>] <directory>\n");
     fprintf(stderr, "        resolve-conflicts <directory>\n");
     fprintf(stderr, "        delete-conflicts <directory>\n");
     fprintf(stderr, "        trash-info <directory>\n");
@@ -190,6 +190,8 @@
                     "Only sync files which have the specified tags\n");
     fprintf(stderr, "        -r         "
                     "Remove resources not matching the tag filter\n");
+    fprintf(stderr, "        -D         restore deleted files\n");
+    fprintf(stderr, "        -M         restore modified files\n");
     fprintf(stderr, "        -v         verbose output (all commands)\n\n");
     
     fprintf(stderr, "Config commands:\n");
@@ -359,6 +361,23 @@
     
 }
 
+void res2map(DavResource *root, UcxMap *map) {
+    UcxList *stack = ucx_list_prepend(NULL, root->children);
+    while(stack) {
+        DavResource *res = stack->data;
+        stack = ucx_list_remove(stack, stack);
+        
+        while(res) {
+            ucx_map_cstr_put(map, res->path, res);
+            
+            if(res->children) {
+                stack = ucx_list_prepend(stack, res->children);
+            }
+            res = res->next;
+        }
+    }
+}
+
 int cmd_pull(CmdArgs *a) {
     if(a->argc != 1) {
         fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many");
@@ -997,7 +1016,12 @@
         curl_easy_setopt(sn->handle, CURLOPT_STDERR, stderr);
     }
     
-    DavResource *root = dav_query(sn, "select - from / with depth = 0");
+    DavBool restore_deleted = cmd_getoption(a, "restore-deleted") ? 1 : 0;
+    DavBool restore_modified = cmd_getoption(a, "restore-modified") ? 1 : 0;
+    DavBool restore = restore_deleted || restore_modified;
+    int depth = restore ? -1 : 0;
+    
+    DavResource *root = dav_query(sn, "select D:getetag,idav:status from / with depth = %d", depth);
     if(!root) {
         print_resource_error(sn, "/");
         dav_session_destroy(sn);
@@ -1005,6 +1029,12 @@
         return -1;
     }
     
+    UcxMap *svrres = NULL;
+    if(restore) {
+        svrres = ucx_map_new(1024);
+        res2map(root, svrres);
+    }
+    
     int cdt = cmd_getoption(a, "conflict") ? 0 : 1; // conflict detection
     
     // lock repository
@@ -1083,7 +1113,13 @@
             }
                        
             // upload every changed file
-            int is_changed = local_resource_is_changed(dir, db, local_res);
+            int is_changed = local_resource_is_changed(
+                    dir,
+                    db,
+                    local_res,
+                    svrres,
+                    restore_deleted,
+                    restore_modified);
             if (is_changed || local_res->tags_updated) {
                 DavResource *res = dav_resource_new(sn, local_res->path);
                 if(!res) {
@@ -1373,10 +1409,31 @@
     return newres;
 }
 
-int local_resource_is_changed(SyncDirectory *dir, SyncDatabase *db, LocalResource *res) {
+int local_resource_is_changed(
+        SyncDirectory *dir,
+        SyncDatabase *db,
+        LocalResource *res,
+        UcxMap *svrres,
+        DavBool restore_deleted,
+        DavBool restore_modified)
+{
     LocalResource *db_res = ucx_map_cstr_get(db->resources, res->path);
     res->tags_updated = 0;
     if(db_res) {
+        if(svrres) {
+            DavResource *remote = ucx_map_cstr_get(svrres, res->path);
+            if(restore_deleted && !remote) {
+                return 1;
+            }
+            if(!res->isdirectory && restore_modified && remote) {
+                char *etag = dav_get_string_property(remote, "D:getetag");
+                if(!etag || (db_res->etag && strcmp(etag, db_res->etag))) {
+                    res->restore = TRUE;
+                    return 1;
+                }
+            }
+        }
+        
         res->tags_updated = db_res->tags_updated;
         if(db_res->etag) {
             res->etag = strdup(db_res->etag);
@@ -1415,6 +1472,10 @@
         SyncDatabase *db,
         LocalResource *res)
 {
+    if(res->restore) {
+        return 0;
+    }
+    
     DavResource *remote = dav_get(sn, res->path, "D:getetag");
     int ret = 0;
     if(remote) {
--- a/dav/sync.h	Wed Jul 11 15:46:15 2018 +0200
+++ b/dav/sync.h	Wed Jul 11 16:40:07 2018 +0200
@@ -63,6 +63,8 @@
 pthread_t start_sighandler(pthread_mutex_t *mutex) ;
 void stop_sighandler(pthread_mutex_t *mutex, pthread_t tid);
 
+void res2map(DavResource *root, UcxMap *map);
+
 int cmd_pull(CmdArgs *args);
 int cmd_push(CmdArgs *args, DavBool archive);
 
@@ -81,7 +83,13 @@
 UcxList* read_changes(SyncDirectory *dir, SyncDatabase *db);
 LocalResource* local_resource_new(SyncDirectory *dir, SyncDatabase *db, char *path, int *isdir);
 LocalResource* local_resource_copy(LocalResource *res);
-int local_resource_is_changed(SyncDirectory *dir, SyncDatabase *db, LocalResource *res);
+int local_resource_is_changed(
+        SyncDirectory *dir,
+        SyncDatabase *db,
+        LocalResource *res,
+        UcxMap *svrres,
+        DavBool restore_deleted,
+        DavBool restore_modified);
 int remote_resource_is_changed(
         DavSession *sn,
         SyncDirectory *dir,

mercurial