summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin C. Pierce <bcpierce@cis.upenn.edu>2007-04-13 21:29:15 +0000
committerBenjamin C. Pierce <bcpierce@cis.upenn.edu>2007-04-13 21:29:15 +0000
commita24ff177104c13cc02a70096d60fda68ef39060e (patch)
tree1f5a9afac71adc5a081d97375eb4929f224988ee
parentd9f3234ea6fe4eb44f14b9ccc455cde49037f9e0 (diff)
downloadunison-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.tex9
-rw-r--r--src/Makefile6
-rw-r--r--src/RECENTNEWS94
-rw-r--r--src/mkProjectInfo.ml6
-rw-r--r--src/uitext.ml100
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