[Unison-hackers] [unison-users] Unison aborts all the synchronization after a permission issue
Jerome Vouillon
Jerome.Vouillon at pps.jussieu.fr
Sun Jun 21 09:07:53 EDT 2009
Hi Benjamin,
On Mon, Jun 15, 2009 at 08:11:05AM -0400, Benjamin Pierce wrote:
> This is a longstanding issue. It's not a bug -- the behavior is not
> only "correct" but deeply built into the spec's definition of
> conflict. Of course, in practice it's often irritating, and by
> hindsight we should have designed it differently! But at this point
> it will take some careful thought to make it work differently, even as
> an option. (If anybody is up for giving it careful thought and
> creating a patch, I'd be glad to consider adding it.)
I believe the following patch (against the developer version) does the
right thing (*). Then, there are some user interface issues:
- With this patch, errors deep inside a directory are not reported to
the user. Unison should report them all while still allowing to
propagate the directory.
- Overwriting (or deleting) a directory with deep errors will fail
during propagation. We should either forbid the user from
attempting to overwrite such a directory, or relax the checks in
function Update.checkNoUpdates. (Or implement partial deletion.)
I will not have time to work further on this this week, though.
(*) We have a change of behavior when one replica contains a directory
with a deep error at some location and the other does not contain a
directory there. Here are the different cases to consider:
1) Propagating the directory.
a) The directory is not in the archive.
If the other side is unchanged, Unison will propagate everything
in the directory but the locations with an error and will update
the archives accordingly. The spec without the atomicity rule
allows this. (Note that, in this case, the change in function
Update.updateArchiveRec does nothing as the archives contain
NoArchive at the location of the error.)
If the other side is changed, the user has to force the
synchronization of the directory. Unison will propagate the
directory and update the archives the same way. We are outside
the scope of the spec, but I think Unison behaves reasonnably.
(b) The directory is in the archives.
In this case, the other side must have changed. So, the user
has to force the synchronization of the directory and we are
outside the scope of the spec.
The locations with errors are going to be removed from the
archives (change in Update.checkNoUpdatesRec). It is not clear
whether this is the right thing to do. One could argue both
ways. One may want to keep the previous archive contents as the
synchronization of these locations was not performed. On the
other hand, the user has chosen to propagate back the directory.
Clearing the archive is a way of taking this into account.
Also, this is easier to implement: this is exactly what we need
for propagation in case (1.b) and in Update.checkNoUpdatesRec in
case (2).
2) Propagating the contents of the other replica.
Unison will not do anything by default, which is correct.
Forcing the deletion of the directory will either fail if the
errors are still there, or succeed if the locations corresponding
to an error are now empty (thanks to the change in function
Update.checkNoUpdatesRec). The spec without the atomicity rule
allows to remove every unchanged part from the directory. So,
what is done here is correct when we are under the scope of the
spec.
-- Jerome
-------------- next part --------------
Index: update.ml
===================================================================
--- update.ml (r?vision 360)
+++ update.ml (copie de travail)
@@ -1646,8 +1646,10 @@
(* the result of patching [archive] using [ui] *)
let rec updateArchiveRec ui archive =
match ui with
- NoUpdates | Error _ ->
+ NoUpdates ->
archive
+ | Error _ ->
+ NoArchive
| Updates (uc, _) ->
match uc with
Absent ->
Index: recon.ml
===================================================================
--- recon.ml (r?vision 360)
+++ recon.ml (copie de travail)
@@ -214,7 +214,8 @@
()
(* lifting errors in individual updates to replica problems *)
-let propagateErrors (rplc: Common.replicas): Common.replicas =
+let propagateErrors (rplc: Common.replicas): Common.replicas = rplc
+(*
match rplc with
Problem _ ->
rplc
@@ -228,6 +229,7 @@
Problem ("[root 2]: " ^ err)
with UpdateError err ->
Problem ("[root 1]: " ^ err)
+*)
type singleUpdate = Rep1Updated | Rep2Updated
More information about the Unison-hackers
mailing list