## ## Copyright (c) 2006 Jason Dillon ## ## Licensed under the Apache License, Version 2.0 (the "License"); ## you may not use this file except in compliance with the License. ## You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, software ## distributed under the License is distributed on an "AS IS" BASIS, ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ## See the License for the specific language governing permissions and ## limitations under the License. ## ## ## $Id: //guest/jason_dillon/p4spam/main/pylib/perforce/commands/__init__.py#2 $ $Date: 2006/04/12 $ ## from perforce import logging import popen2, marshal log = logging.Logger("perforce.commands") def create(name, p4): assert name != None try: mod_name = "perforce.commands.%s" % name log.debug("Loading: %s" % mod_name) mod = __import__(mod_name, globals(), locals(), [ "create" ]) assert mod != None log.debug("Loaded: %s" % mod) except ImportError: raise Exception("Unconfigured command: %s" % name) factory = getattr(mod, "create") log.debug("Factory: %s" % factory) return factory(p4); ## ## ResultSupport ## class ResultSupport: def toString(this): raise "Abstract method" def __str__(this): return this.toString() def __repr__(this): return this.toString() ## ## CommandSupport ## class CommandSupport: def __init__(this, name, p4): this.log = logging.Logger(this) this.name = name this.p4 = p4 this.p4flags = "-G" def convertArguments(this, args): _args = [] for arg in args: _args.append(str(arg)) return _args def createCommandLine(this, args): cmdline = [] cmdline.append("p4") if this.p4flags != None and len(this.p4flags.strip()) != 0: cmdline.append(this.p4flags) cmdline.append(this.name) for arg in args: cmdline.append(str(arg)) this.log.debug("Using command-line: %s" % (cmdline)) return cmdline def processOutput(this, stream): raise "Abstract method" def execute(this, args): # HACK: Convert all args to strings args = this.convertArguments(args) # HACK: Flatten the list into a string cmdline = this.createCommandLine(args) this.log.debug("Executing: %s" % (cmdline)) proc = popen2.Popen3(cmdline) stream = proc.fromchild # # TODO: Try to detect a failure here before we get too far # result = this.processOutput(stream) this.log.debug("Result: %s" % result) return result ## ## SingleResultCommand ## class SingleResultCommand(CommandSupport): def createResult(this, entry): raise "Abstract method" def processOutput(this, stream): entry = marshal.load(stream) assert entry != None this.log.debug("Entry: %s" % entry) return this.createResult(entry) ## ## RawResultCommand ## class RawResultCommand(SingleResultCommand): def __init__(this, name, p4): SingleResultCommand.__init__(this, name, p4) this.p4flags = "" # Clear the -G flag def isValid(this, lines): return True def validate(this, lines): if not this.isValid(lines): raise Exception("Raw content does not look like output from `p4 %s`: %s" % (this.name, lines)) def processOutput(this, stream): trace = this.log.isTraceEnabled() lines = stream.readlines() if trace: for line in lines: this.log.trace(line.rstrip()) this.validate(lines) return lines ## ## StreamedResultCommand ## class StreamedResultCommand(CommandSupport): def createResult(this, entry): raise "Abstract method" def processOutput(this, stream): return StreamedResultIterator(stream, this) ## ## StreamedResultIterator ## class StreamedResultIterator: def __init__(this, stream, resultFactory): this.log = logging.Logger(this) this.stream = stream this.resultFactory = resultFactory def __iter__(this): return this def next(this): try: entry = marshal.load(this.stream) assert entry != None this.log.debug("Entry: %s" % entry) return this.resultFactory.createResult(entry) except EOFError: raise StopIteration