cvsshell-devel Mailing List for CvsShell (Page 8)
Status: Beta
Brought to you by:
stefanheimann
You can subscribe to this list here.
2002 |
Jan
|
Feb
|
Mar
(82) |
Apr
|
May
(14) |
Jun
(3) |
Jul
(27) |
Aug
(18) |
Sep
(10) |
Oct
(1) |
Nov
(8) |
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2003 |
Jan
|
Feb
(1) |
Mar
(1) |
Apr
(63) |
May
(2) |
Jun
(2) |
Jul
(2) |
Aug
|
Sep
(3) |
Oct
(2) |
Nov
|
Dec
|
2004 |
Jan
|
Feb
(5) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Stefan H. <ste...@us...> - 2002-03-16 13:26:39
|
Update of /cvsroot/cvsshell/cvsshell In directory usw-pr-cvs1:/tmp/cvs-serv11151 Modified Files: README Log Message: * fixed some typos Index: README =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/README,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** README 15 Mar 2002 20:22:39 -0000 1.2 --- README 16 Mar 2002 13:26:37 -0000 1.3 *************** *** 15,21 **** ------------ ! CVsShell is written in Python (http://www.python.org) so it runs on ! every platform python is available. You need Python 2.1 or higher ! installed on you system. You also need to install CVS (http://www.cvshome.org) before using --- 15,20 ---- ------------ ! CvsShell is written in Python (http://www.python.org), so it runs on ! every platform python is available for. You need Python 2.1 or higher. You also need to install CVS (http://www.cvshome.org) before using *************** *** 31,35 **** On windows, you can also invoke the script by double-clicking the icon ! of the file install py The rest of the installation process should be rather self-explanatory. --- 30,34 ---- On windows, you can also invoke the script by double-clicking the icon ! of the file install.py The rest of the installation process should be rather self-explanatory. *************** *** 41,45 **** Help is always available by typing `help'. You can get help on a specific command by typing `help <name-of-command>'. If you are not ! familiar with CVS, you should first read the CVS-manual (http://www.cvshome.org/docs/manual/). The configuration file of CvsShell is ~/.cvsshellrc. --- 40,44 ---- Help is always available by typing `help'. You can get help on a specific command by typing `help <name-of-command>'. If you are not ! familiar with CVS you should first read the CVS-manual (http://www.cvshome.org/docs/manual/). The configuration file of CvsShell is ~/.cvsshellrc. *************** *** 47,50 **** --- 46,50 ---- A session with CvsShell looks like this: + -- stefan@kunz:~/cvsshell$ cvsshell CvsShell 0.1 *************** *** 53,56 **** --- 53,57 ---- {a} ~/cvsshell [:ext:ste...@cv...sshe...ceforge.net:/cvsroot/cvsshell] $ + -- This is the startup screen. The second line from bottom is called the *************** *** 67,70 **** --- 68,72 ---- I mostly start my sessions by running `update' to get new and updated files from the server: + -- $ update Root Directory: /home/stefan/cvsshell *************** *** 76,79 **** --- 78,82 ---- {a} ~/cvsshell [:ext:ste...@cv...sshe...ceforge.net:/cvsroot/cvsshell] $ + -- This produces a listing that contains information about the files in *************** *** 81,86 **** easily accessible by just typing the ID and not a long filename. The second column displays the status of the file. For more information on ! this status characters have a look at the manual page of cvs (`man ! cvs'). I have added the following status messages: * OK - the file is in sync with the repository --- 84,89 ---- easily accessible by just typing the ID and not a long filename. The second column displays the status of the file. For more information on ! this status characters have a look at the manual page of cvs. I have ! added the following status codes: * OK - the file is in sync with the repository *************** *** 94,97 **** --- 97,101 ---- To add the file README to the repository, do the following: + -- $ add enter filenumbers/filenames to add: 0 *************** *** 101,104 **** --- 105,109 ---- The files have been scheduled for addition. Should I run `commit' to add the files to the repository (yes|no)? yes + -- Now you have to provide a log message and the file is commited to the *************** *** 119,122 **** Feedback, enhancements and bug reports are very appreciated! ! CvsShell - a console based cvs-client http://cvsshell.sourceforge.net --- 124,127 ---- Feedback, enhancements and bug reports are very appreciated! ! CvsShell - a console based cvs client http://cvsshell.sourceforge.net |
From: Stefan H. <ste...@us...> - 2002-03-16 13:26:09
|
Update of /cvsroot/cvsshell/cvsshell In directory usw-pr-cvs1:/tmp/cvs-serv11072 Added Files: build.py Log Message: initial checkin of buildscript --- NEW FILE: build.py --- #!/usr/bin/env python ############################################################################### # This file is part of CvsShell # # CvsShell is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # CvsShell is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with CvsShell; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Copyright 2002 by Stefan Heimann # Website: http://cvsshell.sourceforge.net/ ############################################################################### # Note: This script requires GNU tar and GNU find to be installed on your system. ############################## # Constants ############################## # all files in these directories will be included in the distribution # Note: subdirectories are NOT included. DIST_DIRS = ['', 'src', 'images', 'etc'] ############################## # Initialization ############################## import sys, os, string thisDir = os.path.join(os.getcwd(), sys.path[0]) sys.path.insert(1, os.path.join(thisDir, 'src')) from app import App from cvs_shell import NAME, VERSION, COPYRIGHT, BUG_ADDRESS class BuildApp(App): def __init__(self): App.__init__(self) self.setName(NAME + " Build Procedure") self.setVersion(VERSION) self.setCopyright(COPYRIGHT) self.setBugAddress(BUG_ADDRESS) self.initOptions() def run(self): os.chdir(thisDir) targets = [] for t in self.restargs(): try: fun = eval('self.' + t) except NameError, msg: self.printErr("Target %s does not exist in this project." % t) else: targets.append(fun) if len(targets) == 0: self.printMsg('No targets given.') for fun in targets: self.printMsg("Target " + fun.__name__) fun() def clean(self): cmd = "find . -name 'build' -o -name '*.pyc' -o -name '*~' -o -name '#*' -o -name '.#*'| xargs rm -r" self.printMsg(cmd) os.system(cmd) def pack(self): self.clean() distname = NAME.lower() + '-' + VERSION destdir = os.path.join('build', distname) try: os.makedirs(destdir, 0755) except: pass def collect(destdir, dirname, filenames): import shutil dirname = dirname.replace(thisDir, '') if len(dirname) > 0 and dirname[0] == os.sep: dirname = dirname[1:] if dirname in DIST_DIRS: for name in filenames: if os.path.isdir(name): continue src = os.path.join(dirname, name) dest = os.path.join(destdir, dirname, name) try: os.makedirs(os.path.join(destdir, dirname), 0755) except: pass shutil.copy(src, dest) os.path.walk(thisDir, collect, destdir) os.chdir('build') tarname = distname + ".tar.gz" os.system('tar cfz %s %s' % (tarname, distname)) os.system('tar tfz %s' % tarname) os.chdir(thisDir) if __name__ == '__main__': app = BuildApp() app.main() |
From: Stefan H. <ste...@us...> - 2002-03-15 20:23:05
|
Update of /cvsroot/cvsshell/cvsshell/etc In directory usw-pr-cvs1:/tmp/cvs-serv5317/etc Modified Files: cvsshell.ini Log Message: added `bin-add' command Index: cvsshell.ini =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/etc/cvsshell.ini,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** cvsshell.ini 15 Mar 2002 10:43:37 -0000 1.7 --- cvsshell.ini 15 Mar 2002 20:23:02 -0000 1.8 *************** *** 10,13 **** --- 10,14 ---- list = cvs_cmds.printListing ad, add, new = cvs_cmds.add + add-bin = cvs_cmds.addBinary ci, com, commit = cvs_cmds.commit delete, remove = cvs_cmds.remove |
From: Stefan H. <ste...@us...> - 2002-03-15 20:22:42
|
Update of /cvsroot/cvsshell/cvsshell In directory usw-pr-cvs1:/tmp/cvs-serv5153 Modified Files: README index.html Log Message: Completed for 1st release. Index: README =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/README,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** README 15 Mar 2002 19:41:10 -0000 1.1 --- README 15 Mar 2002 20:22:39 -0000 1.2 *************** *** 1,8 **** About ----- CvsShell is a console-based cvs client. It provides convenient access ! to the cvs commands through a shell-like user interface. --- 1,13 ---- + Welcome to CvsShell 0.1 + ======================= + + About ----- CvsShell is a console-based cvs client. It provides convenient access ! to the cvs commands through a shell-like user interface. The website ! of CvsShell is http://cvsshell.sourceforge.net. *************** *** 83,87 **** sandbox. ! As you can see in the exampla above, the file README is unknown to the repository, the file someDir/foo has been locally modified and the file someDir/bar has been patched. --- 88,92 ---- sandbox. ! As you can see in the example above, the file README is unknown to the repository, the file someDir/foo has been locally modified and the file someDir/bar has been patched. *************** *** 89,94 **** To add the file README to the repository, do the following: License ! ------ \ No newline at end of file --- 94,122 ---- To add the file README to the repository, do the following: + $ add + enter filenumbers/filenames to add: 0 + cvs server: scheduling file `README' for addition + cvs server: use 'cvs commit' to add this file permanently + + The files have been scheduled for addition. + Should I run `commit' to add the files to the repository (yes|no)? yes + + Now you have to provide a log message and the file is commited to the + repository. Please notice the usage of the ID of the file instead of + the filename. You can also specify several IDs. Type `help list' to + get more information on how to do this. + + To finish your session with CvsShell, just type `exit' or hit Ctrl-D. License ! ------- ! ! Copyright 2002 Stefan Heimann (ma...@st...). ! This software is released under the GPL. ! License information can be found in the file LICENSE. ! ! Feedback, enhancements and bug reports are very appreciated! ! ! CvsShell - a console based cvs-client ! http://cvsshell.sourceforge.net \ No newline at end of file Index: index.html =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/index.html,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** index.html 15 Mar 2002 20:13:05 -0000 1.1 --- index.html 15 Mar 2002 20:22:39 -0000 1.2 *************** *** 24,27 **** --- 24,29 ---- </ul> + <p>You can view a screenshot <a href="images/screenshot.jpg">here</a>.</p> + <hr> <address><a href="mailto:ma...@st...">Stefan Heimann</a></address> |
From: Stefan H. <ste...@us...> - 2002-03-15 20:22:06
|
Update of /cvsroot/cvsshell/cvsshell/images In directory usw-pr-cvs1:/tmp/cvs-serv5044/images Added Files: screenshot.jpg Log Message: initial checkin --- NEW FILE: screenshot.jpg --- ÿØÿà $.' ",#(7),01444'9=82<.342ÿÛ «ì]IG[ðé_RxRëÁqg$PZY¬¯¤AÏÇaÑQn0WäßS×ü+©x\¾cxNÊ;¥Ì]ìHeIçù®Ñص;<T§ÌèØ?~§wex.üãı³YÙu1´°W${f´£µc6Õ/?¡jèû´ð$@ËáÝ'ÿ gÿ û$äR®NÓÙôûK]ç"ɵ±bÑmâ·³Õn5-Ò£à[Dʲ!EnÉÏDî¾úó»ùö¾ÎÕC©jK'£þ§ßª<òÝ^ůjѬ #òþa£L{[¹sî®ÝÙ¡ (è/xI½ÏK¸ñVk3\j°Å:îäTH8åI<Go¯=iÎVxð/hË_Óõ(KØncVÚZ~þED¡(º Zó©÷ÕP<ê}õ ¿^DÂbîÇóÐ×qÁeã ÎÕ6[Á``2NÕVPO'ùë^$øS'¹»é~á^Ìvÿ U' 3Ò2óÚÌ[Òæ¤w¾ÜÇ$ü³'ûêÁW~&´èÛÞH.»ÞGp±ä v»c"&ÇÇmãZïÝ¥ùT¿LÐê^Üè-z¾ü/¡HîË÷£L±Ûc-ÖqÌ.ßÔxVAÆíw°Ó¿?5åøZækÏ%í*C< ú~6¡nÁO)Ú9fyFÜ¢à9b£Ô9àà |;öúPµ¼³ÝDË|ÝK×Ñ·Ò}ó6 ɾɺnÈШÃX)ë©#$ú7 C0Ó,`ôØ,ï{Í´®ý(ùùVV'tjW$à1$ RÖí¡³Ö'· :}=«$y$G.ÑÔ@Op¯¹AÉàOr i¶Ò 5oâÚͨIn-fÉDÐ3)]Í ñèÆkbñ_Ù½ÈÌmɰ)rwmÙ ±³Æ=®(.-=ÆéDEæugWmÃhÊ@²';ùÆ( ¦Ú]>D]MæàDÇ2là±;KÏ`Nqî .êþ´¢[C¤ÑKsæ%0,PG³ÈJ¨h ZNg>£4WÄ-&6S.¤!°ríeÉ p)C¤$´òêVvöýV)¤1\Ú ÷öriÚÍÅZ[y^(r RAÆ}ÜPè @( @( Ϊ¬XÀE+0{îP¢1̬ñÕi#Þ àüø?Ú»×lÍÔw6ÀÑ©C5È++F"cÝIÎãºkqľNV],«,ï.éqBÌd 0Ù<a@ å·-®»g ÏR[ ÊÁÇ£râÅ·mÎK1ÝĨ] cܵ»Ü3ZÅ,PmId0ã°Uû §§êövFÎá´ökë& ±Ì.¦EØK2å@c4xµFäg´ëäH¨T+:ª±`[®Áï¸q@iêþ+Vµ¸IQ/rÛ¥IoÙàS¸1ÙF -í?9åÿ E×äÑcbI*¹$ØÊrÆvpØÞâ£@KwâY¥Ôtû¸äc(?/äÊg úG Û¼¬ò\s´¸ @( @( 2qÇÆ¤½®.SÏ*É«´§ªW67A° ö¼`ýnÆÚÆæm".£F·1Üæ]¦Dô±Âì0vHx}Uï®T´ªþFè£FÊ0D.NAS@+Æ9bO±Ón4ÆÖêk ÜfÎШþÄË@cµ0s´ rùÉ8Çs# éës¸#±5;uXX³pFÂÄ&à¡A!ÞmN·¿¸´dîà,REoäQ¸ ûXLÙ`¸\ÁPÙ!@îËÃtÖÖo-Æ#¼ÜËs-üÝê4aË>6n8aí#$i§ØÞ=¾.éÒ¦«½LoÔ³gÛ³ äI° Y-õ¨$h® ³ ¨v¼dϤr VaǸï >ͨC¡Mp|IÌÖÄj1=Ài×7CÁ7qÈÆÔ_ 1üGs Þe4/ÔneypGVEÙ]ùäî`Ísæ¨ @( @( @( @( û 9æ°Þ$ÕÕ¥)Uc¬s[Ç$j¡¨ÊTc{Ǥ[½Jîù.eÞ#H«´ m¬\ÚŨÆÚ¨GÓuºzFàÞ0¼ÃÁ!H>P @( @( @( @( ؼûÃø«ñÓþ*ØjI*Þ~íÐÿ Gvuþs·]E¿<çÓ&Ü|1êÏ|ävÇ>jüÍ|Ìeÿ ùWïÒ¡T:NÞFìÌ@9àý@K²TpwOýŪþJ¿¦¯ ¥åóG>¿æi~¯ÿ @( @( @( @( @( @( @( @( @( @( @( @( @( @( ȩ ç RO=°f+½NØÃ¬Y´Mm/'N`#1ÂryÁ*q~|PüK%´þ"¾º´»æäZ5uÚÉ C(9Æ;dsÞÊ P @( @( @( @( @( @( @( Ýíñàü!ÇèÒ½åÂ_²ótù®Oݱu--ÆÈÀ¯kç6föKíîx?ºÂ»ÞVs½]GØ{Ôê\7xÞ¯ÈǬóNÊSm¤]ÎÀÒ á@ÒÂ`7ÃóVuü¾g´8õáÝT\ãÑ®¥T¶ôé®MÜK*H¨¶äÎrGãþ8ÍTW Ù´µ$µV¦y/¿Z:3Z/7kÕÎ t2ÁIbWn øò9«w|¬ÇúÅ\\.Ûg w±i{ÊñéîUâDµU¤LÁÝO pk-uuÅÅmíigZdÚµºÝÅ´3Ä!27ÜF#'¾3ýu:Jm&gÙ5§©Ùã©$îLãk>5ì ¥§»;ûv··87b¬3p 8ÆqÏ#.m'i|â,_îÒöoáRÙéÒC~f½µ A£lÈ@˦ҧA<&0M;x)Úu#-><¼íÑã/ª»Ù ·ÒÞá!ýrÜ~ÑîÝ/%FR£,äßjªYÜ×Sµ(9z¨îñKÖöÎ÷ù·ÐîXà¦f+¹ +»»§`}¯â;¾wOêÒõ\_L[»ñ®O/+ê×M+ØÀïÐÜ2mΩ(ÜF3·rä¹ÇÏÛF²]HÕí?èNi4ãw³kÖïûàËLú¥IbEÛóïÄÙQüdàTFJÍ5»Lt¤¢ÓwÒº¥×i|id4cl÷6ñÝõKnÌK3·PTdrGDZ§»wWµÅGE¸ÕÞ*ªù´Þ:'Ó|Ò$D²mÌÆ:¬K)¼Ø\ðH<q»·Ô.×ÿ ¤÷SÎ1Èç$ (bìv¤¤à¢ÛºåÑ>m-ø¤ÊEÑ£ê$vt9 ÿ A¢;sÍYCÙ»EIÅEºÝªÇ>¶ðï ûðrtÏÑÃ'Û árO òýýàx÷ûDUø4½®¾¨m-¡Âù»VÓº-åJÆæHär 9íÍ+Xv¥,ðºÎwÛÁ6×µ,ã|m´óÍ\ÛÎDs@ÍGXÜ®íá{äöçæÑÓWW×áâc©Úßv¦¢ÖcÑÚrIÕ7Éù¾DIf^ª]Û½¨ZàoÚ¸* ®îîö¾cîùÞ ?«KÕq|]1nïÆ¹>|¼®Õ«Z²}±%Eß0Éä9rj¬£FÚZ«Q<SXiòçÊÖÍs ªëéÝ8C=ÕºÌct°m¤não*AÆìû»ñWॹλG©EÕÕâ®ëï¼vÉ$D\Û¼ð&1S¨)ÜÌðÄA=óÛ¦úk¦âÒ{<g{g+÷Áf÷JX¤·´8%ηøéràÀÉÆ RY<pÍ0')7#gvðÄýJ{àÄg8£&Îë'%i´ß¹¤þ>O©j]àgI®ícuâUfl;)ÁÃmÚ9ûâ8 YéÖìÆ=±M'¶©>XO;]¿b}µG/¤H?dÛ"u X(Sy=°0¹àxã9wo©+µÅ¿ÂêêñWuÖ÷æYÏ:èèZ¦k¤`@ FKÁ$>¢÷øsNéì·#úØWQyOñ|{&ò¿gMM¢EÔ-^ÁP$ÄdTS<í=íÎ*89ßĺí.ø\{¥êçkçXµ»^YµËWºÞDhÒW ©»Ð´î$cç9¦¤TdÒVzºÖZ]3ñüyÝiên$©¼VX·izåËìO!ðqì¨Ï=í(f¶¬ik¾:rsõU -ªó»uO3L%ãDMÈÙݼ1Rø#±Î(ãI³¢:ÉÉFm7îi?êZFxÒk»XÝexYÊppÛv~ø' UC ö/~ðþ*ütÿ >Ï7ªµ8<3].ê¼+÷É<ZÌS¤§¡2J©%ÆäL6â#r¹íÉo$%j%XÛïsìsÉzÉ«JÅ.,Ó¯%áJÓMÕ_MGTF%äVÞ¯µl¸âBA÷85ÔáûóúvʵÚmìº_8¼øz¹\×4uy©Ç},>`^Ë{^orOÁàðsߨJjM]ûÈÑìÒÒ¸8S}#KÝvýþÍï¿m>_ùSÉÏûo_§æí·wÙìû±üõ<qã㯿q_éu¦þmW\ªºïãû³ZV0#¤~åwGõ?áYº¼RQõÝ¿|ßÄ»f`Lº¶î+wi¢Lªä« >ʾxÓMÖß3[:ÑÔ\Mb¹¸õk¡].bM:kciJò+Á'rÎ9Ïÿ dÀ;7p®BîfÀÇz·{¯¿w»s/è_öUÖZÍ%~º&° àxXHI¸G¸vǼä1N$q:¥GYÚxÂ¥^öÿ ¦¼¼º«ÇÒ®týiì- ²¨Ì¤náºgÒpqÌcãHã½!©Â«ïÐÑØÖ´øÝrÃV±Åºçø¼2¬þ>¡owªÛÏ|SZÇ u{ò2ähããØÇÀóPæ¥$å±1ìóÓÑ4R}+òúß»{I,îFº·Kr®PÜs=ß>cq¼¬êÇYÁ-9%,[¬xâþö¾kg³H. Ì2É+G(FÈäsÇþ¹È¸Ó²u#ªå¦ÒWn¼>þi¯m§<¶×B%?[áT(;vç8øXÏÍÅK{¬¤F^·¶ríæë ¼rYÔ5é/à]¯7Lrê÷e¢^séLr8Zz®K¼Ç³öèÉ5XÚ¢ém%oÃa©~ÏK¤@¶ì¹+Ò8$dÆ«Çë_³ö£oé¿Òp¾wíââ_¿¿Àõ8VÆ[+kgH]X}²Pì´lNBD1ï'>ê5\)}ãèQvi=E«9[]*JK«ÿ ¸ö{û»{êäª7øûÍI&ÒiRêù¾²5+y5 5JåwN=E·ÎÄcaUIÜÏb 9·ââçó1þkIhÝÇÊ+âÞͪÞÒTTµº+ym®ayaLG F¡ä1<cáÏÆ±J¾®¥%8:jÖUªuâº.dº½yí¢é¡]ª²A*ÄÉªÇ Àø]¢º½½ÓPÔvþÓ^ÔÚê·ËÉÕ¡³ÆÖò³8êϥïèAÎ3Ü1ÍLfª+Ùç©5%%¯'j½©øÚÀ]BÓØ[Ë©1nào Àî¿ù§m8× WÐ>Ï7ªµ8<3].ê¼+÷ÉÜzÓêÞßÇ ï¸¨ªÍª²ü}{»ÔJçõ²²ìJZ0ÑoUçê¸û7¾b÷W±Çù"qqxd<da} ç»çÊZXϼhöNé¹.ê±÷å·ï_ âîòÆêê|¥Â¢Æ±ºù % UÁÙÇnx9ùª%(·uûÿ @( @( @( @( @( @( @( @( ؼûÃø«ñÓþ*ØjI*Þ~íÐÿ GvkÃuâÑM$%.]IUÔ ·zmÍ,m#F¯É"UV $_ÏàÐõ@òFÐD¤Iî#Y[súQ´@É2h7ÐÛ å6h¦!0F½I°¨`voÝ c<Ð+)õ¥¶¶UiJ³zäT ¥eh:rL#H¸ÜÌÃrð9 w 8CÔîÁ ²C¨nò»GmbÏasOÐÉ ßCl'Ù¢Áö&¡ٿvH ó@fP @( @( @(ì^ýáüUøéÿ JíR|£Iª-i·lù'mEÃJ6åö'#çɯ xåå·³ª8ªíFqk.q¨hc]*äL³ZÑäE¸* /)VqÖº¦Ý×:iþösæg {©Nm·Ã³jIÒþݤ¶Ùs{nï<á³Z[A~I£mþÜC2 1d3ï#Ã¥¯©wxÛx~ÿ õ{;oJ-ô_ÛìËB ïKà|/÷[£~]é¶7"AÖ-z~cI¾« >¥»®÷=drOÂú[í/PKûw±ºY®´kHã0°i©uA±P;`çµÍ©Ááë»i´ÔçYmȺÌ^ÙdûJ YN}Xí÷ÐÔ5¬ôZ9mmçÔ¦3õ#exGÙ6ã'ÛÓü DZà KHAÃaï+Ä}ýŽ´ÐèRÆÖFÔ#c¹Eºg'%0> g¿zå( ưæegYÝïTm¤/&@$ðPG§*M£\ŤirÞÙ5¤ó³I#OÖµê©é8P=Ç$÷U1-OÐõA¬i7ë%å³¥²9¨+q^øüüP!Ónµ-+Om:Îw6RÌ}B6v2>rÇx 4ÛÄ,|S¢ÇiÒÚúï©ì¾5kù²c<mÞ¸Vã XÚÈÚpÌw(·Lää¦Äì÷ï@|¥oKRÚ¥°ñÜãÈÁUþlþþãÚº;"½x¥,ìÝ'÷öÄKcë µH¢¸¹ÆÙãKi¤n¬Ö)Un`2ã =äqÚ¾OIF2ÔJ2k*2MVTñK÷ÊÌÛ¢¿Ò.Þ-:Õ D R%n¢ä¶ãÍpöyÃ_³ÍÇMw±Kv¿ÛU ¢ÍSYÁ©¤ét¢æÚyLjY"}ÝÙAô±Æà¯;µ©©®ò*.Ír~ò/¬«±ô¶q{áÝ yë:qôÏ©¨óó×·¢õ5½á¦jYÄp¸w}?SÏ¥;f ݤS]ªXlźôI8⵺ån{óÞ»5´tc)¥ ¬EG>;Mç|Û²©¼g?|Z¬rÛÚËt0@P¦+DVàûÙWÚpǾ¹»\e§¦õTs³M~´Öû¦öuÌ´rêÏça¼¸ÖÅÄ$±;/)1ЬN1_ä{ª=+§©Ú{ÈFÓ®IÞó÷®CM¥eíFÒ=<ë×+§@ÜÉn 1\{ÿ @( @{?x~:ÑE@{ I%[ÏݺôÉ]Ô~V×~è5/Ê¥úfãRöàüDAkÕôäè~¡HîÎmíá:}ÍÔ¡Û¦É*0_S!ÁÈ;q÷¯5%ÂÛ3ÔÔ{8ó·ìU[Þÿ ]|³ûÚéN4dÓ]Í÷iÕwv0H*=CcæÅKn£í1µ{^1Ë~uWâTH&§²'n£lMªNæãñ<>qU¦ÍÜâ®ÞÙ~G~FïÊy¿+?þ;¦vwǵۿ<2«¬ïô¸û¾%ÅÒóî,[is\Y¬°O7R¤i3ÄvúÇ{Ô96ng©Úô£¸É7Ý^pWk´ènµzøèæ2:dzñî;|j8enhµôIz»ço>[I.+Øg·Î ·=À8Ͼ-:uc©-&¥íÅù«-&Ä'KyÙG6ýU<îÚÜ~=ÿ ç$¹eóßàDèñHÑȬ¤«+GpEUªÃ4iÚd±XÝÏn÷ZÏ$)ò$dªàdäöUdÕ¤g-}(IBRI¾WÇn"s¹K®ò£9#æ<üÆ¢~8®~ß¶å±»Ý.%µ8_$xÈVÈÈÁìx©qVÑHëéNNmr¼H»YºwPOk¥L±Ý±36j{¹]5Foµé8ñiÉK)aõi¶|)lÖwpãrÄb`Ì9ädö?£WUë´h¸=E5¹گyÐMm+E<OÝJïìjiÓ4ã8ñAÚð#¨,( üßó~V-üwLìïk·~*Ü2«¬wú\}ßâéy÷ lnà·KmgÆÉ2²20{(ã$¡})ÉÂ2M®WiìBÒVê@±w¨eÚ}üÀäñõ.KHkñqIª¼ßGNúxoëb7Ó¯£Böw)¶4Lí÷á¨àuEhÑxÕuµÒþò§_=ËÛ-Ã\ ÜѲ9#Çç§®«!ö¨æ¸_;Uïé××ËÄ¥B³A8ñÈøÑBOd'Ú4aÍ/6¹oî+UMÍØ·kk8 qºCÚ2=¹~qVá]wúN\Jú^~ðÎ|±Å#YÜ M'°SsîÅ8%½»Fm)«[åb·²MKL¸Ó%'UF®¬ñÉ* ?pLààòW³ök¦àÖÙß6öÕÝÙ\ØJ"»á¨p®0p{ý{ò=Õ¦ékiëGMÚØ±.1¸K[Xgå" :F ¶±9Æ jöiJU&¸dÔ³áãWâ¾C«lÚ~÷¼C:ŵVEq·aþ& ÎvãᲸwÏïôûöE«J8¼íÃÖ×÷'Ïj¿>"ݽå7·r_#H'¤xÒ@ò pǪ¤mÈÀ9RyîÎáu(¦ßïß¹¦¬´å§b'T5ê½ùóK*N¥Ü·ß$òzlÅ2Äsºçàf«§4¯Ñv¾Í9¸÷j\« é^6N¹u#½Úu¶³{(cFyÂlKåôàqÉÉÄI§QUûѤµ$¤Û¥Åô¥Ï¿ÚìulþËü÷Êyo5æwì·S;q·;±ý_=ZãÞñ^.ùpêÿ ×ÍÕ8TmpÄs`Õã8ª}<úû}] i9ÅÝO£~¶¸¹r[r¼fÕ'B·²7¶Ù_|EÛ1ÁðÀ!°=ÕpQ¿¼0ì°iªÙf÷+ø«êlYê]µÓÜuÀy"mø§`&G&Lú3 $í÷ö£8'[ÝoÈàÖìý£R ðûT+5oËs;IÕÚÉ&¹u¹«úè̹È÷îuççÍg§:NÞuv®Ìõ%ú«®(=¼:Óoí"Òͤæ"ÒAØ2a ±OWþí»{ñ) EFËèGiÐÕ·yÅmWýéÕãûü¶ÉÔWV\Ó¤kXmì¶Æì H\ ÎXQä;2¥5/>¤KKWú}D¢Ü§{¸ÞÕ¥Ëü6wvÚuì&u¹%l6a3ê±uΫ5XÉE5÷³4ÖÒÔÖ$WZÿ ^µæïåU1µRIfhOè.A;[ËÚ»ÖOÍÎk.5Å~#±vy-'²ç~Î;¿wаºÌQkú diÈÄágF$qé_lU»Ä§)}îc»6U,ø\$ñË%vûEÂ3Ì¢'a¼ "BSfØfäf§)o÷MÞYìúÎWà \ç:w±q&<.ò5-Ô=Ê X` I¬:ä§7ÎJ¹ÙÖ©ÚKe8yagM!ÎðAr¥ìõ¾NÒrÈ8:kp¿½üþèØÖÖ¬0ÝÛ{oVáVV¹ÍqµÄâÃ̹gc?_o¬/Óä{'!°G¾@ÖTªíõù|ÊCNkz<\<)cñ{ñcÃßj3dXµ+JòKÈ¡l´ÈInÀã¿lÍ3u')6uÅËBzJ-ì .{|¾µRIfhOè.A;[ËÚ»ÖOÍÎjx×ø|×gÒqK.wìã»÷}¡g2_ÍoäÕ¯dY¸.Õ¸ì¹ÛxNqvÕgÏþ»7gÕÓïÔëÃ[5\O|]c|àÎÔd·¸\G>d1EaÊì)$öä¯Ïv¬æÓÊ:û<gX¶ïͶ«ß¬í{ôl¥Ô±Ï=Õ¼ ,ÆeÚN êíÉoϬ§]>FÚ=(8Ío&ÿ C¤ö/~ðþ*ütÿ A XÔtÒâÕd60ÜMìÒ0è,6pUØf¹çè @( @( @( @( @( @( @( ÿ ·HÖ6xÙVEÜ ñ~h( @( @( @( @( @( Z¶§_\Øok9ÌO']6ϵ¶¶fcÈÉ/r Y2-ÒI)AÖhd¹"r¶ìUÕÀ¹QÈäÆqà(ï¢Ù|½cl³bÖXú÷KÔsµ¼j[©öÄXBüò îÐZëW7PË=ëÉí-îRÜÆÇ½_~8QÁ £ªãÏ<nèi· }zâ{:ÊX¬"A d"B®K+`fFZBxì@©m¥CªÒébw¸Y`èÃ#(;l"FAã!³´s´cNÐä[³j×i²aÒtI#µÄL¹m ã@+ù5´O3ÝK"ÇfIÓíOðh6îÙ«¼1 }¯Eµ¨hú~¹âý^ÎÝ[âd¸«#o¹XÈ&s¼çoa»Ò>¯¥Y[iÂæ°Ê%Xú'RìÈbXtÀÚhã¶9]\|½ ß^_3å,åëo;÷ùxÎíÝós@CâºÝgòéÿ @( @( @( @( µ¬Q¾w,ávQçjúdqógã@Eg«Mii-¸NUð:M(U»z³Áí@Ee©\ØoIÑÍ JÇk22pqñ4 @( @( @( @( @(bðGïâ¯ÇOú(¨a©$«yû·Cþoù+ºÊÚïÝ¥ùT¿LÐj^Üè-z¾üÓô)Ùz×Ïýj?#ä|Ü=]ý>¾ü6ݹõc¿ûqÆúòP @( @( @( @( @( @( @( @( @{?x~:ÑE@{ I%[ÏݺôÉ]Ô~V×~è5/Ê¥úfãRöàüDAkÕôäè~¡HîÊUå;'xáwI#QdUbäöEg5¹KdM5ª,h&ëF¬C·nF3ÜÆiFåÃ%O¿´Ù5[Õ7ÏUÏFάlüÜ*8W#"©ÙÜÑóññ8újê*µ»¯/5õÖk ׿%YðȾ°kn®áX {qOÎ1ÏÀä{©¥ªµnμüFºÖâia:óÂwäï:ÖÛÉ%ÅÅÄɾFEXáì 99a÷ÕÔtËïÁô"Zºã"$òë{ð} ®4ëk±ÝÝL%;²":®Éܰ÷©÷U!=LÂ*±»Ò}S=>Ñ©«oN*±»Ò}^¤>Cí{z¿²z}nÞ6mÝíg¾ßV;cß*ýön±u~7[t¼yò¬wùºõn¯ÆënëʲY:<O¨µ½Ó»G0bñÚÜ=G#$|#çÆ_ÔÉi÷êÖ|.¶úýqþ®KK½jÕ¬ß+§ Xóø_ö=o%ÅÀDW`6.âêßzä©Ù}üü*kVUým*{å^z.ÜF¶Òð¦ÚT÷ʼôö×l»|¼ÓIßwR ücéüi/'$ué½GøÒ^NþH®h( @( @( @( @( @( @( @(ì^ýáüUøéÿ HÑ(®s¸HÁ¸Rª§Vn8ÅçÜÑ:Ú|n´|©¯½¸Z!y&Îw¹'¿õÓJXÅãÜÑÓàsÅ&ñåI|ÚZØANF$Xí*XæVz.snÚÂæú¾ï§gzµ M6¶o£^&Xºn-¢·Mht:ȲuGPõASÏ5\$äôó«J·FZPpÒÎ*¸qê¥[²sò¢uöfénè.íÝ ¸ÝÞ×ÿ æUrN@çÒ}üð3ÒÔ 4¼2鮾<ÿ @( @( @( @( @( @( @( û^ò¦ð¥äwXÃugu}¢)mà¹q; ̲7r TP @( @( @( @( @( @( @( @( @( @( @( @( @( @( @( @( ùbcGbÏÛdÈ.A|àgæ8µ"åç7Érßã^;êÅÍãñeÓÛJ}µâ²²nc¸tEBmaûÁüwà«® ¸¦ÿ -§b=Ç£¿;n ]KÖjO~*ÿ @( @( @( @( @( @( @( a©Àî1ì{aË 9NOwãÓg[íϩͫGUÜ\³a$©ÛI¯ÕÓTÙU'ܨÈÎLCr$!ðÇßÜü8¬Þ Ï×»8ÎþÎ{ÍeÙ¸§ÄÚÝrÎ¥w¶-¼rgWIÖ( 'Kk vÉuÎpAÁ-4éã8©Çg:ÄÃ$©+¢åb]îsØd.;ÏRee8Ťùá{¯àêÅeq5»Ïy3 ÀÉÀîØg²jѵ¡(7ö¯¥ì¯wAU5$'r.æ ÎFqÂÄþ`jRob³`®^Þé~äu KàwI#EÎ2IÀ)6éã¹Ëe:ÂP ÍÆsky@ÎÖÚêÅïX<àjÎ nc§¯§¨ê/öyñ]Wµ·RµTØP @($0É;w0Vr3'óR{ãrð^÷K÷#¨,( ©¨ P I¡ *íbªàg<0æ"¥¦·+ Æjãâ½ÎîGPX{w·XḴ6ê 8È÷d lgk#Q½eCw9]ʪ9oÛsØ£\ù}ýùg¨©E¿]$Í<æ±mòü5»D DÞ,Ñ#X²YÔÆãïãù>É8È#ަ߷ÏïäW´W»êíx8m^)lïþEûX&tfF.¡ku@ñ£öÐpx$ú°X^)ÚuÍrø>{îsjÎÞ¤TíðË|âü>IJ«Õ¾OKèj³ÜAte È&)J®8êÈI'òsXT·_týþÓ~ÕÇ¢Òµo¢ÿ Nìò9"¦½Z~ÏsöeûÌø×zåÛµtçóĸciÚ\<vêÅ{oòµVÁÃÆI·²«.Ýæ0v¸dFx㦸Õ}ô=Ã-9O7*§½å;«}jp³YÍxwFÎ+>¬¶ñ¦+tÕ÷37ÚÛ ¿¶¤BDbÅL8.NüãàV%o|òòåï/Ú´§ÝÅú¾«w&·ãþìµ½¸æÊZÜêvÖ¶¶²ù©#Ñ¡XYsrcRBzvü8½ù4[IgÝû=YièËSRK =íÉU.m[ÍõéÊúuåÕÌÐ[JóƼaNåÛß#ýøñÞ¨¡&é#§S´iiÁNrI:Ïß»'0Y\ÝE<°@òGïd(øývû[M¥±:ÚzrféËÇïïsVæ´_/céþYÎÐ.7¾Ûä>xÝÜmǺ´iÖ+ï>CNzn~¼Ú¼[ÚÝz»UVkoZùuX-áºajïl<±{46Æ1(mÒøïvEæOå?¶söYêNQ\U'ø½fÞÏûZ¨Ó¯·:+Ü47:ݺyH 2ÜÛßËá ´ïìsNk¾X5ÓSgâoÖw¶Má*Ŷùn¨cC§Oq{a_$NDr[,x^¤!` 8 â¹Z¶éq:ßkYñß'Z µÕÞ³7j`íHd±Ü ãß6ÔÎ.SJ_±] M=>Ï)i&ò÷»mº¬õÎlê e¾kû«;Eé¦N!?N )`b1qÀã8¢nVâ³ïÇÝ8ÇG»ÓÕF»á¹c{¼º¼åæá·K©î¬î+YÉIÑ3°(=AÛÒÌåxå6à [qxûÏ×ÙEç¨ôã]6ä²·Þÿ ¡3hÅ$kK5ºÜ}ðr'Ù'{ÂTSàÛöùýüñÁvã·}]¯ «Å-ÿ Ù¬Yý®C6rp3Æ01wR¶¿Ï=.Ë¥=&øóþÆÕ-·Kõ»wSU¶cfÖéæU~¤@U9|¾î>mÜÒqÆÙò£~˨¸ÛR\);õܺU¶±Ï}¯«é×ß(ÛÇäî7Ém ¢ô,VÜ Gvk[è7qèw ymÖÙ½!fØÑ<¡²Wha9Á#!½'ËM¡=(Í©=׳áËÃf|åAsOP°ÖEÌ }§]C,ǧMlbÝϲ PéðÞ^Ü%¤R[CM©Ü¦}J¥¶Ø]ÙÀÎOÂþYËl Þ.Ê´q½²ËÕ ²©PÊsÉaÇ¿"8áêèCQ§+µÑµ¿]þKÔ>OùCÈÝy/åé÷Ûícøü5SbÂhwÂâòæ í¢KaqI pd=$ã¶wÆÏ)&b±FÎÁK£' >s öv1ÝXj3%´fTä82*¶x#x=yí@sò^¡òÊFëÉ(è·O¾ßkïÇá 8ÂòÞ{IâÕY]ã*l qÚØøàü(¢IæHa¤Ø*"' ¹t½B·Æê9NÆð°f|´2Nxÿ @($sIJØYWcw ΣóT¦ÑYB2i¾Y^êø2:ÂP @(5½ËÚÈ^5ûlK üÌþºÚØÏSMj*wìm|9i.n$VÝ$]ÛÉ'$ѶݲÐaì°GPXö/~ðþ*ütÿ I³3[Ñ}J;1ê÷ÀßeZgË)o§ÓßÓÙëÏÊ=}¿ôùïvs@f[]ióë/u&¥¼K¥¨êÇ),æÏ¢qµ ýó;fϳ{/¯ôÛåZæ)uH±T qêm 1è²j·ÙFÌD.å³ dÀÆ=awgNr}ýè ñ6½aªYÞÃm#7в:·o¸|Ø>ø9'( 64Ýbm3C¾Îú{[¹®```vBÈ«.îG»,ô 6ÞO5Ýüå§ D©#2Dè1±[Xg8ã¶hvwöVfÆÕîb¬ãϪ6lr öÎF}~å¤Õôãh.ârÜü-ä¸kô'Â,psÂóÜPßj6$¸Tßò·Û"´HäO]$Ä¡ÂîÆ7kÔ8Ü $ékÝN´°ì´ºn¬C.·Ô¼GqÈü"»¥i¦xvïMRY§)¶Ën²*·RKl¦YTçlRg`P/R÷DJ»¾Ûd<LP"u_B³d´Ä#@ijWÚ~«¤ÛØ&°¶Æ Aa,rô¥ oAý*Nr·+§BëOÔnüIvúcRgÇq¥3Ç(-± #¾sós@K&¯§AwÓçäñhw%Ã\ç !<n`óâ^ëÖèsÙ$eòq¢ûlQóøà`Ð?£^G§k}ìÁ+{æp$ `N3ïâÖÕ.4ËÛ}?Oµº¤Äë=c'KÍ7³Ù×8;ÕÝíxÎþö;覵½ó[eDúË"®àÊ8Ù<P¯® @·Ó-oZuòi¤Y³J¬î2$ @( @( @( ú^øËOKYçDaÕaFSzy>ÀA#]ϧ%ü×övï+Â;9%Ô)#j+aÇ8ÀÇ8ÈÈ.Ì776¶×#¨Ý Ù0òªWÓäì8+1( 4ye£¤½ýäâBï?j\mÀvì®rØ +Ýé-khnRîÖåEa1é;B@ Êü`Ú ÃD³E ¤m#¼UQp ±þ p2N 6ÉËíxÎ0ØÞáØ¡Õ/wvùÉáµg|°G .ý¥TööØ' @( @( @( @( @( @(bðGïâ¯ÇOú(¨a©$«yû·Cþoù+ºÊÚïÝ¥ùT¿LÐj^Üè-z¾üÓô)Ù{å+{Åßò\³ê+iÑÝÔ DfþÌåQwgw7v¯(¹Ô>&Û^Ôµhm«w/YÛ"2'IqÃÑw|Ð&ñcHc_ý§<^±"ßj-9ÚÑ´gg¥UN×nHn@÷d0`×aÓÏÈö÷VrMK®nËJ§¨Êª1Æ ÝâC32P©ÜWqR`µ½TLRé£F¸[iÛQiPÃ2Êj;\r{³¶`7¯|Gc5Í6)`æïs]+u¦&Y¤LJ!Ã6=¡Ú:¥ÅªøvkkE±hÞî °}BJ=o0ÝÜ6Hô1À9ÈúµÜ7ÚÛ±DUcUBؼ)b8ã'½JPËLðÍG*1WG*G{@( @( @( @( @( @{?x~:ÑE@{ I%[ÏݺôÉ]Ô~V×~è5/Ê¥úfãRöàüDAkÕôäè~¡Hî˰´«Ïfk©<¤-þ`¦#üë#qå;Ö-t»Í>$¼v´&fZ9¶ÓèÚ É¦Æ1Îw àPf 6ÏEÔÒ{{åníê¡bÅ'Æ%iB¤8`ä w,xCJWc¼ºTrmà|I?YÖÚ/Lº¡Ew {î|ôÁ HaWªüé ,6¥+]É4WÐGmiæ%ÄS~Û²¨ AÜÊpÒ¹õ¨¸³Ñ|ºÛ«EµYdß«ÞCb,ð£öÀ3é9-2+3ªÍv³ØÙÄ×E. Á<²ÄÓ£1éÄÎ6ɰ¸ §ÎNp äû½XçP¨ºMw×ý))fpq³çíÆpqàö -ÚÚéz¥µ¢^@Ó,¬Rʲié dyÎ6Úß¼ñ·¢ÏK±_éêo[XÊJÈ$u ³ªúv2Î}¡@ÊÖl¬maí"UØìÜ¥Är¯¿ª eNưã!x´;;õ ¯Lâ+Ka0XÏV4ÛØçw|`jÿ @( @(bðGïâ¯ÇOú(¨a©$«yû·Cþoù+ºÊÚïÝ¥ùT¿LÐj^Üè-z¾üÓô)ÙÍõïòʱôâ·a7gÉcó¾mØìyEÉnu»û»vi"Ãã¨éi$¼çÖáC? ¸ äf=Jî7µtÖ3^@BÌÅHÆísH<q@K>·q4$RGÓh¡8ÊÇÒª 6ÆWb³©¾øä ÷zÝò*\˽FWhIUS §R»:7RHÒ;íbÙÝÆ9 `F1@K>·q4$RGÓh¡8ÊÇÒª Dçj ÷µÝô"z mÅ-íã1ìQ¸g8ÉÇs@h}^« <ÖqÙK Fò a ´ÆÈ@seâ)¡»{t®c£ióFAÎÕ ¥BrFÞ[#©^ùûÓ8¦8âDÝ"äñ 89àv *P @( @( þ(Ó´û++é noâÀ\*o¹â<c¦mÛÜè{ 1ô&+}báí à³7 ~¼Jߨ àÕmînÇtM6+£")g¨%,¿4RÙé÷º¥þ·É±èÜÞ4ûxؤáBñÒ à ÇH&3 @( @( @( @( @(ÚK$k"¤«"íp§AÁøo,,jò3,kµ 'à2Iü$Ð[ÜÍi)ØíÆNôºaÏÄ1TP @( @( @( @( @( @( @{?x~:ÑE@{õÅÄës(H @( @( @( @( @( @( @( @( :+ÁPÇ e,YhVÒè,n;N¢\, ¢YYU½8ôÙÂå I&Þ@ÉÀá÷ã P̤ åOàs@cгxRò;ɬaº³º¾Q¶ðHI\¸ÄÁfAÙ¹ +¶Å5{-9gU,LU0Ç;AíÎ8 %°¶Ó|E}ki4OsȪ±ïûP@BXH @( @( @( @( f÷Ô£1ìÈÅiÎF 1hÊ:pSA[±2jÒÞÙ^\K¨³ou»D!L'ñDÜì¼>%ÓÍ4)nT:èéHr7sâîóXµ¸Ò Vs®r,·]Hà$åºK´2ObÌï ZÜ,EKªÝ`sÓSé - à±!°wcÙÈ8;ÅÔo|ýÊMÓéíq»9鯩ëÛë 4¤×í~T¼s Lܧyn7Dxsµ© åHÈe^Jð3û[ãJù6VÝ.yw¸fb @( @( @( ]7U##nïW³@T´Ó´«Çi êHzkº)/"BåmiäP¬HPÁBòóè9B+=7Iý¬ð]OeÌWhMä·p0$±ÃÂä¥*¶®z¥YÑ*˵¯*À©=ÊAÛï½&¥õEFðÝ<^ÔFËlÛ¹q»±Û¬èzmÒ¯Q ¼ÒÈ:w䣣Øýµ=\zÌÑlïõÔÇyYâPXlÜ`Ê23ñè 8ô.}5õtñ-"Y7Û4êÒ9V r$Ø ©ðë+JoîåØÀÇ6Þ6ä÷àîíÆhÚ~©6ZçËP¬ÂbaÛ©<77 /¿pÅî§ZXA £éŪÁpϽ\4!0SÞ§vxÆ( þ*{3ã-H¬ò^º.z¸©ÛéÜl|McS²µVñæ n®ßR6ûc"wgiNòÛÿ @( @( @( @( @( ؼûÃø«ñÓþ*ÞnuÍþÆø7îëýhú\´ç-wîRüª_¦h5/nÄGô½_H~NéúìÖ_Ã¥H ±VP`ó/B0ÃöÖM#9B°ÀPG\¢<IªE$$Y:©oÈì¬p»ÔÄäNH *ÚjWv(Ém.ÄiF] !YFr9wb4³ëw÷IIE$}6#ܬ}* J&Os´àbËR¹°Þ 1£ ×ddàã#'âhQêZ¥ÍÝÖ¤'xà^¸0ÇÓé¨1´zxà}Ù ;°ÕµhàÔß¡2ë]½Å¼S3è2Í"Fò~&¥òßó_¶ô<¾í£ö¾K¾ó÷÷÷æÒÕuûmNÈÄ4Õv`ÆBcÄ2m\(Vv ¸áHÞækIL>ÇhÞ2p¥Ô«~! ,Zê×¶p¤0ʽgnÄ®[níÊÀkC 9æÝNûRYáe3Ų¢FƪÌà vÞJã È99]?VÕýͽ .%ÙÌñ>#HÛp]êB¨@Ãjà`ÂÖ-OTîhÕ¢TDPÖTqê;¼p8¨5J=x"KS§9KZÂ[{+ê+»8`çqPÉâ NE®¨û4ÑBÊäAic¸äq½jòöÐÚÈ-R"ÈVH¡ÜÀ ( nÿ òÁr´F×§KÚÖXíäºÁ-¼s* Xc¿×óÐP @( @( @( @( @( ¦yÀ?h JÊïå)`ù2Æ-Í´º¸·Dcê 8·¶ik«øÇ¤Ñ@ùýzÚ/jv¶é²nå5É;T9 ö¶ÐNXi÷I*ßKAäª%\ý¬ûc=ØÉ%h¹Òæ¼¾ÕæÒ¬¥k9FØD(·¹`H<{Á<r@&«}.6¥¬e ô«Ã?ðd|F@I¦_E¦C©Ik*ÙM#Gå},øÏçü8?,hG6®ñ¬Ò¢FÊ#cÚ}¢\(ÎO9ÅõBÚõ´(|Æjê×/oj¶«¹ß6 6îé;vHúoHÓ´&¼M³MXµºÎ³Z 0¹7_û¬mRcHø+lg @]Oˬ¶VµÔ½9.×H÷h{x\@yq´ @( @( @( @( @{?x~:ÑE@{ÍÏÓoøÐ¦ýÑ]ÿ LW,r@=ÆjVV·3ÔízQÜdn¯81ÚÆí:g^¾:9¦qìü{ßc-}'ÅR^®ùÛÏ ÒkKöíóCÆCmÏp3ï£N¥XêEËI©{q~jËI¦!ñ ÒÞvQæM¿UcÏ;¶·#ßç«pzüÎ_iÒÿ IÁ8îjT"}¢EêŦ¼Õ?nÛà¨âûTK³¶UXÇJ( @Ͻ ôyíSÁ. _jÑI¾% o7ìçF1ÙÅ=¼9y2 ãt3´d2{rüâÃ*º2ïô¸8ô¼ýá:ùcF³¸ 1O`§çÝpKz!vÚSV·ÊÅodq¦KOª$]Yã+T~àþ ÁÁä¯gí0×MÁ¬7³¾m'í«!»²¹°EwÃ!Pá\`àö?ú÷ä{ª%MÒÖÓÖµ±b]2cp¶°Ï=ÊDtmbsTölt·3iÔÔiE¼^-9j·TTx&©¾'^l}ÊFÖçð<>cU¦Ôâêù^D£N¾hålî BJÊÂ&ÂÜ1Ç÷æ§[Ñí)¤æíÚMØ·kk8 qºCÚ2=¹~qNUÑ=þ¾¼1-Üéq-¬ñÂøÙ#ÆB¶FFcÅd´#¯¥98FIµÊòHúV£±ÄöK$é¡ |rp1Î*x$QUÚ´\Õ-ò°5=>m3PÖUq±#:Þ Å' S´G_IjGÓèI.1¸K[Xgå" :F ¶±9Æ åIÞãÆjgúÐí0Ö¦¸N¯*×òCscwg·ÍZÏüíêÆW8ïþQ(Ê;¢úzúZ·ÝÉ:èìòÖKå¬í XäêtÀm®ªÞÎq¶®¦QIÑ]YjiñVrªñiµ½xt:{ NêÚåe!ã'Cc<øvÿ jöiJU&¸dÔ³áãWâ¾C«lÚ~÷¼C:ŵVEq·aþ& ÎvãᲸwÏïôûöE«J8¼íÃÖ×÷'Ïj¿>"ݽå7·r_#H'¤xÒ@ò pǪ¤mÈÀ9RyîÎáu(¦ßïß¹¦¬´å§b'T5ê½ùóK*N¥Ü·ß$òzlÅ2Äsºçàf«§4¯Ñv¾Í9¸÷j\« é^6N¹u#½Úu¶³{(cFyÂlKåôàqÉÉÄI§QUûѤµ$¤Û¥Åô¥Ï¿ÚìulþËü÷Êyo5æwì·S;q·;±ý_=ZãÞñ^.ùpêÿ ×ÍÕ8TmpÄs`Õã8ª}<úû}] i9ÅÝO£~¶¸¹r[r¼fÕ'B·²7¶Ù_|EÛ1ÁðÀ!°=ÕpQ¿¼0ì°iªÙf÷+ø«êlYê]µÓÜuÀy"mø§`&G&Lú3 $í÷ö£8'[ÝoÈàÖìý£R ðûT+5oËs;IÕÚÉ&¹u¹«úè̹È÷îuççÍg§:NÞuv®Ìõ%ú«®(=¼:Óoí"Òͤæ"ÒAØ2a ±OWþí»{ñ) EFËèGiÐÕ·yÅmWýéÕãûü¶ÉÔWV\Ó¤kXmì¶Æì H\ ÎXQä;2¥5/>¤KKWú}D¢Ü§{¸ÞÕ¥Ëü6wvÚuì&u¹%l6a3ê±uΫ5XÉE5÷³4ÖÒÔÖ$WZÿ ^µæïåU1µRIfhOè.A;[ËÚ»ÖOÍÎk.5Å~#±vy-'²ç~Î;¿wаºÌQkú diÈÄágF$qé_lU»Ä§)}îc»6U,ø\$ñË%vûEÂ3Ì¢'a¼ "BSfØfäf§)o÷MÞYìúÎWà \ç:w±q&<.ò5-Ô=Ê X` I¬:ä§7ÎJ¹ÙÖ©ÚKe8yagM!ÎðAr¥ìõ¾NÒrÈ8:kp¿½üþèØÖÖ¬0ÝÛ{oVáVV¹ÍqµÄâÃ̹gc?_o¬/Óä{'!°G¾@ÖTªíõù|ÊCNkz<\<)cñ{ñcÃßj3dXµ+JòKÈ¡l´ÈInÀã¿lÍ3u')6uÅËBzJ-ì .{|¾µRIfhOè.A;[ËÚ»ÖOÍÎjx×ø|×gÒqK.wìã»÷}¡g2_ÍoäÕ¯dY¸.Õ¸ì¹ÛxNqvÕgÏþ»7gÕÓïÔëÃ[5\O|]c|àÎÔd·¸\G>d1EaÊì)$öä¯Ïv¬æÓÊ:û<gX¶ïͶ«ß¬í{ôl¥Ô±Ï=Õ¼ ,ÆeÚN êíÉoϬ§]>FÚ=(8Ío&ÿ C¤ö/~ðþ*ütÿ pÞQså( =V#³Ò& §³ß(VbIJ&îIÁ!qÆ{@XºÑCë&Îma-"¥#¡^±p6ï9Îâúr¤%ÒtK9õ¢¸Ôì^!i4±²päE! k.H` À *,s:,*«$LáÄdóh( @( @( @( @( @( @( @( @{?x~:ÑE@{ÍÏÓoøÐ¦ýÑ]ÿ òú¶÷ @(ãI¬Q³°RÄ(ÉÀø @(äHX,±²1PÀ0ÁÁ @(ÛÅ$k<l«"îBÃHÈø?4P @( @( @( @( @( ؼûÃø«ñÓþ*ÞnuÍþÆø7îëýhú\´ç-wîRüª_¦h5/nÄGô½_H~NéúìúëÙ§K7yµ~½ZTúXyX£=ªª>»0$*Û³ÁÇðÊ.gÇáÍ>óXºÑÚê9Ö.ddI3:BH*å÷{G¶9Î@ý [Ô#´¾H`!»Fi7¬~9VÎ}ØäÚݼ[ªùx¥s :ÜýFÉQós :Òïï4ïjSY]Ïm)¼µRðHP²swóPÖWÄ7¡it6¨Ö}Gô#keÆÑnã¨:,zY½{Åþ"ï*²íÇUãß·i.0¹*6;Þ-ÉáÛ(lVUIº ¨ÀLB@_öÌ÷;±( Z¶§_\Øok9ÌO']6ϵ¶¶fcÈÉ/r Y2-ÒI)AÖhd¹"r¶ìUÕÀ¹QÈäÆqà(ï¢Ù|½cl³bÖXú÷KÔsµ¼j[©öÄXBüò îÐZëW7PË=ëÉí-îRÜÆÇ½_~8QÁ £ªãÏ<nèi· }zâ{:ÊX¬"A d"B®K+`fFZBxì@©m¥CªÒébw¸Y`èÃ#(;l"FAã!³´s´cNÐä[³j×i²aÒtI#µÄL¹m ã@+ù5´O3ÝK"ÇfIÓíOðh6îÙ«¼1 }¯Eµ¨hú~¹âý^ÎÝ[âd¸«#o¹XÈ&s¼çoa»Ò>¯¥Y[iÂæ°Ê%Xú'RìÈbXtÀÚhã¶9]\|½ ß^_3å,åëo;÷ùxÎíÝós@CâºÝgòéÿ @( @( @( @( ¢áx l`¹5©æµºE^¤[U"V.QQ@Pìlr§ï wc .Ä[pKxæ {¡Ôí'8Æp3ØP}^þÖiæå³¶÷wÉ~Hp[8q¡2hþ[¿ò[©ÞK©Ð«³ÛÕÛ¿}8ϳéíÅ\ß]fÐZÑvÀÉé1åø#îbsßëøRhkX£|îYÃì£!ÎÕôÈãæÏÆÏVÒÒ[p7« àtP«#võf5+Û9"ËR¹°Þ 1£ ×ddàã#'âhÔ®Íì}_·IDNÑ ´í [mnþÒÝaH°é»ÁÉ9ô9RÉÉ$m#99 -ßùO-ÔoO¥ÔèGÕÙmêíß¾gÙôöâàj÷âòîñnY..ÛtÒ IÞ$ÈDzwª1Úî}jòã¦ZªG G¤Q£0ìYU@|dû@÷?@wq¯_]]As0³ya]©û 1´(Ba @( @( @( @( @( @( @( @( @( @( @( @( @(ì^ýáüUøéÿ GvR¯(¹Ü1<óÇKºI*ã$ ¬¤£'²+9¨EÊ["iQ`ëA7Z5`»pÄ1àààðxä3Hê7.*{ýøý¦ÌáªÜ¸f©¼®xú®|º6uc`׿áQ¼QHöÎà6çÀ÷ÓWUiUÝyx¯®´x[Xn¼°Ýù*ÏEõXuwòÄ$eØ;Ú~q~#ÝM-U«t¶uçâ45Ö·K ׿'xðÉRµ74aÓ lÐÜÈ·cíj".Pe·g¸øë®ikI9:ÄwÎv½«ærO´N.mEpÇ|çdð«Ç©Äö¶vêîg3M¢·,¡Îüûûâ MI»QUmoÑ×OhjêÍÚ«k|áÖÕó%HêÝ-¨íé"¥Âìâ<°\V @( @( @( @( @( @( @( Ä ¹!wH'øÖ2ì²îbÝuÿ vÓÛXÅ4a&꫱tV §¥"¨äI/ðÀãµ!=F¥UUÓªoá÷Ï£SOSU©ðÕVº-ìë {~3YêdØÈ²j/ Ûõ13$dÃPöFÕTÔÐõÓP¸ãÿ @( @( @( @( @( @( @( ؼûÃø«ñÓþ*ÞnuÍþÆø7îëýhú\´ç-wîRüª_¦h5/nÄGô½_H~Néúìôcs½ýË$]d·fpÌòoL³WÚô×\µ7 /#¼Æ«;«è%KoËÁÜ@LdÝ»0Ø>òÂ+hD°êVw»k©R{pê¤# {ñ¥I ¾¡ò4I! @( @( @( @( @( @( @( @( @( @( @( @( @( @( @( @{?x~:ÑE@{ÍÏÓoøÐ¦ýÑ]ÿ £? Á<²ÄÓ£1éÄÎ6ɰ¸ §ÎNp @( @( @( @( @( @( x¨OÎ $©Ó#OQjGm÷'ºð%¶Öïí-Öd ¼¼sC,FÒ0I#B¢ÜÌZ«â$Ip9eç¿ÛóÐ)ªßêrÅg0YDò"ÉÒ8¥Ô8ivå89lò9"¥&Ý"³a9l²p÷Ö6íÚ]µåµÂ·/=ÊL¥H ©^äàFA5áÖ5öÉGkÄ«QÃ.Ç8 #zA#´g8ªiw~OVî/Ãq-äFWbÌ_*B±Ðrîm]Ñ®¿\·å]Zêq{â;Û¨Ö$+Km°Ê+Hª±ª²¹U°IP@õ°ç'47%¼ñ Ϧ½¬q^$B³Þ¢ 7# åc@2ÍÀÁÉä @I<2[\I«¶HØ£®s©i§L¬'ÅN;<Ô$%I]+ïsÃ!sùØ~z+)Æ-'ÏÝGPX++ÞxãÌiNNvÀäã8U[V¥ÉA¼¿µ}/e{¼" ©©$0É;w0Vr3'óR{ãrð^÷K÷#¨,I2\ÜGKºI".qN @( !IܤK¹³p ±?جç+÷º_¹Aa@( @($ðÉmq$®Ù#b¹Î8"¥¦2°g8ìòu=»Û¬%ÊæXÄGud{² @I<2[\I«¶HØ£®s©i§L¬'ÅN;<Ô'Îh.Å´¡C·lR¸`;³`â¬âÓ¦e hNävÏ'xß=·Û\Ï«ÄJ±qÁßý8§iº!ë\¦rO¥míhâêÝìï'¶©xdhدbAÁÅDiÒÔZ¢Ù¤ýä5±x#÷ñWã§ýT¼Üþëý6ÿ ¸dçßß^<N7oÞsê½(êðjË)*Ï ç{5t«ËÚ,űß$Ñ@¦Æv¸5ÖT87sܪ£ý·=Ê5ÏßßÖz[õÒIìÓÎk¦ß/Ã[´IдMâÍ5%ÝLn>øN9ì=á*iðmû|þþExà»EqÛ¾®×ÕâÎÿ ͵ݬuùzr]®oì±²Æ×\úÙ½i¦£ÌâÛtQËÂ,!lÌé%¤R¬q»Ú'Þ0ÎWNXÝsæy½¡¨· e©_®Ü¿yÑvÖÏv2\Aqq%¸0TD`ØÖó¤3{É$üüÏMÚn¶ú3¯µAÂQõªóySUánðxlu§¤W¶u,(nþÚ-0à¸V8y;ó0 I[ß<¼¹{Êö-)÷q~¯ªÝÉøÿ â_tÍ{N£Ôu+Nöò{tMùoKm.?Õ-í ÛÄÂ!0Ô+ä8îà ÜÑAqUbú_>¼-NÕ.ç¼rõ¸SÌsÂ"I_]Ýæ7º^ZÝaù<JÅbŶðÛ»PÇ#ñ|5Ëäv.%÷ßnê¸ê«mºÛ\¶Um'·Ä7âH-൰¹§J m¸E' n<ã$sÀºiMÚÂ3 Brì°ár§o{{l²wêòî^>8¦Gé¶Ï-FÅ:©*q±·É´¤îÏ#*kÕ§ì÷?f_¼Ïw®QyÍ»WNqß<K6¥ÃÈÇn¬W¶ÿ çàwÆE¦NÇeõ%)eþ/ZMìïÕªzUl·3µÆãËÜ´qsJ$hÛ¦»À°Að½¸íYêÛ§Ë¿#¯°¨C ¾+«nöµòu¨[]]ë0Cxö¨ÆÙØ)T&K½ÈPN=øãmLâå4¥ûÐÔÓÓìòo/{¶ÛªÏWüæÎ [濺³´YndéÁÒôá!òF#Ç3&ån+>ü}Ñt{½=YTiÛ¾9§»Ë«Î^htºêÎé"µ;Ô½,ÎWSnÀ·¼ý}^zN1ÕÓnK+}ïðçRyûݻp½iôØ£äyìu-¤±äï*}<±º¹&Òý¾|¾öÜÂmiJ1£m$·iù¨í+ß»^·áU/t¶òvý´¶ØÀbí û± à`sÜII,W%ð7ÐÒÓÔâwÄùº¥'ÛlfÚå²?)¿;ÛH¢ÒdÓDjëÖP1( Agp8Î*r·~>èÆ:=Þ¬ª4íß ËÓÝåÕç/4G º]OugtZÎJLÎAêÞg+Ç)· @( @( @( @tñ±dfRA\©Ç`ë]â¥hH P#¼R,³#©¬§ØDë(EI4Õ¦Þ6,ÊH+8àý`K ⥻¢º«2Xà àüy @( #HTFÂÊ»c¸Èl~u¥6ÊMòÊ÷WÁÔP @( î^ÖBñ¬LHÇÛbYæ`GõÔ¦ÖÆzkQS¿ckàÑÌóIsq$ò¶é$bîØÆI9&¶í#¨Ge:DZx#÷ñWã§ýT¬O¦øºiSâm.§«béRcx̤óß½¡Ã"ÝA<ix÷#xàé#²X\ÄÅ{ndçMwîRüª_¦h5/nÄGô½_H~Néúìú;kÝ2?ÝÁ-ôSÄÝ.¤©ÒN¹Úv 6î*ÞQsÂÿ @( @( @( @( @( @( @( @( òæ»÷A©~U/Ó4}îë{çVýÔ`À©9ÈíÅ{SÔìzÚZqÔN*°¿:n3¦sýðúuèïòKÝüsè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè3¦sýðúî½þI{¿sè\Óãðüêþ[ؤXI³XØÒ`à9ÛÛ;~úä×gÒÒm®wÿ |
From: Stefan H. <ste...@us...> - 2002-03-15 20:19:38
|
Update of /cvsroot/cvsshell/cvsshell/images In directory usw-pr-cvs1:/tmp/cvs-serv4398/images Log Message: Directory /cvsroot/cvsshell/cvsshell/images added to the repository |
From: Stefan H. <ste...@us...> - 2002-03-15 20:16:05
|
Update of /cvsroot/cvsshell/cvsshell/src In directory usw-pr-cvs1:/tmp/cvs-serv3742/src Modified Files: cvs_cmds.py Log Message: Fixed problem with remove command Index: cvs_cmds.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/cvs_cmds.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** cvs_cmds.py 15 Mar 2002 18:58:00 -0000 1.6 --- cvs_cmds.py 15 Mar 2002 20:16:01 -0000 1.7 *************** *** 347,352 **** for e in toDeleteListing.entries: e.status = Entry.S_DELETED ! app.runCvsCmd('commit', rootDir=toDeleteListing.getRootDir(), ! fork=0, args=args) --- 347,354 ---- for e in toDeleteListing.entries: e.status = Entry.S_DELETED ! try: ! app.runCvsCmd('commit', rootDir=toDeleteListing.getRootDir(), ! fork=0, args=args) ! except CvsError: pass |
From: Stefan H. <ste...@us...> - 2002-03-15 20:13:10
|
Update of /cvsroot/cvsshell/cvsshell In directory usw-pr-cvs1:/tmp/cvs-serv2985 Added Files: index.html Log Message: initial checkin --- NEW FILE: index.html --- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>CvsShell</title> </head> <body> <h1>CvsShell</h1> <p> CvsShell is a console-based cvs-client written in <a href="http://www.python.org">Python</a>. </p> <ul> <li><a href="README">Readme</a></li> <li><a href="LICENSE">License</a></li> <li><a href="https://sourceforge.net/news/?group_id=48175">News</a></li> <li><a href="https://sourceforge.net/project/showfiles.php?group_id=48175">Download</a></li> <li><a href="https://sourceforge.net/mail/?group_id=48175">Mailing lists</a></li> <li><a href="https://sourceforge.net/tracker/?group_id=48175&atid=452212">Bug reports</a></li> <li><a href="https://sourceforge.net/tracker/?atid=452215&group_id=48175&func=browse">Feature requests</a></li> <li><a href="https://sourceforge.net/tracker/?group_id=48175&atid=452214">Patches</a></li> <li><a href="https://sourceforge.net/cvs/?group_id=48175">CVS access</a></li> </ul> <hr> <address><a href="mailto:ma...@st...">Stefan Heimann</a></address> <!-- Created: Fri Mar 15 20:53:58 CET 2002 --> <!-- hhmts start --> Last modified: Fri Mar 15 21:09:47 CET 2002 <!-- hhmts end --> <br> <a href="http://sourceforge.net"> <img src="http://sourceforge.net/sflogo.php?group_id=48175" width="88" height="31" border="0" alt="SourceForge Logo"> </a> </body> </html> |
From: <no...@so...> - 2002-03-15 20:09:39
|
Feature Requests item #526935, was opened at 2002-03-07 14:11 You can respond by visiting: http://sourceforge.net/tracker/?func=detail&atid=452215&aid=526935&group_id=48175 Category: None Group: None >Status: Closed Priority: 5 Submitted By: Nobody/Anonymous (nobody) Assigned to: Nobody/Anonymous (nobody) Summary: commit after add Initial Comment: It should be possible that cvsshell asks you if you want to commit the files you have added with the add command. ---------------------------------------------------------------------- >Comment By: Stefan Heimann (stefanheimann) Date: 2002-03-15 21:09 Message: Logged In: YES user_id=327401 ok, feature is available ---------------------------------------------------------------------- You can respond by visiting: http://sourceforge.net/tracker/?func=detail&atid=452215&aid=526935&group_id=48175 |
From: Stefan H. <ste...@us...> - 2002-03-15 19:46:12
|
Update of /cvsroot/cvsshell/cvsshell/src In directory usw-pr-cvs1:/tmp/cvs-serv28859/src Modified Files: cvs_shell.py Log Message: Index: cvs_shell.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/cvs_shell.py,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -d -r1.22 -r1.23 *** cvs_shell.py 15 Mar 2002 17:35:21 -0000 1.22 --- cvs_shell.py 15 Mar 2002 19:46:08 -0000 1.23 *************** *** 417,421 **** class Entry(GetSetProvider): ! S_NEW = 'N' S_ADDED = 'A' S_CONFLICT = 'C' --- 417,421 ---- class Entry(GetSetProvider): ! S_NEW = 'N' # what's this?? S_ADDED = 'A' S_CONFLICT = 'C' |
From: Stefan H. <ste...@us...> - 2002-03-15 19:41:14
|
Update of /cvsroot/cvsshell/cvsshell In directory usw-pr-cvs1:/tmp/cvs-serv27585 Added Files: README Log Message: initial checkin --- NEW FILE: README --- About ----- CvsShell is a console-based cvs client. It provides convenient access to the cvs commands through a shell-like user interface. Requirements ------------ CVsShell is written in Python (http://www.python.org) so it runs on every platform python is available. You need Python 2.1 or higher installed on you system. You also need to install CVS (http://www.cvshome.org) before using CvsShell. Installation ------------ Unpack the downloaded files and step into the directory cvsshell-X.X that is created. Invoke the installation script by typing `python install.py'. On windows, you can also invoke the script by double-clicking the icon of the file install py The rest of the installation process should be rather self-explanatory. Usage ----- Help is always available by typing `help'. You can get help on a specific command by typing `help <name-of-command>'. If you are not familiar with CVS, you should first read the CVS-manual (http://www.cvshome.org/docs/manual/). The configuration file of CvsShell is ~/.cvsshellrc. A session with CvsShell looks like this: stefan@kunz:~/cvsshell$ cvsshell CvsShell 0.1 Copyright 2002 Stefan Heimann (ma...@st...). This software is released under the GPL. {a} ~/cvsshell [:ext:ste...@cv...sshe...ceforge.net:/cvsroot/cvsshell] $ This is the startup screen. The second line from bottom is called the info-line. It contains information about * Options that are activated or deactivated. This is done with the letters enclosed in curly brackets on the left. A lowercase letter signalize that the option currently is actived, a uppercase letter signalize that the option has been deactived. Options: - a: automatic update of the cvsroot variable * The current working directory * The current cvsroot. I mostly start my sessions by running `update' to get new and updated files from the server: $ update Root Directory: /home/stefan/cvsshell : 0 ? README someDir: 1 M foo 2 P bar {a} ~/cvsshell [:ext:ste...@cv...sshe...ceforge.net:/cvsroot/cvsshell] $ This produces a listing that contains information about the files in your sandbox. The first column maps every file to a ID to make it easily accessible by just typing the ID and not a long filename. The second column displays the status of the file. For more information on this status characters have a look at the manual page of cvs (`man cvs'). I have added the following status messages: * OK - the file is in sync with the repository * D - the file has been successfully removed from the repository and the sandbox. As you can see in the exampla above, the file README is unknown to the repository, the file someDir/foo has been locally modified and the file someDir/bar has been patched. To add the file README to the repository, do the following: License ------ |
From: Stefan H. <ste...@us...> - 2002-03-15 18:58:05
|
Update of /cvsroot/cvsshell/cvsshell/src In directory usw-pr-cvs1:/tmp/cvs-serv14646/src Modified Files: basic_cmds.py cvs_cmds.py Log Message: Completed documentation Index: basic_cmds.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/basic_cmds.py,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** basic_cmds.py 15 Mar 2002 10:37:53 -0000 1.17 --- basic_cmds.py 15 Mar 2002 18:58:00 -0000 1.18 *************** *** 28,33 **** def cmdHelp(app, name, opts): """Print this help message. ! If the name of a command is given as a option, ! a detailed help for this command is printed.""" so = string.split(opts) if len(so) > 0: --- 28,33 ---- def cmdHelp(app, name, opts): """Print this help message. ! If the name of a command is given, a detailed help for this command ! is printed.""" so = string.split(opts) if len(so) > 0: *************** *** 35,45 **** cmd = so[0] doc = app.cmdToDoc[cmd] ! app.printMsg("Command %s:" % cmd) ! app.printMsg(doc) return except KeyError: app.printErr("Unknown command: %s" % cmd) first_sentence = re.compile(r'[^\n]*') ! app.printMsg("The following commands are available:") max_len = 0 for x in app.cmdToCmds.values(): --- 35,45 ---- cmd = so[0] doc = app.cmdToDoc[cmd] ! help = doc ! app.more(help) return except KeyError: app.printErr("Unknown command: %s" % cmd) first_sentence = re.compile(r'[^\n]*') ! help = "The following commands are available:\n\n" max_len = 0 for x in app.cmdToCmds.values(): *************** *** 55,65 **** doc = first_sentence.match(x[1]).group() space = (max_len-len(name)) * ' ' ! app.printMsg("%s%s %s" % (name,space,doc)) ! app.printMsg("All commands not listed here are passed " \ ! "to the underlying shell.") def exitProgram(app, name, opts): ! "Terminate the program." return app.BREAK_REPL --- 55,79 ---- doc = first_sentence.match(x[1]).group() space = (max_len-len(name)) * ' ' ! help += "%s%s %s\n" % (name,space,doc) ! help += """ ! All commands not listed here are passed to the underlying shell. ! You can also use IDs from the current listing as arguments to these commands. ! If the IDs should be embedded into other command options, you can enclose ! them with `[[' and `]]'. ! ! Example: ! rm -f [[1,2]] ! removes the files with ID 1 and 2 ! ! More information on the format of the ID-string is available by typing ! `help list'. ! ! You can get more help for a specific command by typing ! `help <name-of-command>'.""" ! app.more(help) def exitProgram(app, name, opts): ! """Terminate the program.""" return app.BREAK_REPL Index: cvs_cmds.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/cvs_cmds.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** cvs_cmds.py 15 Mar 2002 00:47:08 -0000 1.5 --- cvs_cmds.py 15 Mar 2002 18:58:00 -0000 1.6 *************** *** 31,37 **** def status(app, name, args): """Display status information on checked out files. ! This command creates a listing with all checked out files and ! their status. The listing can be filtered by setting the variable ! `filter' in the CONFIG section of ~/.cvsshellrc.""" entries = [] regexHead = re.compile(r'File: (?P<name>\S+)\s+Status: (?P<status>.+)') --- 31,39 ---- def status(app, name, args): """Display status information on checked out files. ! This command creates a listing with all checked out files and ! their status. ! ! The listing can be filtered by setting the variable ! `filter' in the CONFIG section of ~/.cvsshellrc.""" entries = [] regexHead = re.compile(r'File: (?P<name>\S+)\s+Status: (?P<status>.+)') *************** *** 77,84 **** def update(app, args, name, simulate=0): """Bring work tree in sync with repository. ! This command donwloads new files and changes to already ! checked out files from the server. It also brings the ! listing in sync with the repository. The listing can be filtered by setting the variable ! `filter' in the CONFIG section of ~/.cvsshellrc.""" try: (globOpts, opts, --- 79,88 ---- def update(app, args, name, simulate=0): """Bring work tree in sync with repository. ! This command donwloads new files and changes to already ! checked out files from the server. It also brings the ! listing in sync with the repository. ! ! The listing can be filtered by setting the variable ! filter' in the CONFIG section of ~/.cvsshellrc.""" try: (globOpts, opts, *************** *** 109,113 **** """Refresh the current listing by simulating an update. This command runs update without really downloading the ! changes. See help on update for details.""" update(app, name, args, simulate=1) --- 113,117 ---- """Refresh the current listing by simulating an update. This command runs update without really downloading the ! changes. See `help update' for details.""" update(app, name, args, simulate=1) *************** *** 120,125 **** if the cvsroot is already set. * the module to checkout. ! You can invoke the command without any arguments, as it prompts ! you for if needed.""" try: (globOpts, opts, --- 124,129 ---- if the cvsroot is already set. * the module to checkout. ! You can invoke the command without any arguments as it prompts ! you if needed.""" try: (globOpts, opts, *************** *** 159,175 **** """Add a new file/directory to the repository. This command accepts two kind of arguments which cannot be intermixed: ! * list of files/directories to add. ! * some ids from the current listing (these are the numbers on the ! left side of the listing). ! The id-argument must have the following format: #, #, #, ... , # ! - where # is either !% or % ! - where % is either a digit or a range of digits ! (written k-n if k,n are digits) ! All numbers given with % are added to the list of ids, ! all numbers given with !% are removed from this list. ! The id-argument is evaluated from left to right. ! Example: ! 3, 4, 7-10, !8, 12-19, !13-18 ! selects the files with the ids 3, 4, 7, 9, 10, 12, 19""" try: (globOpts, opts, --- 163,172 ---- """Add a new file/directory to the repository. This command accepts two kind of arguments which cannot be intermixed: ! * list of files/directories. ! * an ID-string ! More information on the format of the ID-string is available by typing ! `help list'. ! You can invoke the command without any arguments as it prompts ! you if needed.""" try: (globOpts, opts, *************** *** 227,231 **** def addBinary(app, name, args): """Add a new binary file to the repository. ! """ app.printMsg('The file will be added in binary mode.') add(app, name, args, isBinary=1) --- 224,228 ---- def addBinary(app, name, args): """Add a new binary file to the repository. ! See the help section of the add command for more information.""" app.printMsg('The file will be added in binary mode.') add(app, name, args, isBinary=1) *************** *** 234,238 **** def commit(app, name, args): """Check files into the repository. ! """ try: (globOpts, opts, --- 231,241 ---- def commit(app, name, args): """Check files into the repository. ! This command accepts three kind of arguments which cannot be intermixed: ! * list of files/directories. ! * an ID-string ! * an empty argument list: All modified file in the current directory and all ! it's subdirectories are commited. ! More information on the format of the ID-string is available by typing ! `help list'.""" try: (globOpts, opts, *************** *** 279,283 **** def remove(app, name, args): """Remove an entry (some entries) from the repository. ! """ try: (globOpts, opts, --- 282,292 ---- def remove(app, name, args): """Remove an entry (some entries) from the repository. ! This command accepts two kind of arguments which cannot be intermixed: ! * list of files/directories. ! * an ID-string ! More information on the format of the ID-string is available by typing ! `help list'. ! You can invoke the command without any arguments as it prompts ! you if needed.""" try: (globOpts, opts, *************** *** 344,348 **** def printListing(app, name, args): """Print out the current listing. ! """ app.printListing() --- 353,374 ---- def printListing(app, name, args): """Print out the current listing. ! The numbers on the left side of the listing are the IDs of the files. ! Many commands accept an ID-string, that is string that specifies some IDs. ! These IDs are replaced by the corresponding filenames. ! ! The ID-string must have the following format: #, #, #, ... , # ! - where # is either !% or % ! - where % is either a digit or a range of digits ! (written k-n if k,n are digits) ! All numbers given with % are added to the list of ids, ! all numbers given with !% are removed from this list. ! The ID-string is evaluated from left to right. ! ! Example: ! 3, 4, 7-10, !8, 12-19, !13-18 ! selects the files with the ids 3, 4, 7, 9, 10, 12, 19 ! ! The listing can be filtered by setting the variable ! `filter' in the CONFIG section of ~/.cvsshellrc.""" app.printListing() *************** *** 375,379 **** def readCvsRoot(app, name, args): ! """Read the cvsroot variable from the file CVS/Root.""" newRoot = app.readCvsRootFromFile() if newRoot == None: --- 401,405 ---- def readCvsRoot(app, name, args): ! """Read the cvsroot variable from the file ./CVS/Root.""" newRoot = app.readCvsRootFromFile() if newRoot == None: |
From: Stefan H. <ste...@us...> - 2002-03-15 17:35:24
|
Update of /cvsroot/cvsshell/cvsshell/src In directory usw-pr-cvs1:/tmp/cvs-serv6183/src Modified Files: cvs_shell.py Log Message: ids in the listing can now be used for arbitrary shell cmds Index: cvs_shell.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/cvs_shell.py,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** cvs_shell.py 15 Mar 2002 10:44:13 -0000 1.21 --- cvs_shell.py 15 Mar 2002 17:35:21 -0000 1.22 *************** *** 144,152 **** ! def execShellCmd(self, name, opts): ! if name == 'cvs' and self.cvsChangeCmdRE.search(opts): # command may change the status self.setDirtyListing(1) ! self.shell('%s %s' % (name, opts)) --- 144,174 ---- ! def execShellCmd(self, name, args): ! if name == 'cvs' and self.cvsChangeCmdRE.search(args): # command may change the status self.setDirtyListing(1) ! # pare args as the could specify ids in the listing ! def __doIt(e, filename): ! return filename ! try: ! # ids only ! l = self.applyOnEntryList(args, __doIt) ! args = string.join(l) ! self.setDirtyListing(1) ! except utils.ParseError: ! # maybe ids mixed with other options (the ids are then enclosed in [[ ... ]] ! beg = args.find('[[') ! end = args.find(']]') ! if beg > 0 and end > beg: ! pre = args[:beg] ! post = args[end+2:] ! ids = args[beg+2 : end] ! try: ! l = self.applyOnEntryList(ids, __doIt) ! args = pre + string.join(l) + post ! self.setDirtyListing(1) ! except utilsParseError: pass ! except AppError, msg: pass ! self.shell('%s %s' % (name, args)) |
From: Stefan H. <ste...@us...> - 2002-03-15 10:44:16
|
Update of /cvsroot/cvsshell/cvsshell/src In directory usw-pr-cvs1:/tmp/cvs-serv7430/src Modified Files: cvs_shell.py Log Message: * removed debug messages * added print-out for root dir of listing Index: cvs_shell.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/cvs_shell.py,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -d -r1.20 -r1.21 *** cvs_shell.py 15 Mar 2002 10:37:53 -0000 1.20 --- cvs_shell.py 15 Mar 2002 10:44:13 -0000 1.21 *************** *** 372,375 **** --- 372,376 ---- id = 0 lines = [] + self.app.printMsg('Root Directory: ' + os.path.abspath(self.rootDir)) for e in self.entries: newDir = e.dir *************** *** 381,387 **** isDir = '' colorKey = e.getStatusAsColorKey() - print "colorKey = ", colorKey color = self.app.getConfigMap().get(colorKey, '') - print "color = ", color s = self.app.col(color, formatStr % (id, e.status, isDir, e.name)) lines.append(s) --- 382,386 ---- |
From: Stefan H. <ste...@us...> - 2002-03-15 10:43:41
|
Update of /cvsroot/cvsshell/cvsshell/etc In directory usw-pr-cvs1:/tmp/cvs-serv6625/etc Modified Files: cvsshell.ini default-cvsshellrc Log Message: Changed some default values, added customization support for colors Index: cvsshell.ini =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/etc/cvsshell.ini,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** cvsshell.ini 15 Mar 2002 09:43:51 -0000 1.6 --- cvsshell.ini 15 Mar 2002 10:43:37 -0000 1.7 *************** *** 14,19 **** co, get, checkout = cvs_cmds.checkout st, stat, status = cvs_cmds.status ! auto = cvs_cmds.toggleCvsRootAutoUpdate ! full = basic_cmds.toggleFullStatusLine end --- 14,19 ---- co, get, checkout = cvs_cmds.checkout st, stat, status = cvs_cmds.status ! auto-root = cvs_cmds.toggleCvsRootAutoUpdate ! full-info = basic_cmds.toggleFullInfoLine end Index: default-cvsshellrc =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/etc/default-cvsshellrc,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** default-cvsshellrc 15 Mar 2002 09:43:51 -0000 1.7 --- default-cvsshellrc 15 Mar 2002 10:43:37 -0000 1.8 *************** *** 12,21 **** # Switch colors on or off ! colors = off end # commands that should be executed at start-up section INIT_CMDS: ! auto on end --- 12,32 ---- # Switch colors on or off ! colors = on ! color-info = cyan ! # color-new = ! color-added = purple ! color-conflict = red ! color-modified = green ! color-patched = yellow ! # color-removed = ! color-updated = blue ! color-unknown = pink ! # color-ok ! # color-deleted end # commands that should be executed at start-up section INIT_CMDS: ! auto-root on end |
From: Stefan H. <ste...@us...> - 2002-03-15 10:37:56
|
Update of /cvsroot/cvsshell/cvsshell/src In directory usw-pr-cvs1:/tmp/cvs-serv2767 Modified Files: app.py basic_cmds.py cvs_shell.py parsing.py Log Message: Added color support for listing. Index: app.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/app.py,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** app.py 15 Mar 2002 00:47:08 -0000 1.10 --- app.py 15 Mar 2002 10:37:53 -0000 1.11 *************** *** 1,268 **** ! ############################################################################### ! # This file is part of CvsShell ! # ! # CvsShell is free software; you can redistribute it and/or modify ! # it under the terms of the GNU General Public License as published by ! # the Free Software Foundation; either version 2 of the License, or ! # (at your option) any later version. ! # ! # CvsShell is distributed in the hope that it will be useful, ! # but WITHOUT ANY WARRANTY; without even the implied warranty of ! # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! # GNU General Public License for more details. ! # ! # You should have received a copy of the GNU General Public License ! # along with CvsShell; if not, write to the Free Software ! # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! # ! # Copyright 2002 by Stefan Heimann ! # Website: http://cvsshell.sourceforge.net/ ! ############################################################################### ! ! import sys, os, traceback, getopt, types ! from oo_tools import GetSetProvider ! ! ! _thisdir = os.path.join(os.getcwd(), sys.path[0]) ! AppError = 'AppError' ! ! ! class App(GetSetProvider): ! ! def __init__(self): ! # the directory this file is placed in ! GetSetProvider.__init__(self) ! self.onWindows = sys.platform[:3] == 'win' ! self.THIS_DIR = _thisdir ! try: ! self.HOME = os.environ['HOME'] ! except KeyError: ! if self.onWindows: ! self.HOME = 'c:\\' ! else: ! self.printErr('$HOME is not set.') ! self.HOME = os.getcwd() ! self.name = self.__class__.__name__ ! self.version = '0.1' ! self.copyright = None ! self.bugAddress = None ! self.enableColor = 0 ! try: ! self.path = os.environ['PATH'].split(os.pathsep) ! except KeyError: ! self.path = [] ! self._args = sys.argv[1:] ! self._env = os.environ ! self._opts = None ! ! ! def closeApp(self): ! for x, y in [(sys.stdin, sys.__stdin__), ! (sys.stdout, sys.__stdout__), ! (sys.stderr, sys.__stderr__)]: ! try: ! if x is not y: ! x.close() ! except: pass ! sys.stdin = sys.__stdin__ ! sys.stdout = sys.__stdout__ ! sys.stderr = sys.__stderr__ ! ! ! def help(self): ! """Print the help message.""" ! print "%s, Version %s" % (self.name, self.version) ! print ! max = 0 ! for x in self._docs: ! l = len(x[0]) ! if l > max: max = l ! for x in self._docs: ! spaces = (max - len(x[0])) * ' ' ! print " %s%s %s" % (x[0],spaces,x[1]) ! print ! ! ! def initOptions(self, opts=[]): ! """ ! This method should be called once before getarg is called. ! opts is a list of key-value pairs. ! The keys are the name of the options that should be ! supported, without the leading `-'. If an ! option expects an argument, the name of the option should be ! followed by a colon. ! The values are the documentation of the option. ! """ ! str = '' ! self._docs = [] ! for x in opts: ! name = x[0] ! doc = x[1] ! str += name ! name = '-' + name ! if name[-1] == ':': name = name[:-1] + " <arg>" ! self._docs.append((name,doc)) ! try: ! self._opts = getopt.getopt(self._args,str) ! except getopt.GetoptError, msg: ! self.printErr("%s: %s" % (self.name, msg)) ! self.exit() ! ! ! ############################## ! # script environment services ! ############################## ! ! def getopt(self, tag): ! """test '-x' command arg""" ! if self._opts == None: ! raise AppError, "You have to call init_options before using getopt!" ! for x in self._opts[0]: ! if x[0] == tag: return 1 ! return 0 ! ! def getarg(self, tag, default=None): ! """get '-x val' command arg""" ! if self._opts == None: ! raise AppError, "You have to call init_options before using getarg!" ! for x in self._opts[0]: ! if x[0] == tag: return x[1] ! return default ! ! def restargs(self): ! """get the rest of the commandline arguments (after all options)""" ! if self._opts == None: ! raise AppError, "You have to call init_options before using restargs!" ! return self._opts[1] ! ! def getenv(self, name, default=''): ! """get '$x' environment var""" ! try: ! return self._env[name] ! except KeyError: ! return default ! ! def setenv(self, name, value): # convenient method ! """set '$x' environment var""" ! self._env[name] = value ! ! def cd(self, dir): ! """Changes the current working directory. Returns the old directory.""" ! if not dir: return ! oldDir = os.getcwd() ! self.printVMsg('cd ' + dir) ! os.chdir(dir) ! return oldDir ! ! def isVerbose(self): ! return self.getopt('-v') or self.getopt('--verbose') ! ! def isHelpRequest(self): ! return self.getopt('-h') or self.getopt('--help') ! ! def printVMsg(self, text='', nonl=0): ! if self.isVerbose(): self.printMsg(text, nonl) ! ! def printMsg(self, text='', nonl=0): ! sys.stdout.write(str(text)) ! if not nonl: sys.stdout.write('\n') ! ! def printErr(self, text='', nonl=0): ! sys.stderr.write(str(text)) ! if not nonl: sys.stderr.write('\n') ! ! colDict = { ! "black" : "30m", ! "red" : "31m", ! "green" : "32m", ! "brown" : "33m", ! "blue" : "34m", ! "purple" : "35m", ! "cyan" : "36m", ! "lgray" : "37m", ! "gray" : "1;30m", ! "lred" : "1;31m", ! "lgreen" : "1;32m", ! "yellow" : "1;33m", ! "lblue" : "1;34m", ! "pink" : "1;35m", ! "lcyan" : "1;36m", ! "white" : "1;37m", ! } ! def col(self, color, text): ! """Return colorized text; color can either be a string indicating a color ! or a tuple containing two strings - for color and background. ! Copyright (C) 2001 Andrei Kulakov <ak...@si...> GPL""" ! if not self.enableColor: return text ! bg = "0m" ! if type(color) is types.StringType: ! fg = App.colDict[color] ! else: ! f, b = color ! fg = App.colDict[f] ! bg = App.colDict[b] ! s = "\033[" ! clear = "0m" ! return "%s%s%s%s%s%s%s" % (s, bg, s, fg, text, s, clear) ! ! ! def exit(self, message='', status=1): ! if message: ! self.printMsg(message) ! sys.exit(status) ! ! def shell(self, command, fork=0, inp=''): ! if self.isVerbose(): ! self.printMsg(command) # how about ipc? ! if not fork: ! os.system(command) # run a shell cmd ! elif fork == 1: ! return os.popen(command, 'r').read() # get its output ! else: # readlines too? ! pipe = os.popen(command, 'w') ! pipe.write(inp) # send it input ! pipe.close() ! return None ! ! def main(self): ! """to run the app ! main() is the start/run/stop execution protocol""" ! if self.isHelpRequest(): ! self.help() ! return 0 ! res = None ! try: ! self.start() ! self.run() ! res = self.stop() # optional return val ! except SystemExit: # ignore if from exit() ! pass ! except: ! self.printErr('========== Traceback starts here ==========') ! self.printErr('uncaught: ' + `(sys.exc_type,sys.exc_value)`) ! traceback.print_exc() ! self.printErr(""" ! Program Version: %s ! Platform: %s ! Python version: %s""" % (self.version, sys.platform, sys.version)) ! self.printErr("========== Traceback ends here ==========\n" \ ! "You have discovered a bug in %s." % self.name) ! if self.bugAddress.find('@') > 0: ! self.printErr("Please send a bug report to \n %s," ! % self.bugAddress) ! else: ! self.printErr("Please fill out a bug report at \n %s," ! % self.bugAddress) ! self.printErr("including the traceback above.") ! self.closeApp() ! return res ! ! def start(self): ! self.printMsg("%s %s" % (self.name, self.version)) ! self.printMsg(self.copyright) ! self.printVMsg(self.name + ' started.') ! def stop(self): ! self.printVMsg(self.name + ' done.') ! def run(self): ! raise AppError, 'run must be redefined!' ! --- 1,275 ---- ! ############################################################################### ! # This file is part of CvsShell ! # ! # CvsShell is free software; you can redistribute it and/or modify ! # it under the terms of the GNU General Public License as published by ! # the Free Software Foundation; either version 2 of the License, or ! # (at your option) any later version. ! # ! # CvsShell is distributed in the hope that it will be useful, ! # but WITHOUT ANY WARRANTY; without even the implied warranty of ! # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! # GNU General Public License for more details. ! # ! # You should have received a copy of the GNU General Public License ! # along with CvsShell; if not, write to the Free Software ! # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! # ! # Copyright 2002 by Stefan Heimann ! # Website: http://cvsshell.sourceforge.net/ ! ############################################################################### ! ! import sys, os, traceback, getopt, types ! from oo_tools import GetSetProvider ! ! ! _thisdir = os.path.join(os.getcwd(), sys.path[0]) ! AppError = 'AppError' ! ! ! class App(GetSetProvider): ! ! def __init__(self): ! # the directory this file is placed in ! GetSetProvider.__init__(self) ! self.onWindows = sys.platform[:3] == 'win' ! self.THIS_DIR = _thisdir ! try: ! self.HOME = os.environ['HOME'] ! except KeyError: ! if self.onWindows: ! self.HOME = 'c:\\' ! else: ! self.printErr('$HOME is not set.') ! self.HOME = os.getcwd() ! self.name = self.__class__.__name__ ! self.version = '0.1' ! self.copyright = None ! self.bugAddress = None ! self.enableColor = 0 ! try: ! self.path = os.environ['PATH'].split(os.pathsep) ! except KeyError: ! self.path = [] ! self._args = sys.argv[1:] ! self._env = os.environ ! self._opts = None ! ! ! def closeApp(self): ! for x, y in [(sys.stdin, sys.__stdin__), ! (sys.stdout, sys.__stdout__), ! (sys.stderr, sys.__stderr__)]: ! try: ! if x is not y: ! x.close() ! except: pass ! sys.stdin = sys.__stdin__ ! sys.stdout = sys.__stdout__ ! sys.stderr = sys.__stderr__ ! ! ! def help(self): ! """Print the help message.""" ! print "%s, Version %s" % (self.name, self.version) ! print ! max = 0 ! for x in self._docs: ! l = len(x[0]) ! if l > max: max = l ! for x in self._docs: ! spaces = (max - len(x[0])) * ' ' ! print " %s%s %s" % (x[0],spaces,x[1]) ! print ! ! ! def initOptions(self, opts=[]): ! """ ! This method should be called once before getarg is called. ! opts is a list of key-value pairs. ! The keys are the name of the options that should be ! supported, without the leading `-'. If an ! option expects an argument, the name of the option should be ! followed by a colon. ! The values are the documentation of the option. ! """ ! str = '' ! self._docs = [] ! for x in opts: ! name = x[0] ! doc = x[1] ! str += name ! name = '-' + name ! if name[-1] == ':': name = name[:-1] + " <arg>" ! self._docs.append((name,doc)) ! try: ! self._opts = getopt.getopt(self._args,str) ! except getopt.GetoptError, msg: ! self.printErr("%s: %s" % (self.name, msg)) ! self.exit() ! ! ! ############################## ! # script environment services ! ############################## ! ! def getopt(self, tag): ! """test '-x' command arg""" ! if self._opts == None: ! raise AppError, "You have to call init_options before using getopt!" ! for x in self._opts[0]: ! if x[0] == tag: return 1 ! return 0 ! ! def getarg(self, tag, default=None): ! """get '-x val' command arg""" ! if self._opts == None: ! raise AppError, "You have to call init_options before using getarg!" ! for x in self._opts[0]: ! if x[0] == tag: return x[1] ! return default ! ! def restargs(self): ! """get the rest of the commandline arguments (after all options)""" ! if self._opts == None: ! raise AppError, "You have to call init_options before using restargs!" ! return self._opts[1] ! ! def getenv(self, name, default=''): ! """get '$x' environment var""" ! try: ! return self._env[name] ! except KeyError: ! return default ! ! def setenv(self, name, value): # convenient method ! """set '$x' environment var""" ! self._env[name] = value ! ! def cd(self, dir): ! """Changes the current working directory. Returns the old directory.""" ! if not dir: return ! oldDir = os.getcwd() ! self.printVMsg('cd ' + dir) ! os.chdir(dir) ! return oldDir ! ! def isVerbose(self): ! return self.getopt('-v') or self.getopt('--verbose') ! ! def isHelpRequest(self): ! return self.getopt('-h') or self.getopt('--help') ! ! def printVMsg(self, text='', nonl=0): ! if self.isVerbose(): self.printMsg(text, nonl) ! ! def printMsg(self, text='', nonl=0): ! sys.stdout.write(str(text)) ! if not nonl: sys.stdout.write('\n') ! ! def printErr(self, text='', nonl=0): ! sys.stderr.write(str(text)) ! if not nonl: sys.stderr.write('\n') ! ! colDict = { ! "black" : "30m", ! "red" : "31m", ! "green" : "32m", ! "brown" : "33m", ! "blue" : "34m", ! "purple" : "35m", ! "cyan" : "36m", ! "lgray" : "37m", ! "gray" : "1;30m", ! "lred" : "1;31m", ! "lgreen" : "1;32m", ! "yellow" : "1;33m", ! "lblue" : "1;34m", ! "pink" : "1;35m", ! "lcyan" : "1;36m", ! "white" : "1;37m", ! } ! def col(self, color, text): ! """Return colorized text; color can either be a string indicating a color ! or a string indicating two colors separated by whitespace or a tuple ! containing two colors. If two colors are given, the first is used as foreground ! the second as background. ! Copyright (C) 2001 Andrei Kulakov <ak...@si...> GPL""" ! if not self.enableColor or not color: return text ! bg = "0m" ! if type(color) is types.StringType: ! s = color.split() ! if len(s) < 2: ! fg = App.colDict[color] ! else: ! fg = App.colDict[s[0]] ! bg = App.colDict[s[1]] ! else: ! f, b = color ! fg = App.colDict[f] ! bg = App.colDict[b] ! s = "\033[" ! clear = "0m" ! return "%s%s%s%s%s%s%s" % (s, bg, s, fg, text, s, clear) ! ! ! def exit(self, message='', status=1): ! if message: ! self.printMsg(message) ! sys.exit(status) ! ! def shell(self, command, fork=0, inp=''): ! if self.isVerbose(): ! self.printMsg(command) # how about ipc? ! if not fork: ! os.system(command) # run a shell cmd ! elif fork == 1: ! return os.popen(command, 'r').read() # get its output ! else: # readlines too? ! pipe = os.popen(command, 'w') ! pipe.write(inp) # send it input ! pipe.close() ! return None ! ! def main(self): ! """to run the app ! main() is the start/run/stop execution protocol""" ! if self.isHelpRequest(): ! self.help() ! return 0 ! res = None ! try: ! self.start() ! self.run() ! res = self.stop() # optional return val ! except SystemExit: # ignore if from exit() ! pass ! except: ! self.printErr('========== Traceback starts here ==========') ! self.printErr('uncaught: ' + `(sys.exc_type,sys.exc_value)`) ! traceback.print_exc() ! self.printErr(""" ! Program Version: %s ! Platform: %s ! Python version: %s""" % (self.version, sys.platform, sys.version)) ! self.printErr("========== Traceback ends here ==========\n" \ ! "You have discovered a bug in %s." % self.name) ! if self.bugAddress.find('@') > 0: ! self.printErr("Please send a bug report to \n %s," ! % self.bugAddress) ! else: ! self.printErr("Please fill out a bug report at \n %s," ! % self.bugAddress) ! self.printErr("including the traceback above.") ! self.closeApp() ! return res ! ! def start(self): ! self.printMsg("%s %s" % (self.name, self.version)) ! self.printMsg(self.copyright) ! self.printVMsg(self.name + ' started.') ! def stop(self): ! self.printVMsg(self.name + ' done.') ! def run(self): ! raise AppError, 'run must be redefined!' ! Index: basic_cmds.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/basic_cmds.py,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** basic_cmds.py 15 Mar 2002 00:47:08 -0000 1.16 --- basic_cmds.py 15 Mar 2002 10:37:53 -0000 1.17 *************** *** 79,85 **** if root: app.setCvsRoot(root) ! def toggleFullStatusLine(app, name, args): ! """Toggle between full and abbreviated status line.""" ! app.showFullPrompt = app.toggle(app.showFullPrompt, args) --- 79,85 ---- if root: app.setCvsRoot(root) ! def toggleFullInfoLine(app, name, args): ! """Toggle between full and abbreviated info line.""" ! app.showFullPrompt = app.toggle(app.showFullInfo, args) Index: cvs_shell.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/cvs_shell.py,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -d -r1.19 -r1.20 *** cvs_shell.py 15 Mar 2002 09:43:51 -0000 1.19 --- cvs_shell.py 15 Mar 2002 10:37:53 -0000 1.20 *************** *** 1,416 **** ! ############################################################################### ! # This file is part of CvsShell ! # ! # CvsShell is free software; you can redistribute it and/or modify ! # it under the terms of the GNU General Public License as published by ! # the Free Software Foundation; either version 2 of the License, or ! # (at your option) any later version. ! # ! # CvsShell is distributed in the hope that it will be useful, ! # but WITHOUT ANY WARRANTY; without even the implied warranty of ! # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! # GNU General Public License for more details. ! # ! # You should have received a copy of the GNU General Public License ! # along with CvsShell; if not, write to the Free Software ! # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! # ! # Copyright 2002 by Stefan Heimann ! # Website: http://cvsshell.sourceforge.net/ ! ############################################################################### ! ! import os, sys, re, string, types, getopt, fnmatch, utils ! from oo_tools import GetSetProvider ! from app import AppError ! from interactive_app import InteractiveApp ! from plugable_app import PlugableApp ! ! VERSION = '0.1' ! NAME ='CvsShell' ! COPYRIGHT = 'Copyright 2002 Stefan Heimann (ma...@st...).\n' \ ! 'This software is released under the GPL.' ! BUG_ADDRESS = 'http://sourceforge.net/tracker/?group_id=48175&atid=452212' ! CvsError = 'CvsError' ! InternalCvsError = 'InternalCvsError' ! ! class CvsShell(GetSetProvider, PlugableApp, InteractiveApp): ! ! def __init__(self): ! GetSetProvider.__init__(self) ! PlugableApp.__init__(self) ! InteractiveApp.__init__(self) ! sys.stderr = sys.stdout ! self.setName(NAME) ! self.setVersion(VERSION) ! self.setCopyright(COPYRIGHT) ! self.setBugAddress(BUG_ADDRESS) ! self.initOptions([('v',"Print some extra information"), ! ('h',"Print this help message"), ! ('u',"Delete ~/.cvsshellrc and replace it with the default configuration file")]) ! etcDir = os.path.join(self.THIS_DIR, '..', 'etc') ! self.setConfigFile(os.path.join(self.HOME,'.cvsshellrc'), ! os.path.join(etcDir, 'default-cvsshellrc'), forceDefault=self.getopt('-u')) ! self.setCommandFile(os.path.join(etcDir, 'cvsshell.ini')) ! self.setHistoryFile(os.path.join(self.HOME,'.cvsshell_history')) ! self.CVS_ROOT_FILE = os.path.join('CVS', 'Root') ! self.cmdRegex = re.compile(r""" ! ^\s* # matches leading whitespace ! (?!\#) # line is not a comment (negative lookahead!) ! (?P<name>\S+) # matches the first word of the command ! ( ! \s+ # delimits name and options ! (?P<opts>.*) # the options of the command ! )? # options are optional ! """, re.VERBOSE) ! self.cvsChangeCmdRE = re.compile(r"""\s+ ! (ad(d)?|new|ci|com(mit)?|delete|remove) ! \s+""", re.VERBOSE) ! self.noListingErrMsg = """No listing found. ! You must run `update', `refresh' or `status' before using this command.""" ! self.cvsRoot = None ! self.cvsRootAutoUpdate = 0 ! self.showFullPrompt = 0 ! self.listing = None ! self.dirtyListing = 1 ! self.cvsRootAliases = {} ! self.configMap = {} ! self.aliasesMap = {} ! self.cmdToDefOpts = {} ! self.cmdToDefGlobOpts = {} ! self.defOpts = '' # options for all commands ! self.defGlobOpts = '' # global options for all commands ! self.readCommandFile() ! self.readConfigFile() ! self.listingFilter = utils.splitquoted(self.configMap.get('filter','')) ! self.enableColor = self.configMap.get('colors', 'off') == 'on' ! ! ! def readCvsRootFromFile(self): ! s = None ! if os.access(self.CVS_ROOT_FILE, os.R_OK): ! s = open(self.CVS_ROOT_FILE, 'r').readline().strip() ! return s ! ! ! def getPrompt(self): ! status = '' ! if self.cvsRootAutoUpdate: status += 'a' ! else: status += 'A' ! root = self.getCvsRoot() or '--' ! try: ! dir = os.getcwd().replace(self.HOME, '~') ! # if you delete the dir you are in, getcwd raise an error ! except OSError: ! dir = 'ERROR' ! if not self.showFullPrompt: ! # make the prompt match on one line ! extraChars = 6 ! maxLineWidth = 79 ! minLen = 15 ! ls = len(status) ! ld = len(dir) ! lr = len(root) ! width = ls + extraChars + ld + lr ! if width > maxLineWidth: ! w = max(minLen, (lr - (width - maxLineWidth + 3)) / 2) ! if lr > 2*w: root = root[:w] + '...' + root[-w:] ! lr = len(root) ! width = ls + extraChars + ld + lr ! if width > maxLineWidth: ! w = max(minLen, ld - (width - maxLineWidth + 3)) ! if ld > w: dir = '...' + dir[-w:] ! ld = len(dir) ! return self.col('cyan', "{%s} %s [%s]" % (status, ! dir, ! root)) + '\n$ ' ! ! ! def evalCommand(self, cmd): ! result = self.cmdRegex.match(cmd) ! if result is None: ! return None ! cmdName = result.group('name') ! cmdName = self.aliasesMap.get(cmdName, cmdName) ! cmdOpts = result.group('opts') ! if cmdOpts == None: ! cmdOpts = '' ! cmdOpts = cmdOpts.strip() ! fun = self.getCmdFun(cmdName, CvsShell.execShellCmd) ! return fun(self, cmdName, cmdOpts) ! ! ! def run(self): # FIXME: why must I redefine run here? ! InteractiveApp.run(self) ! ! ! def execShellCmd(self, name, opts): ! if name == 'cvs' and self.cvsChangeCmdRE.search(opts): ! # command may change the status ! self.setDirtyListing(1) ! self.shell('%s %s' % (name, opts)) ! ! ! def toggle(self, oldVal, args): ! if len(args) == 0: ! return not oldVal ! else: ! if args == 'on': return 1 ! elif args == 'off': return 0 ! else: ! self.printErr("argument must be `on' or `off'") ! return oldVal ! ! ! def more(self, lines=None, s=None, numlines=22): ! if lines is not None: ! s = string.join(lines, '') ! elif s is not None: ! lines = s.split('\n') ! else: ! raise AppError, \ ! "Illegal argument: One of lines or s must be given" ! if len(lines) <= numlines or not self.configMap.has_key('pager'): ! self.printMsg(s, nonl=1) ! else: ! import tempfile ! pager = self.configMap['pager'] ! try: ! tmp = tempfile.mktemp() ! open(tmp,'w').write(s) ! self.shell(pager + ' ' + tmp) ! except (IOError,OSError), msg: ! self.printMsg(s, nonl=1) ! self.printErr("Error invoking pager `%s': %s" % ! (pager,str(msg))) ! ! ! ############################## ! # CVS helper methods ! ############################## ! ! def runCvsCmd(self, cmd, rootDir=None, cvsRoot=None, globOpts = '', ! args='', fork=1, getStderr=0): ! """ ! * cmd is the command to execute ! * rootDir is the directory the command should be executed in ! * globOpts are global options. These options ! override the default global options ! * args are the arguments that should be passed to the cvs command ! """ ! oldDir = None ! if rootDir is not None: ! try: ! oldDir = self.cd(rootDir) ! except OSError,msg: ! self.printErr("Could not change to the root directory of " \ ! "the current listing: %s" % str(msg)) ! raise CvsError ! # ! defGlobOpts,defOpts = self.getOptions(cmd) ! cvsRoot = cvsRoot or self.getCvsRoot() ! if cvsRoot != None: cvsRootOpt = "-d %s" % cvsRoot ! else: cvsRootOpt = '' ! # ! globOpts = "%s %s %s" % (defGlobOpts, cvsRootOpt, globOpts) ! args = "%s %s" % (defOpts, args) ! cmd = 'cvs %s %s %s' % (globOpts, cmd, args) ! # on windows, cvs seems to output all information on stdout ! if getStderr and not self.onWindows: cmd += ' 2>&1' ! self.printVMsg(cmd) ! if fork: ! f = os.popen(cmd) ! try: ! lines = f.readlines() ! except KeyboardInterrupt: ! return [] ! if f.close() is not None: # cvs command caused an error ! raise CvsError ! else: ! return lines ! else: ! r = os.system(cmd) ! if r != 0: ! raise CvsError ! if oldDir is not None: ! try: ! self.cd(oldDir) ! except OSError,msg: ! self.printErr(msg) ! return None ! ! ! def applyOnEntryList(self, opts, fun): ! """Applies fun to the entries of the current listing selected by opts. ! opts is a string that may specify some numbers ! which refers to entries in the listing. ! fun must take 2 argument as the entry and its ! filename is passed to it. Returns a ! list with the return values from fun. ! If a error occurs, an AppError is raised. If this error is ! encountered while parsing opts, a ParseError is raised.""" ! nums = utils.parseNumberStr(opts) ! if len(nums) == 0: ! raise AppError, 'No files specified.' ! if not self.listing: ! raise AppError, self.noListingErrMsg ! result = [] ! max = len(self.listing.entries) ! for x in nums: ! if x < 0 or x > max: continue ! e = self.listing.entries[x] ! name = os.path.join(e.dir, e.name) ! result.append(fun(e,name)) ! return result ! ! ! def printListing(self): ! if not self.listing: ! self.printErr(self.noListingErrMsg) ! else: ! self.listing.printEntries() ! if self.getDirtyListing(): ! self.printMsg("Listing may be out-of-date. " \ ! "Run `update', `refresh' or `status'.") ! ! ! def parseArgs(self, args, cvsCmdOpts='', cmdOpts=''): ! """Parse args and separates it like that: ! cvsCmdOpts are the options that are allowed for the cvs command ! cmdOpts are additional options (provided by cvsshell) ! global options are handled automatically ! * global cvs options (as string) ! * command specific cvs options (as string) ! * other options (as dictionary) ! * other args (as string) ! These values are returned as a 4-tupel. ! A GetoptError is raised if there are unknown options.""" ! cvsGlobOpts = 'HQqrwlntvb:T:e:d:fz:as:' ! s = cvsGlobOpts+cvsCmdOpts+cmdOpts ! (opts, rest) = getopt.getopt(utils.splitquoted(args), s) ! cvsGlobOptstr = cvsCmdOptstr = '' ! cmdOptDict = {} ! for x in opts: ! name, value = x ! # getopt prepends '-' to every option ! if name[1] in cvsGlobOpts: ! cvsGlobOptstr += ' ' + name ! if value: cvsGlobOptstr += ' ' + value ! elif name[1] in cvsCmdOpts: ! cvsCmdOptstr += ' ' + name ! if value: cvsCmdOptstr += ' ' + value ! else: ! cmdOptDict[name] = value ! if cvsGlobOptstr: cvsGlobOptstr = cvsGlobOptstr[1:] # remove trailing ' ' ! if cvsCmdOptstr: cvsCmdOptstr = cvsCmdOptstr[1:] # remove trailing ' ' ! reststr = '' ! for x in rest: ! reststr += x + ' ' ! if reststr: reststr = reststr[:-1] ! return (cvsGlobOptstr, cvsCmdOptstr, cmdOptDict, reststr) ! ! ! def getOptions(self, cmd): ! """Returns the options that should be used for cmd. The return value ! is the tupel (globalOptions, options)""" ! defGlobOpts = self.getDefGlobOpts() ! defOpts = self.getDefOpts() ! defGlobOpts += ' ' + self.getCmdToDefGlobOpts().get(cmd,'') ! defOpts += ' ' + self.getCmdToDefOpts().get(cmd,'') ! return defGlobOpts,defOpts ! ! ! ! ############################## ! # Listing ! ############################## ! ! class Listing(GetSetProvider): ! ! def __init__(self, app, rootDir, entries=[]): ! GetSetProvider.__init__(self) ! self.app = app ! self.rootDir = rootDir ! self.sortOrder = ['dir', 'status', 'name'] ! filter = app.getListingFilter() ! if not filter: ! self.entries = entries ! else: ! self.entries = [] ! for e in entries: ! dontInclude = 0 ! for f in filter: ! if fnmatch.fnmatch(e.getName(), f): ! dontInclude = 1 ! break ! if not dontInclude: ! self.entries.append(e) ! ! def sortEntries(self): ! class __EntrySorter: ! def __init__(self, order): self.order = order ! def cmp(self,x,y): ! try: ! i = 0 ! for attr in self.order: ! i = eval("cmp(x.%s, y.%s)" % (attr,attr)) ! if i != 0: return i ! return i ! except AttributeError: ! return -1 ! self.entries.sort(__EntrySorter(self.sortOrder).cmp) ! ! def printEntries(self, verbose=1): ! if not self.entries: ! if verbose: self.app.printMsg('No entries available.') ! return ! max = 0 ! for e in self.entries: ! l = len(e.status) ! if l > max: max = l ! formatStr = " %%%dd %%-%ds %%s%%s\n" % (len(`len(self.entries)`), max) ! oldDir = None ! id = 0 ! lines = [] ! for e in self.entries: ! newDir = e.dir ! if oldDir != newDir: ! lines.append("%s:\n" % newDir) ! if os.path.isdir(os.path.join(self.rootDir, e.dir, e.name)): ! isDir = "<dir> " ! else: ! isDir = '' ! lines.append(formatStr % (id, e.status, isDir, e.name)) ! id += 1 ! oldDir = newDir ! self.app.more(lines) ! ! ! ############################## ! # Entry ! ############################## ! ! class Entry(GetSetProvider): ! S_NEW = 'N' ! S_ADDED = 'A' ! S_CONFLICT = 'C' ! S_MODIFIED = 'M' ! S_PATCHED = 'P' ! S_REMOVED = 'R' ! S_UPDATED = 'U' ! S_UNKNOWN = '?' ! S_OK = 'OK' # file on the sandbox is in sync with repository ! S_DELETED = 'D' # file scheduled for removal has been commited ! def __init__(self, dir, name, status): ! GetSetProvider.__init__(self) ! self.dir = dir ! self.name = name ! self.status = status ! ! ! def main(): ! app = CvsShell() ! res = app.main() ! app.exit(res) ! ! if __name__ == '__main__': ! main() --- 1,430 ---- ! ############################################################################### ! # This file is part of CvsShell ! # ! # CvsShell is free software; you can redistribute it and/or modify ! # it under the terms of the GNU General Public License as published by ! # the Free Software Foundation; either version 2 of the License, or ! # (at your option) any later version. ! # ! # CvsShell is distributed in the hope that it will be useful, ! # but WITHOUT ANY WARRANTY; without even the implied warranty of ! # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! # GNU General Public License for more details. ! # ! # You should have received a copy of the GNU General Public License ! # along with CvsShell; if not, write to the Free Software ! # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! # ! # Copyright 2002 by Stefan Heimann ! # Website: http://cvsshell.sourceforge.net/ ! ############################################################################### ! ! import os, sys, re, string, types, getopt, fnmatch, utils ! from oo_tools import GetSetProvider ! from app import AppError ! from interactive_app import InteractiveApp ! from plugable_app import PlugableApp ! ! VERSION = '0.1' ! NAME ='CvsShell' ! COPYRIGHT = 'Copyright 2002 Stefan Heimann (ma...@st...).\n' \ ! 'This software is released under the GPL.' ! BUG_ADDRESS = 'http://sourceforge.net/tracker/?group_id=48175&atid=452212' ! CvsError = 'CvsError' ! InternalCvsError = 'InternalCvsError' ! ! class CvsShell(GetSetProvider, PlugableApp, InteractiveApp): ! ! def __init__(self): ! GetSetProvider.__init__(self) ! PlugableApp.__init__(self) ! InteractiveApp.__init__(self) ! sys.stderr = sys.stdout ! self.setName(NAME) ! self.setVersion(VERSION) ! self.setCopyright(COPYRIGHT) ! self.setBugAddress(BUG_ADDRESS) ! self.initOptions([('v',"Print some extra information"), ! ('h',"Print this help message"), ! ('u',"Delete ~/.cvsshellrc and replace it with the default configuration file")]) ! etcDir = os.path.join(self.THIS_DIR, '..', 'etc') ! self.setConfigFile(os.path.join(self.HOME,'.cvsshellrc'), ! os.path.join(etcDir, 'default-cvsshellrc'), forceDefault=self.getopt('-u')) ! self.setCommandFile(os.path.join(etcDir, 'cvsshell.ini')) ! self.setHistoryFile(os.path.join(self.HOME,'.cvsshell_history')) ! self.CVS_ROOT_FILE = os.path.join('CVS', 'Root') ! self.cmdRegex = re.compile(r""" ! ^\s* # matches leading whitespace ! (?!\#) # line is not a comment (negative lookahead!) ! (?P<name>\S+) # matches the first word of the command ! ( ! \s+ # delimits name and options ! (?P<opts>.*) # the options of the command ! )? # options are optional ! """, re.VERBOSE) ! self.cvsChangeCmdRE = re.compile(r"""\s+ ! (ad(d)?|new|ci|com(mit)?|delete|remove) ! \s+""", re.VERBOSE) ! self.noListingErrMsg = """No listing found. ! You must run `update', `refresh' or `status' before using this command.""" ! self.cvsRoot = None ! self.cvsRootAutoUpdate = 0 ! self.showFullInfo = 0 ! self.listing = None ! self.dirtyListing = 1 ! self.cvsRootAliases = {} ! self.configMap = {} ! self.aliasesMap = {} ! self.cmdToDefOpts = {} ! self.cmdToDefGlobOpts = {} ! self.defOpts = '' # options for all commands ! self.defGlobOpts = '' # global options for all commands ! self.readCommandFile() ! self.readConfigFile() ! self.listingFilter = utils.splitquoted(self.configMap.get('filter','')) ! self.enableColor = self.configMap.get('colors', 'off') == 'on' ! ! ! def readCvsRootFromFile(self): ! s = None ! if os.access(self.CVS_ROOT_FILE, os.R_OK): ! s = open(self.CVS_ROOT_FILE, 'r').readline().strip() ! return s ! ! ! def getPrompt(self): ! status = '' ! if self.cvsRootAutoUpdate: status += 'a' ! else: status += 'A' ! root = self.getCvsRoot() or '--' ! try: ! dir = os.getcwd().replace(self.HOME, '~') ! # if you delete the dir you are in, getcwd raise an error ! except OSError: ! dir = 'ERROR' ! if not self.showFullInfo: ! # make the prompt match on one line ! extraChars = 6 ! maxLineWidth = 79 ! minLen = 15 ! ls = len(status) ! ld = len(dir) ! lr = len(root) ! width = ls + extraChars + ld + lr ! if width > maxLineWidth: ! w = max(minLen, (lr - (width - maxLineWidth + 3)) / 2) ! if lr > 2*w: root = root[:w] + '...' + root[-w:] ! lr = len(root) ! width = ls + extraChars + ld + lr ! if width > maxLineWidth: ! w = max(minLen, ld - (width - maxLineWidth + 3)) ! if ld > w: dir = '...' + dir[-w:] ! ld = len(dir) ! return self.col('cyan', "{%s} %s [%s]" % (status, ! dir, ! root)) + '\n$ ' ! ! ! def evalCommand(self, cmd): ! result = self.cmdRegex.match(cmd) ! if result is None: ! return None ! cmdName = result.group('name') ! cmdName = self.aliasesMap.get(cmdName, cmdName) ! cmdOpts = result.group('opts') ! if cmdOpts == None: ! cmdOpts = '' ! cmdOpts = cmdOpts.strip() ! fun = self.getCmdFun(cmdName, CvsShell.execShellCmd) ! return fun(self, cmdName, cmdOpts) ! ! ! def run(self): # FIXME: why must I redefine run here? ! InteractiveApp.run(self) ! ! ! def execShellCmd(self, name, opts): ! if name == 'cvs' and self.cvsChangeCmdRE.search(opts): ! # command may change the status ! self.setDirtyListing(1) ! self.shell('%s %s' % (name, opts)) ! ! ! def toggle(self, oldVal, args): ! if len(args) == 0: ! return not oldVal ! else: ! if args == 'on': return 1 ! elif args == 'off': return 0 ! else: ! self.printErr("argument must be `on' or `off'") ! return oldVal ! ! ! def more(self, lines=None, s=None, numlines=22): ! if lines is not None: ! s = string.join(lines, '') ! elif s is not None: ! lines = s.split('\n') ! else: ! raise AppError, \ ! "Illegal argument: One of lines or s must be given" ! if len(lines) <= numlines or not self.configMap.has_key('pager'): ! self.printMsg(s, nonl=1) ! else: ! import tempfile ! pager = self.configMap['pager'] ! try: ! tmp = tempfile.mktemp() ! open(tmp,'w').write(s) ! self.shell(pager + ' ' + tmp) ! except (IOError,OSError), msg: ! self.printMsg(s, nonl=1) ! self.printErr("Error invoking pager `%s': %s" % ! (pager,str(msg))) ! ! ! ############################## ! # CVS helper methods ! ############################## ! ! def runCvsCmd(self, cmd, rootDir=None, cvsRoot=None, globOpts = '', ! args='', fork=1, getStderr=0): ! """ ! * cmd is the command to execute ! * rootDir is the directory the command should be executed in ! * globOpts are global options. These options ! override the default global options ! * args are the arguments that should be passed to the cvs command ! """ ! oldDir = None ! if rootDir is not None: ! try: ! oldDir = self.cd(rootDir) ! except OSError,msg: ! self.printErr("Could not change to the root directory of " \ ! "the current listing: %s" % str(msg)) ! raise CvsError ! # ! defGlobOpts,defOpts = self.getOptions(cmd) ! cvsRoot = cvsRoot or self.getCvsRoot() ! if cvsRoot != None: cvsRootOpt = "-d %s" % cvsRoot ! else: cvsRootOpt = '' ! # ! globOpts = "%s %s %s" % (defGlobOpts, cvsRootOpt, globOpts) ! args = "%s %s" % (defOpts, args) ! cmd = 'cvs %s %s %s' % (globOpts, cmd, args) ! # on windows, cvs seems to output all information on stdout ! if getStderr and not self.onWindows: cmd += ' 2>&1' ! self.printVMsg(cmd) ! if fork: ! f = os.popen(cmd) ! try: ! lines = f.readlines() ! except KeyboardInterrupt: ! return [] ! if f.close() is not None: # cvs command caused an error ! raise CvsError ! else: ! return lines ! else: ! r = os.system(cmd) ! if r != 0: ! raise CvsError ! if oldDir is not None: ! try: ! self.cd(oldDir) ! except OSError,msg: ! self.printErr(msg) ! return None ! ! ! def applyOnEntryList(self, opts, fun): ! """Applies fun to the entries of the current listing selected by opts. ! opts is a string that may specify some numbers ! which refers to entries in the listing. ! fun must take 2 argument as the entry and its ! filename is passed to it. Returns a ! list with the return values from fun. ! If a error occurs, an AppError is raised. If this error is ! encountered while parsing opts, a ParseError is raised.""" ! nums = utils.parseNumberStr(opts) ! if len(nums) == 0: ! raise AppError, 'No files specified.' ! if not self.listing: ! raise AppError, self.noListingErrMsg ! result = [] ! max = len(self.listing.entries) ! for x in nums: ! if x < 0 or x > max: continue ! e = self.listing.entries[x] ! name = os.path.join(e.dir, e.name) ! result.append(fun(e,name)) ! return result ! ! ! def printListing(self): ! if not self.listing: ! self.printErr(self.noListingErrMsg) ! else: ! self.listing.printEntries() ! if self.getDirtyListing(): ! self.printMsg("Listing may be out-of-date. " \ ! "Run `update', `refresh' or `status'.") ! ! ! def parseArgs(self, args, cvsCmdOpts='', cmdOpts=''): ! """Parse args and separates it like that: ! cvsCmdOpts are the options that are allowed for the cvs command ! cmdOpts are additional options (provided by cvsshell) ! global options are handled automatically ! * global cvs options (as string) ! * command specific cvs options (as string) ! * other options (as dictionary) ! * other args (as string) ! These values are returned as a 4-tupel. ! A GetoptError is raised if there are unknown options.""" ! cvsGlobOpts = 'HQqrwlntvb:T:e:d:fz:as:' ! s = cvsGlobOpts+cvsCmdOpts+cmdOpts ! (opts, rest) = getopt.getopt(utils.splitquoted(args), s) ! cvsGlobOptstr = cvsCmdOptstr = '' ! cmdOptDict = {} ! for x in opts: ! name, value = x ! # getopt prepends '-' to every option ! if name[1] in cvsGlobOpts: ! cvsGlobOptstr += ' ' + name ! if value: cvsGlobOptstr += ' ' + value ! elif name[1] in cvsCmdOpts: ! cvsCmdOptstr += ' ' + name ! if value: cvsCmdOptstr += ' ' + value ! else: ! cmdOptDict[name] = value ! if cvsGlobOptstr: cvsGlobOptstr = cvsGlobOptstr[1:] # remove trailing ' ' ! if cvsCmdOptstr: cvsCmdOptstr = cvsCmdOptstr[1:] # remove trailing ' ' ! reststr = '' ! for x in rest: ! reststr += x + ' ' ! if reststr: reststr = reststr[:-1] ! return (cvsGlobOptstr, cvsCmdOptstr, cmdOptDict, reststr) ! ! ! def getOptions(self, cmd): ! """Returns the options that should be used for cmd. The return value ! is the tupel (globalOptions, options)""" ! defGlobOpts = self.getDefGlobOpts() ! defOpts = self.getDefOpts() ! defGlobOpts += ' ' + self.getCmdToDefGlobOpts().get(cmd,'') ! defOpts += ' ' + self.getCmdToDefOpts().get(cmd,'') ! return defGlobOpts,defOpts ! ! ! ! ############################## ! # Listing ! ############################## ! ! class Listing(GetSetProvider): ! ! def __init__(self, app, rootDir, entries=[]): ! GetSetProvider.__init__(self) ! self.app = app ! self.rootDir = rootDir ! self.sortOrder = ['dir', 'status', 'name'] ! filter = app.getListingFilter() ! if not filter: ! self.entries = entries ! else: ! self.entries = [] ! for e in entries: ! dontInclude = 0 ! for f in filter: ! if fnmatch.fnmatch(e.getName(), f): ! dontInclude = 1 ! break ! if not dontInclude: ! self.entries.append(e) ! ! def sortEntries(self): ! class __EntrySorter: ! def __init__(self, order): self.order = order ! def cmp(self,x,y): ! try: ! i = 0 ! for attr in self.order: ! i = eval("cmp(x.%s, y.%s)" % (attr,attr)) ! if i != 0: return i ! return i ! except AttributeError: ! return -1 ! self.entries.sort(__EntrySorter(self.sortOrder).cmp) ! ! def printEntries(self, verbose=1): ! if not self.entries: ! if verbose: self.app.printMsg('No entries available.') ! return ! max = 0 ! for e in self.entries: ! l = len(e.status) ! if l > max: max = l ! formatStr = " %%%dd %%-%ds %%s%%s\n" % (len(`len(self.entries)`), max) ! oldDir = None ! id = 0 ! lines = [] ! for e in self.entries: ! newDir = e.dir ! if oldDir != newDir: ! lines.append("%s:\n" % newDir) ! if os.path.isdir(os.path.join(self.rootDir, e.dir, e.name)): ! isDir = "<dir> " ! else: ! isDir = '' ! colorKey = e.getStatusAsColorKey() ! print "colorKey = ", colorKey ! color = self.app.getConfigMap().get(colorKey, '') ! print "color = ", color ! s = self.app.col(color, formatStr % (id, e.status, isDir, e.name)) ! lines.append(s) ! id += 1 ! oldDir = newDir ! self.app.more(lines) ! ! ! ############################## ! # Entry ! ############################## ! ! class Entry(GetSetProvider): ! S_NEW = 'N' ! S_ADDED = 'A' ! S_CONFLICT = 'C' ! S_MODIFIED = 'M' ! S_PATCHED = 'P' ! S_REMOVED = 'R' ! S_UPDATED = 'U' ! S_UNKNOWN = '?' ! S_OK = 'OK' # file on the sandbox is in sync with repository ! S_DELETED = 'D' # file scheduled for removal has been commited ! statusToColorKey = None ! def __init__(self, dir, name, status): ! GetSetProvider.__init__(self) ! self.dir = dir ! self.name = name ! self.status = status ! if Entry.statusToColorKey is None: ! Entry.statusToColorKey = {} ! for x in Entry.__dict__.items(): ! key, value = x ! if key[:2] == 'S_': ! Entry.statusToColorKey[value] = 'color-' + key[2:].lower() ! ! def getStatusAsColorKey(self): ! return Entry.statusToColorKey.get(self.status, None) ! ! def main(): ! app = CvsShell() ! res = app.main() ! app.exit(res) ! ! if __name__ == '__main__': ! main() Index: parsing.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/parsing.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** parsing.py 15 Mar 2002 09:43:51 -0000 1.2 --- parsing.py 15 Mar 2002 10:37:53 -0000 1.3 *************** *** 88,92 **** n = x[0] l = app.keyValSplitRE.split(x[1], 1) - print l if len(l) != 2: app.printErr("Syntax error in configuration file (line %d)." % n) --- 88,91 ---- |
From: Stefan H. <ste...@us...> - 2002-03-15 09:43:54
|
Update of /cvsroot/cvsshell/cvsshell/etc In directory usw-pr-cvs1:/tmp/cvs-serv21417/etc Modified Files: cvsshell.ini default-cvsshellrc Log Message: Added support for * automatic deletion of ~/.cvsshellrc if requested with the -u option * aliases for arbitrary commands Index: cvsshell.ini =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/etc/cvsshell.ini,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** cvsshell.ini 15 Mar 2002 00:47:07 -0000 1.5 --- cvsshell.ini 15 Mar 2002 09:43:51 -0000 1.6 *************** *** 32,34 **** --- 32,35 ---- DEFAULT_CMD_OPTIONS = parsing.parseDefaultOptions CONFIG = parsing.parseConfigSection + ALIASES = parsing.parseAliasesSection end Index: default-cvsshellrc =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/etc/default-cvsshellrc,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** default-cvsshellrc 15 Mar 2002 00:47:08 -0000 1.6 --- default-cvsshellrc 15 Mar 2002 09:43:51 -0000 1.7 *************** *** 33,36 **** --- 33,41 ---- + # Aliases for arbitrary commands + section ALIASES: + ls = ls --color=always + end + # aliases for cvsroots # |
From: Stefan H. <ste...@us...> - 2002-03-15 09:43:54
|
Update of /cvsroot/cvsshell/cvsshell/src In directory usw-pr-cvs1:/tmp/cvs-serv21417/src Modified Files: configurable_app.py cvs_shell.py parsing.py Log Message: Added support for * automatic deletion of ~/.cvsshellrc if requested with the -u option * aliases for arbitrary commands Index: configurable_app.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/configurable_app.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** configurable_app.py 10 Mar 2002 23:13:59 -0000 1.6 --- configurable_app.py 15 Mar 2002 09:43:51 -0000 1.7 *************** *** 43,51 **** ! def setConfigFile(self, filename, default=None): """Set the name of the configfile. If the configfile does not exist and no default is given, a empty config file is created. Otherwise, default is copied as new ! config file.""" self.configFile = filename if not os.access(self.configFile, os.R_OK): --- 43,58 ---- ! def setConfigFile(self, filename, default=None, forceDefault=0): """Set the name of the configfile. If the configfile does not exist and no default is given, a empty config file is created. Otherwise, default is copied as new ! config file. If forceDefault is true, the default configfile ! will be used no matter if filename exists or not.""" ! if(forceDefault): ! try: ! os.unlink(filename) ! self.printVMsg("Configuration file %s removed." % filename) ! except OSError, msg: ! self.printVMsg(msg) self.configFile = filename if not os.access(self.configFile, os.R_OK): Index: cvs_shell.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/cvs_shell.py,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** cvs_shell.py 15 Mar 2002 00:47:08 -0000 1.18 --- cvs_shell.py 15 Mar 2002 09:43:51 -0000 1.19 *************** *** 45,55 **** self.setCopyright(COPYRIGHT) self.setBugAddress(BUG_ADDRESS) etcDir = os.path.join(self.THIS_DIR, '..', 'etc') self.setConfigFile(os.path.join(self.HOME,'.cvsshellrc'), ! os.path.join(etcDir, 'default-cvsshellrc')) self.setCommandFile(os.path.join(etcDir, 'cvsshell.ini')) self.setHistoryFile(os.path.join(self.HOME,'.cvsshell_history')) - self.initOptions([('v',"Print some extra information"), - ('h',"Print this help message")]) self.CVS_ROOT_FILE = os.path.join('CVS', 'Root') self.cmdRegex = re.compile(r""" --- 45,56 ---- self.setCopyright(COPYRIGHT) self.setBugAddress(BUG_ADDRESS) + self.initOptions([('v',"Print some extra information"), + ('h',"Print this help message"), + ('u',"Delete ~/.cvsshellrc and replace it with the default configuration file")]) etcDir = os.path.join(self.THIS_DIR, '..', 'etc') self.setConfigFile(os.path.join(self.HOME,'.cvsshellrc'), ! os.path.join(etcDir, 'default-cvsshellrc'), forceDefault=self.getopt('-u')) self.setCommandFile(os.path.join(etcDir, 'cvsshell.ini')) self.setHistoryFile(os.path.join(self.HOME,'.cvsshell_history')) self.CVS_ROOT_FILE = os.path.join('CVS', 'Root') self.cmdRegex = re.compile(r""" *************** *** 74,77 **** --- 75,79 ---- self.cvsRootAliases = {} self.configMap = {} + self.aliasesMap = {} self.cmdToDefOpts = {} self.cmdToDefGlobOpts = {} *************** *** 102,106 **** dir = 'ERROR' if not self.showFullPrompt: ! # make to prompt match on one line extraChars = 6 maxLineWidth = 79 --- 104,108 ---- dir = 'ERROR' if not self.showFullPrompt: ! # make the prompt match on one line extraChars = 6 maxLineWidth = 79 *************** *** 129,132 **** --- 131,135 ---- return None cmdName = result.group('name') + cmdName = self.aliasesMap.get(cmdName, cmdName) cmdOpts = result.group('opts') if cmdOpts == None: Index: parsing.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/parsing.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** parsing.py 11 Mar 2002 09:50:41 -0000 1.1 --- parsing.py 15 Mar 2002 09:43:51 -0000 1.2 *************** *** 35,38 **** --- 35,39 ---- else: roots[l[0]] = l[1] + app.printVMsg("Aliases for cvsroots:\n%s" % `app.getCvsRootAliases()`) *************** *** 76,85 **** def parseConfigSection(lines, app): for x in lines: n = x[0] ! l = app.keyValSplitRE.split(x[1]) if len(l) != 2: app.printErr("Syntax error in configuration file (line %d)." % n) continue key, value = l ! app.configMap[key] = value --- 77,95 ---- def parseConfigSection(lines, app): + _parseKeyValSection(lines, app, app.getConfigMap()) + app.printVMsg("Config options:\n%s" % `app.getConfigMap()`) + + def parseAliasesSection(lines, app): + _parseKeyValSection(lines, app, app.getAliasesMap()) + app.printVMsg("Aliases:\n%s" % `app.getAliasesMap()`) + + def _parseKeyValSection(lines, app, map): for x in lines: n = x[0] ! l = app.keyValSplitRE.split(x[1], 1) ! print l if len(l) != 2: app.printErr("Syntax error in configuration file (line %d)." % n) continue key, value = l ! map[key] = value |
From: Stefan H. <ste...@us...> - 2002-03-15 00:47:11
|
Update of /cvsroot/cvsshell/cvsshell/src/etc In directory usw-pr-cvs1:/tmp/cvs-serv29355/src/etc Modified Files: cvsshell.ini Log Message: * improved color support (it's configurable to switch on/off) * made full command working Index: cvsshell.ini =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/etc/cvsshell.ini,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** cvsshell.ini 15 Mar 2002 00:32:58 -0000 1.2 --- cvsshell.ini 15 Mar 2002 00:47:08 -0000 1.3 *************** *** 1,24 **** - section COMMANDS: - exit = basic_cmds.exitProgram - ?, help = basic_cmds.cmdHelp - cd = basic_cmds.changeDir - up, upd, update = basic_cmds.update - refresh = basic_cmds.simulateUpdate - sr,set-root = basic_cmds.setCvsRoot - rr,read-root = basic_cmds.readCvsRoot - cr,clear-root = basic_cmds.clearCvsRoot - list = basic_cmds.printListing - ad, add, new = basic_cmds.add - ci, com, commit = basic_cmds.commit - delete, remove = basic_cmds.remove - co, get, checkout = basic_cmds.checkout - st, stat, status = basic_cmds.status - auto = basic_cmds.toggleCvsRootAutoUpdate - full = basic_cmds.toggleFullStatusLine - end - - section PARSERS: - INIT_CMDS = basic_cmds.parseInitCmdsSection - CVSROOT = basic_cmds.parseCvsRootSection - DEFAULT_CMD_OPTIONS = basic_cmds.parseDefaultOptions - end \ No newline at end of file --- 0 ---- |
From: Stefan H. <ste...@us...> - 2002-03-15 00:47:11
|
Update of /cvsroot/cvsshell/cvsshell/src In directory usw-pr-cvs1:/tmp/cvs-serv29355/src Modified Files: app.py basic_cmds.py cvs_cmds.py cvs_shell.py plugable_app.py Log Message: * improved color support (it's configurable to switch on/off) * made full command working Index: app.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/app.py,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** app.py 15 Mar 2002 00:31:04 -0000 1.9 --- app.py 15 Mar 2002 00:47:08 -0000 1.10 *************** *** 47,51 **** self.copyright = None self.bugAddress = None ! self.enableColor = 1 try: self.path = os.environ['PATH'].split(os.pathsep) --- 47,51 ---- self.copyright = None self.bugAddress = None ! self.enableColor = 0 try: self.path = os.environ['PATH'].split(os.pathsep) Index: basic_cmds.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/basic_cmds.py,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** basic_cmds.py 15 Mar 2002 00:31:36 -0000 1.15 --- basic_cmds.py 15 Mar 2002 00:47:08 -0000 1.16 *************** *** 79,82 **** --- 79,85 ---- if root: app.setCvsRoot(root) + def toggleFullStatusLine(app, name, args): + """Toggle between full and abbreviated status line.""" + app.showFullPrompt = app.toggle(app.showFullPrompt, args) Index: cvs_cmds.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/cvs_cmds.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** cvs_cmds.py 15 Mar 2002 00:31:36 -0000 1.4 --- cvs_cmds.py 15 Mar 2002 00:47:08 -0000 1.5 *************** *** 397,403 **** newRoot = app.readCvsRootFromFile() if newRoot is not None: app.setCvsRoot(newRoot) - - - def toggleFullPrompt(app, name, args): - """Toggle between full and abbreviated status line.""" - app.showFullPrompt = app.toggle(app.showFullPrompt, args) --- 397,398 ---- Index: cvs_shell.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/cvs_shell.py,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** cvs_shell.py 15 Mar 2002 00:31:04 -0000 1.17 --- cvs_shell.py 15 Mar 2002 00:47:08 -0000 1.18 *************** *** 81,84 **** --- 81,85 ---- self.readConfigFile() self.listingFilter = utils.splitquoted(self.configMap.get('filter','')) + self.enableColor = self.configMap.get('colors', 'off') == 'on' Index: plugable_app.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/plugable_app.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** plugable_app.py 10 Mar 2002 23:13:59 -0000 1.5 --- plugable_app.py 15 Mar 2002 00:47:08 -0000 1.6 *************** *** 115,119 **** for x in l: self.cmdToCmds[x] = cmds ! --- 115,119 ---- for x in l: self.cmdToCmds[x] = cmds ! self.printVMsg("registered command %s" % cmdName) |
From: Stefan H. <ste...@us...> - 2002-03-15 00:47:10
|
Update of /cvsroot/cvsshell/cvsshell/etc In directory usw-pr-cvs1:/tmp/cvs-serv29355/etc Modified Files: cvsshell.ini default-cvsshellrc Log Message: * improved color support (it's configurable to switch on/off) * made full command working Index: cvsshell.ini =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/etc/cvsshell.ini,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** cvsshell.ini 10 Mar 2002 23:13:59 -0000 1.4 --- cvsshell.ini 15 Mar 2002 00:47:07 -0000 1.5 *************** *** 15,18 **** --- 15,19 ---- st, stat, status = cvs_cmds.status auto = cvs_cmds.toggleCvsRootAutoUpdate + full = basic_cmds.toggleFullStatusLine end Index: default-cvsshellrc =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/etc/default-cvsshellrc,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** default-cvsshellrc 11 Mar 2002 12:02:13 -0000 1.5 --- default-cvsshellrc 15 Mar 2002 00:47:08 -0000 1.6 *************** *** 10,13 **** --- 10,16 ---- # from the listing as produced by update, refresh or status filter = *.pyc *~ + + # Switch colors on or off + colors = off end |
From: Stefan H. <ste...@us...> - 2002-03-15 00:33:01
|
Update of /cvsroot/cvsshell/cvsshell/src/etc In directory usw-pr-cvs1:/tmp/cvs-serv25778/etc Modified Files: cvsshell.ini Log Message: added command full to toggle between full and abbreviated status line Index: cvsshell.ini =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/etc/cvsshell.ini,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** cvsshell.ini 7 Mar 2002 00:03:24 -0000 1.1.1.1 --- cvsshell.ini 15 Mar 2002 00:32:58 -0000 1.2 *************** *** 15,18 **** --- 15,19 ---- st, stat, status = basic_cmds.status auto = basic_cmds.toggleCvsRootAutoUpdate + full = basic_cmds.toggleFullStatusLine end |
From: Stefan H. <ste...@us...> - 2002-03-15 00:31:39
|
Update of /cvsroot/cvsshell/cvsshell/src In directory usw-pr-cvs1:/tmp/cvs-serv25276 Modified Files: basic_cmds.py cvs_cmds.py Log Message: added documentation Index: basic_cmds.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/basic_cmds.py,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** basic_cmds.py 10 Mar 2002 23:13:59 -0000 1.14 --- basic_cmds.py 15 Mar 2002 00:31:36 -0000 1.15 *************** *** 27,31 **** def cmdHelp(app, name, opts): ! """Prints this help message. If the name of a command is given as a option, a detailed help for this command is printed.""" --- 27,31 ---- def cmdHelp(app, name, opts): ! """Print this help message. If the name of a command is given as a option, a detailed help for this command is printed.""" *************** *** 61,70 **** def exitProgram(app, name, opts): ! "Terminates the program." return app.BREAK_REPL def changeDir(app, name, opts): ! "Changes the current working directory." if len(opts) == 0: opts = app.HOME --- 61,70 ---- def exitProgram(app, name, opts): ! "Terminate the program." return app.BREAK_REPL def changeDir(app, name, opts): ! "Change the current working directory." if len(opts) == 0: opts = app.HOME Index: cvs_cmds.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/cvs_cmds.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** cvs_cmds.py 14 Mar 2002 18:45:46 -0000 1.3 --- cvs_cmds.py 15 Mar 2002 00:31:36 -0000 1.4 *************** *** 30,33 **** --- 30,37 ---- def status(app, name, args): + """Display status information on checked out files. + This command creates a listing with all checked out files and + their status. The listing can be filtered by setting the variable + `filter' in the CONFIG section of ~/.cvsshellrc.""" entries = [] regexHead = re.compile(r'File: (?P<name>\S+)\s+Status: (?P<status>.+)') *************** *** 72,75 **** --- 76,84 ---- def update(app, args, name, simulate=0): + """Bring work tree in sync with repository. + This command donwloads new files and changes to already + checked out files from the server. It also brings the + listing in sync with the repository. The listing can be filtered by setting the variable + `filter' in the CONFIG section of ~/.cvsshellrc.""" try: (globOpts, opts, *************** *** 98,105 **** --- 107,125 ---- def simulateUpdate(app, name, args): + """Refresh the current listing by simulating an update. + This command runs update without really downloading the + changes. See help on update for details.""" update(app, name, args, simulate=1) def checkout(app, name, args): + """Checkout sources for editing. + This command checks out sources from the repository into the + current working directory. It takes two arguments: + * the cvsroot to use. This option is ignored and must not be given + if the cvsroot is already set. + * the module to checkout. + You can invoke the command without any arguments, as it prompts + you for if needed.""" try: (globOpts, opts, *************** *** 137,140 **** --- 157,175 ---- def add(app, name, args, isBinary=0): + """Add a new file/directory to the repository. + This command accepts two kind of arguments which cannot be intermixed: + * list of files/directories to add. + * some ids from the current listing (these are the numbers on the + left side of the listing). + The id-argument must have the following format: #, #, #, ... , # + - where # is either !% or % + - where % is either a digit or a range of digits + (written k-n if k,n are digits) + All numbers given with % are added to the list of ids, + all numbers given with !% are removed from this list. + The id-argument is evaluated from left to right. + Example: + 3, 4, 7-10, !8, 12-19, !13-18 + selects the files with the ids 3, 4, 7, 9, 10, 12, 19""" try: (globOpts, opts, *************** *** 191,194 **** --- 226,231 ---- def addBinary(app, name, args): + """Add a new binary file to the repository. + """ app.printMsg('The file will be added in binary mode.') add(app, name, args, isBinary=1) *************** *** 196,199 **** --- 233,238 ---- def commit(app, name, args): + """Check files into the repository. + """ try: (globOpts, opts, *************** *** 239,242 **** --- 278,283 ---- def remove(app, name, args): + """Remove an entry (some entries) from the repository. + """ try: (globOpts, opts, *************** *** 302,310 **** def printListing(app, name, args): app.printListing() def setCvsRoot(app, name, args): ! "Sets the cvsroot variable manually." roots = app.getCvsRootAliases() if len(args) != 0: --- 343,353 ---- def printListing(app, name, args): + """Print out the current listing. + """ app.printListing() def setCvsRoot(app, name, args): ! "Set the cvsroot variable manually." roots = app.getCvsRootAliases() if len(args) != 0: *************** *** 332,336 **** def readCvsRoot(app, name, args): ! "Reads the cvsroot variable from CVS/Root." newRoot = app.readCvsRootFromFile() if newRoot == None: --- 375,379 ---- def readCvsRoot(app, name, args): ! """Read the cvsroot variable from the file CVS/Root.""" newRoot = app.readCvsRootFromFile() if newRoot == None: *************** *** 341,350 **** def clearCvsRoot(app, name, args): ! "Unsets the cvsroot variable." app.setCvsRoot(None) def toggleCvsRootAutoUpdate(app, name, args): ! """Toggles the auto-update feature for the CVSROOT var. If this option is set, the CVSROOT variable is automatically updated when a new directory is entered. Without a argument the option is toggled. You can set the --- 384,393 ---- def clearCvsRoot(app, name, args): ! "Unset the cvsroot variable." app.setCvsRoot(None) def toggleCvsRootAutoUpdate(app, name, args): ! """Toggle the auto-update feature for the CVSROOT var. If this option is set, the CVSROOT variable is automatically updated when a new directory is entered. Without a argument the option is toggled. You can set the *************** *** 357,359 **** --- 400,403 ---- def toggleFullPrompt(app, name, args): + """Toggle between full and abbreviated status line.""" app.showFullPrompt = app.toggle(app.showFullPrompt, args) |
From: Stefan H. <ste...@us...> - 2002-03-15 00:31:06
|
Update of /cvsroot/cvsshell/cvsshell/src In directory usw-pr-cvs1:/tmp/cvs-serv25116 Modified Files: app.py cvs_shell.py Log Message: added basic color support Index: app.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/app.py,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** app.py 11 Mar 2002 10:09:50 -0000 1.8 --- app.py 15 Mar 2002 00:31:04 -0000 1.9 *************** *** 20,24 **** ############################################################################### ! import sys, os, traceback, getopt from oo_tools import GetSetProvider --- 20,24 ---- ############################################################################### ! import sys, os, traceback, getopt, types from oo_tools import GetSetProvider *************** *** 47,50 **** --- 47,51 ---- self.copyright = None self.bugAddress = None + self.enableColor = 1 try: self.path = os.environ['PATH'].split(os.pathsep) *************** *** 170,174 **** sys.stderr.write(str(text)) if not nonl: sys.stderr.write('\n') ! def exit(self, message='', status=1): if message: --- 171,210 ---- sys.stderr.write(str(text)) if not nonl: sys.stderr.write('\n') ! ! colDict = { ! "black" : "30m", ! "red" : "31m", ! "green" : "32m", ! "brown" : "33m", ! "blue" : "34m", ! "purple" : "35m", ! "cyan" : "36m", ! "lgray" : "37m", ! "gray" : "1;30m", ! "lred" : "1;31m", ! "lgreen" : "1;32m", ! "yellow" : "1;33m", ! "lblue" : "1;34m", ! "pink" : "1;35m", ! "lcyan" : "1;36m", ! "white" : "1;37m", ! } ! def col(self, color, text): ! """Return colorized text; color can either be a string indicating a color ! or a tuple containing two strings - for color and background. ! Copyright (C) 2001 Andrei Kulakov <ak...@si...> GPL""" ! if not self.enableColor: return text ! bg = "0m" ! if type(color) is types.StringType: ! fg = App.colDict[color] ! else: ! f, b = color ! fg = App.colDict[f] ! bg = App.colDict[b] ! s = "\033[" ! clear = "0m" ! return "%s%s%s%s%s%s%s" % (s, bg, s, fg, text, s, clear) ! ! def exit(self, message='', status=1): if message: Index: cvs_shell.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/cvs_shell.py,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** cvs_shell.py 14 Mar 2002 19:06:44 -0000 1.16 --- cvs_shell.py 15 Mar 2002 00:31:04 -0000 1.17 *************** *** 118,124 **** if ld > w: dir = '...' + dir[-w:] ld = len(dir) ! return "{%s} %s [%s]\n$ " % (status, ! dir, ! root) --- 118,124 ---- if ld > w: dir = '...' + dir[-w:] ld = len(dir) ! return self.col('cyan', "{%s} %s [%s]" % (status, ! dir, ! root)) + '\n$ ' |
From: Stefan H. <ste...@us...> - 2002-03-14 19:06:48
|
Update of /cvsroot/cvsshell/cvsshell/src In directory usw-pr-cvs1:/tmp/cvs-serv22746/src Modified Files: cvs_shell.py Log Message: changed prefix for dirs in listing. Index: cvs_shell.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/cvs_shell.py,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** cvs_shell.py 14 Mar 2002 18:45:46 -0000 1.15 --- cvs_shell.py 14 Mar 2002 19:06:44 -0000 1.16 *************** *** 373,377 **** lines.append("%s:\n" % newDir) if os.path.isdir(os.path.join(self.rootDir, e.dir, e.name)): ! isDir = "<dir>" else: isDir = '' --- 373,377 ---- lines.append("%s:\n" % newDir) if os.path.isdir(os.path.join(self.rootDir, e.dir, e.name)): ! isDir = "<dir> " else: isDir = '' |