adds possibility to restore specific files

Tue, 19 Mar 2019 19:14:48 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Tue, 19 Mar 2019 19:14:48 +0100
changeset 527
d0e37224eba1
parent 526
e3c0440bd599
child 528
4c9c8c017d52

adds possibility to restore specific files

dav/finfo.c file | annotate | diff | comparison | revisions
dav/sync.c file | annotate | diff | comparison | revisions
dav/sync.h file | annotate | diff | comparison | revisions
--- a/dav/finfo.c	Sun Mar 17 18:11:31 2019 +0100
+++ b/dav/finfo.c	Tue Mar 19 19:14:48 2019 +0100
@@ -174,6 +174,8 @@
         attributes = calloc(1, sizeof(XAttributes));
         attributes->hash = hash ? strdup(hash) : NULL;
         attributes->nattr = count;
+        attributes->names = calloc(count, sizeof(char*));
+        attributes->values = calloc(count, sizeof(sstr_t));
         int i=0;
         UCX_FOREACH(elm, names) {
             attributes->names[i] = elm->data;
--- a/dav/sync.c	Sun Mar 17 18:11:31 2019 +0100
+++ b/dav/sync.c	Tue Mar 19 19:14:48 2019 +0100
@@ -194,7 +194,7 @@
     fprintf(stderr, "        pull [-cldr] [-t <tags>] <directory>\n");
     fprintf(stderr, "        push [-cldrVRM] [-t <tags>] <directory>\n");
     fprintf(stderr, "        archive [-cldVRM] [-t <tags>] <directory>\n");
-    fprintf(stderr, "        restore [-ld] <directory>\n");
+    fprintf(stderr, "        restore [-ld] [-s <directory>] [file...]\n");
     fprintf(stderr, "        resolve-conflicts <directory>\n");
     fprintf(stderr, "        delete-conflicts <directory>\n");
     fprintf(stderr, "        trash-info <directory>\n");
@@ -1526,9 +1526,47 @@
 }
 
 int cmd_restore(CmdArgs *a) {
-    SyncDirectory *dir = scfg_get_dir(a->argv[0]);
+    char *syncdir = cmd_getoption(a, "syncdir");
+    
+    if(!syncdir && a->argc == 0) {
+        fprintf(stderr, "No syncdir or files specified\n");
+        return -1;
+    }
+    
+    SyncDirectory *dir = NULL;
+    UcxMap *files = NULL;
+    if(syncdir) {
+        dir = scfg_get_dir(syncdir);
+    }
+    
+    LocalResource nres;
+    if(a->argc > 0) {
+        files = ucx_map_new(a->argc+8);
+        // get all specified files and check the syncdir
+        SyncDirectory *sd = NULL;
+        for(int i=0;i<a->argc;i++) {
+            SyncFile f;
+            int err = sync_get_file(a, a->argv[i], &f, FALSE);
+            if(err) {
+                sync_print_get_file_err(a->argv[i], err);
+                return 1;
+            }
+            if(!sd) {
+                sd = f.dir;
+            } else {
+                if(f.dir != sd) {
+                    fprintf(stderr, "Not all files are in the same syncdir\n");
+                    return 1;
+                }
+            }
+            
+            ucx_map_cstr_put(files, f.path, &nres);
+        }
+        dir = sd;
+    }
+    
     if(!dir) {
-        fprintf(stderr, "Unknown sync dir: %s\n", a->argv[0]);
+        fprintf(stderr, "Unknown sync dir: %s\n", syncdir);
         return -1;
     }
     if(scfg_check_dir(dir)) {
@@ -1553,9 +1591,13 @@
     
     // iterate over all db resources and check if any resource is
     // modified or deleted
-    UcxMapIterator i = ucx_map_iterator(db->resources);
+    UcxMapIterator i = ucx_map_iterator(files ? files : db->resources);
     LocalResource *resource;
     UCX_MAP_FOREACH(key, resource, i) {
+        if(resource == &nres) {
+            resource = ucx_map_get(db->resources, key);
+        }
+        
         char *file_path = util_concat_path(dir->path, resource->path);
         SYS_STAT s;
         if(sys_stat(file_path, &s)) {
@@ -1570,8 +1612,12 @@
                 modified = ucx_list_prepend(modified, resource);
             }
         }
-        
+
         free(file_path);
+    }  
+    
+    if(files) {
+        ucx_map_free(files);
     }
     
     int ret = 0;
@@ -1618,7 +1664,7 @@
     UCX_FOREACH(elm, resources) {
         LocalResource *resource = elm->data;
         
-        DavResource *res = dav_get(sn, resource->path, "idav:status,D:getetag");
+        DavResource *res = dav_get(sn, resource->path, "D:getetag,idav:status,idav:finfo,idav:xattributes");
         
         char *status = dav_get_string_property(res, "idav:status");
         if(status && !strcmp(status, "broken")) {
@@ -2104,6 +2150,7 @@
             case TAG_KEEP_REMOTE: {
                 store_tags = TRUE;
                 local->tags_updated = FALSE;
+                break;
             }
             case TAG_MERGE: {
                 UcxList *new_tags = merge_tags(local_tags, tags);
@@ -2183,10 +2230,15 @@
             if(local) {
                 //printf("update: %s\n", local->path);
             }
-            ret = xattr_remove(path, dir->tagconfig->xattr_name);
+            // ignore errors on remove
+            xattr_remove(path, dir->tagconfig->xattr_name);
         }
     }
     
+    if(!ret) {
+        local->tags_updated = 0;
+    }
+    
     return ret;
 }
 
@@ -3124,9 +3176,9 @@
     int ret = 0;
     char *path = args->argv[0];
     
-    int err = sync_get_file(args, path, NULL, &file);
+    int err = sync_get_file(args, path, &file, TRUE);
     if(err) {
-        fprintf(stderr, "err: %d\n", err); // TODO: print nice err msg
+        sync_print_get_file_err(path, err);
         return -1;
     }
     
@@ -3214,7 +3266,7 @@
     return ret;
 }
 
