diff options
author | Benjamin C. Pierce <bcpierce@cis.upenn.edu> | 2007-04-13 21:29:15 +0000 |
---|---|---|
committer | Benjamin C. Pierce <bcpierce@cis.upenn.edu> | 2007-04-13 21:29:15 +0000 |
commit | a24ff177104c13cc02a70096d60fda68ef39060e (patch) | |
tree | 1f5a9afac71adc5a081d97375eb4929f224988ee | |
parent | d9f3234ea6fe4eb44f14b9ccc455cde49037f9e0 (diff) | |
download | unison-a24ff177104c13cc02a70096d60fda68ef39060e.zip unison-a24ff177104c13cc02a70096d60fda68ef39060e.tar.gz unison-a24ff177104c13cc02a70096d60fda68ef39060e.tar.bz2 |
* Very preliminary support for triggering Unison from an external
filesystem-watching utility. The current implementation is very
simple, not efficient, and almost completely untested. Not ready
for real users. But if someone wants to help me improve it (e.g.,
by writing a filesystem watcher for your favorite OS), please let
me know.
On the Unison side, the new behavior is incredibly simple:
- use the text UI
- start Unison with the command-line flag "-repeat FOO",
where FOO is name of a file where Unison should look
for notifications of changes
- when it starts up, Unison will read the whole contents
of this file (on both hosts), which should be a
newline-separated list of paths (relative to the root
of the synchronization) and synchronize just these paths,
as if it had been started with the "-path=xxx" option for
each one of them
- when it finishes, it will sleep for a few seconds and then
examine the watchfile again; if anything has been added, it
will read the new paths, synchronize them, and go back to
sleep
- that's it!
To use this to drive Unison "incrementally," just start it in
this mode and start up a tool (on each host) to watch for
new changes to the filesystem and append the appropriate paths
to the watchfile. Hopefully such tools should not be too hard
to write.
Since I'm an OSX user, I'm particularly interested in writing a
watcher tool for this platform. If anybody knows about
programming against the Spotlight API and can give me a hand,
that would be much appreciated.
-rw-r--r-- | doc/changes.tex | 9 | ||||
-rw-r--r-- | src/Makefile | 6 | ||||
-rw-r--r-- | src/RECENTNEWS | 94 | ||||
-rw-r--r-- | src/mkProjectInfo.ml | 6 | ||||
-rw-r--r-- | src/uitext.ml | 100 |
5 files changed, 109 insertions, 106 deletions
diff --git a/doc/changes.tex b/doc/changes.tex index e1da887..70e8b22 100644 --- a/doc/changes.tex +++ b/doc/changes.tex @@ -4,15 +4,6 @@ donate, you can find a link to the donation page on the \URL{http://www.cis.upenn.edu/~bcpierce/unison/lists.html}{Unison home page}. -\item The native OS X user interface has been enormously improved by Ben -Willmore and Trevor Jim. -% -(We have observed intermittent crashes of this UI when used for large -synchronizations. This problem has hopefully been fixed by a recent -improvement in locking when communicating between Objective C and OCaml; if -any further crashes are observed, we would appreciate hearing about them, -{\em especially} if they are repeatable.) - \item Several small fixes to the GTK2 UI to make it work better under Windows [thanks to Karl M for these]. diff --git a/src/Makefile b/src/Makefile index c902787..ebe0b9a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -198,11 +198,15 @@ prefsdocs: all ./$(NAME) -prefsdocs 2> prefsdocsjunk.tmp mv -f prefsdocsjunk.tmp prefsdocs.tmp -# For developers at Penn +# For developers runtest: $(MAKE) all NATIVE=false DEBUG=true ./unison test +repeattest: + $(MAKE) all NATIVE=false DEBUG=true UISTYLE=text + ./unison noprofile a.tmp b.tmp -repeat foo.tmp -debug ui + selftest: $(MAKE) all NATIVE=false DEBUG=true UISTYLE=text ./unison -selftest -ui text -batch diff --git a/src/RECENTNEWS b/src/RECENTNEWS index f142222..378cd71 100644 --- a/src/RECENTNEWS +++ b/src/RECENTNEWS @@ -1,60 +1,38 @@ -CHANGES FROM VERSION 2.27.19 - -* Copy small fix -------------------------------- -CHANGES FROM VERSION 2.27.14 - -* Copying over changes from 2.27 branch to developer sources (checkpoint) - -------------------------------- -CHANGES FROM VERSION 2.27.14 - -* Copying over changes from 2.27 branch to developer sources (checkpoint) - -------------------------------- -CHANGES FROM VERSION 2.27.17 - -* Restored old OSX GUI from version 2.17. This UI is not nearly as - pretty or featureful as the new one that's been under construction - for a while, but at least it works! (The new one does not handle - multiple UI threads correctly when it is calling back and forth - between OCaml and Objective C, leading to UI freezes and random - crashes.) - - Building Unison with 'make UISTYLE=mac' will build you the old, - working UI. Building with 'make UISTYLE=macnew' will build you the - new UI, in case you'd like to help fix it. :-) - -------------------------------- -CHANGES FROM VERSION 2.27.16 - -* Rename OSX GUI from "mac" to "macnew" (in preparation for restoring old - GUI and calling it "mac") - - -------------------------------- -CHANGES FROM VERSION 2.27.15 - -* Correction to earlier patch - -------------------------------- -CHANGES FROM VERSION 2.27.9 - -* Make the GTK(1) user interface compile again. (Thanks to Zvezdan - Petkovic.) - - -------------------------------- -CHANGES FROM VERSION 2.27.8 - -* Small fix. - - - -------------------------------- -CHANGES FROM VERSION 2.27.7 - -* Tidied documentation in preparation for new release. - +CHANGES FROM VERSION 2.28.-2 + +* Very preliminary support for triggering Unison from an external + filesystem-watching utility. The current implementation is very + simple, not efficient, and almost completely untested. Not ready + for real users. But if someone wants to help me improve it (e.g., + by writing a filesystem watcher for your favorite OS), please let + me know. + + On the Unison side, the new behavior is incredibly simple: + - use the text UI + - start Unison with the command-line flag "-repeat FOO", + where FOO is name of a file where Unison should look + for notifications of changes + - when it starts up, Unison will read the whole contents + of this file (on both hosts), which should be a + newline-separated list of paths (relative to the root + of the synchronization) and synchronize just these paths, + as if it had been started with the "-path=xxx" option for + each one of them + - when it finishes, it will sleep for a few seconds and then + examine the watchfile again; if anything has been added, it + will read the new paths, synchronize them, and go back to + sleep + - that's it! + + To use this to drive Unison "incrementally," just start it in + this mode and start up a tool (on each host) to watch for + new changes to the filesystem and append the appropriate paths + to the watchfile. Hopefully such tools should not be too hard + to write. + + Since I'm an OSX user, I'm particularly interested in writing a + watcher tool for this platform. If anybody knows about + programming against the Spotlight API and can give me a hand, + that would be much appreciated. ------------------------------- diff --git a/src/mkProjectInfo.ml b/src/mkProjectInfo.ml index 74d30ae..4b80e85 100644 --- a/src/mkProjectInfo.ml +++ b/src/mkProjectInfo.ml @@ -5,8 +5,8 @@ let projectName = "unison" let majorVersion = 2 -let minorVersion = 27 -let pointVersionOrigin = 207 (* Revision that corresponds to point version 0 *) +let minorVersion = 28 +let pointVersionOrigin = 229 (* Revision that corresponds to point version 0 *) (* Documentation: This is a program to construct a version of the form Major.Minor.Point, @@ -50,5 +50,3 @@ Printf.printf "MAJORVERSION=%d.%d\n" majorVersion minorVersion;; Printf.printf "VERSION=%d.%d.%d\n" majorVersion minorVersion pointVersion;; Printf.printf "NAME=%s\n" projectName;; - - diff --git a/src/uitext.ml b/src/uitext.ml index 420685a..b2ec468 100644 --- a/src/uitext.ml +++ b/src/uitext.ml @@ -584,44 +584,76 @@ let synchronizeOnce() = let watchinterval = 10 -let charsRead = ref [] +(* FIX; Using string concatenation to accumulate characters is + pretty inefficient! *) +let charsRead = ref "" let linesRead = ref [] -let whatcherchan = ref None - -(* -let suckOnFile () = - let ch = match !watcherchan with None -> assert false | Some(x) -> x in - let rec loop() = - match try Some(System.input_char ch) with End_of_file -> None with - None -> ... - | Some(c) -> - if c = '\n' then begin - linesRead := <turn (Safelist.rev !charsRead) into a string> :: !linesRead; - charsRead := [] - end else begin - charsRead := c :: !charsRead; - loop() - end in - loop() -*) +let watcherchan = ref None + +let suckOnWatcherFileLocal n = + Util.convertUnixErrorsToFatal + ("Reading changes from watcher process in file " ^ n) + (fun () -> + (* The main loop, invoked from two places below *) + let rec loop ch = + match try Some(input_char ch) with End_of_file -> None with + None -> + let res = !linesRead in + linesRead := []; + res + | Some(c) -> + if c = '\n' then begin + linesRead := !charsRead + :: !linesRead; + charsRead := ""; + loop ch + end else begin + charsRead := (!charsRead) ^ (String.make 1 c); + loop ch + end in + (* Make sure there's a file to watch, then read from it *) + match !watcherchan with + None -> + if Sys.file_exists n then begin + let ch = open_in n in + watcherchan := Some(ch); + loop ch + end else [] + | Some(ch) -> loop ch + ) + +let suckOnWatcherFileRoot: Common.root -> string -> (string list) Lwt.t = + Remote.registerRootCmd + "suckOnWatcherFile" + (fun (fspath, n) -> + Lwt.return (suckOnWatcherFileLocal n)) + +let suckOnWatcherFiles n = + Safelist.concat + (Lwt_unix.run ( + Globals.allRootsMap (fun r -> suckOnWatcherFileRoot r n))) let synchronizePathsFromFilesystemWatcher () = -assert false -(* let watcherfilename = Prefs.read Uicommon.repeat in - ... open this file on both client and server and store a channel in - a global variable in each... let rec loop failedPaths = - ... read (on both hosts) from this channel till it is empty, keep - any partial line in a buffer for next time, add all full lines - (from both hosts) to the Globals.paths preference, together - with failedPaths... - Prefs.set Globals.paths (failedPaths @ ...); - let (exitStatus,newFailedPaths) = synchronizeOnce() in - Trace.status (Printf.sprintf "\nSleeping for %d seconds...\n" watchinterval); - Unix.sleep watchinterval; - loop newFailedPaths -*) + let newpaths = suckOnWatcherFiles watcherfilename in + if newpaths <> [] then + display (Printf.sprintf "Changed paths:\n %s\n" + (String.concat "\n " newpaths)); + let p = failedPaths @ (Safelist.map Path.fromString newpaths) in + if p <> [] then begin + Prefs.set Globals.paths p; + let (exitStatus,newFailedPaths) = synchronizeOnce() in + debug (fun() -> Util.msg "Sleeping for %d seconds...\n" watchinterval); + Unix.sleep watchinterval; + loop newFailedPaths + end else begin + debug (fun() -> Util.msg "Nothing changed: sleeping for %d seconds...\n" + watchinterval); + Unix.sleep watchinterval; + loop [] + end in + loop [] let synchronizeUntilNoFailures () = let initValueOfPathsPreference = Prefs.read Globals.paths in @@ -639,7 +671,7 @@ let rec synchronizeUntilDone () = let repeatinterval = if Prefs.read Uicommon.repeat = "" then -1 else try int_of_string (Prefs.read Uicommon.repeat) - with Invalid_argument "int_of_string" -> + with Failure "int_of_string" -> (* If the 'repeat' pref is not a number, switch modes... *) synchronizePathsFromFilesystemWatcher() in |