From alan.schmitt at polytechnique.org Thu Mar 7 06:21:59 2013 From: alan.schmitt at polytechnique.org (Alan Schmitt) Date: Thu, 07 Mar 2013 12:21:59 +0100 Subject: [Unison-hackers] Ignore files above a certain size Message-ID: Hello, I've been asked to add a feature to Unison: ignore the files that are greater than a certain size. I've looked at the code and it seems the least invasive way to do it is to have such file create an Error during update detection. What do you think of this approach? Best, Alan From steve at kalkwarf.com Thu Mar 7 08:33:24 2013 From: steve at kalkwarf.com (Steve Kalkwarf) Date: Thu, 7 Mar 2013 08:33:24 -0500 Subject: [Unison-hackers] Ignore files above a certain size In-Reply-To: References: Message-ID: <5F37053E-44CD-41E4-ACFD-265774CD3D24@kalkwarf.com> On Mar 7, 2013, at 6:21 AM, Alan Schmitt wrote: > I've been asked to add a feature to Unison: ignore the files that are > greater than a certain size. I've looked at the code and it seems the > least invasive way to do it is to have such file create an Error during > update detection. What do you think of this approach? I've never been a fan of using exceptions to dictate flow control, which is what this sort of smells like. Also, what happens if the file threshold is set to 1 MB, and between syncs a file grows from 500K to 1.5MB? Delete it? Leave it? Sync it because it used to be synchronized? There must be another way for the user to achieve this, without adding a pref? Steve -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4322 bytes Desc: not available URL: From alan.schmitt at polytechnique.org Thu Mar 7 09:04:09 2013 From: alan.schmitt at polytechnique.org (Alan Schmitt) Date: Thu, 07 Mar 2013 15:04:09 +0100 Subject: [Unison-hackers] Ignore files above a certain size In-Reply-To: <5F37053E-44CD-41E4-ACFD-265774CD3D24@kalkwarf.com> References: <5F37053E-44CD-41E4-ACFD-265774CD3D24@kalkwarf.com> Message-ID: Steve Kalkwarf writes: > On Mar 7, 2013, at 6:21 AM, Alan Schmitt wrote: > >> I've been asked to add a feature to Unison: ignore the files that are >> greater than a certain size. I've looked at the code and it seems the >> least invasive way to do it is to have such file create an Error during >> update detection. What do you think of this approach? > > I've never been a fan of using exceptions to dictate flow control, > which is what this sort of smells like. I disagree: it's not an exception, it's the result of an update detection that says the file should be skipped. Then at reconciliation time, the file is skipped and the UI reflects it. A cleaner way would be to introduced another update detection results (such as Skip or something similar), but then every UI needs to be adapted to that construct. The advantage to this second approach (which I may tackle if I find the time, but it's an extension of the first) is that the user could then decide to propagate the file anyway. (Thinking about it, this is a bit trickier than that: we need both a Skip and the normal update detection ...) > Also, what happens if the file threshold is set to 1 MB, and between > syncs a file grows from 500K to 1.5MB? Delete it? Leave it? Sync it > because it used to be synchronized? Leave it: files in Error state are skipped (just like doing a manual skip). > There must be another way for the user to achieve this, without adding > a pref? Yes, but it's cludgy: before running unison, run a script that fetches all the files above a certain size, both on the client and on the server, then add this list to the set of files that are ignored for this run. Maybe there is a simpler way, I'd gladly hear about it. Alan From bcpierce at cis.upenn.edu Thu Mar 7 09:05:57 2013 From: bcpierce at cis.upenn.edu (Benjamin C. Pierce) Date: Thu, 7 Mar 2013 09:05:57 -0500 Subject: [Unison-hackers] Ignore files above a certain size In-Reply-To: References: Message-ID: An even easier way is to deal with such files at reconciliation time. We've already got mechanisms and preferences for overriding Unison's default reconciliation decisions based on many sorts of conditions (which file is newer, etc.). The downside is that large files will not, then, be completely ignored -- they will show up in the user interface as conflicts. Arguably, the right thing to do is to truly ignore such files. This will be a bit harder to implement, since it will have to start with generalizing the current ignore mechanism to take into account current information from the filesystem beyond just path names. And it will require a bit of care in reconciliation (because a file may then be ignored on one side and not the other and we'll want to make sure we correctly detect this situation and don't do something silly like delete one of the copies) and in the UI (because we'll have to report such situations to the user in some sensible way), as well as some thinking at the level of the formal spec to make sure that we can make sense out of such possibilities. But if we can figure out how to do it nicely, it would open the door to all sorts of further extensions that people have been asking for for years, like per-directory .unisonignore files. - B On Mar 7, 2013, at 6:21 AM, Alan Schmitt wrote: > Hello, > > I've been asked to add a feature to Unison: ignore the files that are > greater than a certain size. I've looked at the code and it seems the > least invasive way to do it is to have such file create an Error during > update detection. What do you think of this approach? > > Best, > > Alan > _______________________________________________ > Unison-hackers mailing list > Unison-hackers at lists.seas.upenn.edu > http://lists.seas.upenn.edu/mailman/listinfo/unison-hackers From alan.schmitt at polytechnique.org Thu Mar 7 10:28:56 2013 From: alan.schmitt at polytechnique.org (Alan Schmitt) Date: Thu, 07 Mar 2013 16:28:56 +0100 Subject: [Unison-hackers] Ignore files above a certain size In-Reply-To: References: Message-ID: Benjamin C. Pierce writes: > An even easier way is to deal with such files at reconciliation time. > We've already got mechanisms and preferences for overriding Unison's > default reconciliation decisions based on many sorts of conditions > (which file is newer, etc.). The downside is that large files will > not, then, be completely ignored -- they will show up in the user > interface as conflicts. I think that's a good thing that they show up in the interface, so that the user may decide to propagate them anyway. Looking at the code, it seems the simplest is to extend shouldCancel for this. This is much nicer than the "Error" approach: if A is deleted and B is unchanged but above the limit, in the "Error" approach nothing happens, in the "shouldCancel" approach B is deleted. I was also looking at how to log which files have not been transferred because of their size, and one way to do it is to add an argument to Conflict (similar to the one for Problem) that gives the cause of the conflict. This way it would be in the log and could be use in the UIs. > Arguably, the right thing to do is to truly ignore such files. This > will be a bit harder to implement, since it will have to start with > generalizing the current ignore mechanism to take into account current > information from the filesystem beyond just path names. And it will > require a bit of care in reconciliation (because a file may then be > ignored on one side and not the other and we'll want to make sure we > correctly detect this situation and don't do something silly like > delete one of the copies) and in the UI (because we'll have to report > such situations to the user in some sensible way), as well as some > thinking at the level of the formal spec to make sure that we can make > sense out of such possibilities. But if we can figure out how to do it > nicely, it would open the door to all sorts of further extensions that > people have been asking for for years, like per-directory > .unisonignore files. I agree it would be a more general approach, but it requires many more changes as you said. Alan From bcpierce at cis.upenn.edu Thu Mar 7 11:31:30 2013 From: bcpierce at cis.upenn.edu (Benjamin Pierce) Date: Thu, 7 Mar 2013 11:31:30 -0500 Subject: [Unison-hackers] Ignore files above a certain size In-Reply-To: References: Message-ID: Ok, this approach seems reasonable. The only thing that concerns me is adding one more ad hoc preference... - Benjamin On Mar 7, 2013, at 10:28 AM, Alan Schmitt wrote: > Benjamin C. Pierce writes: > >> An even easier way is to deal with such files at reconciliation time. >> We've already got mechanisms and preferences for overriding Unison's >> default reconciliation decisions based on many sorts of conditions >> (which file is newer, etc.). The downside is that large files will >> not, then, be completely ignored -- they will show up in the user >> interface as conflicts. > > I think that's a good thing that they show up in the interface, so that > the user may decide to propagate them anyway. > > Looking at the code, it seems the simplest is to extend shouldCancel for > this. This is much nicer than the "Error" approach: if A is deleted and > B is unchanged but above the limit, in the "Error" approach nothing > happens, in the "shouldCancel" approach B is deleted. > > I was also looking at how to log which files have not been transferred > because of their size, and one way to do it is to add an argument to > Conflict (similar to the one for Problem) that gives the cause of the > conflict. This way it would be in the log and could be use in the UIs. > >> Arguably, the right thing to do is to truly ignore such files. This >> will be a bit harder to implement, since it will have to start with >> generalizing the current ignore mechanism to take into account current >> information from the filesystem beyond just path names. And it will >> require a bit of care in reconciliation (because a file may then be >> ignored on one side and not the other and we'll want to make sure we >> correctly detect this situation and don't do something silly like >> delete one of the copies) and in the UI (because we'll have to report >> such situations to the user in some sensible way), as well as some >> thinking at the level of the formal spec to make sure that we can make >> sense out of such possibilities. But if we can figure out how to do it >> nicely, it would open the door to all sorts of further extensions that >> people have been asking for for years, like per-directory >> .unisonignore files. > > I agree it would be a more general approach, but it requires many more > changes as you said. > > Alan > _______________________________________________ > Unison-hackers mailing list > Unison-hackers at lists.seas.upenn.edu > http://lists.seas.upenn.edu/mailman/listinfo/unison-hackers From alan.schmitt at polytechnique.org Fri Mar 8 13:39:01 2013 From: alan.schmitt at polytechnique.org (Alan Schmitt) Date: Fri, 08 Mar 2013 19:39:01 +0100 Subject: [Unison-hackers] Ignore files above a certain size In-Reply-To: References: Message-ID: Benjamin Pierce writes: > Ok, this approach seems reasonable. The only thing that concerns me is > adding one more ad hoc preference... Here is a first patch that adds this preference. Please comment to let me know if I should commit it. diff --git a/src/recon.ml b/src/recon.ml index 78623f4..77eb87c 100644 --- a/src/recon.ml +++ b/src/recon.ml @@ -211,6 +211,15 @@ let noCreationPartial = It is recommended to use {\\tt BelowPath} \ patterns when selecting a directory and all its contents.") +let maxSizeThreshold = + Prefs.createInt "maxsizethreshold" (-1) + "prevent transfer of files bigger than this (if >=0, in Kb)" + ("A number indicating above what filesize (in kilobytes) Unison should " + ^ "flag a conflict instead of transferring the file. " + ^ "This conflict remains even in the presence of force or prefer options. " + ^ "A negative number will allow every transfer independently of the size. " + ^ "The default is -1. ") + let partialCancelPref actionKind = match actionKind with `DELETION -> noDeletionPartial @@ -236,10 +245,17 @@ let shouldCancel path rc1 rc2 root2 = || List.mem root2 (Pred.assoc_all (partialCancelPref kind) path) in + let testSize rc = + Prefs.read maxSizeThreshold >= 0 + && Props.length rc.desc >= + Uutil.Filesize.ofInt64 + (Int64.mul (Int64.of_int 1000) + (Int64.of_int (Prefs.read maxSizeThreshold))) + in match actionKind rc1 rc2 with - `UPDATE -> test `UPDATE + `UPDATE -> test `UPDATE || testSize rc1 | `DELETION -> test `UPDATE || test `DELETION - | `CREATION -> test `CREATION + | `CREATION -> test `CREATION || testSize rc1 let filterRi root1 root2 ri = match ri.replicas with From alan.schmitt at polytechnique.org Fri Mar 8 13:43:33 2013 From: alan.schmitt at polytechnique.org (Alan Schmitt) Date: Fri, 08 Mar 2013 19:43:33 +0100 Subject: [Unison-hackers] Ignore files above a certain size In-Reply-To: References: Message-ID: Benjamin Pierce writes: > Ok, this approach seems reasonable. The only thing that concerns me is > adding one more ad hoc preference... Here is a second, more controversial patch, to extend the Conflict direction with a string that gives the reason of the conflict, so that it may be displayed in the logs. The main issue with this patch is that it touches many files, and the UI code will need to be adapted (taking into account the extra argument to Conflict). I've dealt with the text ui for the moment. If you agree with this approach, I'll patch the other UIs (ignoring the extra string for the moment, the UI maintainers can then take advantage of it). Alan diff --git a/src/common.ml b/src/common.ml index db74b30..c4fe298 100644 --- a/src/common.ml +++ b/src/common.ml @@ -118,17 +118,21 @@ type replicaContent = props : Props.t list } (* Parent properties *) type direction = - Conflict + Conflict of string (* The string is the reason of the conflict *) | Merge | Replica1ToReplica2 | Replica2ToReplica1 let direction2string = function - Conflict -> "conflict" + Conflict _ -> "conflict" | Merge -> "merge" | Replica1ToReplica2 -> "replica1 to replica2" | Replica2ToReplica1 -> "replica2 to replica1" +let isConflict = function + Conflict _ -> true + | _ -> false + type difference = { rc1 : replicaContent; rc2 : replicaContent; @@ -176,7 +180,7 @@ let riLength ri = begin match dir with Replica1ToReplica2 -> rcLength rc1 rc2 | Replica2ToReplica1 -> rcLength rc2 rc1 - | Conflict -> Uutil.Filesize.zero + | Conflict _ -> Uutil.Filesize.zero | Merge -> Uutil.Filesize.zero (* underestimate :-*) end | _ -> @@ -205,14 +209,14 @@ let fileInfos ui1 ui2 = let problematic ri = match ri.replicas with Problem _ -> true - | Different diff -> diff.direction = Conflict + | Different diff -> isConflict diff.direction let partiallyProblematic ri = match ri.replicas with Problem _ -> true - | Different diff -> - diff.direction = Conflict || diff.errors1 <> [] || diff.errors2 <> [] + | Different diff -> + isConflict diff.direction || diff.errors1 <> [] || diff.errors2 <> [] let isDeletion ri = match ri.replicas with diff --git a/src/common.mli b/src/common.mli index e484c5b..dc12d59 100644 --- a/src/common.mli +++ b/src/common.mli @@ -96,13 +96,15 @@ type replicaContent = props : Props.t list } (* Parent properties *) type direction = - Conflict + Conflict of string (* The string is the reason of the conflict *) | Merge | Replica1ToReplica2 | Replica2ToReplica1 val direction2string : direction -> string +val isConflict : direction -> bool + type difference = { rc1 : replicaContent; (* - content of first replica *) rc2 : replicaContent; (* - content of second replica *) diff --git a/src/recon.ml b/src/recon.ml index 77eb87c..ccd773f 100644 --- a/src/recon.ml +++ b/src/recon.ml @@ -27,7 +27,7 @@ let setDirection ri dir force = match ri.replicas with Different ({rc1 = rc1; rc2 = rc2; direction = d; default_direction = default } as diff) - when force=`Force || default=Conflict -> + when force=`Force || isConflict default -> if dir=`Replica1ToReplica2 then diff.direction <- Replica1ToReplica2 else if dir=`Replica2ToReplica1 then @@ -37,10 +37,10 @@ let setDirection ri dir force = end else begin (* dir = `Older or dir = `Newer *) match rc1.status, rc2.status with `Deleted, _ -> - if default=Conflict then + if isConflict default then diff.direction <- Replica2ToReplica1 | _, `Deleted -> - if default=Conflict then + if isConflict default then diff.direction <- Replica1ToReplica2 | _ -> let comp = Props.time rc1.desc -. Props.time rc2.desc in @@ -253,25 +253,33 @@ let shouldCancel path rc1 rc2 root2 = (Int64.of_int (Prefs.read maxSizeThreshold))) in match actionKind rc1 rc2 with - `UPDATE -> test `UPDATE || testSize rc1 - | `DELETION -> test `UPDATE || test `DELETION - | `CREATION -> test `CREATION || testSize rc1 + `UPDATE -> + if test `UPDATE then true, "would update a file with noupdate or noupdatepartial set" + else testSize rc1, "would transfer a file of size greater than maxsizethreshold" + | `DELETION -> + if test `UPDATE then true, "would update a file with noupdate or noupdatepartial set" + else test `DELETION, "would delete a file with nodeletion or nodeletionpartial set" + | `CREATION -> + if test `CREATION then true, "would create a file with nocreation or nocreationpartial set" + else testSize rc1, "would transfer a file of size greater than maxsizethreshold" let filterRi root1 root2 ri = match ri.replicas with Problem _ -> () | Different diff -> - if - match diff.direction with - Replica1ToReplica2 -> - shouldCancel (Path.toString ri.path1) diff.rc1 diff.rc2 root2 - | Replica2ToReplica1 -> - shouldCancel (Path.toString ri.path1) diff.rc2 diff.rc1 root1 - | Conflict | Merge -> - false - then - diff.direction <- Conflict + let cancel,reason = + match diff.direction with + Replica1ToReplica2 -> + shouldCancel (Path.toString ri.path1) diff.rc1 diff.rc2 root2 + | Replica2ToReplica1 -> + shouldCancel (Path.toString ri.path1) diff.rc2 diff.rc1 root1 + | Conflict _ | Merge -> + false,"" + in + if cancel + then + diff.direction <- Conflict reason let filterRis ris = let (root1, root2) = Globals.rawRootPair () in @@ -534,7 +542,7 @@ let add_equal (counter, archiveUpdated) equal v = (* -- *) let rec reconcile allowPartial path ui1 props1 ui2 props2 counter equals unequals = - let different uc1 uc2 oldType equals unequals = + let different uc1 uc2 reason oldType equals unequals = (equals, Tree.add unequals (propagateErrors allowPartial @@ -542,7 +550,8 @@ let rec reconcile path true ui1 props1 uc1 oldType; rc2 = update2replicaContent path true ui2 props2 uc2 oldType; - direction = Conflict; default_direction = Conflict; + direction = Conflict reason; + default_direction = Conflict reason; errors1 = []; errors2 = []}))) in let toBeMerged uc1 uc2 oldType equals unequals = (equals, @@ -583,7 +592,7 @@ let rec reconcile let action = if propsChanged1 = PropsSame then Replica2ToReplica1 else if propsChanged2 = PropsSame then Replica1ToReplica2 - else Conflict in + else Conflict "properties changed on both sides" in (equals, Tree.add unequals (Different @@ -618,23 +627,27 @@ let rec reconcile (* expect this.) *) let uc1' = File(desc1,ContentsSame) in let uc2' = File(desc2,ContentsSame) in - different uc1' uc2' (oldType prev) equals unequals + different uc1' uc2' "properties changed on both sides" + (oldType prev) equals unequals | ContentsSame, ContentsSame when Props.similar desc1 desc2 -> (add_equal counter equals (uc1, uc2), unequals) | ContentsUpdated _, ContentsUpdated _ when Globals.shouldMerge path -> toBeMerged uc1 uc2 (oldType prev) equals unequals | _ -> - different uc1 uc2 (oldType prev) equals unequals + different uc1 uc2 "contents changed on both sides" + (oldType prev) equals unequals end | (Updates (Symlink(l1) as uc1, prev), Updates (Symlink(l2) as uc2, _)) -> if l1 = l2 then (add_equal counter equals (uc1, uc2), unequals) else - different uc1 uc2 (oldType prev) equals unequals + different uc1 uc2 "symbolic links changed on both sides" + (oldType prev) equals unequals | (Updates (uc1, prev), Updates (uc2, _)) -> - different uc1 uc2 (oldType prev) equals unequals + different uc1 uc2 "conflicting updates" + (oldType prev) equals unequals (* Sorts the paths so that they will be displayed in order *) let sortPaths pathUpdatesList = diff --git a/src/transport.ml b/src/transport.ml index b578e53..b319a15 100644 --- a/src/transport.ml +++ b/src/transport.ml @@ -151,9 +151,9 @@ let propagate root1 root2 reconItem id showMergeFn = {rc1 = rc1; rc2 = rc2; direction = dir; default_direction = def} -> let notDefault = dir <> def in match dir with - Conflict -> - Trace.log (Printf.sprintf "[CONFLICT] Skipping %s\n" - (Path.toString path)); + Conflict c -> + Trace.log (Printf.sprintf "[CONFLICT] Skipping %s\n %s\n" + (Path.toString path) c); return () | Replica1ToReplica2 -> doAction diff --git a/src/uicommon.ml b/src/uicommon.ml index 555a154..34ba3c0 100644 --- a/src/uicommon.ml +++ b/src/uicommon.ml @@ -267,7 +267,7 @@ type action = AError | ASkip of bool | ALtoR of bool | ARtoL of bool | AMerge let direction2action partial dir = match dir with - Conflict -> ASkip partial + Conflict _ -> ASkip partial | Replica1ToReplica2 -> ALtoR partial | Replica2ToReplica1 -> ARtoL partial | Merge -> AMerge diff --git a/src/uitext.ml b/src/uitext.ml index 552c9fd..5fca0d9 100644 --- a/src/uitext.ml +++ b/src/uitext.ml @@ -218,7 +218,7 @@ let displayri ri = match ri.replicas with Problem _ -> alwaysDisplay s - | Different {direction = d} when d=Conflict -> + | Different {direction = d} when isConflict d -> alwaysDisplay s | _ -> display s @@ -254,7 +254,7 @@ let interact rilist = match ri.replicas with Problem s -> display "\n"; display s; display "\n"; next() | Different ({rc1 = rc1; rc2 = rc2; direction = dir} as diff) -> - if Prefs.read Uicommon.auto && dir<>Conflict then begin + if Prefs.read Uicommon.auto && not (isConflict dir) then begin display "\n"; next() end else let (descr, descl) = @@ -271,14 +271,14 @@ let interact rilist = end; selectAction (if Prefs.read Globals.batch then Some " " else None) - [((if dir=Conflict && not (Prefs.read Globals.batch) + [((if (isConflict dir) && not (Prefs.read Globals.batch) then ["f"] (* Offer no default behavior if we've got a conflict and we're in interactive mode *) else ["";"f";" "]), ("follow " ^ Uutil.myName ^ "'s recommendation (if any)"), fun ()-> newLine (); - if dir = Conflict && not (Prefs.read Globals.batch) + if (isConflict dir) && not (Prefs.read Globals.batch) then begin display "No default action [type '?' for help]\n"; repeat() @@ -360,7 +360,7 @@ let interact rilist = (["/"], ("skip"), (fun () -> - diff.direction <- Conflict; + if not (isConflict dir) then diff.direction <- Conflict "skip requested"; redisplayri(); next())); ([">";"."], From alan.schmitt at polytechnique.org Fri Mar 8 13:47:18 2013 From: alan.schmitt at polytechnique.org (Alan Schmitt) Date: Fri, 08 Mar 2013 19:47:18 +0100 Subject: [Unison-hackers] text ui: nothing is logged when there is nothing to propagate Message-ID: Hello, I've noticed that, with the text ui, nothing is written to the log when there is nothing to propagate, even if there were some problems or conflicts. Do you think it's reasonable to print something to the log if skipped > 0 in this case? Thanks, Alan From bcpierce at cis.upenn.edu Fri Mar 8 14:59:29 2013 From: bcpierce at cis.upenn.edu (Benjamin C. Pierce) Date: Fri, 8 Mar 2013 14:59:29 -0500 Subject: [Unison-hackers] text ui: nothing is logged when there is nothing to propagate In-Reply-To: References: Message-ID: <20278988-C273-4BFE-82B2-D182C438D553@cis.upenn.edu> > I've noticed that, with the text ui, nothing is written to the log when > there is nothing to propagate, even if there were some problems or > conflicts. > > Do you think it's reasonable to print something to the log if skipped > > 0 in this case? Yes, this seems good. - B From alan.schmitt at polytechnique.org Sat Mar 9 08:46:03 2013 From: alan.schmitt at polytechnique.org (Alan Schmitt) Date: Sat, 09 Mar 2013 14:46:03 +0100 Subject: [Unison-hackers] text ui: nothing is logged when there is nothing to propagate In-Reply-To: <20278988-C273-4BFE-82B2-D182C438D553@cis.upenn.edu> References: <20278988-C273-4BFE-82B2-D182C438D553@cis.upenn.edu> Message-ID: Benjamin C. Pierce writes: >> I've noticed that, with the text ui, nothing is written to the log when >> there is nothing to propagate, even if there were some problems or >> conflicts. >> >> Do you think it's reasonable to print something to the log if skipped > >> 0 in this case? > > Yes, this seems good. Here is a proposed patch for this. I duplicate the printing code, as I did not find a clean way to factorize it. Please let me know if I should commit this patch and the earlier ones as well. Alan diff --git a/src/uitext.ml b/src/uitext.ml index 5fca0d9..30a428b 100644 --- a/src/uitext.ml +++ b/src/uitext.ml @@ -604,6 +604,19 @@ let rec interactAndPropagateChanges reconItemList if !Update.foundArchives && Prefs.read Uicommon.repeat = "" then Update.commitUpdates (); display "No updates to propagate\n"; + if skipped > 0 then + Safelist.iter + (fun ri -> + match ri.replicas with + Problem p -> + Trace.log (Printf.sprintf "[ERROR] Skipping %s\n %s\n" + (Path.toString ri.path1) p) + | Different {rc1 = _; rc2 = _; direction = Conflict c; default_direction = _} -> + Trace.log (Printf.sprintf "[CONFLICT] Skipping %s\n %s\n" + (Path.toString ri.path1) c) + | _ -> () + ) + newReconItemList; (skipped > 0, false, false, []) end else if proceed=ProceedImmediately then begin doit() From bcpierce at cis.upenn.edu Sat Mar 9 12:36:17 2013 From: bcpierce at cis.upenn.edu (Benjamin C. Pierce) Date: Sat, 9 Mar 2013 12:36:17 -0500 Subject: [Unison-hackers] text ui: nothing is logged when there is nothing to propagate In-Reply-To: References: <20278988-C273-4BFE-82B2-D182C438D553@cis.upenn.edu> Message-ID: Yes, please go ahead with all of them. My only tiny comment is that the new preference should be marked "advanced" (by putting a * at the beginning of its long description, IIRC). - B On Mar 9, 2013, at 8:46 AM, Alan Schmitt wrote: > Benjamin C. Pierce writes: > >>> I've noticed that, with the text ui, nothing is written to the log when >>> there is nothing to propagate, even if there were some problems or >>> conflicts. >>> >>> Do you think it's reasonable to print something to the log if skipped > >>> 0 in this case? >> >> Yes, this seems good. > > Here is a proposed patch for this. I duplicate the printing code, as I > did not find a clean way to factorize it. > > Please let me know if I should commit this patch and the earlier ones as > well. > > Alan > > diff --git a/src/uitext.ml b/src/uitext.ml > index 5fca0d9..30a428b 100644 > --- a/src/uitext.ml > +++ b/src/uitext.ml > @@ -604,6 +604,19 @@ let rec interactAndPropagateChanges reconItemList > if !Update.foundArchives && Prefs.read Uicommon.repeat = "" then > Update.commitUpdates (); > display "No updates to propagate\n"; > + if skipped > 0 then > + Safelist.iter > + (fun ri -> > + match ri.replicas with > + Problem p -> > + Trace.log (Printf.sprintf "[ERROR] Skipping %s\n %s\n" > + (Path.toString ri.path1) p) > + | Different {rc1 = _; rc2 = _; direction = Conflict c; default_direction = _} -> > + Trace.log (Printf.sprintf "[CONFLICT] Skipping %s\n %s\n" > + (Path.toString ri.path1) c) > + | _ -> () > + ) > + newReconItemList; > (skipped > 0, false, false, []) > end else if proceed=ProceedImmediately then begin > doit() > _______________________________________________ > Unison-hackers mailing list > Unison-hackers at lists.seas.upenn.edu > http://lists.seas.upenn.edu/mailman/listinfo/unison-hackers From alan.schmitt at polytechnique.org Sun Mar 10 11:22:28 2013 From: alan.schmitt at polytechnique.org (Alan Schmitt) Date: Sun, 10 Mar 2013 16:22:28 +0100 Subject: [Unison-hackers] text ui: nothing is logged when there is nothing to propagate In-Reply-To: References: <20278988-C273-4BFE-82B2-D182C438D553@cis.upenn.edu> Message-ID: Benjamin C. Pierce writes: > Yes, please go ahead with all of them. My only tiny comment is that > the new preference should be marked "advanced" (by putting a * at the > beginning of its long description, IIRC). OK, I made that change (it's a '!' at the beginning of the short description, by the way). I also modified the way I display the reasons for errors or skips: it's inside the log if items are transferred, and in any case it's in the summary at the end. This makes it easier to grep. This is for instance what I get in the log after a small test: If nothing was transferred: Synchronization complete at 15:59:42 (0 item transferred, 2 skipped, 0 failed) skipped: fable.pdf (would transfer a file of size greater than maxsizethreshold) skipped: fine-esop.pdf (skip requested) If something was transferred: UNISON 2.46.13 started propagating changes at 16:09:09.24 on 10 Mar 2013 [CONFLICT] Skipping fable.pdf would transfer a file of size greater than maxsizethreshold [BGN] Deleting fine-esop.pdf from /Users/schmitta/tmp/unison_test/a [END] Deleting fine-esop.pdf UNISON 2.46.13 finished propagating changes at 16:09:09.25 on 10 Mar 2013 Synchronization complete at 16:09:09 (1 item transferred, 1 skipped, 0 failed) skipped: fable.pdf (would transfer a file of size greater than maxsizethreshold) We could also add this information for failed paths, by changing the 'doTransport' function. This way one would know in the summary why there was a problem, instead of having to go hunt into the log. Let me know if you want me to add this. Here is the modified uitext patch. diff --git a/src/uitext.ml b/src/uitext.ml index 5fca0d9..364cb07 100644 --- a/src/uitext.ml +++ b/src/uitext.ml @@ -578,9 +578,12 @@ let rec interactAndPropagateChanges reconItemList if skipped>0 then Safelist.iter (fun ri -> - if problematic ri then - alwaysDisplayAndLog - (" skipped: " ^ (Path.toString ri.path1))) + match ri.replicas with + Problem r + | Different {rc1 = _; rc2 = _; direction = Conflict r; default_direction = _} -> + alwaysDisplayAndLog (Printf.sprintf " skipped: %s (%s)" + (Path.toString ri.path1) r) + | _ -> ()) newReconItemList; if partials>0 then Safelist.iter @@ -604,6 +607,25 @@ let rec interactAndPropagateChanges reconItemList if !Update.foundArchives && Prefs.read Uicommon.repeat = "" then Update.commitUpdates (); display "No updates to propagate\n"; + if skipped > 0 then begin + let summary = + Printf.sprintf + "Synchronization complete at %s (0 item transferred, %d skipped, 0 failed)" + (let tm = Util.localtime (Util.time()) in + Printf.sprintf "%02d:%02d:%02d" + tm.Unix.tm_hour tm.Unix.tm_min tm.Unix.tm_sec) + skipped in + Trace.log (summary ^ "\n"); + Safelist.iter + (fun ri -> + match ri.replicas with + Problem r + | Different {rc1 = _; rc2 = _; direction = Conflict r; default_direction = _} -> + alwaysDisplayAndLog (Printf.sprintf " skipped: %s (%s)" + (Path.toString ri.path1) r) + | _ -> ()) + newReconItemList + end; (skipped > 0, false, false, []) end else if proceed=ProceedImmediately then begin doit() Alan From bcpierce at cis.upenn.edu Sun Mar 10 12:29:37 2013 From: bcpierce at cis.upenn.edu (Benjamin C. Pierce) Date: Sun, 10 Mar 2013 12:29:37 -0400 Subject: [Unison-hackers] text ui: nothing is logged when there is nothing to propagate In-Reply-To: References: <20278988-C273-4BFE-82B2-D182C438D553@cis.upenn.edu> Message-ID: <9EA51D8C-B243-4E72-9512-0F34AB11ACC5@cis.upenn.edu> Yes, adding similar information for failed paths sounds like a good idea. Do add that if you are feeling energetic? :-) - B On Mar 10, 2013, at 11:22 AM, Alan Schmitt wrote: > Benjamin C. Pierce writes: > >> Yes, please go ahead with all of them. My only tiny comment is that >> the new preference should be marked "advanced" (by putting a * at the >> beginning of its long description, IIRC). > > OK, I made that change (it's a '!' at the beginning of the short > description, by the way). > > I also modified the way I display the reasons for errors or skips: it's > inside the log if items are transferred, and in any case it's in the > summary at the end. This makes it easier to grep. > > This is for instance what I get in the log after a small test: > > If nothing was transferred: > > Synchronization complete at 15:59:42 (0 item transferred, 2 skipped, 0 failed) > skipped: fable.pdf (would transfer a file of size greater than maxsizethreshold) > skipped: fine-esop.pdf (skip requested) > > > If something was transferred: > > UNISON 2.46.13 started propagating changes at 16:09:09.24 on 10 Mar 2013 > [CONFLICT] Skipping fable.pdf > would transfer a file of size greater than maxsizethreshold > [BGN] Deleting fine-esop.pdf from /Users/schmitta/tmp/unison_test/a > [END] Deleting fine-esop.pdf > UNISON 2.46.13 finished propagating changes at 16:09:09.25 on 10 Mar 2013 > > > Synchronization complete at 16:09:09 (1 item transferred, 1 skipped, 0 failed) > skipped: fable.pdf (would transfer a file of size greater than maxsizethreshold) > > > We could also add this information for failed paths, by changing the > 'doTransport' function. This way one would know in the summary why there > was a problem, instead of having to go hunt into the log. Let me know if > you want me to add this. > > > Here is the modified uitext patch. > > diff --git a/src/uitext.ml b/src/uitext.ml > index 5fca0d9..364cb07 100644 > --- a/src/uitext.ml > +++ b/src/uitext.ml > @@ -578,9 +578,12 @@ let rec interactAndPropagateChanges reconItemList > if skipped>0 then > Safelist.iter > (fun ri -> > - if problematic ri then > - alwaysDisplayAndLog > - (" skipped: " ^ (Path.toString ri.path1))) > + match ri.replicas with > + Problem r > + | Different {rc1 = _; rc2 = _; direction = Conflict r; default_direction = _} -> > + alwaysDisplayAndLog (Printf.sprintf " skipped: %s (%s)" > + (Path.toString ri.path1) r) > + | _ -> ()) > newReconItemList; > if partials>0 then > Safelist.iter > @@ -604,6 +607,25 @@ let rec interactAndPropagateChanges reconItemList > if !Update.foundArchives && Prefs.read Uicommon.repeat = "" then > Update.commitUpdates (); > display "No updates to propagate\n"; > + if skipped > 0 then begin > + let summary = > + Printf.sprintf > + "Synchronization complete at %s (0 item transferred, %d skipped, 0 failed)" > + (let tm = Util.localtime (Util.time()) in > + Printf.sprintf "%02d:%02d:%02d" > + tm.Unix.tm_hour tm.Unix.tm_min tm.Unix.tm_sec) > + skipped in > + Trace.log (summary ^ "\n"); > + Safelist.iter > + (fun ri -> > + match ri.replicas with > + Problem r > + | Different {rc1 = _; rc2 = _; direction = Conflict r; default_direction = _} -> > + alwaysDisplayAndLog (Printf.sprintf " skipped: %s (%s)" > + (Path.toString ri.path1) r) > + | _ -> ()) > + newReconItemList > + end; > (skipped > 0, false, false, []) > end else if proceed=ProceedImmediately then begin > doit() > > > Alan > _______________________________________________ > Unison-hackers mailing list > Unison-hackers at lists.seas.upenn.edu > http://lists.seas.upenn.edu/mailman/listinfo/unison-hackers From schmitta at seas.upenn.edu Mon Mar 11 04:21:56 2013 From: schmitta at seas.upenn.edu (schmitta at seas.upenn.edu) Date: Mon, 11 Mar 2013 04:21:56 -0400 Subject: [Unison-hackers] [unison-svn] r518 - trunk Message-ID: <201303110821.r2B8Luqs012647@yaws.seas.upenn.edu> Author: schmitta Date: 2013-03-11 04:21:55 -0400 (Mon, 11 Mar 2013) New Revision: 518 Modified: trunk/Makefile Log: Adding a "git_checkin" target for developers working from git Modified: trunk/Makefile =================================================================== --- trunk/Makefile 2012-11-20 11:01:22 UTC (rev 517) +++ trunk/Makefile 2013-03-11 08:21:55 UTC (rev 518) @@ -37,6 +37,10 @@ $(MAKE) nightly endif +git_checkin: remembernews + echo >> src/mkProjectInfo.ml # so the Rev keyword gets updated + git svn dcommit # no logmsg here: the changes are in the commits + remembernews: logmsg echo "CHANGES FROM VERSION" $(VERSION) > rc.tmp echo >> rc.tmp From schmitta at seas.upenn.edu Mon Mar 11 04:41:33 2013 From: schmitta at seas.upenn.edu (schmitta at seas.upenn.edu) Date: Mon, 11 Mar 2013 04:41:33 -0400 Subject: [Unison-hackers] [unison-svn] r519 - trunk Message-ID: <201303110841.r2B8fXi6013226@yaws.seas.upenn.edu> Author: schmitta Date: 2013-03-11 04:41:33 -0400 (Mon, 11 Mar 2013) New Revision: 519 Added: trunk/.gitignore Log: hush git Added: trunk/.gitignore =================================================================== --- trunk/.gitignore (rev 0) +++ trunk/.gitignore 2013-03-11 08:41:33 UTC (rev 519) @@ -0,0 +1,9 @@ +*.cmx +*.cmi +*.o +src/unison +src/Makefile.ProjectInfo +src/TAGS +src/mkProjectInfo +*.cmo +src/ubase/projectInfo.ml From schmitta at seas.upenn.edu Mon Mar 11 04:41:38 2013 From: schmitta at seas.upenn.edu (schmitta at seas.upenn.edu) Date: Mon, 11 Mar 2013 04:41:38 -0400 Subject: [Unison-hackers] [unison-svn] r520 - trunk/src Message-ID: <201303110841.r2B8fcRl013256@yaws.seas.upenn.edu> Author: schmitta Date: 2013-03-11 04:41:38 -0400 (Mon, 11 Mar 2013) New Revision: 520 Modified: trunk/src/recon.ml Log: Adding the maxsizethreshold option which prevents the transfer of files larger than the size specified (in Kb) Modified: trunk/src/recon.ml =================================================================== --- trunk/src/recon.ml 2013-03-11 08:41:33 UTC (rev 519) +++ trunk/src/recon.ml 2013-03-11 08:41:38 UTC (rev 520) @@ -211,6 +211,15 @@ It is recommended to use {\\tt BelowPath} \ patterns when selecting a directory and all its contents.") +let maxSizeThreshold = + Prefs.createInt "maxsizethreshold" (-1) + "!prevent transfer of files bigger than this (if >=0, in Kb)" + ("A number indicating above what filesize (in kilobytes) Unison should " + ^ "flag a conflict instead of transferring the file. " + ^ "This conflict remains even in the presence of force or prefer options. " + ^ "A negative number will allow every transfer independently of the size. " + ^ "The default is -1. ") + let partialCancelPref actionKind = match actionKind with `DELETION -> noDeletionPartial @@ -236,10 +245,17 @@ || List.mem root2 (Pred.assoc_all (partialCancelPref kind) path) in + let testSize rc = + Prefs.read maxSizeThreshold >= 0 + && Props.length rc.desc >= + Uutil.Filesize.ofInt64 + (Int64.mul (Int64.of_int 1000) + (Int64.of_int (Prefs.read maxSizeThreshold))) + in match actionKind rc1 rc2 with - `UPDATE -> test `UPDATE + `UPDATE -> test `UPDATE || testSize rc1 | `DELETION -> test `UPDATE || test `DELETION - | `CREATION -> test `CREATION + | `CREATION -> test `CREATION || testSize rc1 let filterRi root1 root2 ri = match ri.replicas with From schmitta at seas.upenn.edu Mon Mar 11 04:41:44 2013 From: schmitta at seas.upenn.edu (schmitta at seas.upenn.edu) Date: Mon, 11 Mar 2013 04:41:44 -0400 Subject: [Unison-hackers] [unison-svn] r521 - trunk/src Message-ID: <201303110841.r2B8fiO0013276@yaws.seas.upenn.edu> Author: schmitta Date: 2013-03-11 04:41:44 -0400 (Mon, 11 Mar 2013) New Revision: 521 Modified: trunk/src/common.ml trunk/src/common.mli trunk/src/recon.ml trunk/src/transport.ml trunk/src/uicommon.ml trunk/src/uitext.ml Log: Added a string to the Conflict direction to document the reason of the conflict. The text UI has been adapted to this change, the other UIs need to be modified. Modified: trunk/src/common.ml =================================================================== --- trunk/src/common.ml 2013-03-11 08:41:38 UTC (rev 520) +++ trunk/src/common.ml 2013-03-11 08:41:44 UTC (rev 521) @@ -118,17 +118,21 @@ props : Props.t list } (* Parent properties *) type direction = - Conflict + Conflict of string (* The string is the reason of the conflict *) | Merge | Replica1ToReplica2 | Replica2ToReplica1 let direction2string = function - Conflict -> "conflict" + Conflict _ -> "conflict" | Merge -> "merge" | Replica1ToReplica2 -> "replica1 to replica2" | Replica2ToReplica1 -> "replica2 to replica1" +let isConflict = function + Conflict _ -> true + | _ -> false + type difference = { rc1 : replicaContent; rc2 : replicaContent; @@ -176,7 +180,7 @@ begin match dir with Replica1ToReplica2 -> rcLength rc1 rc2 | Replica2ToReplica1 -> rcLength rc2 rc1 - | Conflict -> Uutil.Filesize.zero + | Conflict _ -> Uutil.Filesize.zero | Merge -> Uutil.Filesize.zero (* underestimate :-*) end | _ -> @@ -205,14 +209,14 @@ let problematic ri = match ri.replicas with Problem _ -> true - | Different diff -> diff.direction = Conflict + | Different diff -> isConflict diff.direction let partiallyProblematic ri = match ri.replicas with Problem _ -> true - | Different diff -> - diff.direction = Conflict || diff.errors1 <> [] || diff.errors2 <> [] + | Different diff -> + isConflict diff.direction || diff.errors1 <> [] || diff.errors2 <> [] let isDeletion ri = match ri.replicas with Modified: trunk/src/common.mli =================================================================== --- trunk/src/common.mli 2013-03-11 08:41:38 UTC (rev 520) +++ trunk/src/common.mli 2013-03-11 08:41:44 UTC (rev 521) @@ -96,13 +96,15 @@ props : Props.t list } (* Parent properties *) type direction = - Conflict + Conflict of string (* The string is the reason of the conflict *) | Merge | Replica1ToReplica2 | Replica2ToReplica1 val direction2string : direction -> string +val isConflict : direction -> bool + type difference = { rc1 : replicaContent; (* - content of first replica *) rc2 : replicaContent; (* - content of second replica *) Modified: trunk/src/recon.ml =================================================================== --- trunk/src/recon.ml 2013-03-11 08:41:38 UTC (rev 520) +++ trunk/src/recon.ml 2013-03-11 08:41:44 UTC (rev 521) @@ -27,7 +27,7 @@ match ri.replicas with Different ({rc1 = rc1; rc2 = rc2; direction = d; default_direction = default } as diff) - when force=`Force || default=Conflict -> + when force=`Force || isConflict default -> if dir=`Replica1ToReplica2 then diff.direction <- Replica1ToReplica2 else if dir=`Replica2ToReplica1 then @@ -37,10 +37,10 @@ end else begin (* dir = `Older or dir = `Newer *) match rc1.status, rc2.status with `Deleted, _ -> - if default=Conflict then + if isConflict default then diff.direction <- Replica2ToReplica1 | _, `Deleted -> - if default=Conflict then + if isConflict default then diff.direction <- Replica1ToReplica2 | _ -> let comp = Props.time rc1.desc -. Props.time rc2.desc in @@ -253,25 +253,33 @@ (Int64.of_int (Prefs.read maxSizeThreshold))) in match actionKind rc1 rc2 with - `UPDATE -> test `UPDATE || testSize rc1 - | `DELETION -> test `UPDATE || test `DELETION - | `CREATION -> test `CREATION || testSize rc1 + `UPDATE -> + if test `UPDATE then true, "would update a file with noupdate or noupdatepartial set" + else testSize rc1, "would transfer a file of size greater than maxsizethreshold" + | `DELETION -> + if test `UPDATE then true, "would update a file with noupdate or noupdatepartial set" + else test `DELETION, "would delete a file with nodeletion or nodeletionpartial set" + | `CREATION -> + if test `CREATION then true, "would create a file with nocreation or nocreationpartial set" + else testSize rc1, "would transfer a file of size greater than maxsizethreshold" let filterRi root1 root2 ri = match ri.replicas with Problem _ -> () | Different diff -> - if - match diff.direction with - Replica1ToReplica2 -> - shouldCancel (Path.toString ri.path1) diff.rc1 diff.rc2 root2 - | Replica2ToReplica1 -> - shouldCancel (Path.toString ri.path1) diff.rc2 diff.rc1 root1 - | Conflict | Merge -> - false - then - diff.direction <- Conflict + let cancel,reason = + match diff.direction with + Replica1ToReplica2 -> + shouldCancel (Path.toString ri.path1) diff.rc1 diff.rc2 root2 + | Replica2ToReplica1 -> + shouldCancel (Path.toString ri.path1) diff.rc2 diff.rc1 root1 + | Conflict _ | Merge -> + false,"" + in + if cancel + then + diff.direction <- Conflict reason let filterRis ris = let (root1, root2) = Globals.rawRootPair () in @@ -534,7 +542,7 @@ (* -- *) let rec reconcile allowPartial path ui1 props1 ui2 props2 counter equals unequals = - let different uc1 uc2 oldType equals unequals = + let different uc1 uc2 reason oldType equals unequals = (equals, Tree.add unequals (propagateErrors allowPartial @@ -542,7 +550,8 @@ path true ui1 props1 uc1 oldType; rc2 = update2replicaContent path true ui2 props2 uc2 oldType; - direction = Conflict; default_direction = Conflict; + direction = Conflict reason; + default_direction = Conflict reason; errors1 = []; errors2 = []}))) in let toBeMerged uc1 uc2 oldType equals unequals = (equals, @@ -583,7 +592,7 @@ let action = if propsChanged1 = PropsSame then Replica2ToReplica1 else if propsChanged2 = PropsSame then Replica1ToReplica2 - else Conflict in + else Conflict "properties changed on both sides" in (equals, Tree.add unequals (Different @@ -618,23 +627,27 @@ (* expect this.) *) let uc1' = File(desc1,ContentsSame) in let uc2' = File(desc2,ContentsSame) in - different uc1' uc2' (oldType prev) equals unequals + different uc1' uc2' "properties changed on both sides" + (oldType prev) equals unequals | ContentsSame, ContentsSame when Props.similar desc1 desc2 -> (add_equal counter equals (uc1, uc2), unequals) | ContentsUpdated _, ContentsUpdated _ when Globals.shouldMerge path -> toBeMerged uc1 uc2 (oldType prev) equals unequals | _ -> - different uc1 uc2 (oldType prev) equals unequals + different uc1 uc2 "contents changed on both sides" + (oldType prev) equals unequals end | (Updates (Symlink(l1) as uc1, prev), Updates (Symlink(l2) as uc2, _)) -> if l1 = l2 then (add_equal counter equals (uc1, uc2), unequals) else - different uc1 uc2 (oldType prev) equals unequals + different uc1 uc2 "symbolic links changed on both sides" + (oldType prev) equals unequals | (Updates (uc1, prev), Updates (uc2, _)) -> - different uc1 uc2 (oldType prev) equals unequals + different uc1 uc2 "conflicting updates" + (oldType prev) equals unequals (* Sorts the paths so that they will be displayed in order *) let sortPaths pathUpdatesList = Modified: trunk/src/transport.ml =================================================================== --- trunk/src/transport.ml 2013-03-11 08:41:38 UTC (rev 520) +++ trunk/src/transport.ml 2013-03-11 08:41:44 UTC (rev 521) @@ -151,9 +151,9 @@ {rc1 = rc1; rc2 = rc2; direction = dir; default_direction = def} -> let notDefault = dir <> def in match dir with - Conflict -> - Trace.log (Printf.sprintf "[CONFLICT] Skipping %s\n" - (Path.toString path)); + Conflict c -> + Trace.log (Printf.sprintf "[CONFLICT] Skipping %s\n %s\n" + (Path.toString path) c); return () | Replica1ToReplica2 -> doAction Modified: trunk/src/uicommon.ml =================================================================== --- trunk/src/uicommon.ml 2013-03-11 08:41:38 UTC (rev 520) +++ trunk/src/uicommon.ml 2013-03-11 08:41:44 UTC (rev 521) @@ -267,7 +267,7 @@ let direction2action partial dir = match dir with - Conflict -> ASkip partial + Conflict _ -> ASkip partial | Replica1ToReplica2 -> ALtoR partial | Replica2ToReplica1 -> ARtoL partial | Merge -> AMerge Modified: trunk/src/uitext.ml =================================================================== --- trunk/src/uitext.ml 2013-03-11 08:41:38 UTC (rev 520) +++ trunk/src/uitext.ml 2013-03-11 08:41:44 UTC (rev 521) @@ -218,7 +218,7 @@ match ri.replicas with Problem _ -> alwaysDisplay s - | Different {direction = d} when d=Conflict -> + | Different {direction = d} when isConflict d -> alwaysDisplay s | _ -> display s @@ -254,7 +254,7 @@ match ri.replicas with Problem s -> display "\n"; display s; display "\n"; next() | Different ({rc1 = rc1; rc2 = rc2; direction = dir} as diff) -> - if Prefs.read Uicommon.auto && dir<>Conflict then begin + if Prefs.read Uicommon.auto && not (isConflict dir) then begin display "\n"; next() end else let (descr, descl) = @@ -271,14 +271,14 @@ end; selectAction (if Prefs.read Globals.batch then Some " " else None) - [((if dir=Conflict && not (Prefs.read Globals.batch) + [((if (isConflict dir) && not (Prefs.read Globals.batch) then ["f"] (* Offer no default behavior if we've got a conflict and we're in interactive mode *) else ["";"f";" "]), ("follow " ^ Uutil.myName ^ "'s recommendation (if any)"), fun ()-> newLine (); - if dir = Conflict && not (Prefs.read Globals.batch) + if (isConflict dir) && not (Prefs.read Globals.batch) then begin display "No default action [type '?' for help]\n"; repeat() @@ -360,7 +360,7 @@ (["/"], ("skip"), (fun () -> - diff.direction <- Conflict; + if not (isConflict dir) then diff.direction <- Conflict "skip requested"; redisplayri(); next())); ([">";"."], From schmitta at seas.upenn.edu Mon Mar 11 04:41:50 2013 From: schmitta at seas.upenn.edu (schmitta at seas.upenn.edu) Date: Mon, 11 Mar 2013 04:41:50 -0400 Subject: [Unison-hackers] [unison-svn] r522 - trunk/src Message-ID: <201303110841.r2B8foZv013296@yaws.seas.upenn.edu> Author: schmitta Date: 2013-03-11 04:41:50 -0400 (Mon, 11 Mar 2013) New Revision: 522 Modified: trunk/src/RECENTNEWS trunk/src/mkProjectInfo.ml trunk/src/uitext.ml Log: Log conflicts and problems in the text UI even if nothing is propagated. Modified: trunk/src/RECENTNEWS =================================================================== --- trunk/src/RECENTNEWS 2013-03-11 08:41:44 UTC (rev 521) +++ trunk/src/RECENTNEWS 2013-03-11 08:41:50 UTC (rev 522) @@ -1,3 +1,13 @@ +CHANGES FROM VERSION 2.46.13 + +* Log conflicts and problems in the text UI even if nothing is propagated. +* Added a string to the Conflict direction to document the reason of + the conflict. The text UI has been adapted to this change, the other + UIs need to be modified. +* Adding the maxsizethreshold option which prevents the transfer of + files larger than the size specified (in Kb) + +------------------------------- CHANGES FROM VERSION 2.46.12 * File system monitoring: the file watcher now fails when unable to Modified: trunk/src/mkProjectInfo.ml =================================================================== --- trunk/src/mkProjectInfo.ml 2013-03-11 08:41:44 UTC (rev 521) +++ trunk/src/mkProjectInfo.ml 2013-03-11 08:41:50 UTC (rev 522) @@ -89,3 +89,4 @@ + Modified: trunk/src/uitext.ml =================================================================== --- trunk/src/uitext.ml 2013-03-11 08:41:44 UTC (rev 521) +++ trunk/src/uitext.ml 2013-03-11 08:41:50 UTC (rev 522) @@ -578,9 +578,12 @@ if skipped>0 then Safelist.iter (fun ri -> - if problematic ri then - alwaysDisplayAndLog - (" skipped: " ^ (Path.toString ri.path1))) + match ri.replicas with + Problem r + | Different {rc1 = _; rc2 = _; direction = Conflict r; default_direction = _} -> + alwaysDisplayAndLog (Printf.sprintf " skipped: %s (%s)" + (Path.toString ri.path1) r) + | _ -> ()) newReconItemList; if partials>0 then Safelist.iter @@ -604,6 +607,25 @@ if !Update.foundArchives && Prefs.read Uicommon.repeat = "" then Update.commitUpdates (); display "No updates to propagate\n"; + if skipped > 0 then begin + let summary = + Printf.sprintf + "Synchronization complete at %s (0 item transferred, %d skipped, 0 failed)" + (let tm = Util.localtime (Util.time()) in + Printf.sprintf "%02d:%02d:%02d" + tm.Unix.tm_hour tm.Unix.tm_min tm.Unix.tm_sec) + skipped in + Trace.log (summary ^ "\n"); + Safelist.iter + (fun ri -> + match ri.replicas with + Problem r + | Different {rc1 = _; rc2 = _; direction = Conflict r; default_direction = _} -> + alwaysDisplayAndLog (Printf.sprintf " skipped: %s (%s)" + (Path.toString ri.path1) r) + | _ -> ()) + newReconItemList + end; (skipped > 0, false, false, []) end else if proceed=ProceedImmediately then begin doit() From schmitta at seas.upenn.edu Mon Mar 11 04:43:14 2013 From: schmitta at seas.upenn.edu (schmitta at seas.upenn.edu) Date: Mon, 11 Mar 2013 04:43:14 -0400 Subject: [Unison-hackers] [unison-svn] r523 - trunk Message-ID: <201303110843.r2B8hEle013390@yaws.seas.upenn.edu> Author: schmitta Date: 2013-03-11 04:43:14 -0400 (Mon, 11 Mar 2013) New Revision: 523 Modified: trunk/Makefile Log: tweaking git_checkin in Makefile Modified: trunk/Makefile =================================================================== --- trunk/Makefile 2013-03-11 08:41:50 UTC (rev 522) +++ trunk/Makefile 2013-03-11 08:43:14 UTC (rev 523) @@ -39,6 +39,9 @@ git_checkin: remembernews echo >> src/mkProjectInfo.ml # so the Rev keyword gets updated + git add src/RECENTNEWS src/mkProjectInfo.ml + git commit --amend --no-edit + $(RM) logmsg git svn dcommit # no logmsg here: the changes are in the commits remembernews: logmsg From alan.schmitt at polytechnique.org Thu Mar 14 12:18:19 2013 From: alan.schmitt at polytechnique.org (Alan Schmitt) Date: Thu, 14 Mar 2013 17:18:19 +0100 Subject: [Unison-hackers] Using git to hack Unison Message-ID: Hi, As it was the first time I used the git clone of the svn repository to hack Unison, I thought I would report with how it went. To summarize: it went pretty well, with one exception. Let's start with the exception (which is the first thing that bit me): I first tried to build Unison, to make sure my recent upgrades would not prevent me to, and it failed, because of the REV keyword. To solve this I created the Makefile.ProjectInfo file from a svn checkout and copied it to my local repository. I searched how to get rid of this dependency, but could not find how (except maybe by adding some hooks on the svn server to update a file containing the revision before serving it). I then started coding, and realized I'd better make a branch with my current changes. This was simply a: git checkout -b new_branch_name I then worked on the code, regularly doing commits. Before pushing everything, I cleaned up and reordered the commits to make them nicer in the history. I then put everything in the master branch. To avoid confusing svn, one needs to do: git checkout master git svn rebase # to fetch any svn commit that may have happened git checkout new_branch_name git rebase master # to merge them with the work then: git checkout master git merge new_branch_name --ff-only to append the commits at the end of the history (the --ff-only guarantees the commits can be applied without doing a merge). I then edit the logmsg, and do a make git_checkin which push everything back to svn. I found this worked nicely, as it lets me have experimental branches in my local repository, under version control, without polluting the main svn repository. Alan