[Cvsshell-devel] CVS: cvsshell/src app.py,1.12,1.13 basic_cmds.py,1.18,1.19 configurable_app.py,1.7,
Status: Beta
Brought to you by:
stefanheimann
From: Stefan H. <ste...@us...> - 2002-05-27 07:32:32
|
Update of /cvsroot/cvsshell/cvsshell/src In directory usw-pr-cvs1:/tmp/cvs-serv20797/src Modified Files: app.py basic_cmds.py configurable_app.py cvs_cmds.py cvs_shell.py utils.py Log Message: see ChangeLog Index: app.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/app.py,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** app.py 16 Mar 2002 13:26:37 -0000 1.12 --- app.py 27 May 2002 07:32:29 -0000 1.13 *************** *** 221,233 **** 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): --- 221,236 ---- if self.isVerbose(): self.printMsg(command) # how about ipc? ! if fork == 1: ! pipe = os.popen(command, 'r') ! res = pipe.read() ! else: pipe = os.popen(command, 'w') pipe.write(inp) # send it input ! res = None ! exitCode = pipe.close() ! if exitCode is not None: ! raise ShellException(exitCode) ! return res ! def main(self): *************** *** 273,274 **** --- 276,283 ---- raise AppError, 'run must be redefined!' + + class ShellException(GetSetProvider): + + def __init__(self, exitCode): + GetSetProvider.__init__(self) + self.exitCode = exitCode Index: basic_cmds.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/basic_cmds.py,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** basic_cmds.py 15 Mar 2002 18:58:00 -0000 1.18 --- basic_cmds.py 27 May 2002 07:32:29 -0000 1.19 *************** *** 98,99 **** --- 98,105 ---- + def setAutoRefresh(app, name, args): + """Enable or disable automatic refresh of the local listing. + If this option is set to `on', the local listing is refreshed + after a command changed some information on the CVS server but not + in the local listing.""" + app.autoRefresh = app.toggle(app.autoRefresh, args) Index: configurable_app.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/configurable_app.py,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** configurable_app.py 15 Mar 2002 09:43:51 -0000 1.7 --- configurable_app.py 27 May 2002 07:32:29 -0000 1.8 *************** *** 49,53 **** 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) --- 49,53 ---- 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) *************** *** 60,66 **** import shutil shutil.copyfile(default,filename) - else: - f = open(self.configFile, 'w') - f.close() --- 60,63 ---- Index: cvs_cmds.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/cvs_cmds.py,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** cvs_cmds.py 15 Mar 2002 20:16:01 -0000 1.7 --- cvs_cmds.py 27 May 2002 07:32:29 -0000 1.8 *************** *** 61,65 **** if headRes and dir is None: raise InternalCvsError, "Parsing of status message failed: " \ ! "`dir' is not set when get file information." elif headRes: name = headRes.group('name') --- 61,65 ---- if headRes and dir is None: raise InternalCvsError, "Parsing of status message failed: " \ ! "`dir' is not set when getting file information." elif headRes: name = headRes.group('name') *************** *** 246,259 **** return if not rest: # commit without an argument ! try: ! if not app.getListing(): ! rootDir = '' ! else: ! rootDir = app.getListing().getRootDir() ! app.runCvsCmd('commit', rootDir=rootDir, ! globOpts=globOpts, args=opts, fork=0) ! app.setDirtyListing(1) ! except CvsError: pass ! return def __doIt(e,filename): if e.status == Entry.S_REMOVED: --- 246,268 ---- return if not rest: # commit without an argument ! answ = app.prompt("No files given. This will commit the whole directory\n" \ ! "tree starting from here. Answer `yes' if you want to do\n" ! "so, `no' to abort the operation or specify some files\n" ! "to operate on. ") ! if answ == 'no': ! return ! elif answ == 'yes': ! try: ! if not app.getListing(): ! rootDir = '' ! else: ! rootDir = app.getListing().getRootDir() ! app.runCvsCmd('commit', rootDir=rootDir, ! globOpts=globOpts, args=opts, fork=0) ! app.setDirtyListing(1) ! except CvsError: pass ! return ! else: ! rest = answ def __doIt(e,filename): if e.status == Entry.S_REMOVED: *************** *** 312,320 **** app.printMsg("Refusing the delete a directory: %s" % name) continue ! try: ! os.unlink(name) ! except OSError, msg: ! app.printErr(msg) ! # Hope that the file already has been removed filenames.append(os.path.join(e.dir, e.name)) e.status = Entry.S_REMOVED --- 321,330 ---- app.printMsg("Refusing the delete a directory: %s" % name) continue ! if os.access(name, os.F_OK): ! try: ! os.unlink(name) ! except OSError, msg: ! app.printErr(msg) ! continue filenames.append(os.path.join(e.dir, e.name)) e.status = Entry.S_REMOVED *************** *** 325,333 **** app.printMsg("Refusing the delete a directory: %s" % name) continue ! try: ! os.unlink(name) ! except OSError, msg: ! app.printErr(msg) ! # Hope that the file already has been removed filenames.append(name) except AppError, msg: --- 335,344 ---- app.printMsg("Refusing the delete a directory: %s" % name) continue ! if os.access(name, os.F_OK): ! try: ! os.unlink(name) ! except OSError, msg: ! app.printErr(msg) ! continue filenames.append(name) except AppError, msg: *************** *** 351,354 **** --- 362,448 ---- fork=0, args=args) except CvsError: pass + + + def rename(app, name, args): + """Renames a file in the repository. + You must specify the file to rename (the `source file') and the new name of + the file (the `target file'). The source file can be a filename or an id in + the listing. The filename of the target file may include the special variable + $OLD_DIR. This variable is replaced by the directory the source file resides + in. + You can invoke the command without any arguments as it prompts + you if needed.""" + specialVar = '$OLD_DIR' + srcText = 'enter filenumber/filename to rename: ' + dstText = 'enter new filename: ' + try: + (globOpts, opts, + myOpts, rest) = app.parseArgs(args, + app.getCmdToAllowedOpts().get(name, '')) + except getopt.GetoptError, msg: + app.printErr(msg) + return + l = rest.split() + if len(l) == 0: + src = app.prompt(srcText) + if not src: return + dst = app.prompt(dstText) + elif len(l) == 1: + src = l[0] + dst = app.prompt(dstText) + elif len(l) != 2: + print 'Illegal arguments.' + return + else: + src = l[0] + dst = l[1] + if not dst: return + # + rootDir = '.' + listing = None + entry = None + try: + srcNum = int(src) + listing = app.getListing() + if listing is None: + app.printErr('Cannot resolve ID: no listing available.') + return + rootDir = listing.getRootDir() + entries = listing.getEntries() + if srcNum < 0 or srcNum >= len(entries): + app.printErrMsg('Illegal ID') + return + entry = entries[srcNum] + src = entry.getFullPath(listing) + oldDir = os.path.join(listing.getRootDir(), entry.getDir()) or '.' + dst = dst.replace(specialVar, oldDir) + except ValueError: + dst = dst.replace(specialVar, os.path.dirname(src) or '.') + app.printMsg('Rename: ' + src + ' => ' + dst) + answ = app.prompt('Are you sure (yes|no)? ') + if answ != 'yes': return + try: + os.renames(src, dst) + except OSError, msg: + app.printErr(msg) + return + try: + app.runCvsCmd('add', rootDir=rootDir, + fork=0, args=dst) + except CvsError: return + try: + app.runCvsCmd('remove', rootDir=rootDir, + fork=0, args=src) + except CvsError: return + answ = app.prompt("\nThe files have been scheduled for removal/addition.\n" \ + "Should I run `commit' to remove/add the files " \ + "permanently (yes|no)? ") + if answ == 'yes': + try: + args = dst + ' ' + src + app.runCvsCmd('commit', rootDir=rootDir, + fork=0, args=args) + if entry is not None: entry.status = Entry.S_DELETED + except CvsError: pass Index: cvs_shell.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/cvs_shell.py,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** cvs_shell.py 15 Mar 2002 19:46:08 -0000 1.23 --- cvs_shell.py 27 May 2002 07:32:29 -0000 1.24 *************** *** 1,2 **** --- 1,4 ---- + #!/usr/bin/env python2.1 + ############################################################################### # This file is part of CvsShell *************** *** 22,30 **** 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' \ --- 24,32 ---- import os, sys, re, string, types, getopt, fnmatch, utils from oo_tools import GetSetProvider ! from app import AppError, ShellException from interactive_app import InteractiveApp from plugable_app import PlugableApp ! VERSION = '0.2' NAME ='CvsShell' COPYRIGHT = 'Copyright 2002 Stefan Heimann (ma...@st...).\n' \ *************** *** 73,76 **** --- 75,79 ---- self.listing = None self.dirtyListing = 1 + self.autoRefresh = 0 self.cvsRootAliases = {} self.configMap = {} *************** *** 94,100 **** --- 97,109 ---- def getPrompt(self): + if self.autoRefresh and self.dirtyListing and self.cvsRoot: + self.printMsg('getting listing from ' + self.cvsRoot) + self.evalCommand('refresh') + self.dirtyListing = 0 status = '' if self.cvsRootAutoUpdate: status += 'a' else: status += 'A' + if self.autoRefresh: status += 'r' + else: status += 'R' root = self.getCvsRoot() or '--' try: *************** *** 127,130 **** --- 136,161 ---- def evalCommand(self, cmd): + if len(cmd) > 0 and cmd[0] == '!': + try: + self.shell(cmd[1:]) + except ShellException: pass + return + try: + notEnclosed, enclosed = utils.split(cmd, '`') + except utils.SplitException, msg: + self.printErr(msg) + return + i = 0 + l = [] + for x in notEnclosed: + if x is not None: + l.append(x) + else: + c = enclosed[i] + i += 1 + try: + l.append(self.shell(c, fork=1)) + except ShellException: return + cmd = string.join(l) result = self.cmdRegex.match(cmd) if result is None: *************** *** 170,174 **** except utilsParseError: pass except AppError, msg: pass ! self.shell('%s %s' % (name, args)) --- 201,207 ---- except utilsParseError: pass except AppError, msg: pass ! try: ! self.shell('%s %s' % (name, args)) ! except ShellException: return *************** *** 443,446 **** --- 476,483 ---- return Entry.statusToColorKey.get(self.status, None) + def getFullPath(self, listing): + return os.path.join(listing.getRootDir(), self.dir, self.name) + + def main(): app = CvsShell() Index: utils.py =================================================================== RCS file: /cvsroot/cvsshell/cvsshell/src/utils.py,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** utils.py 11 Mar 2002 12:02:14 -0000 1.9 --- utils.py 27 May 2002 07:32:29 -0000 1.10 *************** *** 83,88 **** res.append(x) # not only whitespace return res - ############################## --- 83,137 ---- res.append(x) # not only whitespace return res + + SplitException = 'SplitException' + + def split(str, delim): + """Splits str on occurences of delim. Returns a tupel with 2 elements: + 1: list that contains the parts of the string after splitting that + are not enclosed by delim. None marks a place where a substring + enclosed by delim would occur + 2: list that contains the substring that are enclosed by delim + (without the leading and trailing delim). + delim can be escaped with a backslash. The backslashes used for escaping + are removed from the result. + Example: split('\`foo\` `bar \`foo\``', '`', 1) ==> + (['`foo` ', None], ['bar `foo`']) + """ + notEnclosed = [] + enclosed = [] + current = '' + index = 0 + inside = 0 + n = len(str) + while index < n: + c = str[index] + index += 1 + if c == delim: + if inside: + enclosed.append(current) + notEnclosed.append(None) + else: + notEnclosed.append(current) + inside = not inside + current = '' + elif c == '\\': + c = str[index] + index += 1 + if c == delim: + current += delim + else: + current += '\\' + current += c + else: + current += c + if inside: + raise SplitException, "Unmatched '" + delim + "'" + elif current: + notEnclosed.append(current) + return (notEnclosed, enclosed) + + + ############################## *************** *** 93,97 **** import unittest ! class GetNumbersTestCase(unittest.TestCase): def setUp(self): pass --- 142,146 ---- import unittest ! class ParseNumberStrTestCase(unittest.TestCase): def setUp(self): pass *************** *** 99,118 **** pass def testEmpty(self): ! self.assertEqual(getNumbers(' '),[]) ! self.assertEqual(getNumbers(', ,,, '),[]) def testSimple(self): ! self.assertEqual(getNumbers(' 4 '),[4]) ! self.assertEqual(getNumbers('1 , 2,3 '),[1,2,3]) def testRanges(self): ! self.assertEqual(getNumbers('1 -4, 6 -8 , 10 , 12 - 13 '), [1,2,3,4,6,7,8,10,12,13]) def testNeg(self): ! self.assertEqual(getNumbers(' ! 2 '),[]) ! self.assertEqual(getNumbers(' !2, 2'),[2]) ! self.assertEqual(getNumbers('2, !2 '),[]) ! self.assertEqual(getNumbers('1-10, ! 5-7'), [1,2,3,4,8,9,10]) ! self.assertEqual(getNumbers('1-3, !2'), [1,3]) ! self.assertEqual(getNumbers('1-2, !2'), [1]) unittest.main() --- 148,186 ---- pass def testEmpty(self): ! self.assertEqual(parseNumberStr(' '),[]) ! self.assertEqual(parseNumberStr(', ,,, '),[]) def testSimple(self): ! self.assertEqual(parseNumberStr(' 4 '),[4]) ! self.assertEqual(parseNumberStr('1 , 2,3 '),[1,2,3]) def testRanges(self): ! self.assertEqual(parseNumberStr('1 -4, 6 -8 , 10 , 12 - 13 '), [1,2,3,4,6,7,8,10,12,13]) def testNeg(self): ! self.assertEqual(parseNumberStr(' ! 2 '),[]) ! self.assertEqual(parseNumberStr(' !2, 2'),[2]) ! self.assertEqual(parseNumberStr('2, !2 '),[]) ! self.assertEqual(parseNumberStr('1-10, ! 5-7'), [1,2,3,4,8,9,10]) ! self.assertEqual(parseNumberStr('1-3, !2'), [1,3]) ! self.assertEqual(parseNumberStr('1-2, !2'), [1]) + class SplitTestCase(unittest.TestCase): + def setUp(self): + pass + def tearDown(self): + pass + def testSimple(self): + self.assertEquals(split('hello world', "'"), (['hello world'],[])) + def testException(self): + try: + split('hallo "stefan ', '"') + self.fail('should raise a exception here.') + except SplitException: + pass + def testMe(self): + self.assertEqual(split('\`foo\` `bar \`foo\``', '`'), + (['`foo` ', None], ['bar `foo`'])) + def testMe2(self): + self.assertEqual(split('\`foo\` `bar \`foo\`` steven', '`'), + (['`foo` ', None, ' steven'], ['bar `foo`'])) unittest.main() |