# HG changeset patch # User Olaf Wintermann # Date 1531320007 -7200 # Node ID 761dc486720870d6bc137a6617544219ea3b667f # Parent 2f019a4bc78a31553929e97f23655e4317b6e3c0 adds dav-sync options for restoring deleted or modified files diff -r 2f019a4bc78a -r 761dc4867208 dav/db.h --- a/dav/db.h Wed Jul 11 15:46:15 2018 +0200 +++ b/dav/db.h Wed Jul 11 16:40:07 2018 +0200 @@ -56,6 +56,7 @@ char *tags_hash; DavBool keep; + DavBool restore; }; struct SyncDatabase { diff -r 2f019a4bc78a -r 761dc4867208 dav/sopt.c --- a/dav/sopt.c Wed Jul 11 15:46:15 2018 +0200 +++ b/dav/sopt.c Wed Jul 11 16:40:07 2018 +0200 @@ -81,7 +81,7 @@ ucx_map_cstr_put(a->options, "verbose", NOARG); break; } - case 's': {; + case 's': { option = "syncdir"; optchar = 's'; break; @@ -91,6 +91,14 @@ optchar = 't'; break; } + case 'D': { + ucx_map_cstr_put(a->options, "restore-deleted", NOARG); + break; + } + case 'M': { + ucx_map_cstr_put(a->options, "restore-modified", NOARG); + break; + } } } } else if(option) { diff -r 2f019a4bc78a -r 761dc4867208 dav/sync.c --- a/dav/sync.c Wed Jul 11 15:46:15 2018 +0200 +++ b/dav/sync.c Wed Jul 11 16:40:07 2018 +0200 @@ -171,8 +171,8 @@ fprintf(stderr, "Commands:\n"); fprintf(stderr, " pull [-cldr] [-t ] \n"); - fprintf(stderr, " push [-cldr] [-t ] \n"); - fprintf(stderr, " archive [-cld] [-t ] \n"); + fprintf(stderr, " push [-cldrDM] [-t ] \n"); + fprintf(stderr, " archive [-cldDM] [-t ] \n"); fprintf(stderr, " resolve-conflicts \n"); fprintf(stderr, " delete-conflicts \n"); fprintf(stderr, " trash-info \n"); @@ -190,6 +190,8 @@ "Only sync files which have the specified tags\n"); fprintf(stderr, " -r " "Remove resources not matching the tag filter\n"); + fprintf(stderr, " -D restore deleted files\n"); + fprintf(stderr, " -M restore modified files\n"); fprintf(stderr, " -v verbose output (all commands)\n\n"); fprintf(stderr, "Config commands:\n"); @@ -359,6 +361,23 @@ } +void res2map(DavResource *root, UcxMap *map) { + UcxList *stack = ucx_list_prepend(NULL, root->children); + while(stack) { + DavResource *res = stack->data; + stack = ucx_list_remove(stack, stack); + + while(res) { + ucx_map_cstr_put(map, res->path, res); + + if(res->children) { + stack = ucx_list_prepend(stack, res->children); + } + res = res->next; + } + } +} + int cmd_pull(CmdArgs *a) { if(a->argc != 1) { fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many"); @@ -997,7 +1016,12 @@ curl_easy_setopt(sn->handle, CURLOPT_STDERR, stderr); } - DavResource *root = dav_query(sn, "select - from / with depth = 0"); + DavBool restore_deleted = cmd_getoption(a, "restore-deleted") ? 1 : 0; + DavBool restore_modified = cmd_getoption(a, "restore-modified") ? 1 : 0; + DavBool restore = restore_deleted || restore_modified; + int depth = restore ? -1 : 0; + + DavResource *root = dav_query(sn, "select D:getetag,idav:status from / with depth = %d", depth); if(!root) { print_resource_error(sn, "/"); dav_session_destroy(sn); @@ -1005,6 +1029,12 @@ return -1; } + UcxMap *svrres = NULL; + if(restore) { + svrres = ucx_map_new(1024); + res2map(root, svrres); + } + int cdt = cmd_getoption(a, "conflict") ? 0 : 1; // conflict detection // lock repository @@ -1083,7 +1113,13 @@ } // upload every changed file - int is_changed = local_resource_is_changed(dir, db, local_res); + int is_changed = local_resource_is_changed( + dir, + db, + local_res, + svrres, + restore_deleted, + restore_modified); if (is_changed || local_res->tags_updated) { DavResource *res = dav_resource_new(sn, local_res->path); if(!res) { @@ -1373,10 +1409,31 @@ return newres; } -int local_resource_is_changed(SyncDirectory *dir, SyncDatabase *db, LocalResource *res) { +int local_resource_is_changed( + SyncDirectory *dir, + SyncDatabase *db, + LocalResource *res, + UcxMap *svrres, + DavBool restore_deleted, + DavBool restore_modified) +{ LocalResource *db_res = ucx_map_cstr_get(db->resources, res->path); res->tags_updated = 0; if(db_res) { + if(svrres) { + DavResource *remote = ucx_map_cstr_get(svrres, res->path); + if(restore_deleted && !remote) { + return 1; + } + if(!res->isdirectory && restore_modified && remote) { + char *etag = dav_get_string_property(remote, "D:getetag"); + if(!etag || (db_res->etag && strcmp(etag, db_res->etag))) { + res->restore = TRUE; + return 1; + } + } + } + res->tags_updated = db_res->tags_updated; if(db_res->etag) { res->etag = strdup(db_res->etag); @@ -1415,6 +1472,10 @@ SyncDatabase *db, LocalResource *res) { + if(res->restore) { + return 0; + } + DavResource *remote = dav_get(sn, res->path, "D:getetag"); int ret = 0; if(remote) { diff -r 2f019a4bc78a -r 761dc4867208 dav/sync.h --- a/dav/sync.h Wed Jul 11 15:46:15 2018 +0200 +++ b/dav/sync.h Wed Jul 11 16:40:07 2018 +0200 @@ -63,6 +63,8 @@ pthread_t start_sighandler(pthread_mutex_t *mutex) ; void stop_sighandler(pthread_mutex_t *mutex, pthread_t tid); +void res2map(DavResource *root, UcxMap *map); + int cmd_pull(CmdArgs *args); int cmd_push(CmdArgs *args, DavBool archive); @@ -81,7 +83,13 @@ UcxList* read_changes(SyncDirectory *dir, SyncDatabase *db); LocalResource* local_resource_new(SyncDirectory *dir, SyncDatabase *db, char *path, int *isdir); LocalResource* local_resource_copy(LocalResource *res); -int local_resource_is_changed(SyncDirectory *dir, SyncDatabase *db, LocalResource *res); +int local_resource_is_changed( + SyncDirectory *dir, + SyncDatabase *db, + LocalResource *res, + UcxMap *svrres, + DavBool restore_deleted, + DavBool restore_modified); int remote_resource_is_changed( DavSession *sn, SyncDirectory *dir,