added add-directory command to dav-sync

Sun, 28 Feb 2016 13:39:59 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 28 Feb 2016 13:39:59 +0100
changeset 200
cc474cf2c2f5
parent 199
f448fc8c9191
child 201
8e5856182668

added add-directory command to dav-sync

The command starts an easy interactive assistant for basic sync directory configuration.

only basic input validation yet

dav/assistant.c file | annotate | diff | comparison | revisions
dav/main.c file | annotate | diff | comparison | revisions
dav/scfg.c file | annotate | diff | comparison | revisions
dav/scfg.h file | annotate | diff | comparison | revisions
dav/sync.c file | annotate | diff | comparison | revisions
dav/sync.h file | annotate | diff | comparison | revisions
--- a/dav/assistant.c	Sun Feb 28 11:21:05 2016 +0100
+++ b/dav/assistant.c	Sun Feb 28 13:39:59 2016 +0100
@@ -84,9 +84,20 @@
 
 
 char* assistant_getdefcfg(char *cfgname, char *defval) {
-    char *value = assistant_getoptcfg(cfgname);
-    if(!value) {
-        value = strdup(defval);
+    sstr_t line;
+    char *value = NULL;
+    while(!value) {
+        printf("%s (default: %s): ", cfgname, defval);
+        line = util_readline(stdin);
+        if(line.length == 0 || !line.ptr) {
+            if(line.ptr) {
+                free(line.ptr);
+            }
+            break;
+        }
+        
+        value = line.ptr;
+        break;
     }
-    return value;
+    return value ? value : strdup(defval);
 }
--- a/dav/main.c	Sun Feb 28 11:21:05 2016 +0100
+++ b/dav/main.c	Sun Feb 28 13:39:59 2016 +0100
@@ -1174,7 +1174,7 @@
         return -1;
     }
     if(get_repository(sstr(name))) {
-        fprintf(stderr, "Repository %s already exists.\nAbort\n");
+        fprintf(stderr, "Repository %s already exists.\nAbort\n", name);
         return -1;
     }
     
@@ -1206,7 +1206,7 @@
         fprintf(stderr, "Cannot write config.xml\n");
         ret = -1;
     } else {
-        printf("Added repository: %s (%s)\n", name, url);
+        printf("\nAdded repository: %s (%s)\n", name, url);
     }
     
     free(name);
--- a/dav/scfg.c	Sun Feb 28 11:21:05 2016 +0100
+++ b/dav/scfg.c	Sun Feb 28 13:39:59 2016 +0100
@@ -32,6 +32,7 @@
 #include <errno.h>
 #include <libidav/utils.h>
 #include <ucx/map.h>
+#include <ucx/utils.h>
 
 #include "scfg.h"
 
@@ -45,12 +46,43 @@
 
 static UcxMap *directories;
 
+static int create_default_sync_config(char *file) {
+    FILE *out = fopen(file, "w");
+    if(!out) {
+        perror("fopen");
+        return -1;
+    }
+    
+    fputs("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n", out);
+    fputs("<configuration>\n", out);
+    fputs("</configuration>\n", out);
+    fclose(out);
+    
+    return 0;
+}
+
 int load_sync_config() {
     char *file = util_concat_path(ENV_HOME, ".dav/sync.xml");
+    
+    struct stat s;
+    if(stat(file, &s)) {
+        switch(errno) {
+            case ENOENT: {
+                if(create_default_sync_config(file)) {
+                    return -1;
+                }
+                break;
+            }
+            default: {
+                perror("Cannot load sync.xml");
+            }
+        }
+        return 0;
+    }
+    
     xmlDoc *doc = xmlReadFile(file, NULL, 0);
     if(!doc) {
-        fprintf(stderr, "Missing or broken configuration file\n");
-        scfg_print_example();
+        fprintf(stderr, "Broken configuration file\n");
         return -1;
     }
     
@@ -200,30 +232,53 @@
     return 0;
 }
 
