treating some directories atomically, and ignoring socket files

Julian Squires <[email protected]>
Newsgroups gmane.network.unison.devel
Message-ID <CAEbLoBL65L2MonUtekcjzxjLZ8rRYvpAh4-ysycsJ+rxsfj9Ew@mail.gmail.com>
Hi,

I was contacted by a client to add two features to Unison for them,
and although I implemented something that worked for them, I'd like to
ask here about how to approach their implementation in a way that
might be accepted upstream.

The first is to ignore Unix domain socket files, which I did by
returning `ABSENT in Fileinfo.get when such a file is encountered.
I've attached some patches for this, but I realized later that my test
could be cleaner, as I didn't fully understand the test scaffold when
I first approached it.

The second is to treat VCS directories (such as .git or .svn)
atomically; that is, all the changes under such a directory should be
reconciled in the same direction, not merged.

For this feature, I provided a workaround for the client that adds a
predicate preference "atomic" which specifies directories to treat in
this manner, and then in Update.buildUpdateRec I treat anything within
those directories as new if there's been any change.  This seems to
work for them, but is clearly pretty inelegant and far from the
cleanest solution.

I had the suspicion that the best-integrated solution would be to
create a new file type like `ATOMIC_DIRECTORY so that the UI could
present it as a single entry, but it would be otherwise processed like
a directory.

I suspect that this would be too invasive a change for such a patch to
ever get merged upstream, though, which is why I'm hoping the members
of this list will have some suggestions.

I've attached patches for ignoring Unix socket files, which may need
some changes, but is probably otherwise uncontroversial.

Thanks,

-- 
Julian Squires

_______________________________________________
Unison-hackers mailing list
[email protected]
http://lists.seas.upenn.edu/mailman/listinfo/unison-hackers
0001-Add-Unix-domain-sockets-test-scaffold.patch (text/x-diff, 1.9 KB)
From 9e8e2830cf0103111c40fa5d5f252481514880ea Mon Sep 17 00:00:00 2001
From: Julian Squires <[email protected]>
Date: Wed, 17 Dec 2014 14:49:54 -0500
Subject: [PATCH 1/6] Add Unix domain sockets test scaffold

---
 src/test.ml | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/test.ml b/src/test.ml
index 2f02f5b..37ca1de 100644
--- a/src/test.ml
+++ b/src/test.ml
@@ -102,12 +102,14 @@ let extend p file = Fspath.concat p (Path.fromString file)
 type fs =
   | File of string
   | Link of string
+  | UnixSocket
   | Dir of (string * fs) list
 
 let rec equal fs1 fs2 =
   match fs1,fs2 with
     | File s1, File s2 -> s1=s2
     | Link s1, Link s2 -> s1=s2
+    | UnixSocket, UnixSocket -> true
     | Dir d1, Dir d2 ->
         let dom d = Safelist.sort String.compare (Safelist.map fst d) in
            (dom d1 = dom d2)
@@ -120,6 +122,7 @@ let rec equal fs1 fs2 =
 let rec fs2string = function
   | File s -> "File \"" ^ s ^ "\""
   | Link s -> "Link \"" ^ s ^ "\""
+  | UnixSocket -> "UnixSocket"
   | Dir s -> "Dir [" ^ (String.concat "; "
                           (Safelist.map (fun (n,fs') -> "(\""^n^"\", "^(fs2string fs')^")") s)) ^ "]"
 
@@ -133,6 +136,7 @@ let readfs p =
     match s.Unix.LargeFile.st_kind with
       | Unix.S_REG -> File (read p)
       | Unix.S_LNK -> Link (Fs.readlink p)
+      | Unix.S_SOCK -> UnixSocket
       | Unix.S_DIR -> Dir (Safelist.map (fun x -> (x, loop (extend p x))) (read_dir p))
       | _ -> assert false
   in try Some(loop p) with
@@ -148,6 +152,10 @@ let writefs p fs =
                    (Fspath.toDebugString p) s (Fingerprint.toString (Fingerprint.string s)));
         write p s
     | Link s -> Fs.symlink s p
+    | UnixSocket ->
+        let fd = Unix.socket Unix.PF_UNIX Unix.SOCK_STREAM 0 in
+        Unix.bind fd (Unix.ADDR_UNIX (Fspath.toString p));
+        Unix.close fd
     | Dir files ->
         Fs.mkdir p default_perm;
         Safelist.iter (fun (x,cont) -> loop (extend p x) cont) files
-- 
2.1.3
0002-Add-trivial-test-for-Unix-sockets.patch (text/x-diff, 992 B)
From 300e8e7e037d91936c80017ac8f600d6de9526d9 Mon Sep 17 00:00:00 2001
From: Julian Squires <[email protected]>
Date: Wed, 17 Dec 2014 17:22:55 -0500
Subject: [PATCH 2/6] Add trivial test for Unix sockets

We want to ensure they are ignored during synchronization.
---
 src/test.ml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/test.ml b/src/test.ml
index 37ca1de..a0288b3 100644
--- a/src/test.ml
+++ b/src/test.ml
@@ -330,6 +330,13 @@ let test() =
      running fast enough that the whole thing happens within a second, then the
      update will be missed! *)
 
+  if not (Prefs.read Globals.someHostIsRunningWindows) then
+    (* Test that Unix domain sockets are ignored. *)
+    runtest "Unix domain socket files" [] (fun() ->
+      put R1 (Dir ["a", UnixSocket]); sync();
+      checkmissing "1" R2
+    );
+
   (* Check for the bug reported by Ralf Lehmann *)
   if not bothRootsLocal then 
     runtest "backups 1 (remote)" ["backup = Name *"] (fun() -> 
-- 
2.1.3
0003-Ignore-socket-files.patch (text/x-diff, 716 B)
From 9c099d61c4b4c753026a3a82a56769f26ec0491b Mon Sep 17 00:00:00 2001
From: Julian Squires <[email protected]>
Date: Wed, 17 Dec 2014 17:41:19 -0500
Subject: [PATCH 3/6] Ignore socket files

---
 src/fileinfo.ml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/fileinfo.ml b/src/fileinfo.ml
index fe55917..ada91d0 100644
--- a/src/fileinfo.ml
+++ b/src/fileinfo.ml
@@ -79,6 +79,7 @@ let get fromRoot fspath path =
            match stats.Unix.LargeFile.st_kind with
              Unix.S_REG -> `FILE
            | Unix.S_DIR -> `DIRECTORY
+           | Unix.S_SOCK -> `ABSENT
            | Unix.S_LNK ->
                if not fromRoot || Prefs.read symlinksAllowed then
                  `SYMLINK
-- 
2.1.3
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.