Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search

[REBOL] File synchronization

From: g::santilli::tiscalinet::it at: 28-Nov-2002 23:25

[This is a resend... dunno why the first time it didn't arrive. If it did to you, please accept my apologies for the duplicate.] Hello all, I just "finished" (meaning that now it is almost usable :-) a script to sync two dirs (I use it to sync the REBOL dir between my desktop PC and my laptop). The GUI is probably awful (and beta-depended, sorry Carl :-( ), but it is a start. What it does: it asks you the two dirs you want to sync. It then scans them to find all the differences. (This process can take time, and there is no progress bar, so be patient please --- or add a progress bar to it. :-) It then displays a list to let you decide the action to take on files that are missing or that have been modified (only the modification date is checked). The default is to copy any modified file over the old one and add any new file to where it is missing; so if you leave the list alone and just click on "Do it!" it will just do that. But you can also click on the list items to toggle the action. Basically for each item you can select between the default "copy" action, the "leave it alone" action (i.e. do nothing on that file), and the "delete" or "restore" action (depending on the file). If the file is missing on one of the two directories, you can this way delete it from where it is present; if the file is modified but you want to restore the old version, you can by selecting the "restore" option. (I think it is easier to try it out than to explain it.) This can be useful to backup your data files to another drive or so; you can easily keep the backup up to date by synching it every day or so. I hope it can be useful. Also, I hope someone with more free time than me can make a better GUI for it. :-) Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: REBOL [ Title: "File synchronization" File: %file-sync.r Author: "Gabriele Santilli" ] sync-dirs: func [ "Create list of operations needed to synchronize two directories" a [file!] "First dir" b [file!] "Second dir" /local u result ] [ u: union read a read b result: make block! 256 foreach file u [ switch to-bits exists? a/:file exists? b/:file [ 1 [miss-file result a b file] 2 [miss-file result b a file] 3 [check-file result a b file] ] ] result ] to-bits: func [a b] [a: to-integer a b: to-integer b a * 2 + b] miss-file: func [result dest src file] [ either dir? src/:file [ insert/only tail result compose/deep [ (reform ["Copy directory" file "to" dest]) [ either error? try [make-dir (dest/:file)] [ print ["Cannot create" (file) "on" (dest)] ] [ use [result] [ result: make block! 256 modified-file result (dest) (src) (file) do-it result ] ] ] (reform ["Leave directory" file "on" src]) [ ] (reform ["Delete directory" file "from" src]) [ if error? try [delete-r (src/:file)] [ print ["Cannot delete" (file) "from" (src)] ] ] ] ;print ["Directory" file "does not exist in" dest] ] [ insert/only tail result compose/deep [ (reform ["Copy new file" file "to" dest]) [ if error? try [clone-file (dest) (src) (file)] [ print ["Cannot clone" (file) "on" (dest)] ] ] (reform ["Leave file" file "on" src]) [ ] (reform ["Delete file" file "from" src]) [ if error? try [delete (src/:file)] [ print ["Cannot delete" (file) "from" (src)] ] ] ] ;print ["File" file "does not exist in" dest] ] ] delete-r: func [dir [file!]] [ if dir? dir [ foreach file read dir [ delete-r dir/:file ] ] delete dir ] check-file: func [result a b file /local ma mb] [ ma: modified? a/:file mb: modified? b/:file any [ if ma = mb [ ;print ["File" file "seems synched"] true ] if ma > mb [ modified-file result b a file true ] do [ modified-file result a b file ] ] ] modified-file: func [result dest src file] [ either dir? src/:file [ ;print ["Synching" dest/:file "and" src/:file] insert tail result sync-dirs dest/:file src/:file ;if error? try [ ; set-modes dest/:file get-modes src/:file get-modes src/:file 'file-modes ;] [ ; ;print "Cannot clone directory attributes." ;] ] [ insert/only tail result compose/deep [ (reform ["Clone modified file" file "to" dest]) [ if error? try [clone-file (dest) (src) (file)] [ print ["Cannot clone" (file) "to" (dest)] ] ] (reform ["Leave modified file" file "on" src]) [ ] (reform ["Restore old file" file "from" dest]) [ if error? try [clone-file (src) (dest) (file)] [ print ["Cannot restore" (file) "to" (src)] ] ] ] ;print ["File" file "has been modified on" src] ] ] clone-file: func [dest src file /local data] [ dest: open/binary/direct/write dest/:file src: open/binary/direct/read src/:file clear dest while [data: copy/part src 1048576] [ insert dest data ] close dest close src set-modes dest get-modes src get-modes src 'file-modes ] do-it: func [ "Do the list of operations returned by sync-dirs" operations [block!] ] [ foreach operation operations [ ; print operation/1 do operation/2 ] ] view layout [ Banner "Sync dirs" Across f1: Field 300 Btn "Browse..." [ if f1/text: request-file [f1/text: mold first split-path first f1/text] show f1 ] Return f2: Field 300 Btn "Browse..." [ if f2/text: request-file [f2/text: mold first split-path first f2/text] show f2 ] Return Btn-Enter "Sync" [unview] Btn-Cancel "Quit" [quit] ] f1: attempt [load f1/text] f2: attempt [load f2/text] if all [file? f1 file? f2] [ operations: sync-dirs f1 f2 list: make block! length? operations i: 1 foreach operation operations [ insert tail list join i [") " operation/1] i: i + 1 ] view layout [ text-list data (list) 700x500 [ i: index? pos: find face/data face/picked operation: next next pick operations i if tail? operation [operation: head operation] poke operations i operation pos/1: join i [") " operation/1] face/picked/1: pos/1 show face ] Across Btn-Enter "Do it!" [do-it operations quit] Btn-Cancel "Quit" [quit] ] ]