-void scfg_print_example() {
-    fprintf(stderr, 
-        "example sync.xml\n\n"
-        "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
-        "<configuration>\n"
-        "  <directory>\n"
-        "    <!-- identifier -->\n"
-        "    <name>documents</name>\n\n"
-        "    <!-- local path to the directory -->\n"
-        "    <path>/home/user/Documents</path>\n\n"
-        "    <!-- optional trash path -->\n"
-        "    <trash>.trash</trash>"
-        "    <!-- repository name specified in config.xml -->\n"
-        "    <repository>server</repository>\n\n"
-        "    <!-- collection to synchronize (optional) -->\n"
-        "    <collection>somecol</collection>\n\n"
-        "    <!-- database file name -->\n"
-        "    <database>documents-db.xml</database>\n"
-        "  </directory>\n"
-        "</configuration>\n");
+SyncDirectory* scfg_get_dir(char *name) {
+    return ucx_map_cstr_get(directories, name);
 }
 
-SyncDirectory* scfg_get_dir(char *name) {
-    return ucx_map_cstr_get(directories, name);
+
+int add_directory(SyncDirectory *dir) {
+    char *file = util_concat_path(ENV_HOME, ".dav/sync.xml");
+    xmlDoc *doc = xmlReadFile(file, NULL, 0);
+    if(!doc) {
+        free(file);
+        fprintf(stderr, "Cannot load config.xml\n");
+        return 1;
+    }
+    
+    xmlNode *root = xmlDocGetRootElement(doc);
+    
+    xmlNode *dirNode = xmlNewNode(NULL, BAD_CAST "directory");
+    xmlNodeAddContent(dirNode, BAD_CAST "\n\t\t");
+    
+    xmlNewTextChild(dirNode, NULL, BAD_CAST "name", BAD_CAST dir->name);
+    xmlNodeAddContent(dirNode, BAD_CAST "\n\t\t");
+    
+    xmlNewTextChild(dirNode, NULL, BAD_CAST "path", BAD_CAST dir->path);
+    xmlNodeAddContent(dirNode, BAD_CAST "\n\t\t");
+    
+    xmlNewTextChild(dirNode, NULL, BAD_CAST "repository", BAD_CAST dir->repository);
+    xmlNodeAddContent(dirNode, BAD_CAST "\n\t\t");
+    
+    if(dir->trash) {
+        xmlNewTextChild(dirNode, NULL, BAD_CAST "trash", BAD_CAST dir->trash);
+        xmlNodeAddContent(dirNode, BAD_CAST "\n\t\t");
+    }
+    xmlNewTextChild(dirNode, NULL, BAD_CAST "database", BAD_CAST dir->database);
+    xmlNodeAddContent(dirNode, BAD_CAST "\n\t");
+    
+    xmlNodeAddContent(root, BAD_CAST "\n\t");
+    xmlAddChild(root, dirNode);
+    xmlNodeAddContent(root, BAD_CAST "\n");
+    
+    int ret = 0;
+    if(xmlSaveFormatFileEnc(file, doc, "UTF-8", 1) == -1) {
+        ret = 1;
+    }
+    xmlFreeDoc(doc);
+    free(file);
+    
+    return ret;
 }
 
 int list_syncdirs() {
@@ -234,3 +289,29 @@
     }
     return 0;
 }
+
+char* generate_db_name(char *basename) {
+    char *dbname = NULL;
+    int count = -1;
+    while(!dbname) {
+        sstr_t name = count < 0 ?
+                ucx_sprintf("%s-db.xml", basename) : 
+                ucx_sprintf("%s%d-db.xml", basename, count);
+        count++;
+        
+        UcxMapIterator i = ucx_map_iterator(directories);
+        SyncDirectory *dir;
+        bool unique = true;
+        UCX_MAP_FOREACH(key, dir, i) {
+            if(!sstrcmp(name, sstr(dir->database))) {
+                unique = false;
+                break;
+            }
+        }
+        if(unique) {
+            dbname = name.ptr;
+            break;
+        }
+    }
+    return dbname;
+}
--- a/dav/scfg.h	Sun Feb 28 11:21:05 2016 +0100
+++ b/dav/scfg.h	Sun Feb 28 13:39:59 2016 +0100
@@ -57,11 +57,11 @@
 
 int scfg_load_directory(xmlNode *node);
 
-void scfg_print_example();
-
 SyncDirectory* scfg_get_dir(char *name);
 
+int add_directory(SyncDirectory *dir);
 int list_syncdirs();
+char* generate_db_name(char *basename);
 
 
 #ifdef	__cplusplus
--- a/dav/sync.c	Sun Feb 28 11:21:05 2016 +0100
+++ b/dav/sync.c	Sun Feb 28 13:39:59 2016 +0100
@@ -46,6 +46,7 @@
 #include "sopt.h"
 #include "db.h"
 #include "error.h"
+#include "assistant.h"
 
 #include "sync.h"
 #include "ucx/properties.h"
@@ -89,6 +90,8 @@
         ret = cmd_pull(args);
     } else if(!strcmp(cmd, "push")) {
         ret = cmd_push(args);
+    } else if(!strcmp(cmd, "add-directory")) {
+        ret = cmd_add_directory(args);
     } else if(!strcmp(cmd, "list-directories")) {
         ret = list_syncdirs();
     } else if(!strcasecmp(cmd, "version") || !strcasecmp(cmd, "-version") || !strcasecmp(cmd, "--version")) {
@@ -117,6 +120,7 @@
     //fprintf(stderr, "        -r         Read changes from stdin\n\n");
     
     fprintf(stderr, "Config commands:\n");
+    fprintf(stderr, "        add-directory\n");
     fprintf(stderr, "        list-directories\n\n");
 }
 
