From dadcb26edcaf45887d074986bc3b0ff796929a37 Mon Sep 17 00:00:00 2001 From: Simon Cropp Date: Fri, 3 Jul 2026 20:02:06 +1000 Subject: [PATCH 1/2] Prompt to kill locking processes when accepting When accepting a move fails because the files are locked (eg the snapshot is open in Word), show a dialog listing the locked files and locking processes instead of silently leaving the move pending. Options: Ignore, Kill and accept, Kill and accept all pending, or Always kill. Always kill persists to settings (AlwaysKillLockingProcesses) and is toggleable in the Options dialog, so future locks are killed without prompting. Existing per-tool KillLockingProcess (Word/Excel) still auto-kills without a prompt. Split FileLockKiller into GetLockingProcesses (names the processes for the dialog) and Kill; Tracker now re-adds a move kept pending so it can be retried. --- docs/mdsource/tray.source.md | 17 ++ docs/tray.md | 17 ++ .../FileLockKillerTest.cs | 102 +++++----- src/DiffEngineTray.Tests/FileLockUtils.cs | 52 +++++ .../LockedFilesFormTests.Default.verified.png | Bin 0 -> 10607 bytes .../LockedFilesFormTests.cs | 38 ++++ .../OptionsFormTests.Default.verified.png | Bin 25086 -> 28392 bytes .../OptionsFormTests.WithKeys.verified.png | Bin 24453 -> 27850 bytes src/DiffEngineTray.Tests/RecordingTracker.cs | 7 +- ...SettingsHelperTests.ReadWrite.verified.txt | 1 + .../SettingsHelperTests.cs | 3 +- .../TrackerLockedMoveTest.cs | 124 ++++++++++++ src/DiffEngineTray/FileLockKiller.cs | 55 ++++-- src/DiffEngineTray/LockedFiles.cs | 9 + src/DiffEngineTray/LockedFilesForm.cs | 112 +++++++++++ src/DiffEngineTray/LockedFilesHandler.cs | 38 ++++ src/DiffEngineTray/LockedFilesResolver.cs | 1 + src/DiffEngineTray/LockedFilesResponse.cs | 6 + src/DiffEngineTray/LockingProcess.cs | 1 + src/DiffEngineTray/Program.cs | 5 +- .../Settings/OptionsForm.Designer.cs | 17 ++ src/DiffEngineTray/Settings/OptionsForm.cs | 2 + .../Settings/OptionsFormLauncher.cs | 1 + src/DiffEngineTray/Settings/Settings.cs | 1 + src/DiffEngineTray/Tracker.cs | 180 +++++++++++++----- 25 files changed, 665 insertions(+), 124 deletions(-) create mode 100644 src/DiffEngineTray.Tests/FileLockUtils.cs create mode 100644 src/DiffEngineTray.Tests/LockedFilesFormTests.Default.verified.png create mode 100644 src/DiffEngineTray.Tests/LockedFilesFormTests.cs create mode 100644 src/DiffEngineTray.Tests/TrackerLockedMoveTest.cs create mode 100644 src/DiffEngineTray/LockedFiles.cs create mode 100644 src/DiffEngineTray/LockedFilesForm.cs create mode 100644 src/DiffEngineTray/LockedFilesHandler.cs create mode 100644 src/DiffEngineTray/LockedFilesResolver.cs create mode 100644 src/DiffEngineTray/LockedFilesResponse.cs create mode 100644 src/DiffEngineTray/LockingProcess.cs diff --git a/docs/mdsource/tray.source.md b/docs/mdsource/tray.source.md index 67de9ae0..de2ec701 100644 --- a/docs/mdsource/tray.source.md +++ b/docs/mdsource/tray.source.md @@ -49,6 +49,18 @@ Clicking "file1" or "file2" will delete file1 or file2 respectively. The drop do "Accept all" will accept all pending moves and all pending deletes. +### Locked files + +If accepting a move fails because the files are locked by another process (for example the snapshot is open in Microsoft Word), a prompt is shown listing the locked files and the locking processes: + + + + * "Ignore" leaves the move pending so it can be accepted later. + * "Kill [process] and accept" kills the locking processes and accepts the move. + * "Kill and accept all pending" kills the locking processes and accepts all pending moves, killing any other locking processes without further prompts. + * "Always kill" kills the locking processes and accepts the move. The choice is stored in settings, so future locked files are killed without prompting. It can be toggled in the Options dialog. + + ### Discard Discard will clear all currently tracked items. @@ -79,6 +91,11 @@ By default, when a diff is opened, the temp file will be on the left and the tar Control the [max instances to launch setting](docs/diff-tool.md#maxinstancestolaunch). +#### Always kill locking processes + +When accepting a move with [locked files](#locked-files), kill the locking processes without prompting. + + #### Discard all HotKey Registers a system wide HotKey to discard pending: diff --git a/docs/tray.md b/docs/tray.md index cfa30d75..27bd7ce5 100644 --- a/docs/tray.md +++ b/docs/tray.md @@ -56,6 +56,18 @@ Clicking "file1" or "file2" will delete file1 or file2 respectively. The drop do "Accept all" will accept all pending moves and all pending deletes. +### Locked files + +If accepting a move fails because the files are locked by another process (for example the snapshot is open in Microsoft Word), a prompt is shown listing the locked files and the locking processes: + + + + * "Ignore" leaves the move pending so it can be accepted later. + * "Kill [process] and accept" kills the locking processes and accepts the move. + * "Kill and accept all pending" kills the locking processes and accepts all pending moves, killing any other locking processes without further prompts. + * "Always kill" kills the locking processes and accepts the move. The choice is stored in settings, so future locked files are killed without prompting. It can be toggled in the Options dialog. + + ### Discard Discard will clear all currently tracked items. @@ -86,6 +98,11 @@ By default, when a diff is opened, the temp file will be on the left and the tar Control the [max instances to launch setting](docs/diff-tool.md#maxinstancestolaunch). +#### Always kill locking processes + +When accepting a move with [locked files](#locked-files), kill the locking processes without prompting. + + #### Discard all HotKey Registers a system wide HotKey to discard pending: diff --git a/src/DiffEngineTray.Tests/FileLockKillerTest.cs b/src/DiffEngineTray.Tests/FileLockKillerTest.cs index 92a7bc9a..bdca6311 100644 --- a/src/DiffEngineTray.Tests/FileLockKillerTest.cs +++ b/src/DiffEngineTray.Tests/FileLockKillerTest.cs @@ -1,5 +1,44 @@ public class FileLockKillerTest { + [Test] + public async Task GetLockingProcesses_WhenFileNotLocked_ReturnsEmpty() + { + var file = Path.Combine(Path.GetTempPath(), $"FileLockKillerTest_{Guid.NewGuid()}.txt"); + try + { + File.WriteAllText(file, "content"); + var result = FileLockKiller.GetLockingProcesses(file); + await Assert.That(result).IsEmpty(); + } + finally + { + File.Delete(file); + } + } + + [Test] + public async Task GetLockingProcesses_WhenFileLocked_ReturnsProcess() + { + var file = Path.Combine(Path.GetTempPath(), $"FileLockKillerTest_{Guid.NewGuid()}.txt"); + File.WriteAllText(file, "content"); + + var lockProcess = FileLockUtils.StartFileLockProcess(file); + + try + { + await Assert.That(FileLockUtils.IsFileLocked(file)).IsTrue(); + + var result = FileLockKiller.GetLockingProcesses(file); + + await Assert.That(result.Select(_ => _.ProcessId)).Contains(lockProcess.Id); + } + finally + { + FileLockUtils.Cleanup(lockProcess); + File.Delete(file); + } + } + [Test] public async Task KillLockingProcesses_WhenFileNotLocked_ReturnsFalse() { @@ -30,11 +69,11 @@ public async Task KillLockingProcesses_WhenFileLocked_KillsProcess() var file = Path.Combine(Path.GetTempPath(), $"FileLockKillerTest_{Guid.NewGuid()}.txt"); File.WriteAllText(file, "content"); - var lockProcess = StartFileLockProcess(file); + var lockProcess = FileLockUtils.StartFileLockProcess(file); try { - await Assert.That(IsFileLocked(file)).IsTrue(); + await Assert.That(FileLockUtils.IsFileLocked(file)).IsTrue(); var result = FileLockKiller.KillLockingProcesses(file); @@ -45,12 +84,7 @@ public async Task KillLockingProcesses_WhenFileLocked_KillsProcess() } finally { - if (!lockProcess.HasExited) - { - lockProcess.Kill(); - } - - lockProcess.Dispose(); + FileLockUtils.Cleanup(lockProcess); File.Delete(file); } } @@ -63,11 +97,11 @@ public async Task MoveSucceedsAfterKillingLockingProcess() File.WriteAllText(file, "content"); File.WriteAllText(tempFile, "new content"); - var lockProcess = StartFileLockProcess(file); + var lockProcess = FileLockUtils.StartFileLockProcess(file); try { - await Assert.That(IsFileLocked(file)).IsTrue(); + await Assert.That(FileLockUtils.IsFileLocked(file)).IsTrue(); await Assert.That(FileEx.SafeMove(tempFile, file)).IsFalse(); FileLockKiller.KillLockingProcesses(file); @@ -77,53 +111,9 @@ public async Task MoveSucceedsAfterKillingLockingProcess() } finally { - if (!lockProcess.HasExited) - { - lockProcess.Kill(); - } - - lockProcess.Dispose(); + FileLockUtils.Cleanup(lockProcess); File.Delete(file); File.Delete(tempFile); } } - - static Process StartFileLockProcess(string path) - { - var script = $"$f = [System.IO.File]::Open('{path.Replace("'", "''")}', 'Open', 'ReadWrite', 'None'); [Console]::WriteLine('locked'); Start-Sleep -Seconds 60"; - var process = new Process - { - StartInfo = new() - { - FileName = "powershell.exe", - Arguments = $"-NoProfile -Command \"{script}\"", - UseShellExecute = false, - CreateNoWindow = true, - RedirectStandardOutput = true - } - }; - process.Start(); - - // Wait for the process to signal that it has acquired the lock - var line = process.StandardOutput.ReadLine(); - if (line != "locked") - { - throw new InvalidOperationException($"Expected 'locked' but got '{line}'"); - } - - return process; - } - - static bool IsFileLocked(string path) - { - try - { - using var stream = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.None); - return false; - } - catch (IOException) - { - return true; - } - } -} +} \ No newline at end of file diff --git a/src/DiffEngineTray.Tests/FileLockUtils.cs b/src/DiffEngineTray.Tests/FileLockUtils.cs new file mode 100644 index 00000000..1f396c06 --- /dev/null +++ b/src/DiffEngineTray.Tests/FileLockUtils.cs @@ -0,0 +1,52 @@ +static class FileLockUtils +{ + public static Process StartFileLockProcess(string path) + { + var script = $"$f = [System.IO.File]::Open('{path.Replace("'", "''")}', 'Open', 'ReadWrite', 'None'); [Console]::WriteLine('locked'); Start-Sleep -Seconds 60"; + var process = new Process + { + StartInfo = new() + { + FileName = "powershell.exe", + Arguments = $"-NoProfile -Command \"{script}\"", + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardOutput = true + } + }; + process.Start(); + + // Wait for the process to signal that it has acquired the lock + var line = process.StandardOutput.ReadLine(); + if (line != "locked") + { + throw new InvalidOperationException($"Expected 'locked' but got '{line}'"); + } + + return process; + } + + public static bool IsFileLocked(string path) + { + try + { + using var stream = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.None); + return false; + } + catch (IOException) + { + return true; + } + } + + public static void Cleanup(Process process) + { + if (!process.HasExited) + { + process.Kill(); + process.WaitForExit(5000); + } + + process.Dispose(); + } +} \ No newline at end of file diff --git a/src/DiffEngineTray.Tests/LockedFilesFormTests.Default.verified.png b/src/DiffEngineTray.Tests/LockedFilesFormTests.Default.verified.png new file mode 100644 index 0000000000000000000000000000000000000000..918c42a3f6829d2d45a33ab82cbef9619e077cd6 GIT binary patch literal 10607 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 + new( + @"C:\tests\AdviceSummaryTests.BuildWord.received.docx", + @"C:\tests\AdviceSummaryTests.BuildWord.verified.docx", + null, + null, + false, + null, + null, + "docx"); + + static LockedFiles BuildLocked() => + new( + [ + @"C:\tests\AdviceSummaryTests.BuildWord.received.docx", + @"C:\tests\AdviceSummaryTests.BuildWord.verified.docx" + ], + [new(1234, "Microsoft Word")]); +} +#endif \ No newline at end of file diff --git a/src/DiffEngineTray.Tests/OptionsFormTests.Default.verified.png b/src/DiffEngineTray.Tests/OptionsFormTests.Default.verified.png index 0344c533bbc86f20bd2ec6ff9fab5955de654636..fcc67c35d3d4613894350c03b5e3c9edafa5cb3c 100644 GIT binary patch literal 28392 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 IXkCr`FL_1x^8f$< literal 25086 zcmd432~<+;_diOnrInT1WMzucV3S%_YMPiysg?PbIZv5W4oD6-1C|X`4w#T_800;>D553>_ckf;6{>JIqwe-E!U z%huBWLdNT~zDg!_soZDGdF>}f^;f^5n@rIif2AL_-BxH{6tyJ+>Gtd)a2$QzvHw!H zh3;uK4b7$jBP2rFR9_yBT@m0VBw^N&$cXnv0X+j1tr)KYftH3faL%O4xj~M@-gWyT z*Yfow2L6mu9NNuIkGGcue9bZ$6brj0L9hnyH%{-PnhzA6tW?e#S!4?oG;Nh99PZ0|*qbCrrXaDtmrz2SN(q(N7Kb z-#gr^374VTo;U)c(9%&88zao7*zUouD7?grdoZMvSo58SRPJJJ0HOTY1cpJy(Y#q6 zR7;$t%qOROGcRYU)gBl{6qE;PHh|TABY>H{!`TM~fFf?%7O) zllkehx%VE<-S@H@U>c_#TiB=NBls+8yyXM}DVpzC{!2r9Ko9+^6*Y2BtlKjz89c#z z^Gk)C@-Pt?&GVwjLldm!J9KEKw&WS%o$J4?FlKS2!^z@B>1%YTi!FZfkKNj= zk7y626ZnOh#)87U?+eq&_BO*Ie2ajsQztHH#npkQwOd4~XA+ueW5^bR{>qAtAkav# zAR03cjpE*qmL#tP^;^~Qws#mgj7zjBUZQL(CStq$sE@JG!D8GivMNi0akaDY(Q2hY zy@qTv%N-T@gI2EP^pn`$=@pahTgA&Nv$dgoEA(*vXI!1OvD@gKz0XtN`(P{TMe@dZ zi~O)i)tB@zhb)BKC~FYs^VVZ__CBsY7zDZykg5)GH$B&wheJDVd5taF^{-irk}y=i z9`$R5i}i92`b~eFC9RAkF;|RN9%W(<8oPZmru+dDhs+K#^q4pl!!d6>fmDqM?-6ym zVVna23GcYCzEBJv$6Oq9GG4jdJVDM9N%Syttq&8D%I5V-$0ZX*1C_=t#8hJr1bI=l zZt!jqMGU@+?K@Ds9j1jAoIkQ|OXdd}--Ko!z4*N%5blQw%~>1Kb_A8i$08+HqI!tjoBLI z|Ff=fR_MWtU+=A49gxhXqnn+$jp3$MzZ%1f4KTm5@IEr=?K@h$jBi(tJ^EIQqc1)| zjIYXe=GpK#_Xl-bCm2lem5(KhVX1Qi!U8`zU_lpD9Cj?vFKRQxF)O^69l)QZs^}LY zw-}xo1}8G+Ih~(e>*-457Y|vbNyOkWhF1=hFR3rOl24<#^d1sEM>)Z}{Y*ydecXu8 zj_tu{H(_x66b!c`O?=<`+J%-Dsrl(ybk7moon+5Va=?P8w}rEIZJfD5O=7js-GM6+ zyMGiv914~Ad~CC>@x3W(nByVljLL`0K5`wT&vf!q*5d!r6K>cQ4)j;-{eKDTJG9ZxUz71z; zSMCdcPIWxjULV!pF~E!W@~Xn!!;za>nq%fAmtXK6dl9VqD}OKN_6|(f#joEENG7vv zCW7U86Ap@e43q%alGp=ez7R8uUI^D_^7iSkj83fKpKcmA7Jo$QRl2`l$NAl4w3A@NWBqY*v`tCNF;pza7BsW|Q zM$MwIHddF91T6J1&rL?{FdRFlxF$-v zHsJTDH@)Qd^qcCeH33=-NJ!OO{re>A|G)`s&SZ3ECSbpg0|#)D_3mEsA5+zXM;a2Y zXlZM&le)WAN1U+5Ym&9BqZJ)K^^bnbdUZWFq;NMdg>YM}|=-J$bQBSDL z!bOcp&WSAH*yc?wUQyr%-D`;28W+SZT7YhIniYXtphI9jZoJ+n5Be-FBi#S7sQzpN z)t%XG;CxS)D)n7UZ&3{UY2X(G^n$j{W{dJt4v$EN?r*m%(4gx+**x0iD<~}Q! z=TCTq!L`hEf}nceRLwiwu@84@kJ~q)3Bd-Jv5t{tgHeWn7oR6S>Cd5V0)e=xshZ!+ z@0wpQPMF+_-Dh<%^x&-xkTvU8C471R(e>_H(9Z~m{&Vpf*yTv04|c4WWA?|f%kW*U z$fNR**Xu8kVnS*;Vc&$w9C%|6?%Ox7Rey_Y?|R5iNy}bvtLSXj#`c>!StVjv&W?da zgWSLZ(>p^}L}%l-os=i=7K7{sOU^E~Ik#-)#ez0zoK*;t`IiVTDkjHv*@P&Xygzh# z73kO|K(4iN$;bnRYPVJ^fj)l%#mYi81Cyf*3(uqxj8ZAE(2j~zI>>d9C;foZNwuzQciPM9spj6cHe}1q@dI^u z!{?msfx1^G@=gYooo_^yz_=PnC)V@Sq`iF=>}#{%EGMWW)3Rd!TU%7|594|`Bu0ae zqJ0vutgdoO;ByB~RQ^dB@0pRU%svJY()&PVA{4TEkA>lZvhyd0s$3R*g9C{{TV`~B zTOr79>*$kTwyS=eEUcEa}{jNy5&&Vb@x*u#t>r*5RHZe^(MVPIx&S)M2 zE3q2Cao|M??`E=#dW=((RbD&V&T8Nh<8FJl>3#cPRJMG-ZN|E_2|JdZKJj_}jV z@nSb6;;pO8>8G8#br)B5=uTM;y?zj)!I&O-JYFdFo0DVW=h5AZH>e(56FP$6+?Pc> zJ`H9{E|%kvCE&M7r+VJbF@ztCQirzEQ` zSLV}{dZ9TMS>7ssY+JqB23^gnJv&fJ4?k)(W~bph6H^1PSA-GEi{EeT}6pH29F^Y}`!RCa9~L)1gNC z`dhQ@LqA~qxC}2hI0t{bHQ6ys1&!|EQ=z_ias~5j2Vg6?df4Sm66a2U@acY&ef(b& zbmJF}OM6lUy>D!apH!xcDhHcdb=k`oi02G#Nmu)(;l56nRLWfi)-4VbC3EW6e!;cm zNcP1p-og}vlwccGZe93x7-^~YxSOAWwkF)KR;|UW%FzwnGNJbpF_*#>I59RZwF2f5 z6K8$_x=%2kjQLFP8hdyJdVOl7Wmsl1E*=@@C%NG#Fx`duu_$uXBRIxB%k1oyN~xD< z-Pq5M=v~-GS8Ah#b@9!613ziP{e4ZprCTG5x^V1?68c~|YY#SJW1MZVaT~Bb4IW^rwz_#v>z7MGtfY1K*KWxjhXUkgLY` zynL%ZXbL{1maCPC8tPQy%qblFe&HkGh00S|wD_=m149>6_m>)+`)mf(dOn85d2?RK zCgGD~&?)?JUG02~L-idsz}5!r$C`hh^m9=3r7gW>YIxk*+wjQWU)b=Y(OLP2)xVkS z*MVG#%ml{zugZ-9Yh>Dq3G<5-BROG9%l3CXb%K*HVsDzRP0|e&aF>kAUhEPg9_KcD zdWRgaACu*jK%ir?Kuds~2bCiKkDeH=hsf(?zWS6hHDJ%{Zp-T@xr!^AR=}8y_F`nC zCl<3I0Ta6s)G1Y_N|RB~VecoNOu$N~Sa>gEh>m}B)!l!=p~HYMU`81jyQ*yRqs%L1 zpN~7iSli12_?N$~HTiZ9`0wsNfd3}kZR+oLC@ct2gLyv*D1H2g+3|?Byy?En5mDC; zx=xti$aiHog*Eh~-a2+2sf@IdiKm~~UwwixL&6IM>kOx8H#u3~g7lfq&jWHt9P zo>P0aUJErox%(kz^ZWMmC&}%{wfYaZyJ&-A=Tn+Vb56i=?S|2F3yL;8h`fzO*LTQj zO76jAwT%w$Vw|EXb;*>j6v?{QD)6f|Y)>7JLK-?wb6D}Q&o>F&B^%kD?{xW~H!Q>t zw_b$|gT(hHp5HwJn7N6MfMe=c?w7mR3azvavFOrklx~wt<6eIr`6lym*Nop1=+&kM zzq$_^D9h{e5O1K-)CF6{v#2wt2Oosp^1XeDm9BA~!%oq4Y*bp46pBvp2w=#9Zf|W+ zf_?2+4EQN8ld&PtU9s2LXZW^yoRjX0z+JHQVx-lM7iE0<8w4@CYH*p8+^rum(H(Y6 zMJ_pa#Qp^Kq?!jsmqP%>nx1^7ese>OUunFY!OqrmRRxLquWm*CV(A|%_~Jri3?!yS ziMAw8>tC{@R6Ho%tm8p;` zTzEn9J+4TJb>8$LOSV4k&Q)$6_iEZY3QD>-)I!#+g6cofdJTsQ&%>`R-q*>2g=S_X zX0N{o1Vdrbr}nmnX-ixE#ns0GL8+-3pcSCFJ<{_pzvGu1QXb~UF{#oY+X2L3pdA~e z0rCbZ_W_cXMwqT56tK@&T?XvmyDGoi4GU0Uy-V+ zN($lS^0#^#k<}Z80*9x<8=ofj!<}0P_GKEc6TNIlv?)%MvY@=FGl6BA0+Rj)p#vnB1V|mHlkM7NVx-Zx(*qr>+@$FG zD5N56wTUNae$6Gt{?y~;K{(Z6WVIpN1m>1r=$glJqpePU^RMT={W8gk+3?aIn*4pu zQRFfq_&CMlC^4&b;9UBN$}Uc2s*@}4rtTqD5wW=i*0^OF-}K!vaD)Z-_wcqrRc%Z> z&#pAkD~KsS<58Z6zI@&xL}g_6N!93mfjyzGJ6H?iSIfj)FBSSNE}SOrS%73UtaT8bEAM9Sj`O?Xuqv#J7LhfEpYsNZQ)F|sWCpxXzTT% zSC@VIbve2hL>a192IQGDn&c8jd-3d%YMdP_Q;YWb8T?`!-2Vu<-KTVlUNYSc|HyJd ztMzgdXy4s;xGBzST*R$D{gCMlfU}#-oZNM50Kw4pt$GJn z6{z=CQ+1aDL?%1sl7b$R$YB$0mr6%Xxm)AuQ9$`FKY0XS#kVn#L>Aipj{Pjpq zaRpyi@FE8-d0pXdXrt@rG4gRA{ML-IW`8avQl6v5#`$F#Yg@*h?Sb0)KB>4e#Uoh~ z5t9=Q{#TiwGZ}qwaAZ}YXkaR;X&GuxJi=3=y`*;8`_xB1ZmD#&$}doD6YWL}(e;Xu%ZMV5%@{qx%pOskDG2G@!P{0G=X1o!06z`bvuDSo7~2pLoVe(MNz` zJLU>R#)kh-f?*W_AQ&6~f}uk0U!lMwUF2f0Xuz_}tEXzvJ2S^u7gfr>m&U zn^yJ0a=?>_O+%(o?Uw!uEolKFZWPe&UVt%D*OXamZa(b(#!9#oHg2ujFf8z7M%@7< z*#__eOWR>z!_ORLtcQGkm~4Ws2iqz3pEq`xPy^jw&S;!{oT>@Kn|#agS^s&DUx$Ocdpx3abAG9HB8igKL!h`R#Go)eq=D53!1WzL`RqM{*9=E71L- z!53|d@s|{@x}Wn6Fbj6(Xh8T}1Lp`Y^0vjd9q;P=CxPVQ`qfHDu*+Wz_|SVhuk;$6 znw*FW+q~V6QMsY}63bs6!ZFC!fHVY6a>ff^M(%Reu~0E81Q%-@0)e&yYI@!6bCJTV zxZ<4B>RoQfn_`P(8GhrgsR@h)zrPSvZE=|Sc$eK8)2ho%n+3*Q=_ahM>>cvL8X zVq22eB#+vhTT-drHGnc-JJ$W{sa8k*IeT4r1O&2jR;@)B?ND(E#UX{L-o;`QP306S z+T{|<>)t7t?y#87=O(8=;jRP4x^Fds{c*w0R`tgzLqP4H(uL}T_UF_)swo=#r=zt% zpp*SV^}ELpxiVki6M!-A1$Od(J2;I$h`mRyuNeR`JsF>)-@My zS49cxcrV#Bn^(>9Ujyp&^fcM0_IUx*7KSykj6Z_?CaIA;BT!!mJ|40~qFp<^%Av&;f4gOseam)A0nH$&|8Vapr)|kvnQ!Ms2`+nZ zr?|H6y-5xn43Gw-c%9AXS`6yRj~Q>Zr@weLf6OPEF~X)Rqg1bc4lv}V@(P6kD)4lY zjoTFFk-kA-!>CSi*j(P8F{@`^&cf&9 zvTRuLaagf~FT*VI72p{!*w}fz9DQVNecA?H73G%7xM=iN+%8J%z1k|&tyB{l2yIZr z`@}~4hQ-f+s+pD72H3TxH*O^!O4Cz~zODvpU>%FYlK(1H+(Qo>K*u)AK061!!TM5g za0`5>Q|)7UT~1)FOAqv!LG98f70N!7ocvdPi2V1BX|0v2)>W5#g*h>YJI8+X7&!6@ zE1fDgY3A?kFPRZKq6Ezk3ryQh57I(sT-vvR;y+KuVFyP2^%l;FGku|JmvJd3pHoy& z$L%RGr*1TI`YI7So*VSpAqsCXA0Ee!U3W?F0*JmpuS}w!P?0l7jE1U);-SfKiaKHD zM+%=Snr2grO)pKG)19~}LA%F}7X;V7Is)49=&GDjmAjpchryezUlRr-vJPO_@RtkI zw{|#-xXm}p!cZIGaE6(wFq^cCvMcfD%aW7HmbnfAqQ{d{G($1bpcZw1+bkQd64*1x)s!(-{bV^ts z!T0nHjkrq(R=86Y=%646V5`JYQ7|?lVzX!3RZ6|OPwEMw87nw|!=DvxuiO19y^W<6 zdYaoV>>K+%si#ColYK?<9ItmCM@!}p$8Vz=*Z~YRzBJw5#h%~;oCTA^JPbapokaQg2JHhQNkFtdO} zo83Tk!1Mk`jkAOOM!X-+v?883B63P?@N`JHn(F}y%^yegcLEO`>FDq8SLOY>mR4DD zm72fk^qSX}xDHfmP!(P|I3f@D7r8AkE%0Eo+`B@5UPF55EI-?9mSPvi*HRmD(raxx z8#xON!ZVMA)E0M$e|g5%@e-qXGk2oHQ17YV*-jJs(f)-BO8t@19C~_ldq(uqr1Gr5 z&jDQ5Le=LP7?QiihTxd1uXwcCDf+}lQ0d{j*mMbZWz_M(yNI7rNEExIcjd5Wtf6Ed zc&3Qc#@&lG*RSS{(v7My1b)eCR7x z@UJ$Xewi8U325@$QNGKqe{|LO$EZ_^)aD!8)3TV6lUh#*3Zj(sVUCG^t*M++q-M&) zGMZJ{NVUXyW2=pDbjl>=6)DkMRAEC89-nosIhN)Fk3o|I+}Jf<#%2>!D<6XfL$g4! zb}y)TD8L z)=IWSZ&q;F?ZB5Y_GI+h{!zK9o1e90@ykjW8|qx1b#46`C0}7}UO&k79#D$m+VPG3 zB&jSD%E+j0IhS&;swm6KtByTTUWv&XSp_P3s18}NRuHL>A$RtGQ(L^m>sol2E)TbPn|QtlS}r!;w~s&9 zI(Z0#d|p|JQlER*LA1qt5C{%0C^CaRISR;32E$5mRV;H4_Mo=btiT{-;ePj#aFKxS zViakonLf9t2`qYUci7^SdHsV8lLSk?myL@q5PJpYBtiwIvNuJJ7qs==n+1Q;e^tfE`2b;b`#g{+-OFQ)N5^~z;>2G-&~V+(WtzNzxuis-zv=cNLJKX)L>f}=ZoG4~Jxreosa$v$lbwaMonq*{N zClv7aH*f$3DW?EWI7vyc9Wr;DGNhvm03JIajpH*7->5INW)0O$wd1Dv*5OgYbE#7b zQc%&RYOh!|rna(@P+b=_r4@)HWlrEoEIo(!c(Ud2^&5r-@nX$gS^i_s$rG>seVb^TQb~Tk(N`Zr71#3_E1vwWAjY zjN}=+9;}BDh7S0imJWHSIik<&l{5@5Q-3CxU!c2n%0wIF9GM@ktBz#d5muG#Rg#VJcX7)&cW=gU+W{Bp%zuQtZz!Ys z0(Mi#gN-&01tYTR#s-C#i>p7moLP4@uy#WH7w0PzT08Q(DP;@TcDA}>Xmsd!D;ChSkG0X{UZFQp31=xT(f~h^c4RI zQF~0hbeT9y&EhemD+8+)@I#|`U+%IYBtMq}XvpUsy8{%H`9inTZC{&Yc=<(=KVLt) zj`t3HZCpsKMote#&4q-E#w()tQ}$tJ=EGqmDVA*b8G9G|spTtdEyNvKcyjf6{$h<^ zi{ut!?XhMshq*Y1Jt|$!_%CO$TRn!=Ay(%`Pqo3rlO=6FS#>$P zq-yqKKuJ#NY7Hsqd$_4>X`wnq=%D<2TAnr2I#;CG?=#pU?F~y*Qk}Ud6Cw>pcba%w zcDwEzZM<>$AI(jG6B1W}V&6(t=JS7ryzMWPy8pxu*VRe~ejm9bSw#VFq*?9lKpUV8 z09E~Fg8w(9v;&N=_Lyw}nOYb_6@W>W<|cq8R?!O#4UUYo0L1kZ1oS&|6dU@IwB~Q9 z=t(?AWoK7qzP`+?;g%g}lxCl6Vvc7PMZWSyMdGq9PZVqbY6v}mSfNgx@S>_Ylz!|D zVkjnRI5#9Z3$ACfFVM~zSEOQfTL!cn0(3Zd*L*qg;rkB2hLvsjR48{B9j}QsS7pR( zzL|vpO2`~^!{mX-T;s5(nis@(u^URipM~P6a`usq!NJ2<&Yb#*FRxiEe+^@AH)AF% z4DRNae zzi9sHax{snLd>rvHPxHdwe?z3xZJHUSoh#~*n3WMjD23q_5#%C*gMo8pw65Bpv3CF zt=kjtr~>MLi@-DS%sN!;QJJWZZAy7YPf-KZm5ox|iSyV1`CgcrjoQ2#WG~%B|BZab z-;9*^J(E#;iTf$h+^43YK|je}v}kex(Gbr@JXM_@`qDoZDHA)t6JX9Iy(^)mCZ$tu z^UOMzO*x`9$$trsR7kD;(_Jo#$r!q;Eb*U6yHry*O@k)Zx;93%J2^h=Ef!pK%kB!ghZ^(Zp!ZLv_?hoKeXgOO{Pv%9vP>2tY>Vc zWF{INRsdzH*eF_n{h!zxxy<7?MrNgfoI!6|P31!cR zxc80KT@k6^=w`ZLX3<_vM#U^eEq($1%p|wS6j2$ddeNy$3ywINvSfFu>RHh1kvk4t zmFbzkemoIeh#c%Tcvc5YAZ#}wD>4A1^Hpv;k9fy@@R&)1F{0JHZ-7sIBoME~i(w#fqWsuaZ`S(NrgH7~b z&Jq5{Ebs+Ym}jOQ~ zRC2TU5^`6o7MNt{kaZ3JiTC4R*_I?`ZCUi}$Ep&CInn$=w^2>V`0SaQ%V~HTw3tSO z*4e!-D=Rac{pC!!vs-I#fV6Y*s62OW6G8iVf%I zKXaymfIgpZ(*z0^TR?v}urk?ZipjUb=9(*_!z8UtObO$f0;EvQ2LVsb+cOvQ>i$}0 zo!zWJU@-yRz{XhLE9U&G%{_7b0QPy>ckI@wIzqEds|UwVy(s0&(W8ddi=8gpy}$wu z?eDBOYShC`KpoNn1s^=lyD?l+wd+M8x49>7Ss$s|Ch#vTA8TdSMz|mCpf9hW`|IeD z6m(*H58q>?X3Ag{2$dp)FB;VW6_!DYCNT6OdGSm7!japkS_OHB+skKa2$8dDub4<> zZBG<*?Q5guZ?(_tWIDi~%BuTVukv^u1921R>=_z6iD~H2UkOIN6cJzdEhT|Tl};>G zeeCjW?l%{5vaWgbZ1sefg7LY*lY5epX!1N$jDgn6q zN&_+nJpyi{QTb*P!~n;p?($s3VXjbU{9_zBfb$+k7plHY{FY2K@q?;RURko^T zEm+5`_Vpu%GT28CMLZRrdjG(>5C=nCOAMpR7a=idlmXc*05vmtY63m<`9Dmdhf^sl zTb|EJAo5$Mc#3q{PZ3N%PFT;-Pc68ntJSSB)=Tc4nkQmeP;1K@$v)joJHty{7%3PonkOFc;YMJJ$sHKM+z6mPgT?6Y3 z9w(L^9?HcNACOu5mfn{C6~f=tE(Z z%%5M#4=`m^J)-p`hJTlK;L{8A)LbwDWPltvGhYp)MU6KG01E*`yPy8cG4Fp;-v9*F zgCBQTlm7rEUZMp7#X-X#;+lXA6nAiJZ0v(z+wYW%|9X>ejx^^Yss~eymia2-C{DM_02Ha$VT`092p8SRIxPsPP5nH+Ne3H)mgHhKFHBd2AWHD@ zgiI+dURqTTycsiu%&Tl?<}DnA0T?oDHt_XplJy+1`k*UwpzgzTMA&P&9d6w5s_5;+ zQyaFyJjs^b!O|hurOX#lq=@*VkI6oTUE$D$q;mr{_R4p^_f@3motkZ?4NTG0s_m39 zvsdPz%?lTQh;yqYk+#F%QQ?bJ8D5Bs8RR!QIeC9=fB50cB{ zN+OR98lWh(yqAvQLDdnP-wi}{i0WDQt5H#nM#&l)(4v8G9J!h7v2g7i<+ZHR9-+e5 z=Or3a`MT_AEJ9`giX~p7#3xJ-U)ioZOG?`JXOqD?2xk5V4Q%PqxxBQJR=qe{A)Hys ztrodQFL!=DizsGM2#Q@>&wVxc4TM#_6`TKPDigW|_qHA@zdE{i>`52UXbdF0@X`^j>%)((=lXZGj2whf%Y*uukE zy|tXdiCICLKks6ig<}8695z&%!HfU0YK>A*>itKGu&*(;zH7HGOhooQmvjv(-gss_ zT|F_Rw?>sPunG*m#kyESFl=S7rKbpIX z;i(Fg`%#Mz^Fhc0UA&`yx3yk*8j(oA5n@Q z#fN|Bx`@Mcfpnr4UTy*!5P?%CMrb+BL}sV{+n1tu(p5hB2Lk(_aWhPAxt% zUgfxmUlnplONC#gEP>B=g-%iesZEnT6}5pduwK?T;#!M(H(i(Y2*~OcCuPugWmz*3 zQjIQ9fA%2u7IatVbK+R@&rAiXPG^I=iSeFW8zB~1k*8hUYG;G1a}xTXPV^rBj$K^F zv0r9ZFh_>>n&hH7Y5LKHp7CHC=<}fAJ9UVRtCGS_xJ`p@-YT-{S=&cSz<~tw=f8z9xDF|gv^ zeUlldXyTVmFktMJ|3J~T5JL^Ci+)xwKp>A&;AYHPNVRnh>GZM&6mct}L9|2aiNCXFOig z`T=wFc-EZD!;U|1nfe(Zs%;iPgze^>_FQDyuq=<(X>o-Zl(_@8iswG7NKx>hBnII@hM%?n$3OV=ASB zeoQQ+H{HdCMg(P71nLKGeqxr{H8P!=rmPo|Z(MYQyH`27s`Zoof z=Dc3cfw;9NjR(7>7RP`HkP9Ja6OYk4FxVj|hr8?sU<DmX;MXS&dqE}*OK+l z|HdQ7ej@ZBb(^pY$8a>>&$-xNaGA<$CN1dqF4Ta1_>nCFAPBzc64^=u`!%Za{QDp5 zN9irXbxNF2SDpm(D;zkMgT#W?GcS|qc`V93R!zPYojN6UcyF~*VY@rL&$drv+^6-! zUV5WGkjrke&@?1{vPffjx#G(AQ&JRe*@OoXvPIvNy?fg9$;S$H`H^l`F(aMuq{=RM zn|A4B?p4>AAVVPGxCnOa1J||RgbHqKW3ANn@oyc?POK<)wyBe6;`ql?Coa*qCe{x* zUndJQ??M%}VQSuHeYZSR-ovwuR2vbeuow8bBLN1yAihDZi+FM0Jp~k-h&r$`-#~j5 zSY7NfbYUU5k53UE!gXLuh?I$9Xkp@!{sx>vHGU=XND}!+$%~|tQ%oOf3~bs0pP7^8 zUI%w!K{r84rGJFmB6 ze(pMV?$Bu;?(qUXy$T`z+|Y>Yb)Z_$b(G^43_Oj2w{o|D5$IRf4hS8X%h$%Lo}oO2 zIIAZ_ANHXR_t1DtcHj$|XO`bccU|9g@N-HFY9~sK+8pMGJDqRL%$=&K=*<%Cc47Id z6zirBM-_Km)~CT)bYAj@R5(jU6cU62O6V{5zb--?D2pV*(VO10`#2d(*#@+!;{twB zOcc8X{qDxqo?162VY|IuV5KLR3cYl-7LMw!CEK!7=pXklUJK_qtYbK^ccv??NgkF- zzow_ks{c{$JXCtKZ_T!}_sX{DFEpt@uGY4zGjm_1!wrcZOoPM0dl~_WoOQ%laNL2i zgCCicM>VSBa(3MJ(5E&=zC*T)oRFcFI|+=`UI(?jAT>?`rkqKYc6LX-fxn@)R0`_)S)#Ot>POZ&I|rpb#mHz!ocXlOXKDi zGb@!#1eY+QaDBW#FKf3Ip@ihk;JLHQwzA8Lt!!C%8$nLkfZrf5n$Pe1EsgorO31kU zrgd6ZVqYC&#eJM!7=D+pwXXsoL`gqco-R?Q9js*e?{yYAobTX+wOWDcze@y`Aswu> zjl(nt@Vn7m1g6sy*Y~r}x#XEz5|)t;Hgi2tVw}O7urFTJ^9KO1@bdK0q%yRcSGAuj z)#t5=-2Jo=H;be_YdQCk4plP`wlF`u>o{*+tuij}&w;}bdzX;u66ZcV?LA}7wFB(> z@x|>tOojI8lHe@T+swsePmGv!wXqmqNJK_~H=^7MD)NdIb_ufQUl7n-+SQNk=@h|* zibl*}UrpVCcj(?lf&Jc%Y^V2bDoN*?klEAoj44*JBkc$GCiK~iR4`L`=SHYSl2e-* zjbuDt>SE0tIi8^o(Rholzj!5)Tv{go&00AkZ|v>s74IW%(;Fz+q6hGJg-3|&nC7w{ zSKL1Qm8&wnfsxm^txXwR8k6beX6sU$_`e3B>26snvPFAaXQJuNhJ28T_7a5fwg-kta|kH z_psyJ-Re*O@_L4>;6Dqz#H&ky(Ow361f@LJPNq`(Dk+TgL3>7EIf?xp{n#U3c6EOe zRC_AsT}|M17cZ5*3MT2wT=vH~`3i11=Z@g?H2D)y5zK7jPMu2EK9Xcwv46TT)HU(Q z5uCAmJ~631$O3FyVm;*WSQO=OnnfwNR#L$})pz_l@;-4)_^2bPwuElxoa;;W0ylAz z)hb`pCLHg21;6rAb!RB;?AVf={L@A15cv8e*)>+CrA`23VE?3(pXr8mNe`++C)#J;>9`VJjNd-P$2`69*-R z>KX0*gOYWpZvd&UBYyI0|B`ia!znl}RPLNs-<*0xOvoq=&@kCYxcKSEkUF7y)jJQx z`3dA=9U;-bkY)}<(PPbSpH42a>7!PS8^Vpgiw?6V)wI?@&Kd*lIc|p?=5oMoO-mQHQu1imP7ZaZU(Is73RSzu;iM(AyV)uH29^cb?uS;dzw43vxg!S!nk3^7 z?BTO-h4#3i_!47(H;&!ohwQI)oKwjnXIJgFM`L@2id2Uf4RlC`^tjRLOL)LOR2R>xMILRTP6KTSUr@j;y%L^mc;6 zX7sTS)Ui18f*0eewqrNZjc?Ndu2`HNugMOA3 zM_t_7=ld#iKWeA1-;?Q-nvM}v4kveU{6@f1NCNn2eO(6Qc{?r1I?Juk%@*@wf_BTl z0v@ILy+Dv7A_XGPG$5}AP6*HP+$K#~&N8LIE6Yu77nmCgRLq03r-EgQnfvGn1GZk* zW7l-anU3j=@RTrH;Yrrj#veqSb5DZSU=poYqibPYg}8(qNGmAnYrh?srW*IW3|yH9 zzq;7)aZ+@hcHX52z(;#9njW@R)B_B+`skS<=&L$=d}I=0XI;M*&p z&5Z5m&O0LLZha&!ns^<#zcDQkKR$w5U-5sNL2&^?v5yv7k^{uU=?n*2yib-tD6MO? zQq{-ndMZ^__oTy5R*5_P$#=@~TnCF(Px2ciotEt~7)lH{hNU~R%WRVdX42NA-W%A^ zqjKBc6`ol+1nj-fPJus~6Mo?2jc)V_$nIHRpzYb;d&NiZ^nEUZ9MwCFE04$;J%{FTlL&AlE8Ams`;>Xaf4pj z%D5AIZ!x~$5}g_0Xr`wEpbTv8~Upej5rE^N% zraL5~RbxVL*XpmNhNzy!S4;4bDg@bkL2NO-`I=jA+UTqOGK4-}a_H?%l*fx7I;@d_ z9B7$hic9(!I@Il=xjeGaz(YWP1~1SVi#$cwX`7~cso?W+$n=t8EHv>l(lUp3?J`}- z#aO&TK|fn8W_8e&Q4Xi7ycb3;spp< z8Rg;Z72CYtBeO=jEi>Od!sljQM+cPnQ=>68HK7V~uc{0cv{S}d6;`bORm+vfL%sg{ zDZ(k4QAzgo$f+o@)MOh?2gfo}$Py`(J%!0GlT4?=5R$_v`#R2Kh_NMQERlVuvM)o1 z88Mdoe0BTdzFzlt?>+Z*?_a)VzVm&)-|zEzp6By?-V3ELdNF=#etteG@ZN9Dg9Gw& zU26($Z08057N-nRZ5EgI00IE+7wJU!;y6cpHzjb)5V^Y1F0(puoEjt;y;vyX?3kv3 zCBErhh%X=Mxfyy-S!Xn`p(>D7t4XakoBPTty!%%br8^QoUs)AEZ+5)-Q8Qp=A2yg$ z0JnE?`ztUd#olE*1zs)R%641zp)Yg6t_Yy&n?nOb?kJqUsBychqT0{WHAFzUHYGF` z?$@*K%;rbS{xuwUhn_mDeRq{OSK5W6ns&`^(M8QsmDlZIH!=?2!%E(I`zA~Zl zUH@Em{}RBFxF++087q=nCRg=dZw(yt094A8c1N0Dt7+BPmy-NO$i(zzpRK+#UKJ)V zozd}-!JudoAc_EHCSi1AG3Z<7#$H?d#do@gMYZ50_f#tPP3-XdeO5$x_)R$AP>y%k zE^{x;doqzzGn=PZKbMcnvwhh&R!uBebUl0Ln!=l^n`4m+^qv52K54DLG`)MhGWK_* zvKRdOwY}M2$L3j_xxJ;;L0=RXCcjAWi5O31Wp4H>72VZe_48Il42ks1NCnZV*-{!8!zc}0apK`s#t(Z-1T8rOYXdWICVJcLjb)rwK6}Uc@;4p z9ny3>Ue-3l;XId5f7S*$PceDM)=S+?PhwMwPs2Bx&-k#g?tfK zH_5YSfx5;*lUfXDfgG?SWnhK?C1FpfLjJ!KqyERa%POt}d*VYE2^Kci;R~_j&dl!k zu~cFG{mj}BKdYd39s z2|OHCl%kWyQo5{^y>W`rlh0F6J+zur0rTc&pfqF5tGvu)^v+^%R?pQT#ncD#fR4BQ zE#QkMal{)l-uMW9e06xri?R5;^4TYHHVRGK!kx<8!C8U@KPb7SKn?_lnRU%@Fqrltk z!$u0B$uP$JmgUfl&0=|*W6E|2&2p&B?nr2WoDFuamAz19Q#Ksg>&56*3EU7PT<#2j zfD~RnH9T!&lk}If!}xvn<(^P^j6t5|Y4tXu`QR|p*Q;u^oEow`P!;QR01Z(HflLk* zdT;BX(6&wv(wu}-M04TY5gYz?suQ6l>YUHVqt_SKu;>J+J3oA`4W|i@vt`x|^DKlo zeuRfNf^bxd@nW)+O52`%ZDMb>|3?Soad-gOz4=O&I^JiFAZ!*q-gzu#J71w}fTsN} zj_wiMVPs}(8AHe-8z{=;Tu8i(8>g~HS)QJSqe%h-ys%mxu%OJV;r}ukawh<8La1`1`*FO_(fhZQZJy7S8ncYQ z0Zi%`2)UpB1_a)f$5y35at@B#;WSf+F!09CI0BSLWDoz`VsdXD*&mUlFzG40htGeH zlJD}GN{H&EYUxIE4j;Ragos4O%paF~0y53!&u^b#8_u#wk-C~+1k9%VGMG(Ub(hkN z{M}uXR=aQLBe#rwV2HfhF^fsuCbhisz!~vO3eodUB@y0dA+9o-*f8Dn=&7@ zG+@w|lh2jB(@6al^#C$9c$B;7QVbX^k8@F$T>9F#^PB=;s&x-|=hxCmT+^l&T-OWL zzR!BZf=#4~tgmNew;~0g|J@_Sl}dQ`4q&k4cS{r{yP*NUFKZ)*qgSA0f3wLhbCGyc zCXQb5o}FlHyBM5Y0+@bc!Ul*&ZnI4lN#V4_>OW06JPHdgcy(&s)^oTP@0YQ>A5|}b zEw?S5L7;m)BHb+mk({tv))P7W_g$CZv5j%NwY@5<+(iq=4u)92QD2g%NI zvBseDh{ooKbzr@;D#)5(zs(^H72P-o!YE8^a18Vnj1Qvm{$r}%f6X!)_+;nhPJgoz>YdjH@|IRDBX1h#k6Am%RoGL@%T1DM{El{7_P3F>hkt)r zh8eIHzjRUV1*z9b;)bOMaKWs-&CKjn*bd0o;MQ3BLa%d z#gLa3a?^t@$kqX%)V;xuo3Jty5n5r&8@qN#v(_3TP!}dVCypjFoW9eh^4G_LNe9r5 z{zE-Z9=-QHbbzAF}${s=j(kGNw!T7!lHa!a5doJ(F^tfGyd)tIT*Hsvm zc=VJqZju%yuXmZd#l0XgK;}E&j64-BkB5m?XZ zCUf(T%2l;$5A*m=(-XQK=z?Ga(8rdP4${%L6MT+QsLS6|Q*DTNG?!{*-}t^k|Ec=-dzxzH+DHMS1;qzvAG;oCg!?|CcPPC6$|STs`>=_Rgy+KcIp= zuKqE>cuc1`<D(6SRl0zhoxpE>L;K=$Jl>=2E6?I0h8X=CGiGQtCz9TstZ8Sl-E39>VLltVS~%CRYoi3!QB4YAxWttD26iZrQ4^ z^b94OJMP*%iaxD))c5ezt(hgYMG;uBrru%nlZsd*U`N*qR`68~$08kLI$Q3a={F%+ z4o)_tH)V1Jx)_XhM=8MJTAV_2l|J_EK^?4&D2A z6ltfM0A>8CYFGx&T%#rckz2z6{w`N=0f<7(EWy|Hb8mx;M;!6p_A;IFYjCgfsorSn zCrgA9J3SMAy1m?eCNXCyb{P?c?ccdr1%S+rRe3197L>Ja9A4rU6WGGMYFKj^CL;?r z55L-_Ty&I=lWZau-8EP9`qgT_!VJ}#nz41g`tOf2=#ureRR4 zxtK=-)o~Pz79kWOSG*>$-HWmm#t+w>392emtl7^-k%m@dPv)z25xAfG)VN*+v+>kB zKhkj5nbe#j8o9bzmfjI8NP5k_p&VSbevnXHR6rf{moHmlyUiq8pG}X_^{q5y?T7Wf z(1c5~orzpI>j#0O+y`e8(3#Q&j)ePO-3?oRcaUJQE)doinJx7tejf>}JY)a&o-#ku zc+fBn;`uN8tkr##0}AqtW=kb(=fV61V}n7HAp;An(ZF#wWG<895!3*O)w;6Sk7z-& zCRxk(`XRTZB%5g`c1{ng8%N8DmVkxvvCiR-;DDoxcU-@2eE+3jPJ)tzHVh^(4s}j&=Apry8m3;m=oe5N{TT zeya)Qt^@n01HNH!I#woJZE>@?CZ6R}oVbSE%3-(@>@AjC4q&?`T5 zBzue-md4GNKzF4HRVBorE^--sgvYwZ2!y1WbG*)OI>O;gA!ZZ}1UH1dY@x?J%8qA3&+49Mmx3KC}a9 zsBbzPE~$(FH}v^AXyS<^zGZmDadxtuyyJc3Q(D8-`Ny|01b?&4&t|-w(N!Raar{gOQ-aS(*kG)vcp66!Lw%ISrCIfd|LgNW>*g@ zNNKQhvwX5Z{PdDnVy)7CisM1R?yu(`G10OiW(PF+2}oT@ezQnEq#L9ff*z+HkJIPj zV={r=qp|Zo8I}6`G6B{H>I_RY_DUNFVYuUV*ox3oUFSr}{sN~seMF(RMvtInujS~x ze5a>?U-`x<3-QZD4}y;1=Ola$6hZQ$rKCdz#)x6hmM`>uBROBzU&5#}e7*G>fp}bh zJs|t&&sPZIuaW3D-7B;Hi~bhcQSR-lEA|iZPvD{s)am9t|L;6Z42?&!_!|od@EBCi!?`rv+dh*&c`>ycHO>3g!W6 z9q9gPO(+~Q{^3rZy2PGzYe@c>(;rh^P_@^KHiTv1##r4+# zMahn`Y6yUB zoMb!daCNCkFH&S1EcSY#z>I{V)yWuJ?7&`xJ+WIpG?nFj7BpPEN4d}4<6GCO`zm5x zj#?rsub2*>Y)gxBj^^2OO+HFi7@ykO4~n8!eA%8)wOAR88PRfI%%ciUuj}jTTghEw z<>KKrnW!S+d(@&!+SxdlHo!*J|Gmd>TD~j%MfPO!tl{iZkbO_v zdE(9sbxi9Y_-qx6Iw3TKK8xt#F7F1G7`9xWzipdVd*L|ww<|KFc=Yd?zRln3?=ot> z+@bdrRnM!zT>f+vbg1ZWLPlk3_qZlM%W>Fj?0p%)EN()oo@u(KnPNVAp+6P{Y;Jcy zhpX);ITuV&D%QcU3X`Ecmh4!`c62NcAuGl0Qgw^YX*y|d zxj$+xQ7!)ySqv0(z7QP`ZQhQ3Knd#aGCrrlzqH)$_B?B1=`0lX0l#v5Eah&S7~m>5 z=c=WL7^ogm#)}?P zWA>#V?9f_#J*3o diff --git a/src/DiffEngineTray.Tests/OptionsFormTests.WithKeys.verified.png b/src/DiffEngineTray.Tests/OptionsFormTests.WithKeys.verified.png index f359fcd394b98fa38c06e18ec0aa312cad46bf72..605f5968bef69800caaa5258e109a540b1fa6cbe 100644 GIT binary patch literal 27850 zcmdqJcT`hr*Do5kf{M~?s8q3_BA}vxv}_aw3$PUxkP_)4B%vl!LKH*-D2S*?6BU%L zlu#2Okcd>JNev`~fG8~_5dsMzB)JRR`z_~=JH|K8`M&pzasObfWUR0~OG{gV&0D=4<=grNo-f>~le6b#Ok#t_v8fvlh=2zYi z=)Vu&&)zAq80P`rsB}=z&m^VG@D}^%u*&6I`_x63AeNhIrpL^cWc@Us{7&2x34js2{8I^rXFl6#TRm0jIKat z1$mVXwpEIT>4I=ziQ%uS+{Yy!lf*nRkxv$n+qEguBby`UKcj&S>}=$LEA=2XNbHy0 zTP&yL=4?ctJJaAqzB8v!pCk(c6)UhK#Px@R3|u{~zfC!OKZ1b*f$r9px;A(v9mWip z&s`+V>$KOyYk_Bv#_2?iA{hjAE|_by2NJ%#7I^gh@=uMvicOrdI5WVZ1_dHF(Naozr#DVWUSl-*dmzAY8XR;^&tEd-T_at54liy*+@cO z@kk^$FY?RsH~OODIEkNu*4<@3bHXSoi>!S{ZVl+>4Kar#k{vJPiF%Fij0x^xYi3_^ z*j~%o=2v@$gC1m{@vR}8-umaxdCqvQg@oDnBw~10pJcLlDkxhQve=3ab(bsQ41`kE z-Z0mI?h4;WwFuB&#HDdTJ3X{Sj6~6m?{H8-f>bbEL>03pjPPPS1p97K96pBTlk@q^ zQrTgD%ANXMkz>N!SqK_Mb^E$xaO7M7uxm(=O8fF0MBw{b%`LBjGw3;E0L5}Bscl(C zNJG-Bn7FmW_S>V_aedY@WPDgL*#`u2dO;PBBiojQU|m_#!rJEbk5pe^Pm1w->QRHE zkfk5uy@tbZ&5oj;B1b_Ez`1s|&VTVtUf+q0o zsl>NqYe2s%0@B0)XMndYRLT-Y(IU9WdApuV%^msTG3I~+bBM`e3)rmA~UvXjmLSTqu$q&{GBS?gkjbQ1^P*vG+9u3l0iQ1G&VozX`UL(9Ti zMS>DO&4@|z<&o|*FSAq|-<_&Y#t#V-T*=mYIR7B`Ebjk&dQo>jyn77lus zHos>yL||fYA7@)`zLi>ZA%X|Lb_ znK62p<=GVQN%Z`8n|v{0IzZKK&saEJ;F2e$+)BqJCROB6)ZPd$o5}IH>%kqRuAf8) zS>na2&TD$YMVJvpFh-!b{754Cu?9YVeI&qz_6;XjilY~QF3B?Pc3BCc_;VCzoN`fW z_(D>KPh;zXXi=n)83_XU--w*DizL@@Ms3>k>3m&IJJR$ReR)`8yvwKp9?9-(%R$~2 zmu^(nGV)91r;4vPiK+C0RDlcarBIy1?qgnu>O(1iE4AUUr4=ckVN391I#C_VTnJxN z5&b$XtGRv%rJ4g|7p07Hm3VxqvIydDfVUnKr>7fej=9-S;le)9RJW@3t$A*B?x zIl8#lCJoIci zcwU$DPFjX84yYFq7Th`G0`PJA?Pd}@HiJKmoVcjP_NA6E${GDDXEkCXN1X0i-yjE! zb^v4CH46f%dGi?%J^G#HwVe4L@08MiJj%=I1T0M2;y4m~j5NpBu|sOS^Z0vVp@BjL zz!aryh;C^{1D5D$956V0Obpnkn_Haa_-WbvG(S21Oc^i+2=S)sleD^Cw46CG;P9;? zH4I?YKL7V!2OQ<9s;epSC?7=-Xr$&=(SWa9RS4sHGK1k8wE+ZD_&um`INI{FrmA_r z*QxBZ!2-Pf6hOj}ZMTXHlGTpuw}$A}xTN#_T(8$fj5%uIHknX6z`>^g=06&b@7bhY z_fzDjD2K~JPX+=fW_SDcJO%R^sytXG3W;yXBi`^wD9lYz@Z<@tNLahh1tRPqBOl>ZoBPR6aD+^<*z9< zwyxCpb$7onyAVQ1 z!w*Nkz;viW^=Fz9W(^QTZRUC*ut9sDB7+h&b>v>$VT$2Q`9%5XgD5ro4T`@#soOsY z8;}L4GjatWLakc2@rS8|FmR!iLV8!gXLDNtet2V z5GXNgJbvqDb>`lr>KAzA{sO*Ra#i@Nde$O$_VcGB^F2II5+uukZTIMJgc56K8`OU7}kG9r5u_5Xe?wiIt#qO|FXh1(*G1 z9)b4OW>gTz>4n9q10QTqkHRIjxvD8ewP%t@grNE3m=L6voI!!p+> zNF#dNk?V#crR}VgIzgmj%tZa*ArrP#(ypUx+P7=Sn}3iy4oR=jg;l)JemD>Ujm$}M z7c&kM)CMElQhni-m5}@xrHs-LSYE-;NrYb~TX0>l$Grd{lQVN?nn-8s<#omii^%#v zs&Oe`uVyMdb8q|hW>xbKHrGn@|5*B@i#tTm6+rAnQN7)flm7k563O2pE#%Eldp6tR zFUK}NGgajhT87WjHAy@r0ccT5e^LKVdFaH=aO@-R{n^Ag`8b1_3ibh^Q zCmnNT%`%__XA*8G`x<&nbB8tqma0F*#x6(t^YTe5CNf55=+o@0D)h=u9A$*Z#MxUW@0Y0oU z@u}i0IM|@oClBKN2A*bmCz!gPZ8I@2H5aG$1m2mZQz0#bRdz;yQz|5B^s%C=U-d&h zI?%}4YFVTqni9$jk%?iyzm*;AIK(ldT*B%*k$q~=Gz*u&BUezvUn6n!k1YUEQF5Q1 zdzmp+BsoELF5&T&+Fe-<^tX}D=VHU_GOkh{a`#N)gSswq50z@$eSPhIkXL|JoB?N=s0IoTI@#fbTDZZj4lscb zJ9d$GKJ1iHCR6|D@l|I9NK-Qz7vOe=_{%wXKMwqoGg@$9fj+Yk=B`kx z_WNMM*CtbFrP{jIQ`Gki*#~>aqPbxdS-AZsyp(q3%EIoP8_4FnlXW2N`lsclmUbPw zQ73xHg;3fglNX%2h)jMBu_4hc zH|v&oFT+|gxs9*t2tP`H;Ql>sUUQPb613=rGaC~VxOJ)>FJ-miwQm`euaRyUJ=C3$ zzlj)G^++grF1N}JYt|t7@Cu;SUlKnjb{(3R&x;H46B%qlKB7>(=|C zELQ9w(PSS^Eq01+k@0N0?ToH=^mu%&M6!?aSj<4JgcDuTv`91>p)|%vPg~Cl!{bp+ z`@5Y24y@?v%-`C#uagH{f?falD_}?L?Ccy%bf5qZ&Qt&li?li(MmrpcLRkTTbL2O` zHwc$I6#7gexx%5t+l%Pby7km;SQo~w*glHmrCkNQqi3$d!hmDBe4=Fkr)nBbUxYlV5I z8u>A4TGxgCTaVVdQ`>can5yPXPAp|)JU@OeJF!R9fp_NW-bmN9K7c7mVDbJMjd=Yrq9Ovwj!SiJp3h$KQDtOr{T& zKRvb-oXJHJnWfoX0Nd2f8i<$Eql>bGGq-*+nyRK2E%+;XP#nw4rn!OwAI%!5?*tOS zz_A(?4<6#IlvM@z+wTUU^GjqKM@nRSdcry0&OP1w@bog`PyiID?Caej1DRc|dTaZSV^_-Y^z{C_G>yN)2;Ai`WQ)gWvl#n|Dywtj6 zVFu+v)R+Ry8{B!@Rm@Bb64$!YVyJ0D6Q79$s;Uv7H4Zx=k7`kQPT5zkpe|YbQ=?%$6PLiyr@kL|eRT@hZPuXjxL2`#SCQ$$3A{@_ zx|8-(K0N2tSZzpdQ*${3YtujS=&2B2+B5%%@p7@F@W=E%1pc!%QpZ1;Sl(FGGN%ouo}m6)B6ZtKV9Ig-d?X@>S-N3Uromo_Mpp0K`Ca79o#V%*MsZ$2G% z8#+zZBNr31rlVc;+iPXM_vcMyaLfGZ7J1%@XfJ{!WNpX&@%WSt>S4$C>v+)=J5_oO zFC!GxQD^kd>snU27%|U3TN?hIkZJOI{yvg&QREoYv$WOj-PvI!T1~PK?RW>mZU)hW zJEjNA_+i4=7dA!0Ym@W~by0h)UOG~SwFR#ymxqd#OBTkT$Hird>r4a3tsd!2C!lAw zC?rFr`8}xRC{tVvx%N*gIvfhKM|L5mi|1b}=1Jr^90*}GBwq7y?qZmKU=NylnhV}Y z3HouV)jRxN;K50Oj2@0wS7$E~em0L07BrFHllPi@SNC<*w{=k%lMQoTrEe6HxzZKK z6K;nE`4ggPnft5{2H0E;FC9SR#Yn+rjk$sIP%=c}y!d;N;Mo#hD(@Nb7%eoP_%7bU zucoX9mZJ}g{o(5g@Ae?!hnq$I1F)q}j#m%vrH))+$3}5<%ao@Uyq;f<@qQ3Ldgr1*PtQ5Elg%UAti`VJJ{{CJyFR(atWfsSa=V}G;wMqCRnYN4 z?|LrRPH=!jzmIU3XvjA`H8}A$F8bxnMH70tH2niBiGD7^C6SdyB=dTYw^yYYUmrv{edYOOf9pnFjzKY& zUN`SK2G_&nuF9KkExVo{Qmvg$Wk+U9Is9LR41GQAo!JhirOxm5 z^myS^l#&cS+v{+e&ct?wFIn6(Q~b2y#L2Lbmp2DI^A=F^9pbCvgeCzhE*k(R?#d)T zIiKe#Q{0_4Rh=m)WNI91theL~bLn zdy%>eC23)(oxe<=vkRr^dz6Ra$>FQE7}SL(doEfgXqlTQIyT`SQ6*GG(|Z~9J6Ek~ z=JRocxX$L*@Ku2;&ljCB|FfB&$sAJ}U(8BGDTy=RlVgwl_o3kbFI4@)0CNKE1S^TZ zREFjU=ygN-3dENE#b9rgjLhu%*D@v6ppWkX-S|T7c*64gsfF&gi6C9o{g}<}Yr9Hf zUeK0;F@N}DLVg2T$Bf6XU6)+taAX`XoZ&tFt-wd<&OMlhnf|;p_oL1fYz6rrK4JH8 zi+NE|QRz}BL#@;a+xBUblGW@DtxOADCN1S0$DmpAxu`4ASvwHfsQJK}YUPMB=p(XcFH?h`so3;+> zA+)(kt@MZ9`13U&r~6LY0EH{nx<%oAl22M_QhC2Gjs9*LvR*3MGAC?kY+cr?NejVi z=6too2zP)KWQA?mVbs~i>bLxPE*}j=G9xo@4f<}gZ1l}8ukCsgS zU^$huQy6*L({+c{o+4u9;EvumZhyvn-NjY8X22;Q%O^GnlA-uq<~bhi#XyZV*2dMy z^WG7hGD@vrsmy*GO@1T(?M?JrkoIY9g~QZdxmP6t&n$kRRV0}reJ6KyVsYV zx(8LHK`%~}bVm5}vm&}YuP9u}f(KC!{xf z@L;_;gLV_IWYK-&4&6CUmbB9+}znHvd2TKl1y;M&m{z*?uy5T z!+j4Wd8xCr8V~R6XOhRZsVLBRqsQxx{V7tWcT$-dPl9gNAD2M2wv+fmIox*E8E7l> zVhyeM(PBj3+-J@=r@d!_09wet=z>+)K{V*i6b@ESvGa0k>Ie7$YD47BAebD7SuW!VMUkXn*EIY8VNUG z*9TeB9a*QgQ;S*xFolq$B&17b?5avoGBc0O&<|VY|5@YXF(}&iHKhra^Y$IH8v%xs z>C?G^PfE6jro?EV-T)hWRG~FYObxMXHBYn~D8d}+!CDAj)hA9%7j$-H@oD;z!NV;Q zrq%F^yll$IDFKlGo!)D%Vkb7(P5M$Tqqj*%eY>j&rO`Tq8IYX?mX% zbB_qOrEZX-JQ&+Hli$nVc0_SdkJd?@Q8ZcaHsKCS>y3~QsNK>CkvTx2Ob;c(?7kZ` z^s63W|9uqX%%6z0p^o&Yqk)IqGv|r&xJDWevCEr4@m!{kn%2HRs8fq=sMApGNB7US&y-xud#f-G(?g zKd?q;<2MW4401_dq&05O2b5at{*G|ynOLK^v8Q0H5XxB)TCyj!xK>@K9y=T`g6u7k zjpC;;lJL(=V?7LdU?PLcv8@v^S>q3gTUT{w;$BSo*gWEuw%wsxwMves^`GBKtrXnY zvLn3x^FHcU;lAz;+pOR!(;Ybdn~u{u9#ceo4<$sq?Gq|GR2Vm}%RP5NWlWm-(yu-% zFVb4on1uo4|KY0q$Ilz}bKgZu2=c_=uUC}Vdze1DZ8XJALA^iiJfp6|d>A-L}u>;j$t3k9}**Q!0#o%gAFJ=>DGoO z3+m-$gxkc;4~1Es%$CK5fLrvnpE*%#$1ls($#>~f-y4z~GuD^g@QB|5@_YWvOenA~ zMPY=!0g~D3iFLQlUadWPX~n>(VVr7gWz`q|IQZeJI$TXF{P`cf z38WKR-q%EqDn!;T*P|C@k#iidm{W&X3-W*eYazLzgTK$>#a#Muobz?OBIxeLRdycO zq;4p(e=3D7>9VjIbH?!hbh%xz>WqF`BCo8H09~DnSg!zfe z{h=!_&i~`ZLuNooV)Go2#8ui79`>R;qdCxeA~;u9Noz7=(W zmn_T(K&t!0iuy8>^KsGpV{&im6@&v6NNfDs;|6ubsFqIQP-iIQdPTjVED#jB>+*|_ zejC)m!X7Y`$g5>v0~3A4@YoQQl@v|wui*ye%nKmGK1d-T2LCGw+}KeyLN2w7uxBN@ z6!FW)xFTmxDSi!@2oUK0UxYu3`Th?g#D9)zDIqP!c!59<_pX>uIrDR2Q~zKSz(!#1 z$|L_%{)$`qiWBrT{RHMG;8QB-0QvK&i=0oxD?9#u<9|IomLef9d=3;N5f z>l7If$i3U?SeRTFJFJqs-MrxNL#6LqBWu7uvC`_cGa4o=(B0O@MKlv2=(bV4BvqNz zsWvwVWIs4>9l{%F=!ZSqy^P>L?JZRJ!Hv~0_|$NSgH|U0`K-wA7W}E&H>d>(rFTD= zQOG^tGaT5pxpgT@c$r5-)l^vB9bF|}D$lT5ZHpo}RIcRSo`WwDVIKVNhSTiK;5Dxf zQ#$6Z9UR2fK2iI2f1^dIYN_+6vOKsTxLVl1882v~BI8gppx^gi6F(b|=g6qHYoOTL zr%z-W^h6nL-m)X=$5!E?+d2y7pY&>t)Xl)lQ?7Dp89y%6UmR$@;0JDE_Y>= zJijPQu|!*OB^lyXxG88(K3c2Ax`er@itbVwQ3Lj5#-Q3OP8nbZxF1H6H(iemXPRzW zd3)s7+ee}-7qT!#lN#~ij{eaWyHA2|_9nT18u>cxnS7cU6dp%Bhbw^w@ho(OnZ2f5?n0#&YWnXr2FT)z; zP?1|(%#2j5*NfK4Kc^~eIl*iF;2hp=>Q|2`@4@E0#LjDk0Eb(1l^ExvG15EVx@|{>#@d?q0(F z^7SP(|66Z<1DWlcvtZQFN2Ww?DTn+7ysH;Px3Ug9Sokx-2AaxMm=6=SK>?N=Z*vs*u*N>FCQZtF+t>d`&TXCZjZMV?%o?rSEPwjBTCo>38 z>YyD9qRz$TINO1h}YAZk9Q3>?6k_~h&=TFRWpYTMSh znCu{wC$k9RmaiLkQC@~yhY5xU@$aGZY5O%FXDPpEVuU%7twxY@{h>W{?OvBn>OW3| zJg~pVdIB4Ywd3c|eJfKj^(z9X9tL-b&Te+zT z#UH>f;s*Za>{U8yQYvT1({tf_WMK*9WjA-Kx|&_jAg_|!>Xm~xyb9J+rZ&N%&i z8#!*<$5Lp@=#XA0qkzf)k5WgqaL%!1jCSROZoT6|ONr#0Mww7QGT#10jNsq_`vdBM z1)!0uensMw?c3K&sRt%d2#bb|uMY2IM%=Irj&KH10}{UHEsJ`*Ygt1I3i=faIOlR1 ztT@idtSdBg7Mh&Uu0R7*VU7lwv;z+BM1lS$Sl%IUKRxT$p6;XQJI&Rpqx8>zcFv9j zT=b*rs{r(q{zbnvQ5!lkB%|DerBLhc_FTCkJ_#7JqordybA2>br%>U0B!=7XJ^6xk8Z~2Y*0s}LH($r_gzfd_s4=Wg3`}> z1X7@Z>~7zh@%WsLewehO^V zIhVf0RiQ)Z#v7X^9udK&1id7dOBx}m$a5Jc40=Q%Yw)rN8p!q>Un5hpg;Dz{A}zqC zT^2Nux}pca%|x{<2(Jf`bKHB!LJIFdK!i2NFuJndkNe1qE?nv!;FmpytYv;3o^Z zslQ63Pzia*HWta-B{%;1T(VV=fF63{t94mpfig0Lms|xKM_r|b`lzUSP_;DQ6m@Ye z8cmwRSjdR*x9w=Bk(-jR(%%;qxlF=1-*Nh_+!M+(fS5ap=$k|=Bc`r zmVlmxHJ~OBEPl#2!X~KEK|)^eSkD(Cm=1`HPpBdU&FpMamM8M@IVQt9JH46b=DIh;@3;^>8<7Xplg_+bIVT4BYFD_j$)nm_Of?{7RYvmTK1k^i2`kZ+4fkg**W+uk8_=I=r+&aEO%+RIb5gO z-z!$otQ#ptgg!my1@Y}{Yrm*CUes34oAGB2d>3Hrfr`~%9Mr^IMVbuREXyeFoc_>@ z_hi3{V05;(j)ZTh`b}fhEg#YP5C^6ZHhu^O(t6<^Pkn!5KlFvLy>>7~3c177_I?I)qq9Qu0*4`xjvD7wHQ+cd&Soi_y zJtEpF$jRm=UtrndIRdR}o%{=x2VwX&d%+pi*2=M*q{JHLW@^H&d@Pe~IK>^KS&VNL zC}*xQ^GIDGa+3?ZhrIZ5^`zn~pB?rQJ1p$2VdjfPP2M#2`#&MVJWoZHp^s|y%)mb6 z*5F|%h33~LbR}#j?7i7croa6R^{&j^U4~uYoyp7^STN(gHkz^7ghRIelZElC{)~YJ zP-FDy{Ys7-s4T*+GBR4vApSD@)f z|5Xi;ESYTA<_nJWfxSd|sgS~`L!m#Dt3rJqhRzxv7av_2=)tPZW}p=ZVwyDw)Napu010mPZ-{ol>{us0P*)y3~vnyVIi6g#=dzKb>9XbmDt>FBS4Ph zN%IZH=;iQnZY{DsVS+h_Y^%3%+0B_c6EyLR+?GVsYj_=ndAlZ;hGfcZVxst#= zxmnhL$S4t3HUFJxjIeZisi+Dic*!r4-iAn*Ru|8nw<{))TNOE7(ROV#B;-Ys>d-MP z@tLe@(V6w~n%hrPd{$Oc@{4#z7-K=3F>29woI3&0SEc&&@y19>rl$dp#MSXNH{7s&u5z`nE1N}!wstBhP{DWwj?d7 z@R8Gr%p?KvwhEcVKN8B@`{17vv}>Jw zerT|JI{Sg2>jyPAa+&5zrQg6{*tIKpC+srM%MCg^PKGSM@DrSoUyQoK10MP#L)hU~Oie4CFp4NPcYM~sN z&|QJ(J&9dkj(7nX3K6rEdIG320Y}zmvMaMFF14Lr3D-P;a!f8@E-y4GOl9stM<=qGnXkdN&_MG+d!lGDB1#`a*g9k7J-~2YQ zxc6=}jL38Iec)A?d0T3U@V$T~ zSq*M%MBKWJuXjCWlZbB|(CT)kA|j=?M0U|5 zEE=SDyftgsxHVB5b9JEn2TS#^Of0&bkA6_>n16MsoPNZqC{yfq{3f+Ln2JvJR>C z0~~4zfc&fA{`%A$@fcGAjfwClj~BY_CyMVs6mon5ggT#YxEM~)c5tDx_7X> zYVgB|w2`iu@MbU99qx4bxOsh=4iwApu%u2*B6yruC*kwa#>pyeUO34s(u>n^#>yh_v%?eg4&hwKNu2sd;VB)Wt0wL z1`@(-muDbh&IQX;T-fI}(d&Fi9S3PqW z(TT20RiHtV`Agt*g(Wf=Bj!3H*El>cq$;^mqxGyOD}5A8o$%~v?obfLr(R{f{?0~R?RQ`^J1$I^9aD#H!uD|yYpuI!d%N0+$OFE&TtoSWBGbC zn}`m>^5W;(sm^vaJNsHKlg|%-qra85fDxY%HU7r*O5UWSWI?E{+-Fz{zGJH?jB@TU zW*v3Z&z)c@NV&zzd2urh(^B%=T`06bEZx36WqtBhQ1KW+{fcujm9Rf-5B&rYnn$eE z$*_s2%OfIo@!mKea?&m>x^*njG~~J-YAS%C7ct1cu%wcuQA%>-yiH8PTM6gS)+r}H zqV8+W91loPinf=F^NSU`d?49uF^0uK1x-L`hdOvw?6?}I?dkgM@@?{ucL0*lq#T+_ zv7Oxe7uHb2tV1}%4EyqCMyxyDj#aMtxaXHYn*6b-m6^h{Mf+wsP90MM&P492`Fprx znqFM^k9w;AF+VwAn^}W)*&`?we6qSWLn#n_3!-<*1F`~0!X5!`$O*IW{e_Na0q+pdTsYBkUTU>^sa39~&nv{Jp4)9}5wOMG8^ z-riMyjAzlfW3o}bTY-co_<5g)K#Pm9evo{*Q7+u``8EH;^jMr2HbC+GSFrw6p%6Ob z@)g18yd%i*s!wC0E0qPZ>P%%B!541du(U(Lr&-6DGfa}q+P^o0ReN&8>(TeU8Se&8 zB}r0za4$lVHjQ&TE|{=Ot2y1qrUSi2T=(c-*xP4GZYGqhW@!24CC4L;)W=2#8d=M%24~62}=~`jdvvXjFi*-W- ztb5TI1=Diy*sy%Snb-%9-w^fao*V1WP5(QLJ&d`Zy~ycV8Y#89_dFDT8{c+Iuy>Lm zGl46+bOh6I+VVUkJY?}t!5hI><&J-amUeO*i9aU?4j=t4HFQWKc^npXVQA0bTYq1O z?TR5rZKp-{p)BRr+;zXY3PtVYd`OxjD2N|vT0!42$aR{b1+A-O;=(<&HNvXUz~`=J-d%uctZsOI(B z0r``sE65S(n?Qv6C{C=})@MMim?UUqe)S9k{{gz6eExfbQ-`Hv+kvP+%~NG>whVu zxTuyQEDpT_U5@>=pRJPe%8-@S`~o8qX7^W||C=j@`(Hmd%1f>kUQc*cA!5C~aQ0{a z4QF<(PwsQ`0@|KDhyg3m_LpC8Fs)YV(!oP$&W>l_-LLD3G4{J5{R9dt3Fp zPti^jU=C33|9PF{izApx>^)lUcYN6z(A}OlRc_sCfsFn_buyW}GI_`2@%Ya`mtg)8 zOu;YXV0fIlv#`w#cQk*5-u#gTlsgs)XBj^tnuYnyzUJF2;tK?8wgBybisnF{0OW|w z^{;jbKnuaAS)U1I^JU>E-aGFZZY{_Fp00ULR(;7?mi)r3VaIvLMV#!qv4P0i)LrI& ziUQ)+Hxs)+BS-c6U>AY*vM9?L&*mfmpS|{7MOud8cn>|@vUuB{_}%pT64XeeLWd-+ zYFZ`Ge;7?X)k7d|mz2lqzyfS|8cy1^(z8FW?lj+m+QhQ}5~=coU`is>x3+VL2;F+~ zS8d}c#6rQ`ZOmemy369%H?Y|HH|a|7gg1^y2sq~Q?tRPO6m_Px@gEh|C4cyxfC?65 zPT5T94a}C@d^P&HOCs5i9*mx6N(c`2*|A?VMazRm?)-v2Pt45E+|^eioGJCG*)j6r zj|Z-GwP#+TS}Ghm0TrW;nj!Df?y=GwmQ;o{ZXzKq_EGg|s#f8e(mJEWIPSH2DbUE| zuaTn6a`{iO>FR0KZ?ggHRV)nK5(7S1)BV!cT)^ilnaAVIVjaV!)N!?k?-(#1mXG1Q zskg+~o;9H6UujLCX|wC}xbcAvDtk`gl4g|+mn6s z6q27DWm%j!B>G9s=bl&Wh(ahKC~kvj@p`~uTv>nsnZ>_w7;mZ;z+u@<`YSjrf!n>K z>n|K8e_DAbCFBUMYVVe*i=>WEB6FPUQ?)G)7QsSR>NNs4o&B&}aF{}lG=*n@?xs9m zP2=XSHsh4&y?b_;5*z3z99%Db6m-`%dG()vV>5Tn<>vlulgDf_5PPxsAkqXJR*B@E zAio&#z>@AeZZoPgL;xCD{-u`z89w?y7PJibs1{g-9%&Q02Xd1ZV$fE1%(*%g*iyw* z7wJ|+TgOj$_f_m9|yhISbaQu*F@6(>7SEQ!)KtXy>8Ep>}12GH;exK zq4xwmAM`?$ls--L5x@9TOl}d3&Pr3j5)*BwR&&cT3g#cce4@bsR?9}XoqlMuVIBV3 z+=GLMgPZ3y$Ac7jL282P$;HgHUOg&jkfv`qvun!uP^j$w3FY^);l+ZGKV>!wDkI+& zwO-p9(y?BdyRP}BK9#9@s>5hu^iJoqE30a>4(Kyz;oiTPbw_~sbKwRxYh>-Snmtz( zP_kwohU=2Q>oNER^)HhA0%87Ny6u%y}!$qtU4BJ zfna5Q#wO@Ylr8Fu4;&779o@6-jWx9~w@xx!n$ZQ^7pNyhiVkG(cksb&&hw)};PoXmvXgEF9Ob%yP zwpIvEIUNY;SVCoI{OCrXu+^H#a_mkW*@1F{R8Ayor=;VoE^i!fXRamvtYlMfg3l8W z!;vqaIkc3+jK0@`A=-?wa{JI2oM~(Zu~M*S0EQ+ZPy@y6=hw2;Ckn$aW$>3QbVH1W z1-?Y!cNe%z6Ipvj6(=h$-A-39#|>!oRrUKJ>2^G)gxY2x=0h}Ge~=&6Gkx~` zuKxSsI_AzhglAtSew&6^&`*o(pl($i4#&hS`4J#DOL)Qg8Q>f=MlK5{*VC(C zS#&_z5nnmRUI{`<&H6F&x>NL;P+`dA!ns(JQk@{dK7B3Wa8h#U6S9hPhe^?X#wpm@ zRf_D;gbxtZi~`59f(JGFi+``wz;f%hUt(C#j7PEF+bB67xb`tfI8gDZl&B9koI)e_ z1kzuWgyzb==T9fl9_Xhil`ZNS*4LHTkX(Tu%GfslLD|`^GJ7fEb~-sepDB&Y2wK>xtsR6(A62;K~Ax>Sw|N27PzAQwsSIy zB`NP*^rm&vzm==eg?q`U)>iH)0CQjZ@Giq{L@KMlu)_~3_xrRXG*}3nz@ygbYU_Y0 z8T_nArPVS#?$hmSY|U`*vpf{u>F~`|HrXF-@I7MTIki|unR|!P#!MM1A29sFJ6}xe zC`Ox5{Y^7pv@ej}RkrxlY7<(ZOP$ui=Y7YXe^N3TueSE- z(fshIAib_~n^W7O zY0X?@jhx7qT5_yuk2pIfwAjeKn8myUuVo%j)<558A=qzIi)I^c~uNcpx?G;J8j%tZk7wVtvVHIOCk${I?!Um zMDdR6@X9Kcex$uyGlX1HPfQ5F(&BXTB~gzy#|rbQGt_uCAPJGm`vvA5CuuO`fJwie z{TBoRYTh3(qt_>XzT$kg1RqzRN}rHZ$^l|R9p~*MKp(HI0A9d(N+h;~<2iQ^0l4V< zUoZ^gzFA%5{&6 zoK2Ye__#aWR+;>_#M&awq8!aRAy~~yJ zZk^3z_vtm>%m~dp>3r|tk(#B9Ey(TbqCYLL58FeuP%bi4oueHZCXir*x51{Mj8%fI z-=IFH8BzTad5bbAgOQn<*Ac4jJ zIJlkAuH8tdXU}~m3w?2)QC&(I<95%;r0!~H&LDla!4^`aQD0|u5`x|od97@lul`8o z>pg)iM%8y|4X)>5OgTqz)?jY9_lKuJsHu;CYnEejqy$x-U~14BgEXh0j?{gD(gn}H zF#{oe*awk=WahBF+#p(AE zk34nmTr_JSVYsc=V~QNnWrcO7Ur{Oit2eesN8WHYPj^ilXSQ0-mQc$>sp*@-2?fw* zqw6rUS)T7)$_J`~qVY^l={s5B@hW$$po>ob%uMEVf%V#neh+GeyGLOec-bsy0+hsp zE3#K$M)z!Fh@d_82X4;gkJgwQ2ruYO9iK za7k{~RC&Mly5ly2jZLJJ+6q=k`{+y5ceY2aC{#qIL$NGdFlni>0!3ETgG|Q{f;~wrE5pPDvCY zil&U6F&K&?Q_3`XjtFTHS)z%?GK}H~*=20AAZr*ClOS za{t_3vW8(6wf0+9+TxoF3USf{wc%pHYm}HO3LP_{HJ#ng{b9ETa>h5ZFjL$f@BDD% z>PXx~*=WKw(_0ab=rh%EI@c4QE<}KOrIY7i{ADe?XX$lenOloyDiMzuqo5bh7QCE=%=NTJ*aC1xl8gP+YV1m zdC}_?Lz%sS{jV`+D<6-`Y6HtC#gQX%r{`V{w%&>G}%Poqlyy)!0@B=}<0lco0*NlI{;+g@M0r2-F{wXAw$({c<&ZO$j-dDXopvk{Io=A$zCgV?Dp(I^gQy()oydG*ywZn z$8$Oi)AYF`akzz)spgYAqmL7kD4t=?^Vx3WGv^4;jJqDCEPlubI6iKa_YpvCnNW*n;*>2&X3shSd;n2B!8>s2Vut7Pmr^g z0K?Bx5!s^`7CP=vEZya5EAwjUEGpQyGZs04cxX>emUcQ*cyHeM{FW$-V12!g1hzwQ z9<`UG%fQ)AU#5{Oi0t1`GXcx>*-PYNdhW+Dx8b|7;Sby0_Eh=s z26dnGl>bXs&1a3A;U+cf>68}#x=fRFaUH)h=Il&;wqH{_J!|9y75?@|x&WyNHmN%8 z!@j5MpE#bnu@2S;TdlX8DTAvq&Bi)3VXzpx6~7;sXe72n`V#2era^VD|5d#Y0>}Tg z%HY5EPEh;lx(wjYyv(CTnD`@;;_Q0mn2EhGmx$x}QvkWEjAxVv=G1}`Wye3)U8Mk7 z)AE!iCH&Ilp|nbl@vR2!TPnj#G#q!gY?|J}()>h^L22maNu$z)DauT<&Q<3$24?aR zLx+&Zo_B<^_m9j6)fnm+!(5yN*&HYncM>K$qDQ;$V$U_A8e+UF(BabtDMjt^Jj%@- z4yy1(@rF%YgTw^g;iVT{YjMkahjZ-mlQQ+1Q&0f&)!o#(a6TH(8?NKZuuo}wSMW!M zhr2Uy^Ng+^oec7M5p#FpIyL-gtar?JoKk_(>4=cG=Rz~O`1CuIPx4D zb`M>Yi!VJ&hfDG7GsHYJSQPI(#qiPX!_YCqVzt9? zYrNRTG$3uEEH07;FdXF{EGd0%@4_nOdaR1RH)@q`qpqiT(`QuqPn-);brCvCUB@@ zp>R(5Xl0VZB)oZ^PaitMbO5fAvMb7Eo zgz~8Am&SS;QJkHF8&iIbU1?EV;V8eDoU-)NufNl2H#K;pB&2cHrYc20O4S~qj+vVWM)=du zxi?Ttjr&jYzuM4}=Co>*dm|KtVH4JZ7!fFhEqt9a91*+DH~p;b&;9h?AapK=m3o6` zJwXWXG2c^S&1~WnjZ$;>^gk_TYPqq+ar*}12u6pd$=aS8?zvQQ#dtcMfPp7jPhfn6 zg@_lRNtO#OKj}OWD%h!A2;1y*z6Xu)g`B^{lS>P%$b1?;la_!E_E{ITxv1W@_hbvU z2!$!ooQq+fort@x;2iNlxhS>Y?`i|JqgUKF$hA|188i9HSgnhtR`mBJRE?}v*FX=X zKp?&hh@=2yUZ{e_g|x$92hb}W2M_~qKD**ULDOZm4e>9!SY0h5N$<7sJB`sX)_Zx~@u}mU?eQ;|>iv0UmCOBB2CmQjMEGxEx=D(VruoN$bysjnsqF4`8L+`y&mL?~>jqgRPV&*-X&0Iar5XIuuIn8 z8E5CDw>(tcQx?L@!*;R`W>tPT!mX=c&{t0DZt(+k*bmY7f(}7_j|qY22QbCi`s{Ja z@GLuYn46q>1UpT{H^!sVQ4HYZO*2rhv>nvjLSU0Isb} z-lWp>gf{nUe|{3c;xWTKGi`gtzv*!ATJJJ8uBF%1^WzKP=()p(+@AiyB9q0j{|$?BXN3uP$DG z3WGfU-728|U*WX`rN0mkHJ!L)T?b0~V_7wtzI!lQpfGJS>=sA_v+!*Fa*aNVgM>|J&^(Ac()*? z>muH~;M^-VN#9dCxl7)`lit5T*~YverA8*F_JykcfJ}M3b4~3yU6+3^h<)MFlI9r& zqe_Yb-$=BBJzMe^-pX#p?GiMaWb#SQB7pE}G`RhOgHlfA=R5wJuI#q#s&taUmDuz# zM89xUi^n^ZKCyJBVsv(c;l^CLYTwt zk|51dfGo1FT_9)y&||Z$(cAfecWw1#%kbT9O}r4=W8q2FEv3_Fj2=tfMgkecuDNNh z4M?DB0{w*j_%rKmD(FwDh&3`7`?rkH(mr$_#3OsG=AP}t7xq8%^1dh?B9akWxEE`5_5?mo;=y^UaV|k$k*F(t@(vxo3kUp{0YoJRrQOrG58`lfc_aMq zJ#lyaD}H@Ao+DO6Z_{P;f1#-A3llBAtOJ<_WJuLtP14m~dD(;1{!INGcYgf!M@HHu z-{Bc*`a>t@872YwYKJ~v=!qKdigM>s&vM`u%moW$AwgnrZWaxl!?jD3S*jlOMf*TCLR)j_m#u!x+=wPHsJn}Cz}X z7s$F$-O)cuIq~zL>>60cJ%R7pj$Hgy=0vrWo}g7Gew#k$dcbpBHPesx!Q@v&JwP2Od*jvg;A@i8F#~7?#;+#7A7@kCGHZ09YUEqrT4;LB zw;{95)wyy7d0yq61Ub(&V~QsG1ZLi&>#2k{eC_+bSz6CZj$f)rZZ$;QHc*_3v|u*9 zrugq9*p;%s&xGc#>cIeYOPnb!YgqX`kk zdfj^QGo`RqA$D-71>FpHK-ZLqZry?)qQ}UXs#1W)i-*<(6auT=92LhJyJQ78v8Xzt)V|i@BKyui5&QiL28_k0mnv4fW0g=ZGV<0+kSjHu-UGN`@C2g-ZQy+bR zuGk@#VK$87JvbnJexBk+MC+5pckSHw#`(UCS!D@#KRhI)H<~{^nH&7^6VHtr zOyVmLAG2Q%w5WYFe1B}>feY0_?%k}HJy=d}!EyovCmqaKE5(`u9P{>7uZ8D*mO3D0 zsImq&@L^>q6RZ5;YwT-$^wM#Iew%RsN0ca-gd0$#G+_hz6M=l#sTJi2kT1yE{`)Ti zG6V><3hY16uVBVHrs(!b)%!YTe<6E=2<#`iGo=Y=EZ3)}vVbtct5oPCX<{Y5dA|9% zp!x&62uOMZI>I3iNpyjVlMtmJc)}KeJwCj81R-zFg&foa(U=y8C~ArRk&H23?zUW~-s>@Tm`+LZa#%69ia+AP0jN0R~3l$medv+<^OWKiI_&qo3r z7Qb0t<*k9K{^6;5YPQWvM%f7MT3;xwkw7kHtcl>jag@l~ z=rS04e>xbk@DnRJQz0!`W%}~Te0b;v1kvbM!s$5A?>D=EgmzW142qxrKO7O&S0HPD ztb>wR(USnlLED4j=<@X-sJp)PzfJ~brIEqERRAWQ)PykzVTeEp7oZ(u?(rp6pePjR zrz_#*WuXM}7zCvhy94s8;@!~mM2>=4fB<4b#B~rcPyH4Iw7UUiiVu(g7&-VBN}f(U zg}8n$ApLs#W2>XDsmUdQb~tuGAXZ;}e1!SCx*nkZ#HA_z{Uwp8a+>P{auI|8TzP@Z zd8lCUwiwWFE1i3X;oKw=m|vlUs%Fleg%NPT>Ez6=a6*cBW9Bni|7O;(isz z?jK;Op{inqC6j6>Hd?UN0jB&SaSN9Zg6Xbh6-Z#h>akCiInZ7yUiWnM6Myf-KnwsodmD|wdlHniplZwi@bU{()OYS#5P-aPLzx0EumxanK>=bDu&7#t zP*N`>r+j@A*h(a`0Fo@}F}vtMhWsADKJ(X(XI~J&4UE(!qkQGEZ~O zwVvjw#r+f`iiqj%V1;*D3!Va)#e~ZbP08mIyIqGYuiZ{j=rsx&&5*IYrueP6Kch6X z@1>i8h$!Nnkw1-|#xQQ8a@RhdORN#y(K-dqzM`cxvdlEwtWoUR8g%S%28!h4wuuWQ zZ;0V{`Xm6*F6T9;qnNJFYnpt9<*C+K#ZK&!GcCn3_}Mj{jw?f4FNu>M5RWm-(sX{kVQ~pTcl$6TwmM89NvINw;dt)L zfm_owY`q?J$kdP`tdB7Oxz%=ggLkOiG3ut%=Mo`8%GIvW&GA2Q;Jd(xUC!7D5gYx? z)b&oX=T2n5JR(f=2L+nzn*z_8AgOyv8bZV=;FtPLQ_Uq%5rp>{-`<-@?0|#)tlsV` zMEq#F`pb5cOQC< zv84bM6mq=X@v3?|8`FMlTmLI;hk92h7}9>PBV*;h;G2!ds_ e3q1Xi`Q_Kb-P*$joEghV8v5ZO+4!whDW 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 Bj647U diff --git a/src/DiffEngineTray.Tests/RecordingTracker.cs b/src/DiffEngineTray.Tests/RecordingTracker.cs index 64155ec7..3fac9d23 100644 --- a/src/DiffEngineTray.Tests/RecordingTracker.cs +++ b/src/DiffEngineTray.Tests/RecordingTracker.cs @@ -1,11 +1,12 @@ -class RecordingTracker() : +class RecordingTracker(LockedFilesResolver? lockedFilesResolver = null) : Tracker( () => { }, () => { - }) + }, + lockedFilesResolver) { public async Task AssertEmpty() { @@ -13,4 +14,4 @@ public async Task AssertEmpty() await Assert.That(Moves).IsEmpty(); await Assert.That(TrackingAny).IsFalse(); } -} +} \ No newline at end of file diff --git a/src/DiffEngineTray.Tests/SettingsHelperTests.ReadWrite.verified.txt b/src/DiffEngineTray.Tests/SettingsHelperTests.ReadWrite.verified.txt index 83d0fa94..02a3966a 100644 --- a/src/DiffEngineTray.Tests/SettingsHelperTests.ReadWrite.verified.txt +++ b/src/DiffEngineTray.Tests/SettingsHelperTests.ReadWrite.verified.txt @@ -6,6 +6,7 @@ Key: T }, RunAtStartup: false, + AlwaysKillLockingProcesses: true, TargetOnLeft: false, MaxInstancesToLaunch: 5 } \ No newline at end of file diff --git a/src/DiffEngineTray.Tests/SettingsHelperTests.cs b/src/DiffEngineTray.Tests/SettingsHelperTests.cs index 69c839c9..0d1ac165 100644 --- a/src/DiffEngineTray.Tests/SettingsHelperTests.cs +++ b/src/DiffEngineTray.Tests/SettingsHelperTests.cs @@ -20,7 +20,8 @@ await SettingsHelper.Write( Key = "T" }, MaxInstancesToLaunch = 5, - TargetOnLeft = false + TargetOnLeft = false, + AlwaysKillLockingProcesses = true }); var result = await SettingsHelper.Read(); diff --git a/src/DiffEngineTray.Tests/TrackerLockedMoveTest.cs b/src/DiffEngineTray.Tests/TrackerLockedMoveTest.cs new file mode 100644 index 00000000..911e5719 --- /dev/null +++ b/src/DiffEngineTray.Tests/TrackerLockedMoveTest.cs @@ -0,0 +1,124 @@ +public class TrackerLockedMoveTest : + IDisposable +{ + [Test] + public async Task Ignore_KeepsMovePending() + { + LockedFiles? observed = null; + await using var tracker = new RecordingTracker( + (_, locked) => + { + observed = locked; + return LockedFilesResponse.Ignore; + }); + var lockProcess = FileLockUtils.StartFileLockProcess(target1); + try + { + var tracked = tracker.AddMove(temp1, target1, "theExe", "theArguments", false, null); + tracker.Accept(tracked); + + await Assert.That(tracker.Moves).HasSingleItem(); + await Assert.That(observed).IsNotNull(); + await Assert.That(observed!.Files).Contains(target1); + await Assert.That(observed.Processes.Select(_ => _.ProcessId)).Contains(lockProcess.Id); + } + finally + { + FileLockUtils.Cleanup(lockProcess); + } + + await Assert.That(File.ReadAllText(target1)).IsEqualTo("old"); + } + + [Test] + public async Task Kill_AcceptsMove() + { + await using var tracker = new RecordingTracker( + (_, _) => LockedFilesResponse.Kill); + var lockProcess = FileLockUtils.StartFileLockProcess(target1); + try + { + var tracked = tracker.AddMove(temp1, target1, "theExe", "theArguments", false, null); + tracker.Accept(tracked); + + await tracker.AssertEmpty(); + await Assert.That(File.ReadAllText(target1)).IsEqualTo("new"); + await Assert.That(lockProcess.WaitForExit(5000)).IsTrue(); + } + finally + { + FileLockUtils.Cleanup(lockProcess); + } + } + + [Test] + public async Task KillAndAcceptAllPending_AcceptsOtherMoves() + { + var resolveCount = 0; + await using var tracker = new RecordingTracker( + (_, _) => + { + resolveCount++; + return LockedFilesResponse.KillAndAcceptAllPending; + }); + var lockProcess1 = FileLockUtils.StartFileLockProcess(target1); + var lockProcess2 = FileLockUtils.StartFileLockProcess(target2); + try + { + var tracked = tracker.AddMove(temp1, target1, "theExe", "theArguments", false, null); + tracker.AddMove(temp2, target2, "theExe", "theArguments", false, null); + + tracker.Accept(tracked); + + await tracker.AssertEmpty(); + await Assert.That(resolveCount).IsEqualTo(1); + await Assert.That(File.ReadAllText(target1)).IsEqualTo("new"); + await Assert.That(File.ReadAllText(target2)).IsEqualTo("new"); + } + finally + { + FileLockUtils.Cleanup(lockProcess1); + FileLockUtils.Cleanup(lockProcess2); + } + } + + [Test] + public async Task NoResolver_KeepsMovePending() + { + await using var tracker = new RecordingTracker(); + var lockProcess = FileLockUtils.StartFileLockProcess(target1); + try + { + var tracked = tracker.AddMove(temp1, target1, "theExe", "theArguments", false, null); + tracker.Accept(tracked); + + await Assert.That(tracker.Moves).HasSingleItem(); + } + finally + { + FileLockUtils.Cleanup(lockProcess); + } + + await Assert.That(File.ReadAllText(target1)).IsEqualTo("old"); + } + + static string CreateFile(string content) + { + var path = Path.Combine(Path.GetTempPath(), $"TrackerLockedMoveTest_{Guid.NewGuid()}.txt"); + File.WriteAllText(path, content); + return path; + } + + public void Dispose() + { + File.Delete(temp1); + File.Delete(temp2); + File.Delete(target1); + File.Delete(target2); + } + + string temp1 = CreateFile("new"); + string temp2 = CreateFile("new"); + string target1 = CreateFile("old"); + string target2 = CreateFile("old"); +} \ No newline at end of file diff --git a/src/DiffEngineTray/FileLockKiller.cs b/src/DiffEngineTray/FileLockKiller.cs index fdf3de6e..09e5cac6 100644 --- a/src/DiffEngineTray/FileLockKiller.cs +++ b/src/DiffEngineTray/FileLockKiller.cs @@ -51,13 +51,13 @@ struct RM_PROCESS_INFO public bool bRestartable; } - public static bool KillLockingProcesses(string filePath) + public static List GetLockingProcesses(string filePath) { - var killed = false; + var processes = new List(); if (RmStartSession(out var sessionHandle, 0, Guid.NewGuid().ToString()) != 0) { - return false; + return processes; } try @@ -65,7 +65,7 @@ public static bool KillLockingProcesses(string filePath) var resources = new[] { filePath }; if (RmRegisterResources(sessionHandle, (uint)resources.Length, resources, 0, [], 0, []) != 0) { - return false; + return processes; } var procInfo = 0u; @@ -74,7 +74,7 @@ public static bool KillLockingProcesses(string filePath) if (result != errorMoreData || procInfoNeeded == 0) { - return false; + return processes; } var processInfo = new RM_PROCESS_INFO[procInfoNeeded]; @@ -83,29 +83,25 @@ public static bool KillLockingProcesses(string filePath) if (result != 0) { - return false; + return processes; } + var currentProcessId = Environment.ProcessId; for (var i = 0; i < procInfo; i++) { - var processId = (int)processInfo[i].Process.dwProcessId; - if (!ProcessEx.TryGet(processId, out var process)) + var info = processInfo[i]; + var processId = (int)info.Process.dwProcessId; + if (processId == currentProcessId) { continue; } - Log.Information( - "Killing locking process '{ProcessName}' (PID: {ProcessId}) for file '{FilePath}'", - processInfo[i].strAppName, - processId, - filePath); - process.KillAndDispose(); - killed = true; + processes.Add(new(processId, info.strAppName)); } } catch (Exception exception) { - ExceptionHandler.Handle($"Failed to kill locking processes for '{filePath}'.", exception); + ExceptionHandler.Handle($"Failed to get locking processes for '{filePath}'.", exception); } finally { @@ -113,6 +109,31 @@ public static bool KillLockingProcesses(string filePath) _ = RmEndSession(sessionHandle); } + return processes; + } + + public static bool Kill(IEnumerable processes) + { + var killed = false; + + foreach (var locking in processes) + { + if (!ProcessEx.TryGet(locking.ProcessId, out var process)) + { + continue; + } + + Log.Information( + "Killing locking process '{ProcessName}' (PID: {ProcessId})", + locking.Name, + locking.ProcessId); + process.KillAndDispose(); + killed = true; + } + return killed; } -} + + public static bool KillLockingProcesses(string filePath) => + Kill(GetLockingProcesses(filePath)); +} \ No newline at end of file diff --git a/src/DiffEngineTray/LockedFiles.cs b/src/DiffEngineTray/LockedFiles.cs new file mode 100644 index 00000000..faacbd6e --- /dev/null +++ b/src/DiffEngineTray/LockedFiles.cs @@ -0,0 +1,9 @@ +record LockedFiles(List Files, List Processes) +{ + public string ProcessNames => + string.Join( + ", ", + Processes + .Select(_ => _.Name) + .Distinct()); +} \ No newline at end of file diff --git a/src/DiffEngineTray/LockedFilesForm.cs b/src/DiffEngineTray/LockedFilesForm.cs new file mode 100644 index 00000000..a2978fd3 --- /dev/null +++ b/src/DiffEngineTray/LockedFilesForm.cs @@ -0,0 +1,112 @@ +class LockedFilesForm : + Form +{ + public LockedFilesResponse Response { get; private set; } = LockedFilesResponse.Ignore; + public bool AlwaysKill { get; private set; } + + public LockedFilesForm(TrackedMove move, LockedFiles locked) + { + var processNames = locked.ProcessNames; + + Text = $"Locked files: {move.Name}"; + Icon = Images.Active; + AutoSize = true; + FormBorderStyle = FormBorderStyle.FixedDialog; + MaximizeBox = false; + MinimizeBox = false; + ShowInTaskbar = false; + StartPosition = FormStartPosition.CenterScreen; + TopMost = true; + Padding = new(8); + ClientSize = new(560, 150); + + var buttons = new FlowLayoutPanel + { + FlowDirection = FlowDirection.LeftToRight, + AutoSize = true, + Dock = DockStyle.Top, + Padding = new(3) + }; + + Button AddButton(string text, Action clicked) + { + var button = new Button + { + Text = text, + AutoSize = true, + UseVisualStyleBackColor = true + }; + button.Click += (_, _) => + { + clicked(); + DialogResult = DialogResult.OK; + }; + buttons.Controls.Add(button); + return button; + } + + var ignore = AddButton( + "Ignore", + () => Response = LockedFilesResponse.Ignore); + AddButton( + $"Kill {processNames} and accept", + () => Response = LockedFilesResponse.Kill); + AddButton( + "Kill and accept all pending", + () => Response = LockedFilesResponse.KillAndAcceptAllPending); + AddButton( + "Always kill", + () => + { + AlwaysKill = true; + Response = LockedFilesResponse.Kill; + }); + + // One Label per file rather than a single multi-line Label: multi-line + // Labels round each line's leading whitespace independently, so bullets + // that share an identical prefix can end up misaligned. + var filesPanel = new FlowLayoutPanel + { + FlowDirection = FlowDirection.TopDown, + AutoSize = true, + WrapContents = false, + Dock = DockStyle.Top, + Padding = new(12, 0, 3, 3) + }; + foreach (var file in locked.Files) + { + filesPanel.Controls.Add( + new Label + { + Text = $"• {Path.GetFileName(file)}", + AutoSize = true, + // GDI rendering measures whitespace consistently; the GDI+ + // default does not, which is what skews the bullet spacing. + UseCompatibleTextRendering = false + }); + } + + // Dock = Top stacks in reverse add order, so add bottom-most first + Controls.Add( + new Label + { + Text = "\"Always kill\" is stored in settings and can be changed in Options.", + AutoSize = true, + Dock = DockStyle.Top, + Padding = new(3), + ForeColor = SystemColors.GrayText + }); + Controls.Add(buttons); + Controls.Add(filesPanel); + Controls.Add( + new Label + { + Text = $"The following files are locked by {processNames}:", + AutoSize = true, + Dock = DockStyle.Top, + Padding = new(3) + }); + + CancelButton = ignore; + } +} \ No newline at end of file diff --git a/src/DiffEngineTray/LockedFilesHandler.cs b/src/DiffEngineTray/LockedFilesHandler.cs new file mode 100644 index 00000000..4d40d995 --- /dev/null +++ b/src/DiffEngineTray/LockedFilesHandler.cs @@ -0,0 +1,38 @@ +static class LockedFilesHandler +{ + public static bool AlwaysKill { get; set; } + + public static LockedFilesResponse Resolve(TrackedMove move, LockedFiles locked) + { + if (AlwaysKill) + { + return LockedFilesResponse.Kill; + } + + using var form = new LockedFilesForm(move, locked); + form.ShowDialog(); + + if (form.AlwaysKill) + { + AlwaysKill = true; + Persist(); + } + + return form.Response; + } + + static void Persist() => + Task.Run(async () => + { + try + { + var settings = await SettingsHelper.Read(); + settings.AlwaysKillLockingProcesses = true; + await SettingsHelper.Write(settings); + } + catch (Exception exception) + { + ExceptionHandler.Handle("Failed to persist AlwaysKillLockingProcesses setting", exception); + } + }); +} \ No newline at end of file diff --git a/src/DiffEngineTray/LockedFilesResolver.cs b/src/DiffEngineTray/LockedFilesResolver.cs new file mode 100644 index 00000000..56e8bbd5 --- /dev/null +++ b/src/DiffEngineTray/LockedFilesResolver.cs @@ -0,0 +1 @@ +delegate LockedFilesResponse LockedFilesResolver(TrackedMove move, LockedFiles locked); \ No newline at end of file diff --git a/src/DiffEngineTray/LockedFilesResponse.cs b/src/DiffEngineTray/LockedFilesResponse.cs new file mode 100644 index 00000000..b3a0ee83 --- /dev/null +++ b/src/DiffEngineTray/LockedFilesResponse.cs @@ -0,0 +1,6 @@ +enum LockedFilesResponse +{ + Ignore, + Kill, + KillAndAcceptAllPending +} \ No newline at end of file diff --git a/src/DiffEngineTray/LockingProcess.cs b/src/DiffEngineTray/LockingProcess.cs new file mode 100644 index 00000000..ee7a28e1 --- /dev/null +++ b/src/DiffEngineTray/LockingProcess.cs @@ -0,0 +1 @@ +record LockingProcess(int ProcessId, string Name); \ No newline at end of file diff --git a/src/DiffEngineTray/Program.cs b/src/DiffEngineTray/Program.cs index 45f676bb..c3aac851 100644 --- a/src/DiffEngineTray/Program.cs +++ b/src/DiffEngineTray/Program.cs @@ -28,6 +28,8 @@ static async Task Inner() return; } + LockedFilesHandler.AlwaysKill = settings.AlwaysKillLockingProcesses; + Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); var tokenSource = new CancelSource(); @@ -48,7 +50,8 @@ static async Task Inner() await using var tracker = new Tracker( active: () => icon.Icon = Images.Active, - inactive: () => icon.Icon = Images.Default); + inactive: () => icon.Icon = Images.Default, + lockedFilesResolver: LockedFilesHandler.Resolve); using var task = StartServer(tracker, cancel); diff --git a/src/DiffEngineTray/Settings/OptionsForm.Designer.cs b/src/DiffEngineTray/Settings/OptionsForm.Designer.cs index 8343bd6d..f84b425e 100644 --- a/src/DiffEngineTray/Settings/OptionsForm.Designer.cs +++ b/src/DiffEngineTray/Settings/OptionsForm.Designer.cs @@ -28,6 +28,7 @@ void InitializeComponent() this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); this.updateButton = new System.Windows.Forms.Button(); this.targetOnLeftCheckBox = new System.Windows.Forms.CheckBox(); + this.alwaysKillCheckBox = new System.Windows.Forms.CheckBox(); this.maxInstancesGroupBox = new System.Windows.Forms.GroupBox(); this.maxInstancesNumericUpDown = new System.Windows.Forms.NumericUpDown(); this.label1 = new System.Windows.Forms.Label(); @@ -224,6 +225,20 @@ void InitializeComponent() this.targetOnLeftCheckBox.Text = "Open target on left. The default is temp on left and target on right"; this.targetOnLeftCheckBox.UseVisualStyleBackColor = true; // + // alwaysKillCheckBox + // + this.alwaysKillCheckBox.AutoSize = true; + this.alwaysKillCheckBox.Dock = System.Windows.Forms.DockStyle.Top; + this.alwaysKillCheckBox.Location = new System.Drawing.Point(5, 58); + this.alwaysKillCheckBox.Margin = new System.Windows.Forms.Padding(2); + this.alwaysKillCheckBox.Name = "alwaysKillCheckBox"; + this.alwaysKillCheckBox.Padding = new System.Windows.Forms.Padding(5, 4, 5, 4); + this.alwaysKillCheckBox.Size = new System.Drawing.Size(520, 27); + this.alwaysKillCheckBox.TabIndex = 10; + this.alwaysKillCheckBox.Text = "Always kill processes locking files when accepting. When disabled, a prompt is s" + + "hown"; + this.alwaysKillCheckBox.UseVisualStyleBackColor = true; + // // maxInstancesGroupBox // this.maxInstancesGroupBox.Controls.Add(this.maxInstancesNumericUpDown); @@ -287,6 +302,7 @@ void InitializeComponent() this.Controls.Add(this.acceptAllHotKey); this.Controls.Add(this.discardAllHotKey); this.Controls.Add(this.maxInstancesGroupBox); + this.Controls.Add(this.alwaysKillCheckBox); this.Controls.Add(this.targetOnLeftCheckBox); this.Controls.Add(this.startupCheckBox); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; @@ -325,6 +341,7 @@ void InitializeComponent() private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; private System.Windows.Forms.Button updateButton; private System.Windows.Forms.CheckBox targetOnLeftCheckBox; + private System.Windows.Forms.CheckBox alwaysKillCheckBox; private System.Windows.Forms.GroupBox maxInstancesGroupBox; private System.Windows.Forms.NumericUpDown maxInstancesNumericUpDown; private System.Windows.Forms.Label label1; diff --git a/src/DiffEngineTray/Settings/OptionsForm.cs b/src/DiffEngineTray/Settings/OptionsForm.cs index 7f1d10c4..4b99adcc 100644 --- a/src/DiffEngineTray/Settings/OptionsForm.cs +++ b/src/DiffEngineTray/Settings/OptionsForm.cs @@ -19,6 +19,7 @@ public OptionsForm(Settings settings, Func> Save(KeyRegister keyRegister, Tra } await SettingsHelper.Write(settings); + LockedFilesHandler.AlwaysKill = settings.AlwaysKillLockingProcesses; return []; } diff --git a/src/DiffEngineTray/Settings/Settings.cs b/src/DiffEngineTray/Settings/Settings.cs index c441f457..840de049 100644 --- a/src/DiffEngineTray/Settings/Settings.cs +++ b/src/DiffEngineTray/Settings/Settings.cs @@ -4,6 +4,7 @@ public class Settings public HotKey? DiscardAllHotKey { get; set; } public HotKey? AcceptOpenHotKey { get; set; } public bool RunAtStartup { get; set; } + public bool AlwaysKillLockingProcesses { get; set; } [JsonIgnore] public bool TargetOnLeft { get; set; } = TargetPosition.TargetOnLeft; [JsonIgnore] diff --git a/src/DiffEngineTray/Tracker.cs b/src/DiffEngineTray/Tracker.cs index 28c139e3..a12584b6 100644 --- a/src/DiffEngineTray/Tracker.cs +++ b/src/DiffEngineTray/Tracker.cs @@ -3,15 +3,17 @@ class Tracker : { Action active; Action inactive; + LockedFilesResolver? lockedFilesResolver; ConcurrentDictionary moves = new(StringComparer.OrdinalIgnoreCase); ConcurrentDictionary deletes = new(StringComparer.OrdinalIgnoreCase); AsyncTimer timer; int lastScanCount; - public Tracker(Action active, Action inactive) + public Tracker(Action active, Action inactive, LockedFilesResolver? lockedFilesResolver = null) { this.active = active; this.inactive = inactive; + this.lockedFilesResolver = lockedFilesResolver; timer = new( ScanFiles, TimeSpan.FromSeconds(2), @@ -207,7 +209,7 @@ public TrackedDelete AddDelete(string file) => public void Accept(TrackedDelete delete) { - if (deletes.Remove(delete.File, out var removed)) + if (deletes.TryRemove(delete.File, out var removed)) { File.Delete(removed.File); } @@ -217,60 +219,167 @@ public void Accept(IEnumerable toAccept) { foreach (var delete in toAccept) { - if (deletes.Remove(delete.File, out var removed)) + if (deletes.TryRemove(delete.File, out var removed)) { File.Delete(removed.File); } } } - public void Accept(IEnumerable toAccept) + public void Accept(IEnumerable toAccept) => + AcceptMoves(toAccept); + + public void Accept(TrackedMove move) => + AcceptMoves([move]); + + class AcceptBatch + { + public bool KillWithoutPrompt; + public bool AcceptAllPending; + } + + void AcceptMoves(IEnumerable toAccept) { + var batch = new AcceptBatch(); foreach (var move in toAccept) { - if (moves.Remove(move.Temp, out var removed)) + AcceptMove(move, batch); + } + + if (batch.AcceptAllPending) + { + foreach (var move in moves.Values) { - InnerMove(removed); + AcceptMove(move, batch); } } } - public void Accept(TrackedMove move) + void AcceptMove(TrackedMove move, AcceptBatch batch) { - if (moves.Remove(move.Temp, out var removed)) + if (!moves.TryRemove(move.Temp, out var removed)) { - InnerMove(removed); + return; + } + + if (!InnerMove(removed, batch)) + { + // Keep the move pending so accepting can be retried + moves.TryAdd(removed.Temp, removed); } } public void Discard(TrackedMove move) { - if (moves.Remove(move.Temp, out var removed)) + if (moves.TryRemove(move.Temp, out var removed)) { InnerDiscard(removed); } } - static void InnerMove(TrackedMove move) + // Returns false when the move should be kept pending + bool InnerMove(TrackedMove move, AcceptBatch batch) { KillProcesses(move); - if (!FileEx.SafeMove(move.Temp, move.Target)) + if (FileEx.SafeMove(move.Temp, move.Target)) + { + DeleteTempDirectory(move); + return true; + } + + var locked = FindLockedFiles(move); + if (locked == null) + { + // Not caused by a file lock. Drop the move since it is likely a + // running test is reading or writing to the files, and the result + // will re-add the tracked item + return true; + } + + Log.Information( + "Files for `{Name}` are locked by {Processes}", + move.Name, + locked.ProcessNames); + + if (!ShouldKill(move, locked, batch)) { - if (move.KillLockingProcess && - FileLockKiller.KillLockingProcesses(move.Target)) + return false; + } + + FileLockKiller.Kill(locked.Processes); + + if (FileEx.SafeMove(move.Temp, move.Target)) + { + DeleteTempDirectory(move); + return true; + } + + return false; + } + + bool ShouldKill(TrackedMove move, LockedFiles locked, AcceptBatch batch) + { + if (move.KillLockingProcess || + batch.KillWithoutPrompt) + { + return true; + } + + if (lockedFilesResolver == null) + { + return false; + } + + switch (lockedFilesResolver(move, locked)) + { + case LockedFilesResponse.Kill: + return true; + case LockedFilesResponse.KillAndAcceptAllPending: + batch.KillWithoutPrompt = true; + batch.AcceptAllPending = true; + return true; + default: + return false; + } + } + + static LockedFiles? FindLockedFiles(TrackedMove move) + { + var files = new List(); + var processes = new List(); + + void AddLockers(string file) + { + var lockers = FileLockKiller.GetLockingProcesses(file); + if (lockers.Count == 0) { - if (!FileEx.SafeMove(move.Temp, move.Target)) - { - return; - } + return; } - else + + files.Add(file); + foreach (var locker in lockers) { - return; + if (processes.TrueForAll(_ => _.ProcessId != locker.ProcessId)) + { + processes.Add(locker); + } } } + AddLockers(move.Temp); + AddLockers(move.Target); + + if (files.Count == 0) + { + return null; + } + + return new(files, processes); + } + + static void DeleteTempDirectory(TrackedMove move) + { var directory = Path.GetDirectoryName(move.Temp)!; FileEx.SafeDeleteDirectory(directory); } @@ -321,28 +430,17 @@ public void AcceptOpen() { AcceptAllDeletes(); - foreach (var move in moves.Values) - { - if (move.Process == null) - { - continue; - } - - if (move.Process.HasExited) - { - continue; - } - - InnerMove(move); - moves.Remove(move.Temp, out _); - } + AcceptMoves( + moves.Values + .Where(_ => _.Process is { HasExited: false }) + .ToList()); } public void AcceptAll() { AcceptAllDeletes(); - AcceptAllMoves(); + AcceptMoves(moves.Values); } void AcceptAllDeletes() @@ -355,16 +453,6 @@ void AcceptAllDeletes() deletes.Clear(); } - void AcceptAllMoves() - { - foreach (var move in moves.Values) - { - InnerMove(move); - } - - moves.Clear(); - } - public ICollection Deletes => deletes.Values; public ICollection Moves => moves.Values; From 3921b92ee6e6ae1f9a54b355c85589d53c043f07 Mon Sep 17 00:00:00 2001 From: Simon Cropp Date: Sun, 5 Jul 2026 22:08:03 +1000 Subject: [PATCH 2/2] . --- .../LockedFilesFormTests.Default.verified.png | Bin 10607 -> 10623 bytes src/DiffEngineTray/LockedFilesForm.cs | 6 +++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/DiffEngineTray.Tests/LockedFilesFormTests.Default.verified.png b/src/DiffEngineTray.Tests/LockedFilesFormTests.Default.verified.png index 918c42a3f6829d2d45a33ab82cbef9619e077cd6..15aaa41c64720e062550acb5ee7701c70a706be5 100644 GIT binary patch literal 10623 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 literal 10607 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