# p4.py -- Simple Python interface to Perforce, using p4 -G # Gareth Rees, Ravenbrook Limited, 2000-09-25. # $Id: //info.ravenbrook.com/project/p4dti/branch/2000-11-08/re-architecting/code/replicator/p4.py#1 $ # # Copyright 2000 Ravenbrook Limited. This document is provided "as is", # without any express or implied warranty. In no event will the authors # be held liable for any damages arising from the use of this document. # You may make and distribute copies and derivative works of this # document provided that (1) you do not charge a fee for this document or # for its distribution, and (2) you retain as they appear all copyright # and licence notices and document history entries, and (3) you append # descriptions of your modifications to the document history. import marshal import os import tempfile import win32pipe error = 'Perforce error' # p4.run(arguments, input, client_executable, port, user, password, client, # verbose). Run the p4 client with the given arguments. The arguments should # be a Perforce command and its arguments, like "jobs -o //foo/...". Options # should generally include -i and/or -o to avoid forms being put up # interactively. If input is supplied, then it should be a list of # dictionaries. If verbose is true, then the input, command and results will # be printed. These dictionaries are sent one by one to the process. The # results are read into a list and returned. Since the output of the process # is read to EOF and the input is closed, there should be no process left # hanging about. def run(arguments, input = None, client_executable = 'p4', port = '127.0.0.1:1666', user = None, password = None, client = None, verbose = 0): temp_filename = None command_words = [client_executable,'-G'] if port: command_words.append('-p "%s"' % port) if user: command_words.append('-u "%s"' % user) if password: command_words.append('-P "%s"' % password) if client: command_words.append('-c "%s"' % client) command_words.append(arguments) if input: tempfile.template = 'p4dti_data' temp_filename = tempfile.mktemp() temp_file = open(temp_filename, 'wb') marshal.dump(input[0], temp_file) temp_file.close() command_words.extend(['<', temp_filename]) if verbose: print "p4 input:", str(input) command = reduce((lambda x,y: x + ' ' + y), command_words) if verbose: print "p4 command:", command stream = win32pipe.popen(command, 'rb') results = [] try: while 1: results.append(marshal.load(stream)) except EOFError: if (temp_filename): os.remove(temp_filename) if verbose: print "p4 results:", str(results) # Note: this isn't a reliable way to spot an error in a Perforce # command. See job000003. if (len(results) == 1 and results[0].has_key('code') and results[0]['code'] == 'error'): raise error, results[0]['data'] else: return results