diff -r 0d04ccf6747b -r a76e43d89f55 dav/sync.c --- a/dav/sync.c Wed Feb 10 12:32:07 2016 +0100 +++ b/dav/sync.c Fri Feb 12 18:26:58 2016 +0100 @@ -88,6 +88,12 @@ ret = cmd_pull(args); } else if(!strcmp(cmd, "push")) { ret = cmd_push(args); + } else if(!strcasecmp(cmd, "version") || !strcasecmp(cmd, "-version") || !strcasecmp(cmd, "--version")) { +#ifdef DEBUG + fprintf(stderr, "dav-synv %s unstable\n", DAV_VERSION); +#else + fprintf(stderr, "dav-sync %s\n", DAV_VERSION); +#endif } // TODO: cleanup sync config (don't forget to call regfree for regex) @@ -236,12 +242,19 @@ // delete every remotely removed resource UcxMapIterator i = ucx_map_iterator(db->resources); LocalResource *local; + UcxList *rmdirs = NULL; UCX_MAP_FOREACH(key, local, i) { if (res_matches_filter(dir, local->path)) { continue; } // sync_remove_resource does all necessary tests - sync_remove_local_resource(dir, local); + if(sync_remove_local_resource(dir, local)) { + rmdirs = ucx_list_append(rmdirs, local); + } + } + UCX_FOREACH(elm, rmdirs) { + LocalResource *local_dir = elm->data; + sync_remove_local_directory(dir, local_dir); } ucx_map_free(db->resources); db->resources = svrres; @@ -265,7 +278,7 @@ char *etag = dav_get_property(res, "D:getetag"); struct stat s; - if(local) { + if(local && !res->iscollection) { int exists = 1; if(stat(local_path, &s)) { // Ignore the fact, that the file is locally removed. If the @@ -315,6 +328,16 @@ if(util_mkdir(local_path, mode) && errno != EEXIST) { ret = -1; } + + if(ret == 0) { + if(!local) { + // new local resource + local = calloc(1, sizeof(LocalResource)); + local->path = util_concat_path(res->path, "/"); + local->last_modified = s.st_mtime; + ucx_map_cstr_put(db->resources, local->path, local); + } + } } else { if(!tmp_path) { fprintf(stderr, "Cannot create tmp path for %s\n", local_path); @@ -381,17 +404,22 @@ return ret; } -void sync_remove_local_resource(SyncDirectory *dir, LocalResource *res) { +int sync_remove_local_resource(SyncDirectory *dir, LocalResource *res) { char *local_path = util_concat_path(dir->path, res->path); struct stat s; if(stat(local_path, &s)) { free(local_path); - return; + return 0; + } + + if(S_ISDIR(s.st_mode)) { + free(local_path); + return 1; } if(s.st_mtime != res->last_modified) { free(local_path); - return; + return 0; } printf("delete: %s\n", res->path); @@ -402,6 +430,19 @@ fprintf(stderr, "Cannot remove file %s\n", local_path); } free(local_path); + + return 0; +} + +void sync_remove_local_directory(SyncDirectory *dir, LocalResource *res) { + char *local_path = util_concat_path(dir->path, res->path); + + printf("delete: %s\n", res->path); + if(rmdir(local_path)) { + // TODO + } + + free(local_path); } void rename_local_file(SyncDirectory *dir, SyncDatabase *db, char *path) { @@ -549,10 +590,18 @@ if (!res_matches_filter(dir, local_res->path+1)) { // upload every changed file if (local_resource_is_changed(dir, db, local_res)) { - printf("put: %s\n", local_res->path); DavResource *res = dav_resource_new(sn, local_res->path); - if(sync_put_resource(dir, res, local_res)) { - // TODO: I don't know what to do now + + if(local_res->isdirectory) { + printf("mkcol: %s\n", local_res->path); + if(sync_mkdir(dir, res, local_res)) { + // TODO: I don't know what to do now + } + } else { + printf("put: %s\n", local_res->path); + if(sync_put_resource(dir, res, local_res)) { + // TODO: I don't know what to do now + } } dav_resource_free(res); } @@ -616,6 +665,7 @@ int isdir; LocalResource *res = local_resource_new(dir, db, new_path, &isdir); if(isdir) { + resources = ucx_list_append(resources, res); stack = ucx_list_prepend(stack, new_path); } else if(res) { resources = ucx_list_append(resources, res); @@ -706,6 +756,11 @@ return res; } else { *isdir = 1; + LocalResource *res = calloc(1, sizeof(LocalResource)); + res->path = util_concat_path(path, "/"); + res->last_modified = s.st_mtime; + res->isdirectory = 1; + return res; } return NULL; } @@ -822,31 +877,52 @@ return ret; } +int sync_mkdir(SyncDirectory *dir, DavResource *res, LocalResource *local) { + res->iscollection = 1; + int ret = -1; + for(int i=0;imax_retry;i++) { + if(dav_create(res)) { + continue; + } + ret = 0; + break; + } + return ret; +} + int sync_delete_remote_resource(DavSession *sn, LocalResource *local_res) { DavResource *res = dav_get(sn, local_res->path, "D:getetag"); if(!res) { return sn->error == DAV_NOT_FOUND ? 0 : 1; } - char *etag = dav_get_property(res, "D:getetag"); - if(etag) { - if(strlen(etag) > 2 && etag[0] == 'W' && etag[1] == '/') { - etag = etag + 2; - } - } - int ret = 0; - if(etag && !strcmp(etag, local_res->etag)) { - // local resource metadata == remote resource metadata - // resource can be deleted + if(res->iscollection) { printf("delete: %s\n", res->path); if(dav_delete(res)) { - if(sn->error != DAV_NOT_FOUND) { - fprintf(stderr, "Cannot delete resource %s\n", res->path); - } + ret = 1; + fprintf(stderr, "Cannot delete resource %s\n", res->path); } } else { - ret = 1; + char *etag = dav_get_property(res, "D:getetag"); + if(etag) { + if(strlen(etag) > 2 && etag[0] == 'W' && etag[1] == '/') { + etag = etag + 2; + } + } + + if(etag && !strcmp(etag, local_res->etag)) { + // local resource metadata == remote resource metadata + // resource can be deleted + printf("delete: %s\n", res->path); + if(dav_delete(res)) { + if(sn->error != DAV_NOT_FOUND) { + fprintf(stderr, "Cannot delete resource %s\n", res->path); + } + } + } else { + ret = 1; + } } // cleanup