diff -r 91517b874a86 -r ddc4efc9b0f8 dav/sync.c --- a/dav/sync.c Thu Jul 10 13:50:00 2014 +0200 +++ b/dav/sync.c Fri Jul 11 12:47:24 2014 +0200 @@ -47,6 +47,7 @@ #include "db.h" #include "sync.h" +#include "ucx/properties.h" static DavContext *ctx; @@ -89,7 +90,15 @@ } void print_usage(char *cmd) { + fprintf(stderr, "Usage: %s command [options] arguments...\n\n", cmd); + fprintf(stderr, "Commands:\n"); + fprintf(stderr, " pull [-c] \n"); + fprintf(stderr, " push [-r] \n\n"); + + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -c Disable conflict detection\n"); + fprintf(stderr, " -r Read changes from stdin\n\n"); } int cmd_pull(CmdArgs *a) { @@ -145,7 +154,7 @@ while(res) { // download the resource - if(sync_get_resource(dir, res, db)) { + if(sync_get_resource(a, dir, res, db)) { fprintf(stderr, "sync_get_resource failed for resource: %s\n", res->path); } @@ -179,11 +188,12 @@ return 0; } -int sync_get_resource(SyncDirectory *dir, DavResource *res, SyncDatabase *db) { +int sync_get_resource(CmdArgs *a, SyncDirectory *dir, DavResource *res, SyncDatabase *db) { LocalResource *removed = ucx_map_cstr_get(db->remove, res->path); if(removed) { return 0; } + int cdt = cmd_getoption(a, "conflict") ? 0 : 1; LocalResource *local = ucx_map_cstr_get(db->resources, res->path); char *local_path = util_concat_path(dir->path, res->path); @@ -217,7 +227,7 @@ } } - if(s.st_mtim.tv_sec != local->last_modified) { + if(cdt && s.st_mtim.tv_sec != local->last_modified) { // file modified on the server and on the client rename_local_file(dir, db, local->path); } @@ -226,7 +236,7 @@ if(errno != ENOENT) { fprintf(stderr, "Cannot stat file: %s\n", local_path); } - } else if(!S_ISDIR(s.st_mode)) { + } else if(cdt && !S_ISDIR(s.st_mode)) { rename_local_file(dir, db, res->path); } } @@ -366,7 +376,11 @@ sn->key = dav_context_get_key(ctx, repo->default_key); // upload all changed files - UcxList *resources = local_scan(dir, db); + //UcxList *resources = local_scan(dir, db); + //UcxList *resources = read_changes(dir, db); + UcxList *resources = cmd_getoption(a, "read") ? + read_changes(dir, db) : local_scan(dir, db); + UCX_FOREACH(elm, resources) { char *path = elm->data; printf("put: %s\n", path); @@ -434,51 +448,15 @@ } char *new_path = util_concat_path(p, ent->d_name); - char *file_path = util_concat_path(dir->path, new_path); - struct stat s; - if(stat(file_path, &s)) { - fprintf(stderr, "Cannot stat file %s\n", file_path); + int isdir; + LocalResource *res = path_to_local_resource(dir, db, new_path, &isdir); + if(isdir) { + stack = ucx_list_prepend(stack, new_path); + } else if(res) { + resources = ucx_list_append(resources, strdup(res->path)); free(new_path); - free(file_path); - continue; - } - free(file_path); - - if(S_ISDIR(s.st_mode)) { - stack = ucx_list_prepend(stack, new_path); } else { - LocalResource *res = ucx_map_cstr_get( - db->resources, - new_path); - if(res) { - // the file is already in the database - // compare length and lastmodified date - - if(res->last_modified == s.st_mtim.tv_sec - && res->size == s.st_size) - { - // skip this file - free(new_path); - } else { - // add file to list - resources = ucx_list_append( - resources, - new_path); - - // update db entries - res->size = s.st_size; - res->last_modified = s.st_mtim.tv_sec; - } - } else { - // add file to list - LocalResource *res = calloc(1, sizeof(LocalResource)); - res->path = strdup(new_path); - res->etag = NULL; - res->last_modified = s.st_mtim.tv_sec; - res->size = s.st_size; - ucx_map_cstr_put(db->resources, res->path, res); - resources = ucx_list_append(resources, new_path); - } + free(new_path); } } closedir(local_dir); @@ -491,6 +469,104 @@ return resources; } +UcxList* read_changes(SyncDirectory *dir, SyncDatabase *db) { + UcxProperties *parser = ucx_properties_new(); + parser->delimiter = ':'; + + UcxList *resources = NULL; + sstr_t name; + sstr_t value; + + char buf[STDIN_BUF_SIZE]; + size_t r; + while(!feof(stdin)) { + r = fread(buf, 1, STDIN_BUF_SIZE, stdin); + ucx_properties_fill(parser, buf, r); + while(ucx_properties_next(parser, &name, &value)) { + if(value.length == 0) { + fprintf(stderr, "Wrong input\n"); + continue; + } + if(value.ptr[0] == '"' + && value.length > 2 + && value.ptr[value.length - 1] == '"') + { + value.ptr[value.length - 1] = '\0'; + value.ptr++; + value.length -= 2; + } + value = sstrdup(value); + + if(!sstrcmp(name, S("put"))) { + int isdir; + LocalResource *res = path_to_local_resource(dir, db, value.ptr, &isdir); + if(res) { + resources = ucx_list_append(resources, strdup(res->path)); + } + } else if(!sstrcmp(name, S("remove"))) { + int isdir; + //LocalResource *res = path_to_local_resource(dir, db, value.ptr, &isdir); + LocalResource *res = calloc(1, sizeof(LocalResource)); + res->path = sstrdup(value).ptr; + if(res) { + ucx_map_sstr_put(db->remove, value, res); + ucx_map_sstr_remove(db->resources, value); + } + + } + + free(value.ptr); + } + } + ucx_properties_free(parser); + + return resources; +} + +LocalResource* path_to_local_resource(SyncDirectory *dir, SyncDatabase *db, char *path, int *isdir) { + char *file_path = util_concat_path(dir->path, path); + struct stat s; + if(stat(file_path, &s)) { + fprintf(stderr, "Cannot stat file %s\n", file_path); + free(file_path); + return NULL; + } + free(file_path); + + if(!S_ISDIR(s.st_mode)) { + *isdir = 0; + LocalResource *res = ucx_map_cstr_get(db->resources, path); + if(res) { + // the file is already in the database + // compare length and lastmodified date + + if(res->last_modified == s.st_mtim.tv_sec + && res->size == s.st_size) + { + // file unchanged + return NULL; + } else { + // update db entries + res->size = s.st_size; + res->last_modified = s.st_mtim.tv_sec; + + return res; + } + } else { + LocalResource *res = calloc(1, sizeof(LocalResource)); + res->path = strdup(path); + res->etag = NULL; + res->last_modified = s.st_mtim.tv_sec; + res->size = s.st_size; + ucx_map_cstr_put(db->resources, res->path, res); + return res; + } + } else { + *isdir = 1; + } + return NULL; +} + int sync_put_resource(SyncDirectory *dir, DavResource *res, SyncDatabase *db) { char *local_path = util_concat_path(dir->path, res->path); FILE *in = fopen(local_path, "r");