From 5e207b96ff43f0c53591443b737cc0c64e04ac59 Mon Sep 17 00:00:00 2001 From: scumware Date: Sun, 21 Apr 2024 04:16:06 +0300 Subject: [PATCH 1/4] some refactoring --- .../Auxiliary/Formatter.cs | 75 +++++++++ .../DirectoriesComparator.csproj | 1 + Solution/DirectoriesComparator/Program.cs | 159 ++++++------------ 3 files changed, 124 insertions(+), 111 deletions(-) create mode 100644 Solution/DirectoriesComparator/Auxiliary/Formatter.cs diff --git a/Solution/DirectoriesComparator/Auxiliary/Formatter.cs b/Solution/DirectoriesComparator/Auxiliary/Formatter.cs new file mode 100644 index 0000000..1213c0a --- /dev/null +++ b/Solution/DirectoriesComparator/Auxiliary/Formatter.cs @@ -0,0 +1,75 @@ +using System; + +namespace DirectoriesComparator +{ + public class Formatter + { + public static string SizeToFormatedString(long bytes, bool noFractionalDigits) + { + if (bytes == 0) + return 0.ToString(); + + const string kilo = "KB"; + const string mega = "MB"; + const string giga = "GB"; + const string tera = "TB"; + const string peta = "PB"; + const string exa = "EB"; + const string zetta = "ZB"; + const string yotta = "YB"; + + var resultValue = noFractionalDigits ? "{0:.} {1}" : "{0:.##} {1}"; + var dimensionValue = "bytes"; + var convertedValue = 0.0; + + + // bytes + if (bytes < Math.Pow(2, 10)) + { + convertedValue = bytes; + } // kilo + else if (bytes < Math.Pow(2, 20)) + { + convertedValue = bytes / Math.Pow(2, 10); + dimensionValue = kilo; + } // mega + else if (bytes < Math.Pow(2, 30)) + { + convertedValue = bytes / Math.Pow(2, 20); + dimensionValue = mega; + } // giga + else if (bytes < Math.Pow(2, 40)) + { + convertedValue = bytes / Math.Pow(2, 30); + dimensionValue = giga; + } // tera + else if (bytes < Math.Pow(2, 50)) + { + convertedValue = bytes / Math.Pow(2, 40); + dimensionValue = tera; + } // peta + else if (bytes < Math.Pow(2, 60)) + { + convertedValue = bytes / Math.Pow(2, 50); + dimensionValue = peta; + } // exa + else if (bytes < Math.Pow(2, 70)) + { + convertedValue = bytes / Math.Pow(2, 60); + dimensionValue = exa; + } // zetta + else if (bytes < Math.Pow(2, 80)) + { + convertedValue = bytes / Math.Pow(2, 70); + dimensionValue = zetta; + } // yotta + else if (bytes < Math.Pow(2, 90)) + { + convertedValue = bytes / Math.Pow(2, 80); + dimensionValue = yotta; + } + + return string.Format(resultValue, convertedValue, dimensionValue); + } + } +} diff --git a/Solution/DirectoriesComparator/DirectoriesComparator.csproj b/Solution/DirectoriesComparator/DirectoriesComparator.csproj index a03f1c4..31dd9f1 100644 --- a/Solution/DirectoriesComparator/DirectoriesComparator.csproj +++ b/Solution/DirectoriesComparator/DirectoriesComparator.csproj @@ -54,6 +54,7 @@ + diff --git a/Solution/DirectoriesComparator/Program.cs b/Solution/DirectoriesComparator/Program.cs index 78f97e6..4359992 100644 --- a/Solution/DirectoriesComparator/Program.cs +++ b/Solution/DirectoriesComparator/Program.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using DirectoriesComparator.CommandLine.Parser; using DirectoriesComparator.Win32.Interop; @@ -40,120 +41,56 @@ static void Main() - int groupNumber = 1; - var firstPass = true; var equalGroups = (new FileOperations()).CompareDirectories(parameters); - foreach (var equalFilesGroup in equalGroups) - { - const string commentString = "rem "; - if (firstPass) - { - Console.Write(commentString + "Groups of equal files:" + Environment.NewLine); - firstPass = false; - } - else - { - Console.WriteLine(); - } - - Console.WriteLine(commentString + "---- Group {0}", groupNumber); - - if (parameters.TargetListSpecified) - { - Console.WriteLine(commentString + "Source equal files:"); - var firstFile = equalFilesGroup.SourceFiles.First(); - Console.WriteLine(commentString + " ( " + SizeToFormatedString(firstFile.Size, false) + " )"); - - foreach (var sourceFile in equalFilesGroup.SourceFiles) - Console.WriteLine(sourceFile.FullName); - - Console.WriteLine(commentString + "Target equal files:"); - foreach (var targetFile in equalFilesGroup.TargetFiles) - Console.WriteLine(commentString + +'\"'+targetFile.FullName + '\"'); - } - else - { - Console.WriteLine(commentString + "Equal files:"); - var firstFile = equalFilesGroup.SourceFiles.First(); - Console.WriteLine("rem" + " ( " + SizeToFormatedString(firstFile.Size, false) + " )"); - - foreach (var sourceFile in equalFilesGroup.SourceFiles) - Console.WriteLine(commentString+"del /Q " + '\"'+ sourceFile.FullName + '\"'); - } - - ++groupNumber; - } + PrintGroups(equalGroups, parameters.TargetListSpecified); Console.ReadLine(); } - public static string SizeToFormatedString(long bytes, bool noFractionalDigits) - { - if (bytes == 0) - return 0.ToString(); - - const string kilo = "KB"; - const string mega = "MB"; - const string giga = "GB"; - const string tera = "TB"; - const string peta = "PB"; - const string exa = "EB"; - const string zetta = "ZB"; - const string yotta = "YB"; - - var resultValue = noFractionalDigits ? "{0:.} {1}" : "{0:.##} {1}"; - var dimensionValue = "bytes"; - var convertedValue = 0.0; - - - // bytes - if (bytes < Math.Pow(2, 10)) - { - convertedValue = bytes; - } // kilo - else if (bytes < Math.Pow(2, 20)) - { - convertedValue = bytes / Math.Pow(2, 10); - dimensionValue = kilo; - } // mega - else if (bytes < Math.Pow(2, 30)) - { - convertedValue = bytes / Math.Pow(2, 20); - dimensionValue = mega; - } // giga - else if (bytes < Math.Pow(2, 40)) - { - convertedValue = bytes / Math.Pow(2, 30); - dimensionValue = giga; - } // tera - else if (bytes < Math.Pow(2, 50)) - { - convertedValue = bytes / Math.Pow(2, 40); - dimensionValue = tera; - } // peta - else if (bytes < Math.Pow(2, 60)) - { - convertedValue = bytes / Math.Pow(2, 50); - dimensionValue = peta; - } // exa - else if (bytes < Math.Pow(2, 70)) - { - convertedValue = bytes / Math.Pow(2, 60); - dimensionValue = exa; - } // zetta - else if (bytes < Math.Pow(2, 80)) - { - convertedValue = bytes / Math.Pow(2, 70); - dimensionValue = zetta; - } // yotta - else if (bytes < Math.Pow(2, 90)) - { - convertedValue = bytes / Math.Pow(2, 80); - dimensionValue = yotta; - } - - return string.Format(resultValue, convertedValue, dimensionValue); - } - - } + private static void PrintGroups(ICollection equalGroups, bool p_printBatFile) + { + var firstPass = true; + int groupNumber = 1; + foreach (var equalFilesGroup in equalGroups) + { + const string commentString = "rem "; + if (firstPass) + { + Console.Write(commentString + "Groups of equal files:" + Environment.NewLine); + firstPass = false; + } + else + { + Console.WriteLine(); + } + + Console.WriteLine(commentString + "---- Group {0}", groupNumber); + + if (p_printBatFile) + { + Console.WriteLine(commentString + "Source equal files:"); + var firstFile = equalFilesGroup.SourceFiles.First(); + Console.WriteLine(commentString + " ( " + Formatter.SizeToFormatedString(firstFile.Size, false) + " )"); + + foreach (var sourceFile in equalFilesGroup.SourceFiles) + Console.WriteLine(sourceFile.FullName); + + Console.WriteLine(commentString + "Target equal files:"); + foreach (var targetFile in equalFilesGroup.TargetFiles) + Console.WriteLine(commentString + +'\"' + targetFile.FullName + '\"'); + } + else + { + Console.WriteLine(commentString + "Equal files:"); + var firstFile = equalFilesGroup.SourceFiles.First(); + Console.WriteLine("rem" + " ( " + Formatter.SizeToFormatedString(firstFile.Size, false) + " )"); + + foreach (var sourceFile in equalFilesGroup.SourceFiles) + Console.WriteLine(commentString + "del /Q " + '\"' + sourceFile.FullName + '\"'); + } + + ++groupNumber; + } + } + } } From 3795996591fcbac6ebb1a37c0d1a3639be38f9c4 Mon Sep 17 00:00:00 2001 From: scumware Date: Sun, 21 Apr 2024 14:53:56 +0300 Subject: [PATCH 2/4] DirectoriesComparator/DirectoriesComparator.csproj --- .../v16/TestStore/0/000.testlog | Bin 46743 -> 161673 bytes .../DirectoriesComparator.csproj | 2 +- .../DirectoriesComparator/FileOperations.cs | 4 ++-- Solution/TestProject1/packages.config | 4 ++++ 4 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 Solution/TestProject1/packages.config diff --git a/Solution/.vs/DirectoriesComparator/v16/TestStore/0/000.testlog b/Solution/.vs/DirectoriesComparator/v16/TestStore/0/000.testlog index 8d4cc21a1c0a682523df19ad10be9b2bdd055a25..6e56e021f56bb6e9ce3f26f1cc23493a0dd13b05 100644 GIT binary patch literal 161673 zcmeFa37i~Nxi+53B8Y@7h#(=fA>1UA8fsrg5Qi)fLP*Gj0A@l`%c)75neL&xhh$ik zKoB&bD8Y?IL?W^%L6X2F1X_uBy%*b=_KLRf*ZV1=AEF{$1VrKgoKrpB)m=TE>Qqm@ zB!u6ON_SP)oT~SI&-O0Q^PvxA=4R4l@wic=Moq;3^uP1Rjv94yOCF!tVRT^%U;K}w z|5hD_u01#E2>eo3B}KPXhf^F`5-Y85F9Y=K>P3Lq~7dXwr zLD5x(GYm&EB}Y*eo~P}P-bU6CyDyVWwVix&PdY==8PhR)GbDBLB|_nZ#rVE3mHY&; zGeYZmnRs`ao@t$%?ntIG#GzmA_ka0P%iyT-gQMO%IBL}3sDr=Jn$5q1{|Xn)Z0kHf znOYT3bajwSXFA!JvPrsgRy>72oJ_?@dS2xrlTV zGfgTkv^w40_xpdjF+nmif8*7K*!&K9epWnfCodr>lDb4}r6*=~o9Xm9W)IoWvh&~U zxc0Ki?U_s}ZuMnIdUBgEWAaQhL%Ncw{>g2VC(oEXi=^#Tyq7+(cVe!Ce|Oe2Zamwx zNH>03dK{cvVs`hD#r?em=R5kLjh@yHw4Lahe8rBVC;Q*Btc=NzR5u3ow5R(M_J)>W zFYWkbQ(kMRCEx25+phgGrzexpU;=M5&NaK!R)#=#m#3k`mGSNd4nb=3$?>+1J*IRad zXd%2TsIF{tvTiDzWQhVtOdAKHi-Mqun&1))K#DGig5z?k=JK3v+B)YD)#5~369mcD z6;-#{(31bpl{5ZWIJv@X7n+%skYwDUU7cQOEq){P3O%u@`b2R|Ioumla&7T9e&`J= zxsUztWBJ^&S6;d~fA_ui`fy!7ciN^GkIMD@?C91VvC1A5c(i&wE5Gg5Pp!&dx%9bn zawo5R>WZMzZfMC(ng35K|L0#GwKccqzsb{uCDCmm@QAIjiQMXkKREA=(|h$%qjz2P zhO0`3>lmEwI1Xn?rppoAHZgq&2IdjRvK78CMGy^QNv^{=q9}2KD=D0#+ajl$u0$+R z5ma0Asa~#7{oDj*m1J+(o@XW#HpbEf{-28>m896@vbFZic}PdEz)(UKj}w8X*`!_bHzYZ50Z zlE!JOs&ay^8Jr~X77=)j*D7qFt-=OoCo-x2xd}JPy8g@*G3huvC*DoG5w+s_6Fa$H zGzqLX=whRZ1H;5hlc;#8CfmcJ==MtNM|K1vnhuOXG<4N=6b^b%9#xfXNzn{J@C^uB9b=fAxCEnryo*@` zzR*cxXij*n-o=qJgWS1CA9BjDE2s@EjZXpjTmLe4oi|>0D^I?BTLksEy6advI-t%A z4#(@d&Jo2`INg*DkvNX7N;bx8)e#ICa?qd4$$}udmdN8*l21V&3#*{>5_YnuCz+^LMd8E>O%3<6 zy;5WUHSxOFJ|972yn-I#$^vJ~mc;4A)i9tbCg<3SMGW0FEnC9I+AuBG5N%Gip*Bgv zI@o|hIaR>Vus(7G$G`d&!fI@2FWkSiLPMp~d!>bA84C;7wH?!uEk$*GV_fAVRcKPdr`u2QMO!8lnGXYrlaz_ zsOpN0!Bdc3>>dr7<83Tmc*(+~Xkt+!+q!A;g3X(*<1>Zn6@zE>qn|-Ci_An9p+CCc z|7E0g7D|pj_>dmgb!|2+?ygO0DfNrIb#LL+jKeZn4D$tGKWkUQLIPBjILx*!1TRWcuDmU;o6fpbZKC>H}_n!0_sbpU- z+rU2zUDP_iSE^;pJtuD396>F*t+>3Q$e6)gEbA;o;RFp**CfZ{4G9i=1KTLmhC|=g z4GsgR&Y9SFak}jqoMwnnm+bI@rTf$}t8TyWsi}I1?C2$S-0YqSCwjUtHRKQXO1=H_ zxIsi%BKX5BO_l`F!t&iFoN4fIirF&Z2-X;~3U8P!VCBIh=z`da3|FWPrAdX(n+I^u(IMvJ4eI57FdYbUfKK5Ye>s!W7#T44xoxz|!b8Q2RMccCg~DL%)1%1Uqmsof?{h9iXNf98Y5vrfVATPCs|h;3>H%tN=a``~2-R)bs%_~Rr_c5stGeGLXqnu6t<9JmVeC>uCFr4gEE zhCvS9nB>__re+8cJw}O-f>a3qlRgyij1k4 zC#nXYHhQAy@({FU@uEO@LFX+j(-cF|5jN&j#2DcfGT;?Ll!-&6Q70JY4YgwZTPd!<@lU-HvyqxiTTH~?f@(I9XlV)YDH0m0gcGkHZ4W$b1| z10Fkx*Gxr2TuBuX+7ne#<G7u=zY&gc?)pihjaAZz)bzK!DNtR^nG!6X56kM!$5m(|A z7p^rygpWs4iDbDF_L(}{(6q3nZSI7#uem6H-{Cj>vnW!3jGRRw=^%GPbpp-0M{A^# z%}$tBH*q$!)Va9hs>%$lUCfe0I$5zbU#gb>98!a-^W(}XWne>h^0W9t@!XbglK|(Btd^W7{Bpqu!Npl4vDYUm>uPCS@(M^fwE~&_K zAxK}q;*XPDY!h7&kb_>1dxD5bFum5a~)yqv$KeaUILIS0P@ z`c5np2?yVQc#N9A^K0wx3uPYpA9LSZo`3b=2|o#|fZXV(myPq3@UK7RZ-}A^dkO3OqBA+NzrV{5Xe!CA(MmWK7ZB4AHvVz)*R&eKe!o4DRY zQ&hrPzZv~{?xf#uc(tAq=IlF4$lrJTiYQ7zE|-fPFzjE3czMSlG)WWQejR&dm&cs% zAW1~C5w5YZ97YHL(QZ1m7@}!&h-Bj*Y_E|>UhWC`-}L?H&fJBQ)^4q*gbVi_C5(CD zAD@k)1WiXQ8dlrSR?AArDHm<)&mHrbkJs%9@qI@L;z>6g5k(1t1+iKfS$LHeO_(}7i7MT9 zz-R9g7o!i|j_|x|NTv)e@rYDwy5d4#h@lbWPzesY3-X(NN|^AW*t7ZVv;X;Ky`HdU z-%-NC`J1;!Q34VIv4hZgtYKLW8r`QWNE|>i8p6YZB_Pij-Wf~Q6$e`m0ls=@NkCVj z+2#UrJ>bJNCDHIt%rh>1X;%K$MGs_)O7J_~atE*a=`mDc6L*^uF5Y(6;q}*Ln8%|` z%&VR~>oZZ5AgUUHo6CXJ5vW%odt^C56G-vb1yhwBBB_NbL{)i7q*Dd&2pp0Hk@$)I z29j$e5mf@B<*2^xMtO5p_QzbZv)ayDzS9B)e9eA*bjWksu9O6b3T(}E~U zP)q|u4v%zq8G{h2T@X`J;T4f}L=mwnMce>$g6qnn>L8XNNG|s1SS+FEpgSNaFR3)! zPvDuexTu7eKQ`@{{7+~6;HIJy{251in(aZAaLn#f0?Sw#Q6-4iekRgzBsi+fBN2@H z384vATjFR)AybeCt0^w_2?*>FA_|INBAJ$ExF8oDetj9k7cawkg31+B@d7%bo>2S9hs zNEg>^0h6|Y>M$EQ5eTPSblYY_iwL=yrhj5qemC`m+{AU4Jy1^xx9>YjIQNvBRz^_* zc4~-S!(*Wfx`j|B^0SZ~iLau9%zjDJG=j~VVwol~h2SH!bsLigOR=LK4#LAN>&QrN zU>PUHo^a^A4?mK7|BCLGdP>-_%Sxc7ZwfN8bGl~*uQi&!BSd&V0pchpF zuMpxxysjeG)xl)o(#@J{z&nJzMa;m+uoE=`Z>^$mGNx-$lMLw1w`0z&?rY2DdbhuC zeH|sVjM;aTaMBH5zb%RqP=P9&HddP${Y{7->2eZwz%)}48)H*(uvtKmA35MMUBfyq z;(0ucRLGiwTx3naT&|#I)nK8#;>7&I+iy?LISVhnq^Jac#zt=b(H~ewC+11Jtb_&~ zc=_$0x@f|PPR#aY>u!vq1Ou@LWYHs1N-PvRpkxKHJKzcMisfK^ij}E}IYG4q6#XI0 zitPeI78(K+JbW57?MAVIF`%ikZ*`PA^t-2a`>7P7LH%SXGhAE^DSGpeNV}p}~y-->HS^8+`!fk0yc;n&Tp3Eh0b5 zE5|A-;il>DoSOgH`nz5!D#2gjpWkxSM<&rZ;o#k+g#0%9ttUrxPB?w-LytvKf-ISE z)QLJGoABLf1e-Mn0X0q&UCb4ht|7Gpu51-$r8M;o9zFQ8MOM*hprX-oBox|U;_wPR zib{C=o-efJUpw#5j~10s1n^-s^|`Un9{40x!eP5h3Aq(#ZJs)!N|@KTHMtG1k4_*2>sFe1q&f42Qd)KFbci9l<+rHELn-@B z{kUJ6Wr@6Wc-MHXq);a5kc!G)eEs&dH?O6<^=g13g*Q)Sl_o_#uaYnV|#d*pXF{v>#77#C~ysfl-<9lSM60zvk7w`-pX z-Wq1roc-XLho2U_HB6i^d%5$Msli*r1lzNd#@%&D@YXPavFzpVJbZ7BTSLqS*|*pI z+mzs~VRm@g_66~k!CS)wk+Ofe_=-1!w}we~%Ua2MejL0tjITJmZSGmO1#b=G;mjU7 z@zNWDw}y$|XUE;&_V?heVZuDwyZX|bgSUp+bYzpSzW!YB)-X%u>|-y#kOKq~XOn-Q`{m%RMu^(j?EJ@8ek*uum;#;b zz`~vydJR+Hk)80xf!<)NVTuv5Ew?YJv2F^JFrV%F!OL^1T5V+Uxu9|-kA>b4;%gNU zEc-fi%|n9?V|R^0aOCR+v6}+DIHE`jqds!Qx1)$OOn+RiKFVb&aH0#MIA`LUIVQg*)^Pz6= zch46ozy6u2QA8SMzHhW3w{8@%DIy)w%F36HTYFa&k%n0ZHCpJJs}~d8^F`V^>AOFQ zBGNGH!$yl$bM+#8d%j42J^!k|L=kD2b#tSIrulmDx;ENUmN*LUTk)iwv47QdTJ8iS*RJz9-UB zKa39ryQhYLH=VY1Uv8r$k)qDXo^T#szGx_O4B7gkuKIY-W)}wVFDvadTNM}p)NE;b3{6lxcR@k;rcH{ z5owr!5k!h)z3{XKxq9FLd%j37oBrC!ld4^YB>0HHlV3Ht$r_5da92N2r167~ZKQ3CP(07CUi;KO8=?*|ZK zeBxC!%)TY+egL7J4o4%8*s&i#Xb(`regL68KneQ+g!TX>><19q1C+2IKxpSm*bg8? z_X+y}gzE1T!jwWIp0FQ4sGci(KY-9qhog~)(%KIov`7AAW7ef8c$%;^T>Mua;Z=@CWCG`>DC@JNF9_4Qv?L zHu(A2;MId`2c8(%GI-s<_JPL-9vXN&Ht@vYl>?6tUW2b&2R09E!G%ZYFK-yUs`v|h z*fO{l$4x^&{xmzWcJS&L?s$A)8}8gbxIQ-U;Nbefs|K%UXXzb-SEDg@g*NiY!1wUy zx8eVX@cEG#PHh=@7=P+YTqr%xqxgeQ;1TdpIK8R(IMX`F>88D^uXiC>)#BY|7of|g z7w(9~VrC{rS=@>cZ9?npL?#7lb~j1SLKv6epLiD|3138dK?X|}CgX_=y*h1rES`w% z5`vn)$|ZsAFlcG?M=7ek7eJu=KKiu3x-`s z0&Xe?_1?e@!9VLnm!2o{and@Tgo%duUe*%H8$y` zyza5pW;&KxnM$rsj6cYw-0m?u*_X(~rip<4mbB@yt`q@-XbL|v6R}H4Dmnh3Iq_6F z6Jx*5w2eQADmb2SlB?65rrjIwNxH30cX!44b~}|!#M7NAVkMKAwt#0Wtp#xhYLo@0ExD@VoDeFehlB z-v*2@pj3HKFA&E;$92KUqZ8;Hz`+s`#RiC}%IamMj}wD8->v#`2LrdGuhU3fvWb4kbY;#MHNG&YO4W?y#(kj1fOoi%}rhdE23kY^FA zudDWT3WPj4c5*t|m$FHl-PY-S5;|k0&thlnA{lz!`{Z5sK8u}!%Tj0HFG`(k zoktl67!5&%slT^m;ob*n+W$7))Q|kDe)8G~rmk6*AOcbz)4#;V2NBK|c&q?Oufy{q zYYxE{A~YdD+0+@z2%RoAludo>&}@-j436=VofkGXWX+Xi_q)fIH7xrIx9nNA>@#I* zgp7f~JNWmp#qk!lS2V(f6Ps>?7ryz-xG0m9CBjoG@eYXSM9NjFVfA8Q+o2Mbm>@a; z!7rGKLX+f_jgVnnQ6s#$WQ3KI6l2lx4z+}~aN@`bt?QTxw{48jbHSnuN@PLfTp8T1 z0tk*d70zbP)pb*~=mbXB@u6eVKA}+*D=M@vm4p^*k`k&Xsc$yatrz$A#%;6vytLUx zc2B1kb#&^x_N-1_Yf@spn=%bCx}l0GW~g_U40ZLiruXjOw*T(=D81VR3$*Hh*UePH za3xq^?v@0wX~4-(9jxF=w7^Xnnun}xs0=BD8tRuzhFaCTDNz|?E2|LN=whc{J+1iR zrNvDb+VkH!tk5&Af*GSB*EE=EMNu#%5Tt@t)ga)NR~78)L~tm9;LubBLuw#1-6u50 zZwsM)r6jb`gX60wx^h3XDyiiFFw1>FuO{mHFZ_ zYcf+?e>LV?7)PiZx%^j`FQ1)CB~z_%8_r$8K2DpP$Vg(0(9<)M4w(__$fU65jP;oP z7Mau6-A$i&`uKyY{}g>d{FIn@T(}*k6>o#HaOI2`y*M9#E!M;SB>mcM+jJ8PGI{(n zBjz=mig&Hd;M?iRWH*7EvoB2+6;H9hztT*RSehP(?y&k?m!vx2;_zBoz`Uv09DD!b z@n_FGZ_(Vv7cOsKym-;v)6ZKxyCaq+c6%n1LPJ9@m+qpkRc_dtlS=kreZ8i?d=3wD zb}~`*LwhB$SDl$mXX=Zj)rQ&|mB}u@a#3R=@=~6T7ZKATsn!~=H5=|k_>j9|r1+sM zK!;?o4;%UcmGJ5P8L}XSzck-Wttwf8U#CNsP*2VcKT=6ow1<=eD%1k%chTler`0VD z?e#>7IZ7CBHak=dxMRI>R-WJ#KRmOg=>x9)%+FtrGD~TWBr6U!LZa!a;HHL;gi=-@ zh|lwuB-svlxe#>@OIcbTa2a$hou$578gR#yV<|KMMLA8qLya}4{LGe-6WZ5~Jp7d? zLURS%RKferS%zwXY#Q-rUP0s@WPS)q0sKeev3m^7c{ zO!?z&FbZSSC~=_PvRtrf8>WdZVrZ86vd}z~ehBT>VT8tL=-I(9w5_+6WJN#xaqNWC z&S|>P-gn^zY9yfv0?1~;t)?1=Ln%)kP66RNhY=1oCfQ(t$CwtH3%e{dhHy?T?Y5H8 zs>U=*mdzNm{X!eXwku3lBPX<+d}1<+&=i$n!fPC*E9DfLM1%f{l{fEN8u(#lfXhJB zVTl3DLi14gAhg>{LaQ9p7;_*y)E64UCCwhwVvnb4@EC<*#b9hKQQ(ilH1aN_-l!r% z0h>t}LJdZ66GaqA^W?jYW+bSMFytYOEG&vP!Zh+OWGD%0BMk2d<6n!SjWCV83&~A_ z+6Y5g!YJ*cXd_G`a4ji@qKk^aAvq6p(vm@wbX274m=@B}9otY%LN^Yhy;_jHpBE*l zjWBE{j3qFNHo`RWE~HcmY9kC$3S$6`qKz<(ybIY_g4zhfvBIcaqi7>cBkw{Ym!LMn z(6ca#+bG%y)5yD!1Ez*H!tydl(ng3zFpIz2=wpJ~2tx|P_^P95BTOTRJiXhPXM)-Y z!zaUt$D?Q?Oe5$U?>5q!pfDP}%(MFg?kQw-H3Jf&$nb)6QOe{r0uTR#r{p)-ai2w}xz@a1rvCi+DE&_fh-=mh3!~%GpWF+7NnN0))q~9nP^(QR)Cz!ZM8P-;Zc}?T}rTY?vkry}KmY+VzBf5!d_$mE@M1SMqn? zYcuGe(NyqbbMkG6Z7B<~oYVQ{`)_v={aM_2wrP=W{B&lwnNFW$_7I#y9(Er=B@@B`s#h>FX`9K7m~M*2O?s$)q>5 z1kdf*T=}p{IDG{Ew(lvu#%fD{X0p2*4}_664e$UAgK@ic9_eSVv(SvER)|ZNRw!!O zjH>U;mM+69j$XQ~@bO(5hWtwJtldlO^bfY55<5GI^0!zK2`4r?aY-DQH$4PcIv-Wn zA9{6gLA?$RIcY|N4GK%)?qu_hL-%cTR*ibf92BW&dHs;@~JC=CLRRAO@8i$Gdw=G`?z_> z1vMEaLd?R@H$~87m_`~6Ll?A=nyiK(*i7%MKDk$F^z|h_y*8-PFi~a}%Km%=jfQEY z(NK0l38~S_GW_q+yDCrZmD>Dp+uNIi+6)tIU?GjMl?B}mjkIAJX*8rU>`2?u+a1qf zAxG8L%D#B(6#D&vs_#Wb9yK^>)ZnOtn>WzzIB~cYk^kxHEr}W*iVI7dIf?t9vlX*A zt0G$Q)}dbxnoyWDca}?kKm-#C(@3Ma^aZ_QKKgS z3)4uW6$1r%XS!p!RdZ3ipFSg%?CWLlY!5??wa)LA8r^cwiJO8N4O0-nstz_s=#60- zX|(E~FsrUcePdGfxZMFrGC(uVgoiR+m>Tkjd!@?%dEDTrpvuEk9k9}dnp> zG%2IdR?&?sVXkLV+-3N^7#at|W2w0Q#7?dk^$QM)CNKIYRxZ#g9;(U9vqjODXBCfE zTAYpR7-a|TC`_gYODDM{!q^a|kw()=s=PRr?_7b^g7h)~!7Ga!|8jvPM{H%54!e8>W#)Q&XxoZ*??V4WqriLbcUb_e$N) zS=W^e>NZRc3QKhPZUo(iX{6Cam%_*DjQ$nc8xAVHaAK&R?Ul;@uZh>a7F2ea6c?69 z6U8kXrjbVTXbM7DWe;f86X(L9{+6RsDV zEGe&Y!mYZvS88_78S(1O6L`(TB$TtP^{S=Gdlh&pupfHFX}f z$#%3Nx*gSd*pg+9%eXaM0AWh)SUumU2$mJ55i9~lgIJP_EIUyIT&@e|Ku5PlFc7#B zu}~nc+FH2|yvjEVI8rby^_Dvn{C76eohZE#{Igx~>`*J)TKja-s19qoQ5|1tRMk(} zWJ@|Px+PUVVaa^v%~X1V15=nPW>zZwdW7jJOe2k!N*7M97?^erCAtZjQxpui1piyK znZuiIGqFmW2|QYpjb=%7qX|4>$!gv>y;l!fjS-@vH2bG3f4TmZ2v!rO5iD{VDqAhg zsIVG3>{b!zV8)_n*3Mm&fqxF+X11gMfO zp>U>-$!RJma$HF_iEhwYs>R1#d*9(V{IjTkzgsy^y>IllCortU+_G0*x|yX~-?;A4 z>NH#|qh}{f3zV4~TIyWfaaCoK=`JSymRs{>o0guScEV{nD|Re$A;{x_H=tdolrp@b zWhXz_aZPjHq@q>d+mxQ9_S+04FEgL(_Q1Q$O;eoqS)lwRi486FukX07Id9@`)Au4( zr|ab_hfdoZ{q(YNo?H0e&)xdlV1Kks%~mwiD z%HI&wpRFhWUB=qlab?1}Hkc_ez`C4ip`OT8bb;55?C);ZJ`+WMVH$z{G+EPh5%A-d zW^qIj430Mq5raIq$V?R=$FlCzALSQjoVE4zH)r3`U;e)1R|NH^NRlhNpt_c22#t3P z3JR@hoT)p&{o{E>a_sD+ad#aOMSo!$X@Cip&4-KxmC=XR)8B>rj{e5H@Q=?1^+y5r zc|f6au7&lCrKA5jvLtefWP! zap@AkWm~+Jz1;cB)F}E3(+Dk*a}CLqVMSmY0&|1n!k&06k`37v9E=2lAo=t+f%02# zpZ(7_>*;UJzN5c|^EYn|>QA;MjTdyV{W&7&nJC`5s(@|?SQI+dtl(%)_VRZgzBh{g z!Zd=MWJ}f+2RyZcNhk#zD9upL>v94}qD)yaCDHJ&UuInT(k#Z$ThyQ551Ko8)lZM1 zx}Lb(^mp;LyAH3v`o(f5%KBy1vuAxKs6SEFh=J;7C=Aq4D%8d)Jd{XuQ5Q^Ac8H{A z|8nsaZ${Bym_`~P6!zx7jn_;P7@=-ae|~>Jen(r&kyL+Y?JoW0U%dUqD@Rm+v8Vo3 zV?S>Z8~g&G!^`!9d@%>Ur1{ywm~^q1>zedo~;)nEVpn-&E7pJEyqBYBAf1r86MU<_Y8qYc(A zhhQ}?I);^fYT}(|N6}xHMjBu~@$~od$EF>_I8BQB^VeapM0TpbV|JJRSTg>I>QB7( zGd0Ffkjj9~!?i*1p+bo)=;CNRh>T=I)D#!{KRvr`?pe1*(O;NG8ld}O`pZ$KA4cR; zPk*QGJNkQI#+ZKv`=6|-s;Mbp>H>)*xbBG!x-Q+|bP2RK7Ljc%M6-uZy!3`B`U}$t z_V13WXy73N)sCrfwh8oR*|g|R-i872s%x75^$Vr9V(eA*^mqHdqrY=cxoKrkf7rb9 zM27237j%o$!1>ELrh~7dLf|~pG>zEVyH}k`|u---l(4bcI>kLXkB>&{iJ*X6h(hw8o~ZOEHR%qey;9o%QDKnI{IrFv+wBd zq#M3|TTp+lY|EyN{R3t?6Ivti7sJ)T$qFJ#aDY141ZLM1o_#us{=zhZd>TQsWx9)T zTtVh|5lBw5rr0#srob$lgd7bvFj}XCUZj5=?y>v20EiFyCO}17De9IoLetyl9%)_66~kQS=w4kp{@w zz5aLTcTeqNwChFv6|sO=ZF!EOWl;Scvb*%h5I;s#f0wVj=gFY{T-gyU8CgC$0Uaa} ziAzcP47jr;aP?W(3kq8HgJ&LoS`__-X$0|H0-p~r;Q=f`fQ=e`wXF z)z_bkqQ5YWApU?Q6mb=}f>d7QEEkJVSHQ~HB#4nnhK^vMKYmn?J*3qC_e_4*?tl5WI$q1?+9!-TwqF06z3=F+aIWx7P=B_pD!hXPNtxHN zesN`$b6th*BveCELD*~wa`wpYZv06U{e@`+`#%KQ;j}~4!NO7sJx|9b5RpmEagi1y z5?MA_)@E`2a?|v8PR;*p{avpV_2*By%x^jBBa^7E58hq+%Wt#adU8bPzth(~^jJ`T zvSh+fE$T>}fa_W#*uOgnyK|c8VqUa#O|?k&?REb)C5rySG=lh1SUy+JfA;u2Uua`Y ztwsI$v-fjjpFQwNs=vc_m;Q1q&e}Y6MD;hXZ)JC*n_Il`3m+Rm zUJcVke$%|%8TtP^?HhlsjnH}EbJnQo$NkbQBXmCUkN^C1l{tn)d1XMdyZ$<1uxhKU zhDxmha1^g|(AxiV-|gksnYMoH*Q;J<43-3toyub(k!(vtG#mSL&B9;_KwLq!a3Hdq z9d)4i`%@~jlW=P|z|o_@t&UEL^b{FGu&AmWvZ1j0F|ltGZ~^&<2)-M31KEP?-MuZs z31?q(5qMbn%+qv2c6eac?2dVh7cAt|GbR3vnM;PSZ4aO%)33fW_|6>f z!|%SgF5Ig%Kn8!!8BeVWiXN$vn(hFISQL1yp$!eIG1UcnuC9qZPYlgKqGsWYv!_HM zsz!2|P~u{s1#Z2~-GOK}7jJo2Fv8+@Xt*$q_cJ;R8eWj=U^gICOd z-;lh=cw&D3*5|zszdz!zrpx==SGO$*%3HS`mrfU0?kbplbxgb}CGIvg(Xm9#E6B~u zet*<+4@Hr;j=rQ)eIn!4Mpwc@18!Zy3E-ZWh^?bIgKr=a&nIt|jR$!rhLLxkX6ms+ zkQn^ccOd4Xyp4Zry1bv+_S_pmd26;RyEc#24z+6D(J*nVFmee@g>bu@is;(eOZlnm z9;+;uX=rGXMccwY3OQYt3G`{Yx)WVdK%NP2%gBclbWv>}an2`inmtEFoh-?FOyO_s z=`=}YS}BHM!tU-%Bd0aynn+@IT4Mtn2DS};J~nvu;M##F2DS`dH?V!+@qvd19*+$? zF?i*`(+tI16y$65&Fv;2Cpjq0w1;vuElZF(2qaOPOKfgI)*zQAJ~RFw-2t5 z4Lmrwe()Ba)$Kcgyj9sCPJTmY-{P}J8{~>&SB!*L41|G(rx)K*kkMk)0;1hTR zJQPlEDn8D%4syC_uj=bvh*aHpx7igZ>FI?#VzHQ+iB;tCH-Hc@ZF(%8h(%9>uWZsz zw{-)qJf?}`55g$Vk{rE*f2f&WvUu;qpT4o9>8AhIzplC|X!^Vb*s;}SI+j_PO0G_fKggxE95FlD2QcDkXk3-_ z>9H;fFhf%Kk(r2Hin6ou2hE8CIVi?{ooO3?5VehX!bz@9cbax@yeH{WAp45*?KVJ; z0o*%vHs#kRQeYHzQd?CCW#on~(@Ag9rTJKKjo zEpP9}(iJtx<)Uz=&T8|(`W(kOKTJUngJ!oO7)jUrvPjKUf9)^AII`|tK+rXrZcQYjDuBuF|POS(7}$25nMtQbc7l}V?y@YP|g zt4@VuGfk?hnITKk6mN_n=Fc~>#L1eL^oQ#`OZxjEH#FUn`d@u$LeP@n=@e~b&T~kF zL-0YsCsDL1b-AI-t|dE?=w^-0?;Iax=cUOak6aLhq_Dr>;MR4Ktc5+VOe}(3pXTa< z(SQrqXGzQt3rotBEXlVVqD}_tqh*I$@`jj;@>agoba@}J==dvx@^(=UL4)f3y4TaaMCIQKndW~ z2_14O%R9&7PLOwBN#3IiVzKA8rwGG~E$zByuL0O7z^2gB=@%;xtnxNS+u`)GT84b=AI$au`jHot#egrEJn>w-w2# zgw9y$v)CCsIb)`}NQPebK6%%@&thlbveX&)i&7_B4nOnC#ar_9P|-`6|LuRr{ayKz z*GpbM;{#3aCH&TJ-xKU5nq>(hLN8eANNiLR;eUhw6VV|Z&Nx|f2+4l+zKy4@jnGRh zLsfZ2(U9YZ?I6k*1O)C41>=(~83J!8hK}WM=)hjNm$2v_?I4$wd&$sl2fve{xITl~7VS52bkptkiOt(S7qnjs zt}jjE9gdgb@KRI_D>VZfJC&%!L@W{2aYEMFaNYVSv#KofD&4Yim|Go`yupZhgiUGo zmjfTNir}}>Kw?kXeseUthnnu{lKocBsx0%zJJgbQ;^>i+_n_1EqoBM|9fm!upmFdj ziU2Y|3{pkFgafVu+%0s*#ZKwRU;Xzf8zYPtj)W+uf}B#+YTJNJK%#+&1awZ<6uM2b z2uge#NW}5Un`YxsQLib1!xI^k!Jj1Ag2yymLvD5&#OC4`GC6x&Jyz(WwIqV9TR z&|7+T(wX8hQN|Prktb6o_^a@dqL|k}20V(_If`55fPhLc4cK_-WY4mVvy4w_-YhWX zg_6sTOX?_g7G8RZckquXMeob&H}l0Y<#)@PF7H(r-~Col-mW5uq5wn&*+FrTK?DWP zIc&M%x;2sZZmNPIWiR;arAPOSs|b!a6eE#j;7mYqoIp^<0tYmT#|&NIEJ=Xub-~gE ztU-u_R8Sqs?Z^egaPPR-pV>ToG&1tm1e8$7#AQQ=Pu{G;3-Z3yH>TV|7t_U!a%I>c z2z^wI6GeT=WOc0MUv7(yKd4B&H+MlRb*7w?%*=s@*_l1$f^Lh=O!jpM@?TxPe0D08Otr!ZJ$C{7I1RvFk{BcO z^vt9~X2d*%lUR@0Z;?5D-QDy}rjI|U`cKgZ#7~LYg9uSPGp%?VT+b_K#F#4xe=XL- z{v`d{ZrjwufYNdNGb83Tn~Ha>%-~xQBPQ0DCX0%v*xz4irbsMJk3)A@eXdJV9dKQF ztt?=^d3Y|ofARRUXP&oc?&1rVw=Z72XzuCfEuP&GOB0(iUZSC)mrHli*D5z`%}FJD zunk$$Up|M2IXjuC`k}p&*sIP=rZe?L(rRN<(x^;!`ISNDndpl3jL1uQI$lIfhoo9- zyw+@l2N99zijm@nvH%^D!FF}%2UNnR_h-n06#mkDGqtK@1%90lSwcNIH~dH?T~$Q( zcHTvsH;HFf7Q27aBN!Xn5{nY^V&!S&C_7ZljiXCLwD;kS3)VD!tUjV;``?3OwdMdh z%fWt8r06-K0S6X^jX>rM&s&mYJIE!>{?A9A7!ze~6ctp-m_WOL6Q0M)UIT6rJXlzM zJ802V1SIh{P{>jqt8=uPg$~n~mB#8Zm2+e7_V=x44qaP_$12VOe3sn=qdn=vPXRIuD2t}+h!3CWM^Z77Ro3Em}MhRIsZN5TQmq8BPn?hJO#}M;4%}khdzz*&oep*%3wFNY*6CG)MV~X&|V8 z%p3TFv8j|?-9p$&L>@ZUx&-?y1q&6<5D_{=6aWqr8OtJGhUQ&WG8NNHl=aD*R=ZMB zUoo7#S1p?U1S^NFkauzI2Qe4r9sg_7<^B50lcojbjgn79UQNVDWtXD$p)d|RdI_6s z06C#b6d6N8cKn~;`dbuv+XNy61|Ou1wY+R2v?2lSgp&=R3eXH%Fpf7+7+#ilo>hlK z-k%&s-mG$*9sKg%{DqR3*@q8(`fmp{UEc27m;I)OyafS;PpBDF4a1=|G=L<8RdE>2 zVcC)mQ!}%@2fXuS6nPWi8X_wLNf}7W2hav2?;`qvbTa|iGpHD~=-wuDA!%9OIa*Ch zMg6IgysO6V_pj(~VdbWNd5`kOZz|@IllR0U)KNisD=K3p(>PlH!U4kqou1g(+wcJW zp+P@@NM?_3dtz!7dFzIvW8RfHSHj-L)zFh@RX#H8iH0&o6+veQ_7yg9yDaZK%ie~( zuPn*Ca{OkQ-Rw|T-q#-8e1G=$$9%sUDYlW!Z70EAMp7qVB0M>imOAPVwitR~*|KV)0f;9| zemP5FKV+9B8>Wdu?=DGp_~6ixh-?0WN^(ohE435op#%0`c~SZ1`R#!1@Hd0IiFWjhIPqXbGO%vAObLl^K&~A~M~TO!ZH0n~b(+k+hwPGY5}%Vy=UK z1Ap81lwM=Cbucs8-HivrIGhHz1O~~t-8zr-v)5T@##1ZArAvz*GtXPJY(~}hWlNV$ zzGBDdrOOHpes*;0j(s0|KMeWLeukk`_26G&CHo%3P#Cs^{ge#lb#`6zcsEcoz{g@E zAp`l3l8acUY{8vH-I=y!O0+7>)C@N}u(0QrD9kTm8bOXV@~$-={xo<`0bE7>AF_id zgS*K96ugAW6$arkn$=epIJ%-3+LpD}PGzG%>4+nFj@(=RSOan(!ZOx3=}f7l@TmDn zO=j`<_%3a`{F3Xe`Isdlk5$Lo_Xamg4ge=K2XS$DH~<+Zi9nAO5S6!GQwP+vYXbB( zJK>81z3VG?oegc2!Zd;`PWU4Q2bfEmiU>6zXk?0E0^kWi;3Ix4%7(*$mx@*+`QN>c z)%cS`Hqm?hCq~MG7>>`dy97Y+ZoBnUtMXSaeeRsl6ao~B$fJO`kDGT~P?N}MP!(Bb z5R!1J8|eR{i^50&*w-{08X!zow&nIEFWnSDlVKWxD?@?940#qDl8MmkB|s1opur%f zg#sPTv4Q8qAnb~o)Iw^K5y1PBXE)RPs!#5f8hw4qPp=JX)IlIlMj<=IhzOvm+6sp> zbMy*;h>Hl?0ZB*5_Wj`HIZ-HL!!&}bE?zSgO>hA14Bxh>qCx|mns5N^HdI=51NsWj zLH3_3XZ*3Cgw$wd7U=irU6rTyN^O3)?d{D$ZQ1}Lkedd75%)W+3+Axh^ekQyDP#R!F>42z5MT3J*iusuUfflfrSURXI3#ZsW z^$KlzU5ZmL^YuoBvD{9sc_uHJgds5}x?Ry0JNKKx#7e}A9 zs~)g4Utj;?&4&c7NHP%GWM(5GREdNu1l?o?5ejTqUR06RDP`~Z{Tqi|5n+@M(+KDx zL3rXi2=k$G3%Oh<`~*h~%|Eww)8qlv2I>som@vJr6@i&;k(uaXb#auYt@LH2?1Uke zHg$$(Xw}{f{oq!`4eCw+t|e52vb|33H2nKl`)$Mg4GY^@0afjWhV>87wH?l~0S$r;H}Kgk8$h*6cK%~4zjbp2m4|5r z0cR`$L8m5js%C?)2pOKJ%|MwPkONhu-2#WEVwqjJDD!EKnnEjEN0T-2O#j>j0+;Db zyvwA%`bUPluvhBz%Wb#r=Um>;xm>DVteqLqDCaVOb2Sr?xr&1|kcCV_RQn;P%|*YI zkzs|&K+isJ{&~&V2rGLMq7mc}x`F{9dmEW`NX3_^I}qDOk?uJNP~^eDC>9eL*gkDI zA4&&`R5OS?vyp*)@gj2c`vXTFWj%N;0G6Pm>`#(V7zQ2^9^^p2g+yD$LZT8uX(q+x!5qT!>-&+?&{J{!iJe?8 zT9%)ow>g$IvC^_C9;(R(wJ5qlRXkqFj>dJ2vV(SHn>tp0aJ3N)41yApS}6=Oz}VrW zae(m+cpN8t^s`r9bxVZRNti}pN5EZBZFq}dGN6FvF&-hwmm0UKf{9Jh41qys)N}$? zzB65slollTLW$pL5dk&5$Ld`iDGSP-d-NfvG$ya~^BnHG5p)}-5j+YaFcQ-6!Q5wI`jHek1`Ln^%Yq=f zfR)6fF!st~ul-n^(Z51_!{K2SP7L+4y;9l#HSxOFf*qNssHmv!=1duR_<+jSFgOA$ z)Ug!{)CaC<*;4lW-%J{a;?)n+2;wvb0Bj5qgdH{o=cOen1`H1T9e5T&G#tUPeH~c{ ztL&kK&i<_x$}OGVE46tjzplD|2wm6IQDZ_o2(UI#?5Y8qM#i!qC^c{ofDz0>O>_40 z)QX8wCfqQMz^8`{cyM$h;10eHAmh;y8LY;X5`woB9Zc+FfHKDZfL1i(XW4f$92tlleuYH z*FFnay(CegmWtCg-le3O(D@CcpI$c3TLAz2xm$l5oHs2~LoD3Hsz?D(A7HdG&;b<; z2h%u2%`6(6| zs5S-8uGb%x#`^u6)-*^0qp#I>U0*fLxe6kFo@s2?&Ni~EFb#P3%JaSTiOf+fS zU57-`UzkQ30QU7LQhw9-qdOTIZaw{7xbNt1%nSecY*2p`Mu11@HRoDb&mcC0kdZ8b z++ISQ9(zo92l?!{``i8=MSo!$!M;ON0n`Zx6+)*1ywq5(suT}K2HX{*Sjan+RbT(3 zBoK__p`QNY`;Pv^lWsU7s6SLuV{e90idSWTu$wyK4JysCL*Nf6?HI|B-*>t5m#I^u5f zIDhljp#I?VM7Ep`=tqb7%4oW+f=n>DNs+W80JT!Js;Mg1K+IBL`&IKkTDZ~QQK@T#94L;LE)-KM{bx7~Gk{nan>Yk$mrZ+ZUJgD3oC z7uKJvo;|AuMLQU62zL4a@uYCoD%1wQ4U|Z95!7L-><~%K{^jB;-i)HZFpV^TRPD`w z6r`FVH5c`Fgin9@9c?W~QvIE^yY!cT@%9t198vwnp8A&=?0*&k7=;Q{Xv5Z!c!eky z;13n7L`AUW={#6!Z8dvWUwU&C{e@|y0TeV(e+&SP0u>eYcer1FchCF}j_U6NyGwt$ z{?>OM9Z~)D-@j==P=AUELRg1Kh*ZX?2`Xkp*%|z_ZaD<2dC@Vf>{Ao(JUfd1!ZgwV zl8L8324eEl89%tGs6T(sD@z)r`a5QK>2KsI+Qn->Q)B!D5)HsOfSx2BQ%`@V?mPN>V8)n#1^b_jQ~)@% zfky^_PB1lqB2%)FZ>UQEyg_z}jfH6T(21Ac5Ji7s8fgG2%hMkP$zm8-_4If9zN5c$ zPq}GjP=DCGBQprDGw?H0Vp`<=BG(^Z!D$cYnFd+|JA2ovZ!e3Yzc7t7fK24+kAf00 z%%OVv+p){~J9*_(SM0WA+{Wopi(3ZwuYBN6}xHMjAjp_SP>iy#4lchG$&VpFh)E zq4-6XfYOJMxgu!U51x7WX;Jj&BFAoLjlh(U=K*XwJb)#DO3_h~`Ja0G#IDS%4eTLs&Pk$fWck~y(?fesi`Xerd_(NVQ@);ByB$O`-*hzrH3xvZi09ze7 zn|$^4=c4E@Od}2O4SD^KQ4LW}ntJ-<_Z|IR{I#itp#I<{CW2|wT?686aJKNYP(|hx zOLh%IL5Fm#>|-y#kcgtcFpZ%9*@omI?1yY83;+taJQ0rssR__DiDFAAq_SB8qu2i! z2@d0Asi(i$`;Pt!=L*jR^@r*vg?GTGDDx;?<|zp>aEs|q0{nfbCI%s=oIUcp8-Ef- ze_wVqQ5YWG=P-qtv?w^>TBoy`O%{O-s{s}ZtSxMK1ua=*zVF_ZpB%fr;e!p=Jjo@ zP7-beAM{2@<7SVSgbJnso+%8!7v&=f2y^uQP4^*soW; z4shhre~>u>$Rk-q!3+|WurM(dQUwtgH|*>sw;uAFQ!2BQ8sb<9(?|o^g6!SB zB??O!#JhJhi(!ZI8&md4noh_L56qg~F>mpLg`9e(#Gf&9$q=@!N3l2Sfax&?0X^$z zcL@y?d;f9tpQ=Og65jxwQ0q%C-X9b_^1dA4Rv=p)NP5_lVPZlU4P<4=vj)Px;s~ys z?Rd|o*P=i`hiRmN#0H<}X?6n@c+W7RXPFP)!A~bN#uM`~3zro?{P43)m-mrVubmr| zH_!_xg`veE8P(=A3u^$?H3=sGOCC65VD1(9?DOl+S`B_Cx(%C zo@VN?Lk-C7S;zeFvqgEo^qr>5d+uX@xHKql8G!xR;vn710$dD?8TRdhj86oQ7Vtl0 zK^N8Rkwkm`vC7)OhK80fjWm!r=aVtC zwhewhHhA^m+JPqqwhUf3uzle1frkbjj}1IAc;&$3gV*5e)`86fTX5kK`pX*zuPXim zAGQpx#c|Wnk3Y>$tR1{MhC3b~*oHf|53Y|5JUF<1@T$S<*;#tW;MHi1U7?LUGVne8 z`EB_BA$)!$hErPx9>$-#5*JF3^Cg!#IwApyK*#*MX z>4iIDj1nqr2}O0aQ?nRxD$B2i*l;wFvEi^JNAKVtYNnSg-un=1{b< z$ZJAr3f8PZG%!)qjO-`Tz|`vUiVQkLO$3Em_RPyx{P6q;rXQve`o1A^o_wZ1fhIn| z^m|LD??dxSNy*B0j&2*Z*y#SR?lT>H>(5L0?-FUnNo{Mxx^t0b0*&8~nX62^C}TG)f~fb{{4j|dMjm^vLT``jl_I`Wwa zYrQayG>{2fw#qzBhouI2amgyj3wCR$gvzh7)7euD85s}C}=(Zd@}+5a*BpNr!V25y3@IhaS{R_ z2t0xGYqM;jUW-GMmcc>itOMYE{YU2XTl(gmN7?ex@C0Tdk_g)h6wml5YZsg zZo%6KCky};98e??c&<^nt;xFTX5Vx8M?d_&2$NWtMjA*QEL%pNW)D)MNS7_6a7MlL z+Y%uAyZxA{2qv*q3XuN^N#T#RY`SXn|ak8c*&5?_i)N@bMEvfgO30%;UG#Lfh8n8eOz^J0)6xB1D zggq~~`w0AZnyU*&_OC6s9v@}r6{e8}T(CY%Vt!ayQl?}{zU2_@xztC?4mIW7b5Bv; z8;qvQd;J#8qC^4HKFGL{%1sbI5L{p`TyxBN?GF)pZkR?I z2sxGIonvt)$h)s3?@(miQZ*U(-8DLC8RZ6_(qLg?{gfW60ePF%Uu(BG)MXV6{)OM} zVT9avTalPb?5su39mDmEnd%}LvGZi_LtE*T)Om6`*_W~jJ>`9pI@xlVMiTS%P|-^~ z|J#`#-C%gVpZe0}=%=q3GGs=V@PzvQiJzNCU~9WgE}a zj8AIbEHLGTk}JZ2EF082_~l*nzMS^zTi%%Rv6&xly1c)0@Q3fHA#WKF5b%z00zrid z(i~9NW#~Y`kp##d>>(PG`=09V+tD+wA~@bqj6@32NCU-PK6$eWFUb2+-T}&4@ z$}#%c$B$l7G1^HvXU@wcgwXt#m7WPBJqG9%g6u8k;bJ zzqZ)SWM8)vOC+gJIpHwJa%}2MEKx~MFC$20p54rv%+%IjjrkTvub7#MmH+DU<+D?% zWU3WT=(!8n$7#S(mBbjKr)MS|G9%_8oWy#}ev8cM>+Yt{JAM2?)qjdUAbv{B9_CJ( zR=f?a=an;J%oT*c7VBYul74NsZR%k_={WwG5%Zc&#k*E!@U4hM66;HoMa5I>@2@md zB$lSfp*yTT*CnYAxURfb7BIoUbK(7q$Dcj(yhU>tU%0$|@!~~uPd{(*?2cHP*zK82 z3JndtT)KxbzcEAFKcM zk=t$!j@6=q0u~cM6uN~RP##1!m>}Ue2ezPSAZbQGetq_qfd_sVWo``9NCSl|<*_

VptylM3w74_vMc~|XkCa$~e0ao5uA@8vzF?%0QKlOi`Zr{hfaQVETypcyqBqaD# zOd$z{1`c9EfJ_BClx|t7AW8ty$^Ll$gBM1TcbG;RD0KD7n^wD0QC~5fyjLxn{sb$B zt&n$d?FTUz31gPYxsRJgppO2fw@@zMv##_Q5$NeofQm-T%%x%Y*h! z06B=P3?yYBUmh43ki4saN=DEHq(}$=j>X>Q@Yi1bbrgArX{3Qd(z3jBw3?KP`cox& zSB>BAU(wyd%1!<9F2)b3m`6_Dx=yW{3LnzVRzfx9?lexqn@iyiw@q+KOv{r4Xs4DuCe}#{n&p4agS>(pukTqM)JAAd^(fj1(@0^843I(* zmDb?ffevgFL!d)c%yD=6_AFEgQ6n~3*=?sJ9dDL#`~yFykTgVB9i84gVu#KRU53f z#nZ-OZDS3H;?Nx7QM3`J5okj<0922BC*DQ;4*_zlcM(6q@}3Bi23}#T!srCxflsrf zlHnk!nxYMcGSyUVFr+L`8wW0TJ{;^DVYsmw0e2K_glVKv0&W&U8m>URDcTrOI^>s* zTYFbf8(}!78L@Q~ZG>qAxf=};Tj%PPd++($Xr1)k9|g4$hBum#Q%BK8m_{&CHAGJB zCD9C1yuIgZqAey@g@h*=12I6$~PUmN`TXQl@GhT*D`;X1&>qz*$1 zp!z8Auu-(A3I^O10GLwv?A?9$9UDm-AsWHFAsWPD_^SVZd*>b`MRCXRgA>J)@DQW& zkV=$74H+`;2Z@S^5k-Y6s8T2l_RRDcR3L&{RMebCd=SJ)5ckN~NE_avZkE^ZoeopW2*VB(*|N8sUA$Nr$ zb=*R70p0+u#K7fj3uSk0vWEFe@+h^522(t#?OvRzwj_J;XMTRqq;xc7Xt^B8nv@9JB8GI{e#Abq;8Zr;Tyipa`HCG9X)cK=v=BB^yN=HKmlFCV}S)w8HkZMV+{8o24$WiBy#;wy| zvC`3yp_p=1YL;loJOo+8s!*x9O30$lAC0Hi-%~<>Q-(syQKwm=A@h)GQKz|q6#zt? zKN^pdbC;KRH)Qdo*JP+t=rVZH&WuA0)hS1%<0nI!tm7=_1#>Q^b5R}6Zx&xn=FK~s z%%W}O`0F^!I?nRac}sibhM)DRpMP)r;g96zZ==ui>q^NksE)IIAXxMzc<0VMe%5i8 zT|0htoMqRJUma)JuJNnmEGhIu44t8*!BK&>5l9%C22hSq3>}rZx*yuScCaAlUdLHB zpnzP4G+D=4O6(u%I7=vS0Oo~T2AYApC62@JVn}x>CTN?s7iuBIo|DTPfBOD6->F#j zQ^#4>ahARR{&AD6(T?YVwwe;i^RXIWMJ>Nrbw(=NGXSI1dGSbsLsrJI%C%*eO& z8Mr0Ky2nE-n>x|I5DFTjra;NNa{jE2v#jdWEag>E>Nv{+U9n5?ANwsBym8b%`O}YA4;(L)^FV}3hF6yv zisxCOqf#iXLq^PjzLf>iqzW8_ra6)4hmNM}4lW#MwoYAQu=^giV!%MLbPt~*%Yxc6 zlrsF3$l6{g-Zd=G+sKo>`@S(lGn9tnaqZ~V8TXHRm5Cy?&Up0k+6(MH`9hzU(*Bmw zzRfJK>(Kz<9!&)(R|9@8fY?Z2YntL(PH4H78yOx@6hw0Z(=$9Jj5JeG^$-wH2k1}J z(G1+Sp%e-}iATqL_(VP#1NI8+{=w|-miXoHEsky&L3{dY#_iq{gC5LQg5m^HW!vpLoPy*i%6x%Wb zbZufQ7H|W07#VtCS?J%6>7d&~&(L?6G^Pd-G6Llx%wP zm~OeF4}51D!=;UUYiUcG?08(!&B=$aFZrbA{{G(BGsFvem@j4Y`8fn23q#Kb8eSu= ztq>n7?2Ij-MBp$pMsQ$J5aca2$_4?rzUc3sx$|e8*N~gtW8IQ2uA0wDGObsjFC?Af z=wA-3d8hc!ZO>0kzl1U*&dj(^o0zua<2tOvq~i4mDsC2g+k6L{K9B0qhoS8I?mzDH zhGM5^qjXrueP+Ua4w+o+jQm5>*~8DOd9S?V<~5=|3x+Bg5+}!fW|bR59~^Y?m1%#=prA7Irks#kk%p}(Atq6qB8!j#G8V@Z-1}-{JrP% z8`QMFWzeXcznWz{fzD;%x-KXNW&~MS%Z?Ny3@DU(LrqhoFeIUojlX(R(cg`^F(d9; znj63Uj8oY7U4c^C*5C26n)mMo=U)4Vw7-4V!8XN27DNYX0CLd=v~rOT(eNJ(({NlY z!Q;#C?E6L*f0Ga$+oT4zMyi8B1^<7?!$?j6Vb-mXSXPKsf#>)hl;MdIg%ksPL;(oW zL!vk~HK1bd669u>TifVWCz22N-QuFZh4JK90~UXpXFt+<)$n(`tkA!AzFTvDzc_if zsF8*Bi3|!LGjBjOLLaKwkUfUiFlwVv8;L}S?_ymNcoqpEP@Ro8aB~@dC#V4q9Z0dJ z;P0L9CjOq-cWur6ed57Wu1oiCj3@2S)38ZE4Hcr_fsOZv_&QKxz75bkg?fO4F`KIJ zcNU(;Ps{ncG*5%`9a@{<=7PVcZ>zb#4>@$$1!;ey!-Y{0Qiz~~b&S0`_$9W3i_CcPf$KlYGM*scg%R4Iic12B7;A>A=oTZBIGT^#uIp$4c;UKZTU52MO1Df6 zQtW{SRd`T=kuQT?U^A_DaXevC0PJ_Sl=JtXh0|Jc{72jVouqo3CQjd0@b?2PHTU+tuIqQ86QpWb;(ulzg5?Yft(2TSvi8VhdT`a$wx z(rIqZ{r&p%&70HymH|L>%Jg9wc$g+}bW;z}t5x4ps0)097pTBVm^ii2byo{rj3(!`+FfZ7SY9>L#5%Jk3n`8zjl)Q&TAr_R0J|G!2u7q-yo zNrf&o8>e%7F%Xpy5mlVl?C!n3#1>kHmdugNTmD-d0;>s`_Py3{F!a@yj3keR_D2A?aks^=L?(5)e;;1Hv8% z^0rw06PzhUW<ed?J$UA_l~?ZY61unhk;3KZ2OTd46(h} z!9ewKwM)S~X)2-aP{l+MfMQ}&)g8mbrZg1&y%%rST+ZJW@OJI&?}e=^rV0MWMMxPw zMf{Jew=WV*G1kd!+T*b^Pb7kA*C}7YI*9+J6DOLn7GHx2}cU1XfUX5CRXOUq9UKA z=)?ty%*HHZha|u;5>8H4KfW@2zl2h&jNlhn6%(F{2FvUc;;FB!+$or%!AN`PKu2Lg z<%3Plra5Aw1#x-qf`4VI|MickO1K|2IfG+0^!Ds3twcFGl11yeLwCUX}5uK$=u!4wUa zkpqkUIcvmC4oqbTTk#=R5C4nsR5Vy-s~G?K^}AOIrp&_>2uPcvpeS$%PIv8T)K>({o6|=gra4% z|2belcq$q!vjd4&-_);4m}U0oNO`eqIlDa499V35U;#w^?7Mi z8FU2aQwXMLuuO(GZaHG~n}R7CY&uAg;fPwnF56USNZELSKI|Ik89p@wtb*cxLw~q9 zZ7M?^;dm3l6b+U+0*L1~Pd-^NMS}r%Hq{8_HY&x~fVB=5KPY8ZQep{dQyFj#r{f5w zXs}FqV|-`Rsc#9UXs|^*UxWMwc22&kpp4hXLKBtNrt2g9?&?5s`th?vSDcwPmBxn( zrf9HCQ9}IoF&_>VOj(x*3`fOafRipAhrSq-QD2CrVIX-ONeOuC|GN1rXBM?kkmyjqykFQ#?=rD_a|eY;9=R+R!IAdgh*Ia(ym(VGx^`hjv&HIz;+3 zOAus^MUVrl>z7v2U;o;(pOGvGRN}^eUAd^PJn?Q9Wv5Ag_sf|)O2bI`J z1LG2@31kcalEfk$|Cq=rSHuPvgK$Dey$S6vC&}bMvjjmV`HIb2Xj@L8Aq(fBh%P|x z9i=X;p418uMb(Z7Np21$6LTe6a4`sXb)O(GP0uVrz{&KNrtGVzH%fxgZ^Ab=mV*Qr zgYfiz2cc66b7l#G%t22TMMy~ySp88sHt^mc^uP@mNNMa(?x@oRfvIa|34%XlLs~qsT71$yH609Y-E-o$eb5rpCBt{l>~w7Sp9j?%H4$^ z^lvjKn)Nf4e|vt%?^6(|JZ;5I?X9q?-JO)LogJ1Pjd^Urwr*eB1L%rxD{%`5_MPMMppZu$Ik?Bs!S^~jW>@hvrj{|b%FZyrTgex3= I2^Gfw06zO|2mk;8 literal 46743 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 KbJW`tU;TeWSmxgV diff --git a/Solution/DirectoriesComparator/DirectoriesComparator.csproj b/Solution/DirectoriesComparator/DirectoriesComparator.csproj index 31dd9f1..dbcbf81 100644 --- a/Solution/DirectoriesComparator/DirectoriesComparator.csproj +++ b/Solution/DirectoriesComparator/DirectoriesComparator.csproj @@ -28,7 +28,7 @@ true - x86 + AnyCPU pdbonly true bin\Release\ diff --git a/Solution/DirectoriesComparator/FileOperations.cs b/Solution/DirectoriesComparator/FileOperations.cs index c1c2281..d88c845 100644 --- a/Solution/DirectoriesComparator/FileOperations.cs +++ b/Solution/DirectoriesComparator/FileOperations.cs @@ -77,8 +77,8 @@ private LinkedList> GetEqualFilesGroup( ICollection p_SourceFi { var result = new LinkedList>(); - var sortedSorceFiles = new SortedArray( p_SourceFiles, File.CompareBySize ); - var equalSizeFilesGroups = sortedSorceFiles.GetEqualItemsGroups(); + var sortedSourceFiles = new SortedArray( p_SourceFiles, File.CompareBySize ); + var equalSizeFilesGroups = sortedSourceFiles.GetEqualItemsGroups(); foreach (var equalSizeFilesGroup in equalSizeFilesGroups) { diff --git a/Solution/TestProject1/packages.config b/Solution/TestProject1/packages.config new file mode 100644 index 0000000..c5d1914 --- /dev/null +++ b/Solution/TestProject1/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From b0a369021e8b5874703b8696c990cde78a31f01a Mon Sep 17 00:00:00 2001 From: scumware Date: Sun, 21 Apr 2024 15:02:11 +0300 Subject: [PATCH 3/4] cloned sln and proj for .net 4.8 --- Solution/DirectoriesComparator.sln | 30 ++++- .../DirectoriesComparator .net4.8.csproj | 118 ++++++++++++++++++ ...roj => DirectoriesComparator .net4.csproj} | 0 Solution/DirectoriesComparator/app.config | 2 +- Solution/TestProject1/Tests .net4.8.csproj | 103 +++++++++++++++ ...TestProject1.csproj => Tests .net4.csproj} | 4 +- 6 files changed, 252 insertions(+), 5 deletions(-) create mode 100644 Solution/DirectoriesComparator/DirectoriesComparator .net4.8.csproj rename Solution/DirectoriesComparator/{DirectoriesComparator.csproj => DirectoriesComparator .net4.csproj} (100%) create mode 100644 Solution/TestProject1/Tests .net4.8.csproj rename Solution/TestProject1/{TestProject1.csproj => Tests .net4.csproj} (98%) diff --git a/Solution/DirectoriesComparator.sln b/Solution/DirectoriesComparator.sln index a04467c..1602b30 100644 --- a/Solution/DirectoriesComparator.sln +++ b/Solution/DirectoriesComparator.sln @@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30330.147 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DirectoriesComparator", "DirectoriesComparator\DirectoriesComparator.csproj", "{D4A43F32-7DC7-4E4D-96D8-D5647F8C0FF8}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DirectoriesComparator .net4", "DirectoriesComparator\DirectoriesComparator .net4.csproj", "{D4A43F32-7DC7-4E4D-96D8-D5647F8C0FF8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject1", "TestProject1\TestProject1.csproj", "{15CDC8B8-1FD8-48E6-ABC2-0FF13D66EC95}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests .net4", "TestProject1\Tests .net4.csproj", "{15CDC8B8-1FD8-48E6-ABC2-0FF13D66EC95}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9EA941C2-13E0-4277-9ADE-8DA9C08BE544}" ProjectSection(SolutionItems) = preProject @@ -14,6 +14,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DirectoriesComparator .net4.8", "DirectoriesComparator\DirectoriesComparator .net4.8.csproj", "{19C06DD7-79C3-4410-8708-1B9BBD4917D3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests .net4.8", "TestProject1\Tests .net4.8.csproj", "{F4758CD8-217F-43E2-BC9F-1840619B47C8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -45,6 +49,28 @@ Global {15CDC8B8-1FD8-48E6-ABC2-0FF13D66EC95}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {15CDC8B8-1FD8-48E6-ABC2-0FF13D66EC95}.Release|Mixed Platforms.Build.0 = Release|Any CPU {15CDC8B8-1FD8-48E6-ABC2-0FF13D66EC95}.Release|x86.ActiveCfg = Release|Any CPU + {19C06DD7-79C3-4410-8708-1B9BBD4917D3}.Debug|Any CPU.ActiveCfg = Debug|x86 + {19C06DD7-79C3-4410-8708-1B9BBD4917D3}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {19C06DD7-79C3-4410-8708-1B9BBD4917D3}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {19C06DD7-79C3-4410-8708-1B9BBD4917D3}.Debug|x86.ActiveCfg = Debug|x86 + {19C06DD7-79C3-4410-8708-1B9BBD4917D3}.Debug|x86.Build.0 = Debug|x86 + {19C06DD7-79C3-4410-8708-1B9BBD4917D3}.Release|Any CPU.ActiveCfg = Release|x86 + {19C06DD7-79C3-4410-8708-1B9BBD4917D3}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {19C06DD7-79C3-4410-8708-1B9BBD4917D3}.Release|Mixed Platforms.Build.0 = Release|x86 + {19C06DD7-79C3-4410-8708-1B9BBD4917D3}.Release|x86.ActiveCfg = Release|x86 + {19C06DD7-79C3-4410-8708-1B9BBD4917D3}.Release|x86.Build.0 = Release|x86 + {F4758CD8-217F-43E2-BC9F-1840619B47C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F4758CD8-217F-43E2-BC9F-1840619B47C8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F4758CD8-217F-43E2-BC9F-1840619B47C8}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {F4758CD8-217F-43E2-BC9F-1840619B47C8}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {F4758CD8-217F-43E2-BC9F-1840619B47C8}.Debug|x86.ActiveCfg = Debug|x86 + {F4758CD8-217F-43E2-BC9F-1840619B47C8}.Debug|x86.Build.0 = Debug|x86 + {F4758CD8-217F-43E2-BC9F-1840619B47C8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F4758CD8-217F-43E2-BC9F-1840619B47C8}.Release|Any CPU.Build.0 = Release|Any CPU + {F4758CD8-217F-43E2-BC9F-1840619B47C8}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {F4758CD8-217F-43E2-BC9F-1840619B47C8}.Release|Mixed Platforms.Build.0 = Release|x86 + {F4758CD8-217F-43E2-BC9F-1840619B47C8}.Release|x86.ActiveCfg = Release|x86 + {F4758CD8-217F-43E2-BC9F-1840619B47C8}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Solution/DirectoriesComparator/DirectoriesComparator .net4.8.csproj b/Solution/DirectoriesComparator/DirectoriesComparator .net4.8.csproj new file mode 100644 index 0000000..838a3ad --- /dev/null +++ b/Solution/DirectoriesComparator/DirectoriesComparator .net4.8.csproj @@ -0,0 +1,118 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {19C06DD7-79C3-4410-8708-1B9BBD4917D3} + Exe + Properties + DirectoriesComparator + DirectoriesComparator + v4.8 + + + 512 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + true + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Solution/DirectoriesComparator/DirectoriesComparator.csproj b/Solution/DirectoriesComparator/DirectoriesComparator .net4.csproj similarity index 100% rename from Solution/DirectoriesComparator/DirectoriesComparator.csproj rename to Solution/DirectoriesComparator/DirectoriesComparator .net4.csproj diff --git a/Solution/DirectoriesComparator/app.config b/Solution/DirectoriesComparator/app.config index e365603..786a845 100644 --- a/Solution/DirectoriesComparator/app.config +++ b/Solution/DirectoriesComparator/app.config @@ -1,3 +1,3 @@ - + diff --git a/Solution/TestProject1/Tests .net4.8.csproj b/Solution/TestProject1/Tests .net4.8.csproj new file mode 100644 index 0000000..7f2cfb1 --- /dev/null +++ b/Solution/TestProject1/Tests .net4.8.csproj @@ -0,0 +1,103 @@ + + + + Debug + AnyCPU + + + 2.0 + {F4758CD8-217F-43E2-BC9F-1840619B47C8} + Library + Properties + TestProject1 + TestProject1 + v4.8 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + x86 + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + x86 + false + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + false + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + false + + + + + + + + + + + + + False + + + + + + + + + + + + + + + + + + + + {19c06dd7-79c3-4410-8708-1b9bbd4917d3} + DirectoriesComparator .net4.8 + + + + + \ No newline at end of file diff --git a/Solution/TestProject1/TestProject1.csproj b/Solution/TestProject1/Tests .net4.csproj similarity index 98% rename from Solution/TestProject1/TestProject1.csproj rename to Solution/TestProject1/Tests .net4.csproj index 0749160..47e2d7a 100644 --- a/Solution/TestProject1/TestProject1.csproj +++ b/Solution/TestProject1/Tests .net4.csproj @@ -82,9 +82,9 @@ - + {D4A43F32-7DC7-4E4D-96D8-D5647F8C0FF8} - DirectoriesComparator + DirectoriesComparator .net4 From db62f849fd54e9355e7c67c2cbf87a41304bcd9d Mon Sep 17 00:00:00 2001 From: scumware Date: Mon, 22 Apr 2024 01:26:36 +0300 Subject: [PATCH 4/4] refactoring, fixed some tests --- .../v16/TestStore/0/003.testlog | Bin 0 -> 24742 bytes .../v16/TestStore/0/testlog.manifest | Bin 24 -> 24 bytes .../Auxiliary/Formatter.cs | 17 ++ .../CommandLine/Parser/CommandLineParser.cs | 81 +++++----- .../CommandLine/Parser/ParsingContext.cs | 42 +++-- .../CommandLine/Parser/States/Initial.cs | 11 +- Solution/DirectoriesComparator/Program.cs | 2 +- .../DirectoriesComparator/packages.config | 20 +++ .../TestProject1/ParametersParsingTest.cs | 147 ++++++++++-------- Solution/TestProject1/PathValidatorTest.cs | 14 +- Solution/TestProject1/Tests .net4.8.csproj | 5 - Solution/TestProject1/app.config | 15 ++ Solution/TestProject1/packages.config | 4 +- 13 files changed, 218 insertions(+), 140 deletions(-) create mode 100644 Solution/.vs/DirectoriesComparator/v16/TestStore/0/003.testlog create mode 100644 Solution/DirectoriesComparator/packages.config create mode 100644 Solution/TestProject1/app.config diff --git a/Solution/.vs/DirectoriesComparator/v16/TestStore/0/003.testlog b/Solution/.vs/DirectoriesComparator/v16/TestStore/0/003.testlog new file mode 100644 index 0000000000000000000000000000000000000000..29fd21d64a1da6a340320099e73a8946206515f1 GIT binary patch literal 24742 zcmd^H3zSsleP;n%oA{;@P^*9#CGsuzyZ8I zXw;CXt)wR>q7|#BCu*wotpr&W^JvXbhgjXCG41Kmq&BvxkD5eI?C+ZymOHz{GRvLa zLzHu1_uf0hef+-v>-Yct@AT=#Ma6zB2AGd{Q&%D}iUoL=+Gi#t|{D zZ-^1G6H2W;?Wz8mMk;MQ77#_HA~fQPh!9_LjTiYIb>dKQdpqMdCGMuHP&9?2(4xCo zx%B>7=U}^bkF>obmoFMUFP|5^c7OY+rnppOR~x%=Z*t>r+MXYG;Pc}Setz7z=f@qe zvAwVS0si!_*ehU@m$1U(xxmPt)hm*_+jVE>_w0_sPSDD~_|G3szUiy|(-wEw{ks5J z>$ck+^E*YMaF*yY>)ZDHnXT7;WyZW>F`tn=MN^nDm(HFsUlh&iT)ub4+!-@w&sbmz zDxc}L>#(|Gk;czGof=;}6F7F_qXU(Mjp z#qSP~8IKJ~YCk70GR4CBwxRpBK2(3Pyg4L>{NIVIte&j#Mb6K4cH)8nYXOTLhMiIEXPDj! zLQ6y@zsg;{ybhw3vj=UjT)q;wIDYxc{&UhV{=xRA3Quo7Y1)}NB|4{_m&xkf#f51L zvuiW?T(-+(i_<=P$ZuDP3FG(P)wtXbg>gL+8ZRVq=r9uaoD<~+e&lh@aSRU0p~9D% z5kHCq;jS-9EVxUQF+SCt3fHN)&++Adx^VU{`-8eAyf9nL_b$rDIlH%gQFbkUWL69N z%&{RlGkS?AUT6<~f4GA+j{~P;Jx*zE<~Pq)olg0G+wSNu|J&WCP8xwrD1Gk!Hzt?5 zwohr_dQ`o|)m`pz_Ez4s;qr^hS1fQ-s_NAyqoa!<-wr&|LD`q+i)g@4DY*%mDD#zNRJptx+I8QjyxiY z2xF9TFLGlZ(*BtN(lx0lN3sSB*Rcsn7N-z_^lL= zRCx{y;#d=o(uzpw3KCKi5iRgEDUA#dkm!gY3bhxY@^X;`Q5VluhDH*FhmLOxMZF*q z;dq@J9Gtw_8n)A1k|`qlL8&;9^*pw_12tf3MOEukobsFPhdt0*U|zWPz>X>~e{{z^ z@~srWfG|LX8+*j%p&~4DQRngq)Pa(*Cu9_8#!>9L%8Lx_AdVfEm@o{8=Y|epP7rek z-wz^|0A_X_FsEcX&Dq@sbb`(E?IBy(+P#$xTi6b4)G#=#`}XVGQ=l$_*o#765RZjEalHV!X23(_pRo{;rz4+P4;RQt&{&XI1A1<= z66$J!62*8}9jIKwD3O)StwX&&E191+75MEvRSUYh<6HJ{yn)XgNJM6gED-fk6RBLx4iH1A}u}NVs-T#e1$B zdw@rIF%MK6BT71gpuh`>5}rc>9mDus!&p=ag0)(J)mh!5EQrNi_pUkyl&J!hmc`#i zVAK!??dKn9yt{_VAqnr>zbw5Y8*)*qVAt2j$I5WG9#il92Vc*O;d5d5fHX#Z-Hk78 zxiW=OYnMC7Gd<$R8cP9-1st=(iR%YO$&hkovrz}!z9&E&NJoK32sze|rISp=VyrX{ zH{k8^)ul<(r@dU>yl}^F8yMn%XYCm)fJWc5PH#JMaT*YO2boWVjK`0VnF<#kY+nuPYE?FO9=5BclxP!6P^T&mnGsc=*{A@c_L6&SGS4uFEOmKoz0D)4*E@ zxE*DD*SaF@Ba5H{4oje)AW+gVAtj1CMYZqv$nz7fsJ}jo7+gxDLR+||M|2{C=qj9= z&-HXyvWQ1_v%j_+l7)2HR;+f}-8xq8tWtH4YG5z??DCf{0}F&P;3>Cd-Z(^n!q+iWsOUM>S#39o?OoA`H7?(3OoU zTWGiM8?;@+Z*t4c`MBMgbMoq1Y|qPEY0t^)95Cof`*q!TYYKxl(ic?P#t%>@ZfJ`# zTX3U3aC}ENA^HJOc5o&FPHp7VmaRbr;kY~^5!aN0O5-x97qlEuQj;l@^4f#tekbmtQbxR6)4w zFMoDyn$Cz4_QB)%Qvq5Yy-7__@`O-6A(+XKSsDW%xSkjI(4VnbAZ~Fm9wGv7$O4D^ zZs77DnSz#Yp7p_J%G=l7`Bn{tB>m75=ThFJ-hZaG1pLF3KYetSfai}~`(J6+HMrFf zl_VOzC=y8+g%L<0G=crlMQ0=oeJNv5u}BI+$BRiMDOyb0hxhT}VUYBNkxLa4h6-m_ zUDu_q-`u~kbkK>{{c-J)CNuL=?uOS-wd?wbv0B%q%xULN9o2O`<#$ng8W6PW3h>!3 zaln;8I~hS-EfuW$j<(P=${#C6?$Qau>{Xv)3;u`6gNTz!o!2-C|rzjsg+a1@%f%;XpX)!vli4cGmVZAfR!B76o{e$OWG%;Pgnu(8fVNXN<=YScK(K zw530hL3myq5V%c;7=?bPW;Ev17Xf(CT^U6A+8=*+PI=?$OQtq(X63)1|07~QJ9(@? zDD}2~@WiN=I_Ir>@<&IeV4aPI3E-&`!4ZidB6rbPhV)1J8eFswe317fV`H(2EI<5Ihb&<%5d=`r=Iz@I$;*_3jb;6?(lh86ay|!cLP{M-^ z_SL{VvgMKKQ}vN)m`iPOj9QgGMh$bZ1JNqq`}8|crASmWU+h2??q6p(He_L)(L$e@Dtt+hh8849I*uxypwua@Q0y5%tp8NIX7+WSZy z3q7#Awk#S}(ie`IjgNXI{euUuyFE>dkcKX+3?rhk;1Q5ThC~56fLeLbYHER~2T^AL z&4P(hKf69eof0EOB)0P;!oc%F9ti0|Wvr+MV!aNmagWpDT#?tJSBy!!M!v_zqUDQv|9m<>8ZM7lPd84PrDsXd2c*ox9*E9lAZ z{?**_yUX5uqV`CWV{oO3FYo`1g=@?ti=|bkKXm-4=8^J@_nu2b5@GB;GBM~M6{6h< z!6EEGQ>Yh|kwyj(h`SDA46;pBSWszcP=#n_Yj`C@8z1VF7^88RcT0?}mQK9ouuqo% z^{q7z|3R+nlMkGBa+-CG`A%ghNP<|{VPAtzgOmdEo;GZIN;766@NSZYT)SWjgn|CY zdKFHQpVLrt&~E59M+s$5Y4(?YwV=FV>3w~*N19BjO9x!EZK_?@W7i5=v+2%5M|EA_ zx9!N=(trR;JMz(LBN(nmE5bk>&(KzYNLwoDq4UP%3>5W1v@N!&lNc7b7EwJJJrjgHh%@ zVhE%Gs?iYb9WFuHFi0Iyj-aCek_>QxGxeZ$b8S8AFvaa4gK(2{X^H>G@yC{qy80{k zH2|R{dCRB{dR?fGKOoJzR$+|ZC4`_}i0&G?Fj&`+7ZE1$oLK-7l187|msFxf17g|% z>yME=K^zJ0(pMZhb2Qg{mY^X^2mixoR+pyz&%1xyz+VsanGf9Sbv;5Fa`gMm8=kvh zN1AmVV1_^N;5Oi@?Q92l7nkC74w$q84%)$VKSV4L_2W$s4B85b8Goh%P-GtRdF5b9 z>p)3p(03(|C4RxC-qO_T&u`RcZppeHRdLooKm62HY1Vb@aD)CZl57mF5ispY_&`>G zJr5MdYCIa*bqyJ`7o%ej!Vv-s4#_wejR-*#vLdcLEPhpacS5z+Ex+IKZn-pX(u5<2 zTi5eHJnQ-!@Bj3mH0#<^=u#jRAsjC-yL;ueqRn&!OMkQ3D~#`t1Ab`qBfoth))R)!q#|xS(nv zML~W+p|OIvCm^wpense^gyBs2nCBa`{H#Z)Odz!Fnm{=1@wU4!*foK0_b0zPH5j<2 z@f9BeSxXb5uD|j{WNGaa}snZn|=LXg>xOYRlM(`@ypZRJ##1;%@k>Uhx}^pzo$W?nUj13 zE5V^?G$Y#T+cx3$*V3TT%t=0i%CMnmH1ocjKL55qo0kTSW==BFm+A~lRqgwp>g?m0kjjyj>RUC>&GyTlIjo*Cf*J;pb<|HF+ znhr}owgin)?L)8myI2iH1N7b=XZ-sPUSp0(gGMtav5M4@yhvc!k)wSdjg7@OP92Iy zGd<3}tB?8GX=%`C<|H4%M(R*Bni0eFZTS36VHz}=Imt*BH^b7&`@U^#I6pW3{{hwy BNEQG9 literal 0 HcmV?d00001 diff --git a/Solution/.vs/DirectoriesComparator/v16/TestStore/0/testlog.manifest b/Solution/.vs/DirectoriesComparator/v16/TestStore/0/testlog.manifest index e92ede29d76aefe079835aeae278da5341f6e15c..12ea3476212c16abe527ae0da30df0e9427adc3f 100644 GIT binary patch literal 24 acmXR;&-W=QP7PsZU|;}Y5C~=QISv3tK?JA( literal 24 WcmXR;&-W=QP7PsZKmZO+yIuf90t7Vx diff --git a/Solution/DirectoriesComparator/Auxiliary/Formatter.cs b/Solution/DirectoriesComparator/Auxiliary/Formatter.cs index 1213c0a..8c3e226 100644 --- a/Solution/DirectoriesComparator/Auxiliary/Formatter.cs +++ b/Solution/DirectoriesComparator/Auxiliary/Formatter.cs @@ -71,5 +71,22 @@ public static string SizeToFormatedString(long bytes, bool noFractionalDigits) return string.Format(resultValue, convertedValue, dimensionValue); } + + public static string Unquote(string p_str) + { + if (p_str.Length < 2) + { + return p_str; + } + + if ((p_str.StartsWith("\"") && p_str.EndsWith("\"")) + || (p_str.StartsWith("\'") && p_str.EndsWith("\'")) + ) + { + return p_str.Substring(1, p_str.Length - 2); + } + + return p_str; + } } } diff --git a/Solution/DirectoriesComparator/CommandLine/Parser/CommandLineParser.cs b/Solution/DirectoriesComparator/CommandLine/Parser/CommandLineParser.cs index 8e19a48..5d2ec9d 100644 --- a/Solution/DirectoriesComparator/CommandLine/Parser/CommandLineParser.cs +++ b/Solution/DirectoriesComparator/CommandLine/Parser/CommandLineParser.cs @@ -1,48 +1,57 @@ -using DirectoriesComparator.CommandLine.Parser.States; +using System; +using DirectoriesComparator.CommandLine.Parser.States; namespace DirectoriesComparator.CommandLine.Parser { - public static class CommandLineParser - { - public const string SourcePrefix = "/source:"; - public const string TargetPrefix = "/target:"; - public const string MinFileSizePrefix = "/minsize:"; - - public static Parameters ParseCommandLine( string p_Args ) - { - var result = new Parameters(); - - if (string.IsNullOrEmpty( p_Args )) - { - //result.Empty = true; default value for that property - return result; - } + public class CommandLineParser + { + public const string SourcePrefix = "/source:"; + public const string TargetPrefix = "/target:"; + public const string MinFileSizePrefix = "/minsize:"; - string args = p_Args.Trim().ToLower(); + public Parameters ParseCommandLine(string p_Args) + { + var result = new Parameters(); - bool quotesOpened; - var words = ParametersSplitter.SplitString(args, out quotesOpened); - if (quotesOpened) - { - result.Empty = false; - result.Incorrect = true; - return result; - } + if (string.IsNullOrEmpty(p_Args)) + { + //result.Empty = true; default value for that property + return result; + } - var parserContext = new ParsingContext( result ); - AbstractState currentState = InitialState.Item; - foreach (var word in words) - { - currentState = currentState.ProcessWord( word, parserContext ); + string args = p_Args.Trim().ToLower(); - if (currentState is ErrorState) + bool quotesOpened; + var words = ParametersSplitter.SplitString(args, out quotesOpened); + if (quotesOpened) { - break; + result.Empty = false; + result.Incorrect = true; + return result; } - } + var parserContext = new ParsingContext(result); + SetupParserContext(parserContext); + AbstractState currentState = InitialState.Item; + foreach (var word in words) + { + currentState = currentState.ProcessWord(word, parserContext); + + if (currentState is ErrorState) + { + break; + } + } + + + return result; + } + + public Func GetAppFileFullNameOverride; - return result; - } - } + private void SetupParserContext(ParsingContext p_parserContext) + { + p_parserContext.GetAppFileFullNameOverride = GetAppFileFullNameOverride; + } + } } \ No newline at end of file diff --git a/Solution/DirectoriesComparator/CommandLine/Parser/ParsingContext.cs b/Solution/DirectoriesComparator/CommandLine/Parser/ParsingContext.cs index 18fcd63..72cd6c3 100644 --- a/Solution/DirectoriesComparator/CommandLine/Parser/ParsingContext.cs +++ b/Solution/DirectoriesComparator/CommandLine/Parser/ParsingContext.cs @@ -1,20 +1,34 @@ -namespace DirectoriesComparator.CommandLine.Parser +using System; + +namespace DirectoriesComparator.CommandLine.Parser { - internal class ParsingContext - { - private readonly Parameters m_Parameters; + public class ParsingContext + { + private readonly Parameters m_Parameters; + + public Parameters Parameters + { + get { return m_Parameters; } + } - public Parameters Parameters - { - get { return m_Parameters; } - } + public bool ApplicationFileSpecified { get; set; } - public bool ApplicationFileSpecified { get; set; } + public ParsingContext(Parameters p_Parameters) + { + m_Parameters = p_Parameters; + } + public Func GetAppFileFullNameOverride; + public string GetAppFileFullName() + { + if (GetAppFileFullNameOverride != null) + { + return GetAppFileFullNameOverride(); + } + var currentProcess = System.Diagnostics.Process.GetCurrentProcess(); - public ParsingContext( Parameters p_Parameters ) - { - m_Parameters = p_Parameters; - } - } + var appFileFullName = currentProcess.MainModule.FileName.ToLower(); + return appFileFullName; + } + } } \ No newline at end of file diff --git a/Solution/DirectoriesComparator/CommandLine/Parser/States/Initial.cs b/Solution/DirectoriesComparator/CommandLine/Parser/States/Initial.cs index c50baec..c38a399 100644 --- a/Solution/DirectoriesComparator/CommandLine/Parser/States/Initial.cs +++ b/Solution/DirectoriesComparator/CommandLine/Parser/States/Initial.cs @@ -20,11 +20,10 @@ public static AbstractState Item public override AbstractState ProcessWord( string p_Word, ParsingContext p_ParsingContext ) { - var currentProcess = System.Diagnostics.Process.GetCurrentProcess(); + var appFileFullName = Formatter.Unquote(p_ParsingContext.GetAppFileFullName()); + var word = Formatter.Unquote(p_Word); - var appFileFullName = currentProcess.MainModule.FileName.ToLower(); - - if ((appFileFullName == p_Word)|| (Path.GetFileName(appFileFullName)== p_Word)) + if ((appFileFullName == word) || (Path.GetFileName(appFileFullName)== word)) { if (p_ParsingContext.ApplicationFileSpecified) { @@ -34,12 +33,12 @@ public override AbstractState ProcessWord( string p_Word, ParsingContext p_Parsi return this; } - if (p_Word.Equals( (CommandLineParser.SourcePrefix) )) + if (word.Equals( (CommandLineParser.SourcePrefix) )) { return ClauseSourceInitiated.Item; } - if (p_Word.Equals( (CommandLineParser.TargetPrefix) )) + if (word.Equals( (CommandLineParser.TargetPrefix) )) { return ClauseTargetInitiated.Item; } diff --git a/Solution/DirectoriesComparator/Program.cs b/Solution/DirectoriesComparator/Program.cs index 4359992..e1fc999 100644 --- a/Solution/DirectoriesComparator/Program.cs +++ b/Solution/DirectoriesComparator/Program.cs @@ -12,7 +12,7 @@ static void Main() { Console.WriteLine( Environment.CommandLine ); - var parameters = CommandLineParser.ParseCommandLine(Environment.CommandLine); + var parameters = new CommandLineParser().ParseCommandLine(Environment.CommandLine); parameters.Validate(); if (parameters.Incorrect) diff --git a/Solution/DirectoriesComparator/packages.config b/Solution/DirectoriesComparator/packages.config new file mode 100644 index 0000000..db1b7d8 --- /dev/null +++ b/Solution/DirectoriesComparator/packages.config @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Solution/TestProject1/ParametersParsingTest.cs b/Solution/TestProject1/ParametersParsingTest.cs index 4c21d54..a131038 100644 --- a/Solution/TestProject1/ParametersParsingTest.cs +++ b/Solution/TestProject1/ParametersParsingTest.cs @@ -5,72 +5,83 @@ namespace TestProject1 { - [TestClass] - public class ParametersParsingTest - { - [TestMethod] - public void TestSimple() - { - var result = CommandLineParser.ParseCommandLine( TestConsts.arg0Quoted ); - - Assert.AreEqual( 0, result.SourcesList.Count ); - Assert.AreEqual( 0, result.TargetsList.Count ); - - Assert.IsTrue( result.Empty ); - } - - - [TestMethod] - public void TestTypicalUsage() - { - Console.WriteLine( TestConsts.TypicalUsageArgs ); - - var result = CommandLineParser.ParseCommandLine( TestConsts.TypicalUsageArgs ); - - Assert.AreEqual( 1, result.SourcesList.Count ); - Assert.AreEqual( 1, result.TargetsList.Count ); - - Assert.AreEqual( result.SourcesList.First(), TestConsts.sourceDir1 ); - Assert.AreEqual( result.TargetsList.First(), TestConsts.targetDir1 ); - } - - - [TestMethod] - public void TestComplicatedUsage() - { - const string source12 = CommandLineParser.SourcePrefix + TestConsts.sourceDir1 + " " + TestConsts.sourceDir2; - const string target12 = CommandLineParser.TargetPrefix + TestConsts.targetDir1 + " " + TestConsts.targetDir2; - - const string source3 = CommandLineParser.SourcePrefix + TestConsts.sourceDir3; - const string target3 = CommandLineParser.TargetPrefix + TestConsts.targetDir3; - - const string args = TestConsts.arg0Quoted + " " + source12 + " " + target12 + target3 + source3; - Console.WriteLine( args ); - - var result = CommandLineParser.ParseCommandLine( args ); - - Assert.AreEqual( 3, result.SourcesList.Count ); - Assert.AreEqual( 3, result.TargetsList.Count ); - - Assert.IsTrue( result.SourcesList.Contains( TestConsts.sourceDir1 ) ); - Assert.IsTrue( result.SourcesList.Contains( TestConsts.sourceDir2 ) ); - Assert.IsTrue( result.SourcesList.Contains( TestConsts.sourceDir3 ) ); - - Assert.IsTrue( result.TargetsList.Contains( TestConsts.targetDir1 ) ); - Assert.IsTrue( result.TargetsList.Contains( TestConsts.targetDir2 ) ); - Assert.IsTrue( result.TargetsList.Contains( TestConsts.targetDir3 ) ); - } - - [TestMethod] - public void TestIncorrectUsage() - { - const string source12 = CommandLineParser.SourcePrefix + TestConsts.sourceDir1 + TestConsts.sourceDir2; - const string args = TestConsts.arg0Quoted + " " + source12; - Console.WriteLine(args); - - var result = CommandLineParser.ParseCommandLine( args ); - - Assert.IsTrue( result.Incorrect ); - } - } + [TestClass] + public class ParametersParsingTest + { + [TestMethod] + public void TestSimple() + { + var result = CreateCommandLineParser() + .ParseCommandLine(TestConsts.arg0Quoted); + + Assert.AreEqual(0, result.SourcesList.Count); + Assert.AreEqual(0, result.TargetsList.Count); + + Assert.IsTrue(result.Empty); + } + + + [TestMethod] + public void TestTypicalUsage() + { + Console.WriteLine(TestConsts.TypicalUsageArgs); + var commandLineParser = CreateCommandLineParser(); + var result = commandLineParser.ParseCommandLine(TestConsts.TypicalUsageArgs); + + Assert.AreEqual(1, result.SourcesList.Count); + Assert.AreEqual(1, result.TargetsList.Count); + + Assert.AreEqual(result.SourcesList.First(), TestConsts.sourceDir1); + Assert.AreEqual(result.TargetsList.First(), TestConsts.targetDir1); + } + + [TestMethod] + public void TestComplicatedUsage() + { + const string source12 = CommandLineParser.SourcePrefix + TestConsts.sourceDir1 + " " + TestConsts.sourceDir2; + const string target12 = CommandLineParser.TargetPrefix + TestConsts.targetDir1 + " " + TestConsts.targetDir2; + + const string source3 = CommandLineParser.SourcePrefix + TestConsts.sourceDir3; + const string target3 = CommandLineParser.TargetPrefix + TestConsts.targetDir3; + + const string args = TestConsts.arg0Quoted + " " + source12 + " " + target12 + target3 + source3; + Console.WriteLine(args); + + var commandLineParser = CreateCommandLineParser(); + var result = commandLineParser.ParseCommandLine(args); + + Assert.AreEqual(3, result.SourcesList.Count); + Assert.AreEqual(3, result.TargetsList.Count); + + Assert.IsTrue(result.SourcesList.Contains(TestConsts.sourceDir1)); + Assert.IsTrue(result.SourcesList.Contains(TestConsts.sourceDir2)); + Assert.IsTrue(result.SourcesList.Contains(TestConsts.sourceDir3)); + + Assert.IsTrue(result.TargetsList.Contains(TestConsts.targetDir1)); + Assert.IsTrue(result.TargetsList.Contains(TestConsts.targetDir2)); + Assert.IsTrue(result.TargetsList.Contains(TestConsts.targetDir3)); + } + + [TestMethod] + public void TestIncorrectUsage() + { + const string source12 = CommandLineParser.SourcePrefix + TestConsts.sourceDir1 + TestConsts.sourceDir2; + const string args = TestConsts.arg0Quoted + " " + source12; + Console.WriteLine(args); + + var commandLineParser = CreateCommandLineParser(); + var result = commandLineParser.ParseCommandLine(args); + + Assert.IsTrue(result.Incorrect); + } + + private static CommandLineParser CreateCommandLineParser() + { + var commandLineParser = new CommandLineParser + { + GetAppFileFullNameOverride = () => TestConsts.arg0.ToLower() + }; + return commandLineParser; + } + } } diff --git a/Solution/TestProject1/PathValidatorTest.cs b/Solution/TestProject1/PathValidatorTest.cs index acc7aa4..1e72672 100644 --- a/Solution/TestProject1/PathValidatorTest.cs +++ b/Solution/TestProject1/PathValidatorTest.cs @@ -20,14 +20,14 @@ public class PathValidatorTest [TestMethod] public void ValidatePathTest() { - using (var file = new System.IO.StreamReader(@"C:\temp\TestData.txt", Encoding.GetEncoding("cp866"))) + string[] paths = { - string dir; - while ((dir = file.ReadLine()) != null) - { - var result = Validator.ValidatePath(dir); - Assert.IsTrue(result, "error validating path: " + dir); - } + "c:", "c:\\", "c:\\temp", @"c:\temp\", @"c:\temp\1", @"c:\temp\1\", @"\\system07\C$\", @"\\system07\C$", @"\\?\c:\temp\1\", @"\\?\c:\temp\1" + }; + foreach (var dir in paths) + { + var result = Validator.ValidatePath(dir); + Assert.IsTrue(result, "error validating path: " + dir); } } } diff --git a/Solution/TestProject1/Tests .net4.8.csproj b/Solution/TestProject1/Tests .net4.8.csproj index 7f2cfb1..ffb044c 100644 --- a/Solution/TestProject1/Tests .net4.8.csproj +++ b/Solution/TestProject1/Tests .net4.8.csproj @@ -58,13 +58,8 @@ false - - - - - diff --git a/Solution/TestProject1/app.config b/Solution/TestProject1/app.config new file mode 100644 index 0000000..5cdf296 --- /dev/null +++ b/Solution/TestProject1/app.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Solution/TestProject1/packages.config b/Solution/TestProject1/packages.config index c5d1914..3299dfc 100644 --- a/Solution/TestProject1/packages.config +++ b/Solution/TestProject1/packages.config @@ -1,4 +1,2 @@  - - - \ No newline at end of file + \ No newline at end of file