-static int isfileindir(SyncDirectory *dir, const char *path, SyncFile *f) {
+int isfileindir(SyncDirectory *dir, const char *path, SyncFile *f) {
     char *fullpath;
     if(path[0] != '/') {
         size_t wdlen = 256;
@@ -3257,13 +3309,15 @@
     return 1;
 }
 
-int sync_get_file(CmdArgs *args, const char *path, const char *dir, SyncFile *f) {
-    SYS_STAT s;
-    if(sys_stat(path, &s)) {
-        switch(errno) {
-            case EACCES: return 2;
-            case ENOENT: return 1;
-            default: return 3;
+int sync_get_file(CmdArgs *args, const char *path, SyncFile *f, DavBool dostat) {
+    if(dostat) {
+        SYS_STAT s;
+        if(sys_stat(path, &s)) {
+            switch(errno) {
+                case EACCES: return 2;
+                case ENOENT: return 1;
+                default: return 3;
+            }
         }
     }
     
@@ -3301,6 +3355,17 @@
     return 0;
 }
 
+void sync_print_get_file_err(const char *path, int err) {
+    switch(err) {
+        case 1: fprintf(stderr, "File %s: not found\n", path); break;
+        case 2: fprintf(stderr, "File %s: permission denied\n"); break;
+        case 3: fprintf(stderr, "File %s: stat failed: %s\n", path, strerror(errno)); break;
+        case 4: fprintf(stderr, "File %s is not in any syncdir\n"); break;
+        case 5: fprintf(stderr, "File %s is in multiple syncdirs\n"); break;
+        case 6: fprintf(stderr, "Syncdir not found\n"); break;
+    }
+}
+
 
 int cmd_add_directory(CmdArgs *args) {
     if(!get_repositories()) {
--- a/dav/sync.h	Sun Mar 17 18:11:31 2019 +0100
+++ b/dav/sync.h	Tue Mar 19 19:14:48 2019 +0100
@@ -183,7 +183,10 @@
  * 5: file is in multiple syncdirs
  * 6: syncdir not found
  */
-int sync_get_file(CmdArgs *args, const char *path, const char *dir, SyncFile *f);
+int sync_get_file(CmdArgs *args, const char *path, SyncFile *f, DavBool dostat);
+void sync_print_get_file_err(const char *path, int err);
+
+int isfileindir(SyncDirectory *dir, const char *path, SyncFile *f);
 
 int cmd_add_directory(CmdArgs *args);
 int cmd_list_dirs();

mercurial