##
## 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: __init__.py 78 2009-08-25 12:21:04Z mindwanderer $
##
import os, sys, popen2, marshal
from p4spam import log, config
# Logger for the create() factory method
_log = log.getLogger("p4spam.perforce.commands")
def create(name, p4):
assert name != None
try:
mod_name = "p4spam.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 = log.getLogger(this)
this.name = name
this.p4 = p4
this.p4flags = "-G"
this.pipeMode = 'b'
def createCommandLine(this, args):
cmdline = []
for arg in config.P4_CMDLINE:
cmdline.append(str(arg))
if this.p4flags != None and len(this.p4flags.strip()) != 0:
cmdline.append(this.p4flags)
# Only append command name if this is not a special raw command
if this.name not in ("raw", "rawstream"):
cmdline.append(this.name)
for arg in args:
cmdline.append(str(arg))
# If this is not a posix system, then need to convert cmdline to a string
if os.name != 'posix':
buff = cmdline[0] # don't quote
for arg in cmdline[1:]:
buff = '%s "%s"' % (buff, str(arg))
cmdline = buff
this.log.debug("Converted cmdline sequence into string for non-posix os: %s" % cmdline)
return cmdline
def processOutput(this, stream):
raise "Abstract method"
def execute(this, args):
cmdline = this.createCommandLine(args)
this.log.debug("Executing: %s" % str(cmdline))
(fromchild, tochild, childerr) = popen2.popen3(cmdline, mode=this.pipeMode )
# Try and detect early failure if anything has been written to the childs stderr
#
# NOTE: This is less than ideal, as the errors might not have poped out yet
#
#errors = childerr.readlines()
#if len(errors):
# for line in errors:
# this.log.error(line)
#
# raise "Child process spat out some errors: %s" % str(errors)
result = this.processOutput(fromchild)
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
this.pipeMode = 't'
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):
lines = stream.readlines()
for line in lines:
this.log.debug(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 = log.getLogger(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
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #1 | 7731 | Matthew Janulewicz |
Adding P4Spam 1.1 code from http://p4spam.sourceforge.net/wiki/Main_Page "P4Spam is a Perforce change review daemon which spits out sexy HTML-styled notification emails." |