355 } |
355 } |
356 } |
356 } |
357 |
357 |
358 if(cdt && exists && s.st_mtime != local->last_modified) { |
358 if(cdt && exists && s.st_mtime != local->last_modified) { |
359 // file modified on the server and on the client |
359 // file modified on the server and on the client |
360 rename_local_file(dir, db, local->path); |
360 rename_conflict_file(dir, db, local->path); |
361 } |
361 } |
362 } else { |
362 } else { |
363 if(stat(local_path, &s)) { |
363 if(stat(local_path, &s)) { |
364 if(errno != ENOENT) { |
364 if(errno != ENOENT) { |
365 fprintf(stderr, "Cannot stat file: %s\n", local_path); |
365 fprintf(stderr, "Cannot stat file: %s\n", local_path); |
366 } |
366 } |
367 } else if(S_ISDIR(s.st_mode)) { |
367 } else if(S_ISDIR(s.st_mode)) { |
368 //fprintf(stderr, "Error: file %s is a directory\n", local_path); |
368 //fprintf(stderr, "Error: file %s is a directory\n", local_path); |
369 } else if(cdt) { |
369 } else if(cdt) { |
370 // rename file on conflict |
370 // rename file on conflict |
371 rename_local_file(dir, db, res->path); |
371 rename_conflict_file(dir, db, res->path); |
372 } |
372 } |
373 } |
373 } |
374 |
374 |
375 int ret = 0; |
375 int ret = 0; |
376 char *tmp_path = create_tmp_download_path(local_path); |
376 char *tmp_path = create_tmp_download_path(local_path); |
497 } |
497 } |
498 |
498 |
499 free(local_path); |
499 free(local_path); |
500 } |
500 } |
501 |
501 |
502 void rename_local_file(SyncDirectory *dir, SyncDatabase *db, char *path) { |
502 void rename_conflict_file(SyncDirectory *dir, SyncDatabase *db, char *path) { |
503 char *local_path = util_concat_path(dir->path, path); |
503 char *local_path = util_concat_path(dir->path, path); |
504 char *parent = util_parent_path(local_path); |
504 char *parent = util_parent_path(local_path); |
505 |
505 |
506 int rev = 0; |
506 int rev = 0; |
507 struct stat s; |
507 struct stat s; |
508 int loop = 1; |
508 int loop = 1; |
509 do { |
509 do { |
510 sstr_t new_path = ucx_asprintf( |
510 char *res_parent = util_parent_path(path); |
511 ucx_default_allocator(), |
511 char *res_name = util_resource_name(path); |
|
512 |
|
513 sstr_t new_path = ucx_sprintf( |
512 "%sorig.%d.%s", |
514 "%sorig.%d.%s", |
513 parent, |
515 parent, |
514 rev, |
516 rev, |
515 util_resource_name(path)); |
517 res_name); |
|
518 sstr_t new_res_path = ucx_sprintf( |
|
519 "%sorig.%d.%s", |
|
520 res_parent, |
|
521 rev, |
|
522 res_name); |
516 |
523 |
517 |
524 |
518 if(stat(new_path.ptr, &s)) { |
525 if(stat(new_path.ptr, &s)) { |
519 if(errno == ENOENT) { |
526 if(errno == ENOENT) { |
520 loop = 0; |
527 loop = 0; |
524 fprintf( |
531 fprintf( |
525 stderr, |
532 stderr, |
526 "Cannot rename file %s to %s\n", |
533 "Cannot rename file %s to %s\n", |
527 local_path, |
534 local_path, |
528 new_path.ptr); |
535 new_path.ptr); |
|
536 } else { |
|
537 LocalResource *conflict = calloc(1, sizeof(LocalResource)); |
|
538 conflict->path = strdup(new_res_path.ptr); |
|
539 ucx_map_cstr_put(db->conflict, new_res_path.ptr, conflict); |
529 } |
540 } |
530 } |
541 } |
531 } |
542 } |
532 rev++; |
543 rev++; |
|
544 free(res_parent); |
533 free(new_path.ptr); |
545 free(new_path.ptr); |
|
546 free(new_res_path.ptr); |
|
547 |
534 } while(loop); |
548 } while(loop); |
535 free(parent); |
549 free(parent); |
|
550 free(local_path); |
536 } |
551 } |
537 |
552 |
538 char* create_tmp_download_path(char *path) { |
553 char* create_tmp_download_path(char *path) { |
539 char *new_path = NULL; |
554 char *new_path = NULL; |
540 char *parent = util_parent_path(path); |
555 char *parent = util_parent_path(path); |
642 return -1; |
661 return -1; |
643 } |
662 } |
644 |
663 |
645 int sync_success = 0; |
664 int sync_success = 0; |
646 int sync_delete = 0; |
665 int sync_delete = 0; |
|
666 int sync_skipped = 0; |
647 int sync_error = 0; |
667 int sync_error = 0; |
648 |
668 |
649 // upload all changed files |
669 // upload all changed files |
650 UcxList *resources = cmd_getoption(a, "read") ? |
670 UcxList *resources = cmd_getoption(a, "read") ? |
651 read_changes(dir, db) : local_scan(dir, db); |
671 read_changes(dir, db) : local_scan(dir, db); |
653 UcxMap *lclres = ucx_map_new(db->resources->count); |
673 UcxMap *lclres = ucx_map_new(db->resources->count); |
654 int ret = 0; |
674 int ret = 0; |
655 UCX_FOREACH(elm, resources) { |
675 UCX_FOREACH(elm, resources) { |
656 LocalResource *local_res = elm->data; |
676 LocalResource *local_res = elm->data; |
657 if (!res_matches_filter(dir, local_res->path+1)) { |
677 if (!res_matches_filter(dir, local_res->path+1)) { |
|
678 if(res_isconflict(db, local_res)) { |
|
679 printf("skip: %s\n", local_res->path); |
|
680 sync_skipped++; |
|
681 continue; |
|
682 } |
|
683 |
658 // upload every changed file |
684 // upload every changed file |
659 if (local_resource_is_changed(dir, db, local_res)) { |
685 if (local_resource_is_changed(dir, db, local_res)) { |
660 DavResource *res = dav_resource_new(sn, local_res->path); |
686 DavResource *res = dav_resource_new(sn, local_res->path); |
661 if(!res) { |
687 if(!res) { |
662 print_resource_error(sn, local_res->path); |
688 print_resource_error(sn, local_res->path); |
720 // TODO: free res |
746 // TODO: free res |
721 |
747 |
722 // Report |
748 // Report |
723 char *str_success = sync_success == 1 ? "file" : "files"; |
749 char *str_success = sync_success == 1 ? "file" : "files"; |
724 char *str_delete = sync_delete == 1 ? "file" : "files"; |
750 char *str_delete = sync_delete == 1 ? "file" : "files"; |
|
751 char *str_skipped = sync_delete == 1 ? "file" : "files"; |
725 char *str_error = sync_error == 1 ? "error" : "errors"; |
752 char *str_error = sync_error == 1 ? "error" : "errors"; |
726 printf("Result: %d %s pushed, %d %s deleted, %d %s\n", |
753 printf("Result: %d %s pushed, %d %s deleted, %d %s skipped, %d %s\n", |
727 sync_success, str_success, |
754 sync_success, str_success, |
728 sync_delete,str_delete, |
755 sync_delete,str_delete, |
|
756 sync_skipped,str_skipped, |
729 sync_error, str_error); |
757 sync_error, str_error); |
730 |
758 |
731 return 0; |
759 return 0; |
732 } |
760 } |
733 |
761 |
813 } |
841 } |
814 } else if(!sstrcmp(name, S("remove"))) { |
842 } else if(!sstrcmp(name, S("remove"))) { |
815 LocalResource *res = calloc(1, sizeof(LocalResource)); |
843 LocalResource *res = calloc(1, sizeof(LocalResource)); |
816 res->path = sstrdup(value).ptr; |
844 res->path = sstrdup(value).ptr; |
817 if(res) { |
845 if(res) { |
818 ucx_map_sstr_put(db->remove, value, res); |
846 //ucx_map_sstr_put(db->remove, value, res); |
819 ucx_map_sstr_remove(db->resources, value); |
847 ucx_map_sstr_remove(db->resources, value); |
820 } |
848 } |
821 |
849 |
822 } |
850 } |
823 |
851 |