# HG changeset patch # User Olaf Wintermann # Date 1456663199 -3600 # Node ID cc474cf2c2f51025f6d2f6bc3eae2e38fd9e1509 # Parent f448fc8c9191fc765b10a1178f74ba614342a0b6 added add-directory command to dav-sync The command starts an easy interactive assistant for basic sync directory configuration. only basic input validation yet diff -r f448fc8c9191 -r cc474cf2c2f5 dav/assistant.c --- 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); } diff -r f448fc8c9191 -r cc474cf2c2f5 dav/main.c --- 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); diff -r f448fc8c9191 -r cc474cf2c2f5 dav/scfg.c --- 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 #include #include +#include #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("\n", out); + fputs("\n", out); + fputs("\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" - "\n" - "\n" - " \n" - " \n" - " documents\n\n" - " \n" - " /home/user/Documents\n\n" - " \n" - " .trash" - " \n" - " server\n\n" - " \n" - " somecol\n\n" - " \n" - " documents-db.xml\n" - " \n" - "\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; +} diff -r f448fc8c9191 -r cc474cf2c2f5 dav/scfg.h --- 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 diff -r f448fc8c9191 -r cc474cf2c2f5 dav/sync.c --- 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; +} diff -r f448fc8c9191 -r cc474cf2c2f5 dav/sync.h --- 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