From a812c1e4f0fb9ff810ab819d90a3ea46d6e4d728 Mon Sep 17 00:00:00 2001 From: David May Date: Fri, 1 Mar 2024 03:18:50 -0800 Subject: [PATCH] #4 Update README for v2 (almost done) --- README.md | 174 +++++++++++++++++++++++++++++++++++++++++++++++++- gitspaces.png | Bin 0 -> 17665 bytes 2 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 gitspaces.png diff --git a/README.md b/README.md index 5380f07..f90d9be 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,176 @@ # gitspaces - A git development workspace manager -TODO update docs for v2 (golang, simplified, edition) +## Overview + +GitSpaces creates multiple independent development environments (spaces) for a single repository. + +A GitSpace projects are the containers to manage these spaces. + +## Commands + + +Command | Description +------------|------------------------ +`gs switch` | Switch to a different top-level gitspace project. (default, runs with `gs` alone) +`gs switch` | Switch to a different top-level gitspace project. +`gs rename` | Rename a current gitspace +`gs sleep` | Archive a gitspace (not using it currently - renames to _.zzz-# and hides from lists) +`gs cd` | cd around a gitspaces project. Switch gitspace, repos, folder +`gs cd -` | Switch to a different gitspace (allows you wake one up you put to sleep to use fresh) +`gs co` | Choose from a list of 'BranchSet's (in gsconfig.ini) and will git pull each repos to it's specified branch +`gs code` | Launches Visual Studio Code with .code-workspace file updated with proper paths for debugging +`gs init` | _TODO_: Creates project gitspaces.ini, spaces-dir, and first gs space folder (firstspace) +`gs cp` | _TODO_: Copies an existing gitspace folder to create another (and puts it to sleep) + + + +## Project creation and layout +``` +$ gitspaces create git@github.com:davfive/gitspaces.git -n NUM_SPACES +~/.../projects + └── project-a + ├── __GITSPACES_PROJECT__ + ├── .code-workspace + │   └── project-a~active-1.code-workspace + ├── .zzz + │   ├── zzz-0/ + │   │   └── ... repo cloned here + │   ├── zzz-1/ + │   │   └── ... zzz-0 copied here + │   ├── zzz-... + │   └── zzz-N/ + ├── active-1/ + │   └── ... active repo/space + ├── active-... + └── active-N/ +``` + +## User options and dotfiles +``` +# Created first time gitspaces is run +~/.gitspaces/ + ├── config.yaml (must be filled in before use) + └── shells + ├── bashrc (bash wrapper function) + └── zshrc (zsh wra...) +``` + +## User configuration file +`~/.gitspaces/config.yaml` +```yaml +ProjectPaths: + - /path/to/a/projects/directory + - /path/to/another/directory + - ... +``` + + +## Background + +The general idea is that for any given project you might be working on a feature here, a hotfix there, another feature there, +and a bugfix somewhere else. You may handle all of these "concurrent" activities by forcing yourself to commit on your branch, +change branches, or stash stuff. I've found that to be a lot of overhead especially if you are coordinating this across multiple +repositories in a project. + +For those of you with a, ahem, ClearCase background, you're familiar with the concept of ClearCase Views. Essentially it's an +isolated workspace that has all of your project code where you can work on ONE THING. If you are asked to fix a bug or +something else concurrently, you just create a new view (they're cheap) and work there. Unfortunately, git has no concept +like this. Clones are expensive, committing just to context switch is a pain and messes up your commit history to boot. + +Gitspaces are essentially a lightweight implementation of ClearCase Views for git projects. + +## Command overview + +Once gitspaces scripts are available in your environment, all gitspaces commands are prefixed with `gs`. e.g. + +Command | Description +------------|------------------------ +`gs switch` | Switch to a different top-level gitspace project. +`gs ls` | List repository information (e.g., what branch they are on) +`gs mv` | Rename a current gitspace +`gs sleep` | Archive a gitspace (not using it currently - renames to _.zzz-# and hides from lists) +`gs cd` | cd around a gitspaces project. Switch gitspace, repos, folder +`gs cd -` | Switch to a different gitspace (allows you wake one up you put to sleep to use fresh) +`gs co` | Choose from a list of 'BranchSet's (in gsconfig.ini) and will git pull each repos to it's specified branch +`gs code` | Launches Visual Studio Code with .code-workspace file updated with proper paths for debugging +`gs init` | _TODO_: Creates project gitspaces.ini, spaces-dir, and first gs space folder (firstspace) +`gs cp` | _TODO_: Copies an existing gitspace folder to create another (and puts it to sleep) + + +## Quick Setup + +1. Download/Clone gitspaces repo and add it to your .bashrc file + + ``` + cd ~ + git clone .gitspaces + echo ". ~/.gitspaces/gitspaces.sh" >> ~/.bashrc + cp ~/.gitspaces/userfiles/.gitspacesrc.sh ~/ + perl -pi -e "s/^#alias/alias/ ~/.gitspacesrc.sh # aliases gs=gitspaces, cds='gs cd' + . ~/.bashrc + ``` + +2. Create a code project folder (will house projectA's gitspaces) + + ``` + mkdir -p ~/code/projectA + ``` + +3. Setup a GitSpaces project folder + > Future: this is what 'gs init' will do + ``` + cd ~/code/projectA + cp ~/.gitspaces/userfiles/gitspaces.ini . # See file comments for details + mkdir $GITSPACES_SPACESDIR # defaults to '_' # Where all of your project spaces will live + mkdir -p $GITSPACES_SPACESDIR/firstspace # First project space, you can rename it later + cd $GITSPACES_SPACESDIR/firstspace + + # A GitSpaces project folder has the following structure: + ~/code/projectA/ + |- gitspaces.ini + |- _/ + +- space-1/ + +- projectA-repo-1 + ... + +- projectA-repo-N + ... + +- space-N/ + +- projectA-repo-1 + ... + +- projectA-repo-N + ``` + +4. Clone all of your repositories into the \_.first gitspace folder + + ``` + cd ~/code/projectA/_/firstspace + git clone + ... + git clone + ``` + +5. Create additional GitSpaces for projectA + > Simply 'cp -R firstspace secondspace' (way faster usually than re-cloning) + > Note the copy operation is way quicker if you clean your firstspace repos' (git clean -dx -f) + ``` + cd ~/code/projectA + cp -R firstspace secondspace + ... + cp -R firstspace nthspace + ``` + + You can add a new gitspace folder anytime you want when you need more. I've generally found that 5 are sufficient. + +6. Add your new GitSpaces project to GITSPACES_PROJDIRS in ~/.gitspacesrc.sh and resource + +7. Start using GitSpaces + +8. Optional: Include ~/.gitspaces/userfiles/gitconfig + + My common git aliases are in the userfiles folder. Just add the following to your ~/.gitconfig + + ``` + [include] + path = ~/.gitspaces/userfiles/gitconfig + ``` diff --git a/gitspaces.png b/gitspaces.png new file mode 100644 index 0000000000000000000000000000000000000000..6f860e101993c8c4799935efcc369396d0cb5442 GIT binary patch literal 17665 zcma&OWmr_-7xztfhyp_lAu7!f4&5aNB?zc9l!%~o_t51KDoRVKNH;^bgw)UsASDt~ zGdOhK2mSq@=YH|LcwR7E*UUNl?7h~m^*P_QqxE&QXsOt!2nYyh@7>ifARr)Ay8NRc z1HNID@fQRB5xN;@sS%V6f`1bbs1V%KP<`Z0xb=}7bJIGd#7px%H=QiqZJHbRNK`dc zuCQplBfs~IJLR#LEF^@Gm?!y)yQ&Lip;nkCMB~ZePb&WQoSP4sDMPM4w}@aJd86^} zrtE6-*VTlTuNUWq4J{=F+lcv%`Ubz_()0DguXDb~561CcfglE|FrsV~{wx2#|LL2P zo;NoeAya9iiB>Q?Wx_=i$j}|I0>wewC!B)D-_pczRE_C3hH!H<<{@dSp(lYjJ{ju$ zFeA%{Q52+V!TJ_iOhY|V5rzwdLz_=`Xt3sVCvESpG+oj7`*WM&!uTT}`dZ4TDW-)7 zoHjE~ZM|1kA}JVvdWy+V+4}mmnGW?XOg9~Xl<>sKM53Wl`rM2Zq_0YYOveKj%xrC( zx6X5qWcQ_M+fT1t=K+3NFAS=z<_hx}8pOOl-4f_M)JvwbL_}S=Z2g|01!X~%bgjad zsB)&MJ9v5ei4Za6e^oi=&-yKUBW-l|ow$-t-D<~l*_D4S)UPAbeeO@e8T{P1E>p6F zdeP&5HPrt|lz`bI9MT(oz`Opm1!)=J{Lo$FuYtb^Eo^QDFBHG{o_>5*bYx1#u9nQj z^S3}*s@gJd34hXzFhtrc=1-<|=430~m73b?YL~a}nh@%s{a(crO-{#3eyKR$if4zD zJ4JSKU$#vxxEZKrF+dvo z%b>k9vUoF*rT>!MwZNDB7G9%VoX!%9l47juwg}Jf^91K>zlACA>S0k6RAD>S6Sw99 z%863v&lV)!{kEv_vdlBYZ0$K-9YCK%U0gvpReJ)gDKj}cR=}mk?V(jUMU-`J#o?LkgPMpZwjj8iD z{`ySRm^%jB=^OL2rJpcx|0Qji{KnO{(LXJv%9c%R@NN$CcW^BIBu?c>3epv!D_zpl z(F;d`ieO4CA?;5`=Ycs5OS|=&GO8l7(lEJj5#<4N;{3ILouM^PDC>6VAm|3}d^z%Af6S*$kaaY*F3+@X zkI?P+r!x+^?BXoqr0|FeRyfT-ZjzZY`ecp_#m;y}NHBoz9QYb+y70(&Hbb&SwDtZK z@ph_jEc3P>{cSAfNz6lwyJX#U>{-j$71&ooly$`(%0xRW9!~u(qZkv}Yff4SCbMEfj;MR zhc?YHE8rQ$?*q<@?V9rJ@^F)3n}g%tBpf;P?|Zd<#JLBfr~izeCX&Dq9+EAS2GTaA zk}ciWpM^0}EU}*_6#s4_g(~tvpRhfqS!ag0nt{NPjZDBW zwtU1B<5Y{TnyoKh+$dvkzm}R=6FjBk`J`t{|MRkqi2>eC=eJx0LqF1S&b(7! zBurYrI8&Z7Lmv)2A|CUHYGwA(#M^O{#ieF;fiI^E;=G_feNQqQh?}TDUA%-ckuHLf zmUdtnVujrp*B9xY_{HFS%Ud44Ee8_NBi?_|K7%VVxg2RUZ-`J9p5&81nd%lArd9}h zl_=7i2ADj(CPSAjA?}8yX39%09Mp!_`{@}XBy$So;WoyjGYoMNk|*A_o}WH$RSTVH zId7IsIxkigLtp`M*Gs75L=ss!lj`%AL>B&}Uv`nad?J*tafoP#!dmsR;VynK3_%ag zPq&;rR9txcY`Ff{kHLF!Tpct~U4%R|uy6M`PH(4bV^!#uJIef{BX_CxtC@vqQ{S6* zf)}56!^=ol>N_g%V@pq&j7eJV79mAO{yrp_C^aK=$J2o;EWJ2Gx3{9ukIgoyu6@cB z_HI&z&*OVtvB)&uQr>w&`q^DZ{*yHKyUz zR?MHLJZ@8($jXM|ooS*y-y>NCVg}+O6_)vhj|w_Y9)~QO#71eHM#=M3#~kQ7+P3oM zsRer{qpt3f)tVPI3sao$$nuU}_A(F`0QXpYl+kh0kzv`75F7}ay$}H(w&0yEdJo#S zOH6I}SaMf|P=)U{d%s3A)8cG!NhSAR(;Jnju$V7@&2lESe`)KR8FUb2H?V${?Y$lL zm?8DmcH;AzJ@=G>+^ij+t#oqP2{8k0jTE2*e#rMcI2qZUAk@LmF4P)+Y(L(!bM2fO zlXG89m^+^y=&~rBSyBSI>a6KMy6iJ~L7+)rXEscIPaXV*$rIFmGi6;z;&_BJ*RKM* z5?6(l`5<*Vk5>VPAEWdwa7>sWbs1u?Ua!aS3Z(m9)B{VG9##n76hr#m9@ACu@=JtC z2SR^;%VSd_2S$2&CpNE?2(oYn-X!!aUuQ$z=QwR4a@BKvylrQ}R+}joK8bdoV}Sw zo4lc+Mjcp2$HdzY*FB8qG(4b9rWRMwu^wiGxvj(&4+gfK;)YJsXR9TbM_9YhfOTg= z2am5Uwkrabo%&90Gq}g7m`MPf<;2HZ9^=b0HWUL@5=C^Mal(R3C(J%gohIg#)u+w7 zjXlJ>{k)NL2Qb6<(sO%VNjmZ*N1BS?wYaJz@P(4G+7T8@ks-Y=3rVOeI*X`ITNfjc1^YJ$1)(-+=&obUIhwPe_r21dY8Ki*`QB+J6OG4)U z3G4(;T;<*!F|TU>1o3KJpqshQo&l3$M$i5QrG z)!3v27k9ErfZ9zTVhLXxJA{fPeY3raih;JQW|;yzfwz(^nksmFo$lMGh(V3WBP0J8 z?T5YcgsF47I3G+=SKU}A%U4CleWAQ>`>{{VYLL$no_>;g4gDyB4aU^W1aZ!! zrPNB*jyMX^2m``|Q$uHI@8GzrW*BmnhM~hd%{kUvxUP5!H?NH6_OdbjMl zM!6=>cS~Rl3D13F?x+4|pdZ%EnPH)=k`AAkXR8k1-N_G!ew2nPC4FP8qwNnEjPP6B zd!uc5!y{2PmVLUSNYMU6Nqvy4g53ziEdh%MH**51l7D29!4!n{out)GD^_Z*ZW1FN za?wJpUV>1Y_AjS%Mo7GfZK54q^*duoON<5pfz4Kvb4t}e5htNX?5LWK&kI9hDX*H zim)DUmZZdz`Y_XOzxzMF>6-I?^3?lB9APOL%HAmwn2)#_#eCw!3hK3usvhx9+YB2g8n#^#f{(Sb~X!BRBNQ($}jvkc;Qna+J!Qcmjey57h+>P%hPl0<1 zjMg)BmuO-4T0*r(xcvMP5$LbiUk`Y175S$uhJ9LkJE$>pf6xQY$n=&m&s9!&-12dT zg8-OjxJhI+<`p8fqXcK2Ojp+qTY!WKxiVoaW#brTe$H_GWZTkjL!GY zJ!qc*iEGQ_`gLzUOlJIeoT{VQF$l`t~qwU^03p$28Ro zt86ALIgRJnBb@vrds3&fVmci#M`1hwcO3qi{z#S_UU2R06GEr>XcluqQNeC+dmT)H z^UA~l*jY;4^v>dzj;BjgCLS(B*%*2w2Uz#>6;(drIOohd+!RPXBM|P{dY(wwr#p{V5&E5_&bNJiM5_Z#Re# zb%z+p%(+X{nhp)E2i+W$L3^6m1l`V?eYFA_>gLw+o}&-%&YC%PKaq7x!uPqceO{9S zjjk@qGV*^8y0fxn^R<;&%%#@T1=VM#jqi<0biK_{a>ahiHKL=33UmYL%zQZtFtyNCNObuJ50)Q9)|sMyOx;0s zqxQbCZf|pda*_lsOgy-1LG_YE1L$()mgGdReXmLCIgf+~yz;>s4 zq%%5?Z*iFPaQdJiHE1O4W4P3X!TS%$mw`J9IaJBEC#t%m4?rK4pE@fQ(Z*e8MWo4h z{MJlDvG1?evzUK$N3kQg53Q4PHsRVQv8xP*t`Z8wHWk!tvcD`w>1Pr)X~T6xc6 zAGgF+n$`h9=U}P4>;d9PGR@4W?ye-yoqNIez(wCDfk^*_h1dGC$6O=H1uF-thqpg( zMeNDOV8h+~$yZN0Ec%o+$Lo^U8PMt_LAPIc-Ue?7^w~pO`YhD%uGH|C&XZdwJ3Z;1 zdZldXAFI&t(anMW)70+zJLDswXOEejdC@7&r7BET_JiwY#PUJ8HixHX-Yid3y2Ki# z*Sl7KeJ{o#%Dy;_iG$cBk=@w_tr~8>L;8#g(v1S*&ddQ!;LcDR_DrvqE23?!i?f5D zJu`PT#MXrNGv0I+{yCMQBPS>t#RewUm5ON+>pQPm@gm+N%AdjCH^Y+Qvo?=+{Q}uC z)v34Ixdbp|aI!J%@q43lbJ@hSR_1_Li}Y#`gV`umlU7Oh!VZ@O8Q7D1%EJh#vM3dn zQn%7Cb$)O`Z6aDpnLp43Z{C_X1WDhSV?50-Rh30~?v3p_lAxU=npAr=3pm7ksARm0 ze!qlnU9EoI;^Xpz1{-p#6<0#nO|YuQUK1wc?HQm?#2fRSR6dNF?3pxK4$CHW{bFO zX?}NQHF+|I6kBs*KYPAXewgO%6wFhsAmw+@_G)2!w0_N!oe7r?_7#TVDaT3H3Qy!U z@hGZfXZBWf*5HaX@;HEiH#qy~C3lT_19gdRV49Zc$F{2Fi3hd_)ahw^!RSt`Ns>+e zs!!2&2_BSaaj-^tdz14&*v-~csT+mF1}=3HJmI|s}1nUQPW z|EbKB+FgBUGnwrpx3XH~%n>g={(Y(WDk_*KLOHLlXHkUtr8aA4;=_gF6`z|kkX6$P4;`AzsNTBUqx{q z5W|c-WG5ccPllOMrKw9aJ?zn>^TK_~vmD#ITijAyE7>Z~)kwfcm8{ezCwfk~SOZ&@EK@uL5b0%Iyzb_Tj(+L6!yQ{FTNyv9yDl+=1 zZ0fv28M(UzcQe~eAP9g?B`;5?FjNwa6z0?*)ekENG$+c$r&qtTrZ$+n8)YPPPhCuv zL2iyB;r2zP_Jf+gqI-&gS>%@XbKl=TCr{I91EhrsHQSLB;w{*q+b#J;^@?^xnZZo0 z&N>*mH(m0Dd8NMdRNvqDq})3F>FV13r%3ED+7H z;_TLL9yL9F5p1RRoAa?5igv(BBAvohM1IOVWoAximM*-iNE7czn@(*#@yW*=6*EUJ zYb6-&;X9YMG1h0NgElUz=LM?j{}K^9p!w_dni1hO2iPIk8gH~@i)@*wHn5pKl8xIh z#c{h=&Pyn{iF(L`-yJ=1>J|(nvEB^aR2n-L#365J$=tEC!^*NWlp-!>qDvA~701V; z;NS~|n1RlSXOal*`R5)*Id*?g5v3h>hIEpvQ2SEhCySomY`j$Dm8GN&PZ3Knkj)+( z&v!mcJ@Ut#&M3^o%^y9HF{=&ZcO~_1liPXtBCqpZ*4zbcV7Q}|rBdxJ?`)#$Ji;gHd&^p}8SeXDek^$2Zb!A|n(kO%rUs_O+M0J=|F1TnJ5p&mpy?c)Paxo zo0fVmAARu#=fOtAT+8upLxP~U(43D%2)j)>Y4wJiTgy)L`unP7G{2}|GM*w1U;4w% z)+e`Y6iciu1wT_yS}9Q0i&Q3|WuX>@PUgvLNZ#r{x|T4QDOz3hWP7(VHDg+Y_Fh9z z=Qdik5Uw$OtnsnFo_9LV8Co=@6}?$+PvdEQL1C8F6agxjcSjwA)#0FC&a^+ZV>%p8 zgxv)SDD&XJ8IoR_fqv%snT4$~DVeq^5@GTL)sOo@dTrMie4YUP1XqFG;r5eZjSEp0 z!N7j~B)VSj|LOzMlv%Qo>-Kk(zbtNdrhaCN%f@`3ShP9)ZM|LGEl*gDnbHBv$(eY6 z&~7K{W@&t|S?|_zB|==LWIZW%=?z|{eSX7L9P4BI0ZIEs z2%!zSV>Es@+LN2S!&{t-|8`c z8mM9hRA>8W4pyCmid#)W%;}z)2DEJ6yY4C55`ONaFw;36a|6V1-L0xuvxP)UPP#-5xv_7XqeI%_P?$=o1Ntzp5*Pgi*6N*dD>3W6Xvp%{fDdQ(lYfYu zH^-dJ)$u1p7zvREB@ayIY-u1N?AM)N&t!doPQh+tp~0zBHNKd(Afq=93SD|&qb@;a z_JR`j#EG=wp%LdNk!fm6o4eh4M;ugWl@A_5e)Ac~8Nf7oI=uTH*O> z?cJf_CecQ?TmVzG(y?q&`o2xlQJUowXw-C0y;n=(8L8PebgD#mUR>b&q1-%aA53;R zhdrK^b^3rz&-l~MS}oDub}qSi4aa#mw70QHp%Dl7n~Zn%M>897v?CFQ&WTfa1gFf} zDMwkuh2-6cp1y2K9jvXhZ6_WKjCCfhLU@&l#G|(_Wb_vEzzf1l?9B-Qhg)tcnT+P) zuBF9O;xpAPS5JxVTba`B76ubve6%$=aNy8Ax>+066$LMvJaYJejJ++n5YIae(8RSh zk4AlaQVd%U2dYRa>?F&vdrSO+Y(HY`c;a-Q9Cp{E&`EmFCu-@CADU+N>)F|$Lm~WE z6|JYe${spMF8+F5(UQU4VlKb|Hu_#9E#vid&L?NA*S23d`;R^`Q^)&pjamQ9htYEW zVzF=I9bH;JH7|&UgVW)=>9o&_9ux;sm|4v7IzP!w)8eQJOSeQ~_i(rKHd1A~xk`iS z+i!|7haa?OW(l9UZFjpJS>lj28;!}5@$#0W$z*3EX*ms48mVvRe7HKj=pX0b`2d_LpyZ!A&vGecvKQdld5OY;|A6{{SuC85`O&Xi$6dz}hwX zXQv{o{Z{{XBmQLtdb9VaT&M|cuH$rLjGPGZXj^vlj4HlzP`YiRjATsw^j$qWw5hT+ zv4NouGn9SgqVFc&aI_3)jEP>%lmZn zM0xsJrEJ!R`*65 zSQEr~qf`epCkbt$!Cf`7lCogWFjc9hn|Z02Wett%rFVo=>M+Xa?7>IW5iK=?} zUKQDx19;3WIi_yvbZqe{#it!#$dQmWrC9UDBb7Ty!(-Vku^oS#-M>R~s?i)G)t|cFTo# zggQSI*(Q^T6z+9{I3WvpcgP z&M_8Syt(5nwg~W4E%!^FDw$3e8N|DD#rEp8l+4*`@MR_o@Q_)3qHc^uhe+GE!BwKpB)i|eHFuiDF0QoA; z17eq}^0k+0e%Pnk5>**-?_8jky-`JrvQvRzI-F99I3w(ZgMI!FQgc#1%GY5l6*T`N zxTr5)boN97_P@`;uH&PkNFhsyy9{;7?`_Y(b(p6~aq|JBnTNtZi0iKUzUlqld8jbB z+9n!P+A*Sk6RKQO{oywCJ2MmlI@uDG`)00meQNKKa`3?Q&PQg4W~Cm!5fYG4$?KZG zo*kICXT(43>wGUQl6gkPA-d@rz-GTwBr|ts2LU66mVdC|Dr0wr*2a7>P5#VQA|lu@ z-O$F76)gAv33~Cqbf->3pNqYuv-8afxk8>$Q$<}mjb86lBGUBU^5F=`lG8goRPD%);HSXTa`sNPB-caP$7&$_@BaS zRdjmz6l!3n6a}|mW2uvIQL66ke6Mv)$*(+sX**K)nimFz{$RhJb9AKX%47RfR?TgU z1x$WoQ%hJNL+;ro8scz0yeZ7EbqQj?*MPGL$pv=gJEU7YAoHOd)4zr3Eh+hdf|nlB zt2DH0Ej!63=nOy!tIwp0i0agc-QmvkwO0#dl-ZIh8)j6gbbOQ#X)$LGMxqTUlTcGw zLzMtfRFTQApU6Gi4-bAf8P_HMS-*uIq~M@5@<=iGvay>kKcyfwfR>lijWD`yW6SK< zE}|bE$D0lS<1AU`B`&8>!v!(DmEVb^WZEt0hL3aG$PBwsD3EPk{bU~KhB}BWV{>N*=5IwW;A8xG4wzFKWJ>c& zn3TN3_54N-mI@>3;V=(?WM`rqCboIHS7dHK)s%tQAocL~kH+sQ+E?F!c;-BInu&W3 z$^BNPKz_k|vtw4_jhw58j(3oWG&cepZ)2QBTbizk_C8vW_4Fj~A80g8z}zeN5ixyF(qYeG=sP*H{Y>M{Tx5K=R{bN3 z&#vOEnM;BU%R+BnNSoHC$)}IIu2dB`7nP=!Y=15gRQP$qkq_7II_Qte+%2G+PfVE| zL4-wbJ{v4(w{nX$`#Kyi8mzk^_WJVq(>Z6bn@cB||DLaM)?H%RSA7xA-(zfIw8Jl- zG21yPy7BY&&f7UAmVJ0*<&&J}{(Sgck+3LNrlIu4(4`Lnm|`y-==}M3q-mAN$PB*z zNbQU>69_4V9L&#UHtW1~Dqnp+gdaPrC`pa2sp7scc!J@y5F^$GwGxfvnN?NdNEm&>ALTh*56QZ(#TMh`q!ZO zu5`7JzK-JP!vDMPZExpu|G8rqNcva<;-Ok3m92qaYXt|wv2j3WL7?pR?k8%+ImGA* z{mxJOT7rI|4!Nnli73yQmBWkI9|E+U=f6Sfa}|TfRl1AGIWDp&VujH z00Ur*(fOx)@(a7DdCaF65SDNVqMgXPF!I*1`dBFQjChlzDQq4C5a%@%WEL@)IJYCl zF#;;M^MV@7=uOZiG;=+%&r-Q;&xU$9nd&W)c9sX!jm|9h85abt@{MWGd*0K2CfZXT z9yij`cV9}YTas&JH=V_su2(^izM{pc9eOv{I$)oG`~z~LQ@qV7xN1h4c{0%6f=@C^{VI=S_((#R28BK&5o9DTQ`_AAZ1Au%Iv zQ(a$CsEXBg*#+7YJC(w;eb8SR-MW1DKy6B7_hf2y*rHH4B?AzCwH~{t38iLQg^zNl zm;;eR2V`K?e#q_Z?n@3jg&JhT(NcNVP5{`9km1azm3o#ruCh_r*Pq};NHJg94qMCv z3n)9xmn~!lC80I94YT#-3l$;+n6$j6XXK|=IZt-ZKKa&D1(Fx4zj%1wgG1AiPd@uH zeF4)Tu1N>ppgGwPeCl5e^}t=+^L8g}-fvpX9^XGh=v_N!5hfJyZ<4khtlPg}w4O>e zr8elh+>ehx-JQC3Dpcwqab!u7kSYer>2Zlk$qm&diBps#_17>^v-($o9GL?4T#1 zu5bih}@yYLSD};j!@AU&v4%bPL>KrI1D>=8nY}sV)ZgwdXA;2s#BCXSE7$sWIU7$sSuG7R57F%X zUKcAwQxeS43jRAxVx9uDu0BL7iDQ!z;?R@w!$ZLCeXQQ7n`)Km)QeF!*4RrBz8Lrq zgg>h3>1;V^u#{{zuItG!l`{Lj?G@^y59;VOqL0O@*n)Uxq!vby@RQRZ(zkXOB__wD_LN)gPr7s# zIeV(Hf_=jP+{RYw6oDN0UP7K5jp(AyB^6 ztR~bGMRFy|IBTElI*gt*3j5R+Lvb~A&8c&HWkNSEqo`;a9lcL4=bGtCi}3?E$YUY^ z#k7zfZ5g5 zZw1agW4|%H1;|`4$xVvlxY?5JJ6T6YviZZ?G75n!KbkK+>vHJ&b`&-*wg`PQlWkft z@!JWXS9m)a#pnwV%EV0GhhLZ2OCe|jbfJa3t+j8XqB69FcELv92A`&RrbLj?3YfMT zFzr;TQhn=~BUVIgPSYgmpy^OAe8olNe9FT%Bko962%cnRZ$uw|avwwXnx*+tUbFYIdw+Rip0jBr+Bw_TbULwff2UhQ_`Q}=;m@BUAz$r8fRWeEv$#L4D31E_ZaIv zrEBXGw%l-0E;AZ$Y>{j9A9P2N#=^zwMLG{8(;3)A_`mcfga%(bsRuvOmM?>r*pMgmi~CJ-UuQ!*hK*h zy12lztH-yThh5M1kD$9Zat+o*^s69em_g>PctCC|j4tb3Wy!P(DBk~#!3>nK3)2Ax zth5VcQy?ntE$#qbN?j6ifDOt2Z8GznwPEBCp+|RmK_hqieXp2aYH1s9)t3;X)YhfV z`IJeI>nRzbCutoTB8~%CDGae(%8ps=RtvQe=Yhu2ujAg*AQ4x9&RCXTV83uw|ypgCUgH6(6R=m(O#xPY>Dq!v0{RwM9QT%r?<( z&X$odQnsjo@h5Z&G=GVC|0OX8SlWCYz!Pc5wGM~FE-AN>DHy@tMDN=5i0VZ0k&8BO zYVl(aV4jiqz&iBuBednof{blFd18`-IzEktFT}J@5XxVHZpfd>F5_W&i#$RbT~?DL z9^a4>M_qsVp@`H>2~jtJ~DW6|bktth*u%wa~?LYCy= z&Xzitw&OgE5L4Y!YvJO~?W5}AxN+ZqMtz3Tm(Xlx2;I(~xE&R66WaxBW z{_252EeV3UMqNU)A(gEfZ5`3Q{J7GikqI8d0W5Q-cM9Q~6?wzQmYtExhf;#uH}`dF9E}`K715xjTtIg^#++M&j-Fcn_iy*@z&QG z3Sk*hduf9ZOXUqIl>N1>$B)@YI$u%0@NyQJ!)&>o&1|o$F8K5^p-_{=uzt7eCZ_TN z-Ae}O{5QKXaA8l#(`6osJMIOo@B9~FL-&5JOivi6nQ}H*%?Eh}7r&!jjKxXGkPMQF zCVss>*^EqFLc~YBaGTiOCz)Je68So_#rd2olLV$I+adlfUfpPA)g{I2-yZAa5_I=~ zhKqq0i{e9Dol_gD_HD9>%a1?YS+i&qY3Ob{$P70-7#>*NN(^9yQg%>}-J_jPBcFXg zHDEKg=vM~$6$5n#gsIYd>wC8^M@0wCV+vrFoLGHk50M&s-JQXN`>90LyM1ThcV~A4 z&o%?%E-oD11uLHjCWoC(W4)J;zu*GO(o&z^ZQPVqz-p;56~Bx(GQ6N{WZI0ljOhkT z%j+=u0-Tis3!3MbpxUAl*;H`Q#G*{@`I0vF1r=tw8fk3Q1O_S6CPu&)H%mmm+hr9j z8DK9JtO~$tZ=W82Sp*+vrI1B?03n>-csyKx8L@>pqZTHM$dzUS#{{wz6r~mKz_@3L zy8496Nxt|q6xeUgJERxHBzGxf)?$60X4{X>crE3=k8-L&81kCS7zn0 zXF%6Bx_q$mIxDegWmvIrLn`M5CLr<1304JaAAA!h4s4q)!wJW^>tcc{tC~)Q-GqVa zqyLb$9d$WC>vhQ|{#riQ_LmBR&SQo`{k7^h4TDYZzaE)VVuPXE za)Na|*R{q}39mT@mccL&Bqo0Q8F;V(vE@qw9S9uBkh6NAx-KgzF=I#L{{nhxp} zM0TIDW7s#h**Y?iv7chPr-4Q{(XUHjG9hugnOp#hmc8{4MazcTz>Gd7noR6N#OoOi zHX@Urw6l(Jv@sh$=^puxfVLF2?daI}#99t^b}@8W6*E45KivpAC;52O$rSZbt4W#0 zY*S!!?)*w)>$(AYXWjDb|AN@ZIwl}EF<00<3mPk6Zz{}bm*2`W_DZj889GP$wEF=2 zr5PIuG$S)GlQOizzT5Yl{j(z%;PO;^(p6Q{>N2y*4&_z@3mQYJA}HKq6#8$)v&`H#VatdQpj>Qj>SSBQ+l`L@gV`ZVf5 z2{$>()d;(L<_J^oo5ue1S(gIs6NzpzvhV!7XwOQ?kh8mQ(rUbr+L4}p$0@=stHcVC zQ90kC+#z8>;|ko)%}IVAa01^DeEkI?bq?&!2ly`yc)aDCz!+7-W7$mty4_Wp>S@No z5V^E@oiQvo@P=Krzw^$(k_$Ie*-5RUt%QfTvJRH6On%PZ*K8=xiWX4J#v1lvRpM+o zaP4R&(XUyti`sb`+BMh2Yg)T4NyW$n04Ymccd&75*bEso&E3*?ujuzc*vIUtU8&Xi zLHO}O!Fr-!3tMgRRvtHa6`d{RTb7M}L(ff+^;%sXl~v1%E&)$!Y++h+oo+vYiR8ZI`t zf}b~5=L9vTRz zv7Y?ee|8qVB%gJZ1#6t3IVCzI-K0Xrybg=_U6F}xv(jI2VVX@^MKFWO658^BPV$O5 zUOhkPcC20NvOd(sZ*~xZrY)m{cEgUkZw=WUd0hBETym57NqH!_NvPRPDya;bK14+hKWq(ykwQWcrWC0e z2QJf1x|SdttwW|=yA}_j8pEZ^b9Bh`7AaEgZP{`SFPJ`FW!Ak+DRth|`KC7UrvkYB zrXr`70U>#MAXS~{RZ%!h#Iw!7*7t&Xvv+yU{A1rn*P#NZWFzx_aLxwdI3_#BsZCv9 z%M{wuu*jcGC(zs9S%voIv?PVwEEl~hL4Kp&zhAcTp`EoyFPJjZPC3*-x29`#M^@?u z_3y&6n~an&{l3<7G0=KJ!qVGS6+Fg?6;P)EQnv^qL!V>HUEjAdN*=73<@-BSX8z3E z!DfA2-_Qro{5hRoT@Uy;`9K}eV*J=A7NdUWNT;ko8A#ZYHF9F4*g(_WI0H7&Ue;`J z72mS@oXK%5+Lj;3ub0#Tef)LDxI5nLu1OGRW{X;BYoXDuw$aP&3n?~sdejh%>%`4S zkvl@*jH!$bEFu(oQP903R~ToR5jGN zP27zgQ7mh;XHQ-EDaNsRN0$hVJe(H2F-h3WJ{VNcMQYmRMrcne;JWfm@OFlJunW`U zw=L;JX12d`><;W}ert<8H1z%pg*`Jl!dsRll&b%v9|BPL*DF=KIJRu73RJ&Skl-M) z7=yHc-F*?`$=tcYXCt z&74NC8wbO)2_dwQjAj4`>mj1$gv&TSuiXL}vI6C}e-09xx;v#eM8s>P%>oVDjc?cY*+Dxk(?AHcw zB-f4HYIEt0($Bg|>SH@6eNl&LR>uSM4BJj$(XQVtvE z=BXqS?Ss$dfovWuT0C|f3+MlRxRqLuaxyuTkO_V(1bxI;nEs`dXY(cICmsnc8SS^> zCK(XQ10=(9JfEs48Sk#tNX`_Cx1m0sPPu%WTDY40HS6``jE~dRv7#gW>ybOlOk?t- z%->hzW@_7lx`Rz%PK*s##$Lem5(dRfe*-Ab9xplH}%YbkG&f;#dxduk*zk!08O%&1$x;VfcjS@G6cE$+{Rv&@4^>lZauT-o{cWwix3jQ#MP=RnSv z=%-{xk0*0KbE-n9lDp5IcA&0U&#V^+a$0x)l?~4Vvf;VgfNZ$(pKLh6%NaVam{3SI zCpqjd^sK}cnRq*%wp5_r#opvUMeuCz_`WpbtPH9zH>fgm)WQ{Ym7UZlK$uuI>ASmu zX43Ev3Tcl&*%;4fK$CeV@)ATE)fd@u+I(EE9sG=2tNjNNj-zh(L?Nx)_&a6m$a%%4Au6fBenOp7K zg1`di&Am<1sjYA^noOa-!?E=zwN&=S9@k1&)KfDO9-&oJj+J}Pn<;h2Fyp`oCo>NI zK6Wa@f5Ib(5BX?oZp~&c(K4TXq*}(qNSX8v(tPqIxbrKpjq&jbfmtwF9z-rlv5q6D03O@Djq)l#94wnC+?C;ZlZO zoBW~*hO|g4WileyiwYxOOAWdWraf^^Z~Iope3XHA@&kH!7C!oS36&r#CLeLaosK>UE9)USO!Ez^^=b7 zCDX5b%_9xl8l(6h0@CuUon~c)eBMg5_SQ1V4nktjsu+_y7CC9ZswbO~t|A!8r-j}e z-D;>pT93$Y*e3m7&{C}F^`IY%xn_GMYyhi$$nRaF^$jQFOdgr{`y(Oh^oF1TcYQq* zWs60Pu4_6eU0Ei@1J!Rhfd!K94$h3;&1WOXJpEwX9V7np5K}wEYO8X{MjcPY10ZoL z9(Rjkv=9K1%;t)^VbuPCM39m*DPj5!W=+?DYLAXx>rIl0Vx0A%_~EU;>D5+@-nTC1 zShvYwR2@OHhksSD%s=DPLRwU%X}Y)0rsm2k$-hmoq0u{pf2xi#5FyMig4y+WshztUpY({?K9TlyHtn^Qn*h{<|T56H=Rc^4}QA zrb0`twSCNyE#S~;DnRPcvn9q)CKg}6O^f>R7vRlnicxf*3-2{jp+dzJFRSbOuysnm zp{Yh?mbMjn@u)|#=Sp9ou77b}S&ie+Yx(LatplUitc}C&1h~JKv0~eBA7-A^e zcduAp>2TDz9M-<#SQ;6ElDvC+ric-=ONrdCf?S(}ef>iYnQb6jI*jO+kVPMQrxcJ~ z7GKv{936^JzMpL*x>~NeK~GymPyIL3_YtsWF50z;e-#`+TXWb1iL|6=*U1OtC?0wE z$5&!Y@MpkT03@ZCX8}}Nn*LWwIw}k;oP02{pudglRxOk3#plF6D<#52^UiX`E<_-O zoq96oWgfYQfy!SUq!CNlNfq!yrH9o}U~^KxQ~aeb>e;xYHa!E7Bq1kgAwBwqOF2X^ zrrmhTNQ~9>+fT-4cIfZv74h8-`T+FlpAGohb7{h!;?~!UwhzA8S2_oxj&(!KoW{KJ zdpw=#-v@x>_z>jAA^*AonI>WP^f^bb6z##m6)@c_#A$dJ6{4&%W#xCy-5y;A{^vI_ zTPooP;Q%*Fp6}Q^ASo-v+!Jo^!V>b`Z@j4KueZZ=2iJ%H^{`kTm9To}mT%%q?w96z z73O@r`{B{&8`>}*rwGH=k{44ViaJ;TgIu~N`Gzh|EOQnV2Po4J45#S6K04Y>%EKFQ zvX)?398|`z;JPCLtUVX^Y7K?#*J^l8el&KlU}s?>ec3M~G=MB}mb=B}6`7K)UsbO8 zGeTKlp1Ki-%{74^O!*GHl>J$G|9Xxlo5<{kmg>}Ok04EPkJ4&(C#co<#ox@{aw4-| z=D`(wbgx++rp#bQPQl(bcQ1d52?CPYL0PZE+pJS(yifkb#RL*waLr%ZmgPDyeAO3O zSZ90BpUeQxbpS)(Fp<@_OEBD1^ZKB0)B8pQ|gm5bG^th z9Q6O@3dSCwx;3=6QbuW+xzg7>BmQ^&xj@$UMpDPnf`0V;Rrd?|*1o?dKmeyC2;n65 z%Lso^SOa%>U9+dVw9yr+_XR;0569V@W#3yP&YjnR$m_oo9-;x)G1ihCI{<<2UKzuG z-{u3~3OY0F_MJkT3fs0lF1;K^RQ=Gx`qdx99tQ;4V8y5m^54bsq{dlylq2Cln@lO~ z)c?EI$U;!^gmU*4;#`?KsV(*IAr#pv#Z1oqP7PF)q##BZ7;srUD;F!t zsspX%I5;gCVg~c_16@~sh^A>o4G{j@KY^$ zrg}~_NFXl^IPm}U