# HG changeset patch # User Olaf Wintermann # Date 1574595628 -3600 # Node ID ab159748055c1eb77099e5ee54de5d7e716d983f # Parent 487645580b5eaa1cbada59b89a352a336f6060b7 add more symlink tests diff -r 487645580b5e -r ab159748055c dav/db.h --- a/dav/db.h Sat Nov 23 17:49:18 2019 +0100 +++ b/dav/db.h Sun Nov 24 12:40:28 2019 +0100 @@ -71,6 +71,7 @@ char *local_path; char *link_target; + char *link_target_db; FilePart *parts; size_t numparts; diff -r 487645580b5e -r ab159748055c dav/sync.c --- a/dav/sync.c Sat Nov 23 17:49:18 2019 +0100 +++ b/dav/sync.c Sun Nov 24 12:40:28 2019 +0100 @@ -969,6 +969,8 @@ SyncDirectory *dir, SyncDatabase *db) { + DavBool update_db = FALSE; + char *etag = dav_get_string_property(res, "D:getetag"); if(!etag) { fprintf(stderr, "Error: resource %s has no etag\n", res->path); @@ -1017,6 +1019,19 @@ if(SYNC_SYMLINK(dir) && nullstrcmp(link, local->link_target)) { ret = REMOTE_CHANGE_LINK; nochange = TRUE; + + if(local->link_target) { + LocalResource *local2 = local_resource_new(dir, db, local->path); + if(type == REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED && nullstrcmp(local->link_target, local2->link_target)) { + ret = REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED; + } + local_resource_free(local2); + + if(!nullstrcmp(link, local->link_target)) { + ret = REMOTE_NO_CHANGE; + update_db = TRUE; + } + } } else if(issplit && local->hash && hash) { if(!strcmp(local->hash, hash)) { // resource is already up-to-date on the client @@ -1040,11 +1055,26 @@ ret = type; } } else if(link) { + // new file is a link + ret = REMOTE_CHANGE_LINK; + if(exists && type == REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED) { - ret = REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED; - } else { - ret = REMOTE_CHANGE_LINK; - } + // a file with the same name already exists + // if it is a link, compare the targets + LocalResource *local2 = local_resource_new(dir, db, res->path); + if(local2) { + if(local2->link_target) { + if(strcmp(link, local2->link_target)) { + ret = REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED; + } + } else { + ret = REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED; + } + + local_resource_free(local2); + } + } + } else if(exists) { ret = type; } else { @@ -1053,7 +1083,6 @@ // if hashing is enabled we can compare the hash of the remote file // with the local file to test if a file is really modified - DavBool update_db = FALSE; char *update_hash = NULL; if (!iscollection && !link && @@ -1155,6 +1184,10 @@ if(!local->hash) { local->hash = update_hash; } // else: hash already updated + if(link) { + nullfree(local->link_target); + local->link_target = link; + } } free(local_path); @@ -2210,6 +2243,7 @@ sync_error++; } else { DavBool equal = FALSE; + DavBool res_conflict = FALSE; int changed = remote_resource_is_changed(sn, dir, db, res, local_res, &equal); if(equal) { char *etag = dav_get_string_property(res, "D:getetag"); @@ -2231,6 +2265,14 @@ local_res->hash = NULL; local_res->skipped = TRUE; sync_conflict++; + + if(local_res->link_target) { + free(local_res->link_target); + local_res->link_target = local_res->link_target_db; + local_res->link_target_db = NULL; + } + + res_conflict = TRUE; } else { if(local_res->link_target) { printf( @@ -2252,7 +2294,11 @@ if(!err) { LocalResource *dbres = ucx_map_cstr_remove(db->resources, local_res->path); - ucx_map_cstr_put(db->resources, local_res->path, local_res); + // in case of a conflict, don't store the resource + // in the db, if it is new + if(!res_conflict || dbres) { + ucx_map_cstr_put(db->resources, local_res->path, local_res); + } } } @@ -2847,6 +2893,9 @@ if(db_res->hash) { res->prev_hash = strdup(db_res->hash); } + if(db_res->link_target) { + res->link_target_db = db_res->link_target; + } // if the resource is splitted, copy the part info to the new // LocalResource obj, because we need it later @@ -3005,11 +3054,21 @@ return 1; } + char *link = dav_get_string_property_ns(remote, DAV_PROPS_NS, "link"); + int ret = 0; if(err == 0) { char *etag = dav_get_string_property(remote, "D:getetag"); char *hash = sync_get_content_hash(remote); + if(res->link_target_db || link) { + ret = nullstrcmp(res->link_target_db, link); + if(ret && equal) { + *equal = !nullstrcmp(res->link_target, link); + } + return ret; + } + if(hash && res->hash && equal) { // if requested, check if the local and remote res are equal if(!strcmp(hash, res->hash)) { diff -r 487645580b5e -r ab159748055c test/bin-test/test-dav-sync-symlink1.sh --- a/test/bin-test/test-dav-sync-symlink1.sh Sat Nov 23 17:49:18 2019 +0100 +++ b/test/bin-test/test-dav-sync-symlink1.sh Sun Nov 24 12:40:28 2019 +0100 @@ -265,3 +265,107 @@ check_tmpout "0 errors" "test 6: wrong error counter (pull)" check_tmpout "intern1" "test 6: intern1 not updated (pull)" + +# ---------------------------------------------------------------------------- +# test 7: change intern1 target on both sides +# expected result: conflict + +# preparation: add regular files on both sides and sync + +echo "test7-new2a" > tmp-sync/test7a/new2a +echo "test7-new2b" > tmp-sync/test7b/new2b + +dav_sync_push test7a "test 7: push a failed" +check_tmpout "1 file pushed" "test 7: wrong push counter (push a)" +check_tmpout "0 conflicts" "test 7: wrong conflict counter (push a)" +check_tmpout "0 errors" "test 7: wrong error counter (push a)" + +dav_sync_push test7b "test 7: push b failed" +check_tmpout "1 file pushed" "test 7: wrong push counter (push b)" +check_tmpout "0 conflicts" "test 7: wrong conflict counter (push b)" +check_tmpout "0 errors" "test 7: wrong error counter (push b)" + +dav_sync_pull test7a "test 7: pull a failed" +check_tmpout "1 file pulled" "test 7: wrong pull counter (pull a)" +check_tmpout "0 conflicts" "test 7: wrong conflict counter (pull a)" +check_tmpout "0 errors" "test 7: wrong error counter (pull a)" + +dav_sync_pull test7b "test 7: pull b failed" +check_tmpout "1 file pulled" "test 7: wrong pull counter (pull b)" +check_tmpout "0 conflicts" "test 7: wrong conflict counter (pull b)" +check_tmpout "0 errors" "test 7: wrong error counter (pull b)" + +# test: change symlinks + +rm -f tmp-sync/test7a/intern1 +ln -s -r tmp-sync/test7a/new2a tmp-sync/test7a/intern1 + +rm -f tmp-sync/test7b/intern1 +ln -s -r tmp-sync/test7b/new2b tmp-sync/test7b/intern1 + +dav_sync_push test7a "test 7: push a failed (a)" +check_tmpout "1 file pushed" "test 7: wrong push counter (push a 2)" +check_tmpout "0 conflicts" "test 7: wrong conflict counter (push a 2)" +check_tmpout "0 errors" "test 7: wrong error counter (push a 2)" +check_tmpout "intern1" "test 7: intern1 not updated (push a 2)" + +dav_sync_push test7b "test 7: push b failed (b)" +check_tmpout "1 conflict" "test 7: wrong conflict counter (push b 2)" +check_tmpout "0 errors" "test 7: wrong error counter (push b 2)" + + +# ---------------------------------------------------------------------------- +# test 8: pull test7b +# expected result: conflict + +dav_sync_pull test7b "test 8: pull failed" +check_tmpout "1 file pulled" "test8: wrong pull counter (pull)" +check_tmpout "1 conflict" "test 8: wrong conflict counter (pull)" +check_tmpout "0 errors" "test 8: wrong error counter (pull)" + +$DAV_SYNC_BIN delete-conflicts test7b > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "test 8: delete-conflicts failed" + exit 2 +fi + +dav_sync_pull test7b "test 8: pull 2 failed" +check_tmpout "0 files pulled" "test8: wrong pull counter (pull 2)" +check_tmpout "0 conflicts" "test 8: wrong conflict counter (pull 2)" +check_tmpout "0 errors" "test 8: wrong error counter (pull 2)" + +dav_sync_push test7b "test 8: push b failed (b)" +check_tmpout "0 files pushed" "test 8: wrong push counter" +check_tmpout "0 conflicts" "test 8: wrong conflict counter (push)" +check_tmpout "0 errors" "test 8: wrong error counter (push)" + + +# ---------------------------------------------------------------------------- +# test 9: add new link on both sides +# expected result: conflict + +ln -s -r tmp-sync/test7a/new2a tmp-sync/test7a/newlink1 +ln -s -r tmp-sync/test7b/new2b tmp-sync/test7b/newlink1 + +dav_sync_push test7a "test 9: push a failed (a)" +check_tmpout "1 file pushed" "test 9: wrong push counter (push a)" +check_tmpout "0 conflicts" "test 9: wrong conflict counter (push a)" +check_tmpout "0 errors" "test 9: wrong error counter (push a)" +check_tmpout "newlink1" "test 9: intern1 not updated (push a)" + +dav_sync_push test7b "test 9: push b failed (b)" +check_tmpout "1 conflict" "test 9: wrong conflict counter (push b)" +check_tmpout "0 errors" "test 9: wrong error counter (push b)" + +# pull + +dav_sync_pull test7b "test 9: pull failed" +check_tmpout "1 file pulled" "test9: wrong pull counter (pull)" +check_tmpout "1 conflict" "test 9: wrong conflict counter (pull)" +check_tmpout "0 errors" "test 9: wrong error counter (pull)" + +$DAV_SYNC_BIN delete-conflicts test7b > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "test 9: delete-conflicts failed" + exit 2 +fi diff -r 487645580b5e -r ab159748055c test/bin-test/test-dav.sh --- a/test/bin-test/test-dav.sh Sat Nov 23 17:49:18 2019 +0100 +++ b/test/bin-test/test-dav.sh Sun Nov 24 12:40:28 2019 +0100 @@ -51,6 +51,9 @@ exit 1 fi +# clear test repo +dav rm dav-test-repo/tests > /dev/null 2>&1 + do_test() { printf "TEST: $1 ... "