@@ -1030,4 +1034,63 @@
 }
 
 
-
+int cmd_add_directory(CmdArgs *args) {
+    printf("Each sync directory must have an unique name.\n");
+    char *name = assistant_getcfg("name");
+    if(!name) {
+        fprintf(stderr, "Abort\n");
+        return -1;
+    }
+    if(scfg_get_dir(name)) {
+        fprintf(stderr, "Directory %s already exists.\nAbort\n", name);
+        return -1;
+    }
+    
+    printf("Enter local directory path.\n");
+    char *path = assistant_getcfg("path");
+    if(!path) {
+        fprintf(stderr, "Abort\n");
+        return -1;
+    }
+    
+    printf("Enter webdav repository name.\n");
+    char *repository = assistant_getcfg("repository");
+    if(!repository) {
+        fprintf(stderr, "Abort\n");
+        return -1;
+    }
+    if(!get_repository(sstr(repository))) {
+        fprintf(stderr, "Repository %s doesn't exist.\nAbort\n", repository);
+        return -1;
+    }
+    
+    printf("Enter collection relative to the repository base url.\n");
+    char *collection = assistant_getdefcfg("collection", "/");
+    
+    char *db = generate_db_name(name);
+    
+    SyncDirectory dir;
+    memset(&dir, 0, sizeof(SyncDirectory));
+    dir.name = name;
+    dir.path = path;
+    dir.repository = repository;
+    dir.collection = collection;
+    dir.trash = ".trash";
+    dir.database = db;
+    
+    int ret = 0;
+    if(add_directory(&dir)) {
+        fprintf(stderr, "Cannot write sync.xml\n");
+        ret = -1;
+    } else {
+        printf("\nAdded directory: %s (%s)\n", name, path);
+    }
+    
+    free(name);
+    free(path);
+    free(repository);
+    free(collection);
+    free(db);
+    
+    return ret;
+}
--- a/dav/sync.h	Sun Feb 28 11:21:05 2016 +0100
+++ b/dav/sync.h	Sun Feb 28 13:39:59 2016 +0100
@@ -47,7 +47,6 @@
 
 int cmd_pull(CmdArgs *args);
 int cmd_push(CmdArgs *args);
-int cmd_sync(CmdArgs *args);
 
 int sync_get_resource(
         CmdArgs *a,
@@ -76,6 +75,8 @@
 int sync_delete_remote_resource(DavSession *sn, LocalResource *res, int *counter);
 
 
+int cmd_add_directory(CmdArgs *args);
+
 #ifdef	__cplusplus
 }
 #endif

mercurial