Contents

Class P4 < Object require "P4"

Description

Main interface to the Perforce client API. Each P4 object provides you with a thread-safe API level interface to Perforce. The basic model is to:
  1. Instantiate your P4 object
  2. Specify your Perforce client environment
  3. Set any options to control output or error handling
  4. Connect to the Perforce Server
  5. Run your Perforce commands
  6. Disconnect from the Perforce Server

Class Methods

P4.identify P4.new
identify P4.identify -> aString

Return the version of P4/Ruby you are using - for diagnostic purposes.
    ruby -rP4 -e 'puts( P4.identify )'
      
new P4.new -> aP4
Constructs a new P4 object.
    p4 = P4.new()
      

Instance Methods (sorted by type)

Get

charset? client? cwd? exception_level? host? password? port? user?

Set

api= charset= client= cwd= debug= exception_level= host= maxresults= maxscanrows= password= prog= port= user=

Specs

delete_<spec type> fetch_<spec type> save_<spec type>

tagged parse_forms

format_spec parse_spec

Execute

connect disconnect

input output

run run_filelog run_password run_resolve at_exception_level

errors warnings

Instance Methods

at_exception_level p4.at_exception_level( lev ) { ... } -> self
Executes the associated block under a specific exception level. Returns to the previous exception level when the block returns.
    p4 = P4.new
    p4.client = "www"
    p4.connect
    p4.at_exception_level( P4::RAISE_ERRORS ) do
      p4.run_sync
    end
    p4.disconnect
      
api= p4.api=integer -> self

Sets the API compatibility level desired. This is useful when writing scripts using Perforce commands that do not yet support tagged output. In these cases, upgrading to a later server that supports tagged output for the commands in question can break your script. Using this method allows you to lock your script to the output format of an older Perforce release and facilitate seamless upgrades. Note that this method must be called prior to calling P4#connect.

See the Perforce C/C++ API Release Notes for the API integer levels that correspond to each Perforce release.

    p4 = P4.new
    p4.api = 57 # Lock to 2005.1 format
    p4.connect
    ...
      
charset= p4.charset = aString -> aBool
Sets the character set to use when connected to a Unicode enabled server. Should not be used when working with non-Unicode-enabled servers. Returns true if the charset was valid and returns false or raises a P4Exception (at exception level P4::RAISE_ERRORS or higher) if the charset is invalid. [Note: some versions of Ruby seem not to honour the boolean return value and return the charset string instead. This appears to be a bug in Ruby]
    p4 = P4.new
    p4.client = "www"
    p4.charset = "iso8859-1"
    p4.connect
    p4.run_sync
    p4.disconnect
      
charset? p4.charset? -> aString
Get the name of the character set in use when working with Unicode-enabled servers.
    p4 = P4.new
    p4.charset = "utf8"
    p4.charset?
      
client= p4.client = aString -> true
Set the name of the clientspec you wish to use. If not called, defaults to the value of P4CLIENT taken from any P4CONFIG file present, or from the environment as per the usual Perforce convention. Must be called before you connect.
    p4 = P4.new
    p4.client = "www"
    p4.connect
    p4.run_sync
    p4.disconnect
      
client? p4.client? -> aString
Get the name of the Perforce client currently in use
    p4 = P4.new
    puts( p4.client? )
      
connect p4.connect -> aBool
Connect to the Perforce Server. You must connect before you can execute commands. Raises a P4Exception if the connection attempt fails.
    p4 = P4.new
    p4.connect
      
cwd= p4.cwd = aString -> true
Sets the current working directory. Can be called prior to executing any Perforce command. Sometimes necessary if your script executes a chdir() as part of its processing.
    p4 = P4.new
    p4.cwd = "/home/tony"
      
cwd? p4.cwd? -> aString
Get the current working directory
    p4 = P4.new
    puts( p4.cwd? )
      
debug= p4.debug = aNumber -> true
Set debug level. Debug output is written to $stderr. Debug levels are:
0: No debug output (default)
1: Log connect/disconnect and command execution
2: Log user interface function callbacks
3: Log data
4: Log Ruby garbage collection
Note that levels are cumulative so level 3 includes levels 2 and 1.
    p4 = P4.new
    p4.debug = 1
    p4.connect
    p4.run_sync
    p4.disconnect
      
delete_<spec type> p4.delete_<spec type>( [options], name ) -> anArray
The delete_* methods are simply shortcut methods that allow you to quickly delete the definitions of clients, labels, branches, etc. They're equivalent to p4.run( <spec type>, '-d', [options], <spec name> ).shift
    require "P4"
    require "parsedate"
    include ParseDate
    now = Time.now
    p4 = P4.new
    begin
      p4.connect
      p4.run_clients.each do
        |client|
	atime = parsedate( client[ "AccessDate" ] )
	if( (atime + 24 * 3600 * 365 ) < now ) 
	  p4.delete_client( '-f', client[ "Client" ] )
	end
      end
    rescue P4Exception 
      p4.errors.each { |e| puts( e ) }
    ensure
      p4.disconnect
    end
      
disconnect p4.disconnect -> true
Disconnect from the Perforce Server.
    p4 = P4.new
    p4.connect
    p4.disconnect
      
errors p4.errors -> anArray
Returns the array of errors which occurred during execution of the previous command.
    p4 = P4.new
    begin
      p4.connect
      p4.exception_level( P4::RAISE_ERRORS ) # to ignore "File(s) up-to-date"
      p4.run_sync
    rescue P4Exception 
      p4.errors.each { |e| puts( e ) }
    ensure
      files = p4.output
      p4.disconnect
    end
      
exception_level= p4.exception_level = aLevel -> aNumber
Configures the events which give rise to exceptions.
  • P4::RAISE_NONE -- disables all exception raising and makes the interface completely procedural.
  • P4::RAISE_ERRORS -- causes exceptions to be raised only when errors are encountered.
  • P4::RAISE_ALL -- causes exceptions to be raised for both errors and warnings. This is the default.
    p4 = P4.new
    p4.exception_level = P4::RAISE_ERRORS

    p4.connect			# P4Exception on failure
    p4.run_sync			# File(s) up-to-date is a warning so
    				# no exception is raised
    p4.disconnect
      
exception_level? p4.exception_level? -> aNumber
Returns the current exception level.
fetch_<spec type> p4.fetch_<spec type>( [name] ) -> aHash
The fetch_* methods are simply shortcut methods that allow you to quickly fetch the definitions of clients, labels, branches, etc. They're equivalent to p4.run( <spec type>, '-o', ... ).shift
    p4 = P4.new
    begin
      p4.connect
      client       = p4.fetch_client()
      other_client = p4.fetch_client( "other" )
      label        = p4.fetch_label( "somelabel" )
    rescue P4Exception 
      p4.errors.each { |e| puts( e ) }
    ensure
      p4.disconnect
    end
      
format_spec p4.format_spec( <spec type>, aHash )-> aString
Converts the fields in a hash containing the elements of a Perforce form (spec) into the familiar string reprepresentation that users know and love.

Requires parse_forms() mode.

The first argument is the type of spec to format: 'client', 'branch', 'label' etc. The second is the hash to parse.

Note that there are shortcuts available for this method.

    p4.format_<spec type>( hash )
      
instead of
    p4.format_spec( <spec type>, hash )
      
Where <spec type> is 'client'/'branch'/'label' etc. etc.
host= p4.host = aString -> true
Set the name of the current host. If not called, defaults to P4HOST taken from any P4CONFIG file in effect, then P4HOST in the environment and finally the operating system host name.
    p4 = P4.new
    p4.host = "perforce.smee.org"
    p4.connect
    ...
    p4.disconnect
      
host? p4.host? -> aString
Get the current hostname
    p4 = P4.new
    puts( p4.host? )
      
input p4.input( aString ) -> true or false
p4.input( aHash ) -> true or false
p4.input( anArray ) -> true or false
Call prior to running a command requiring input from the user. When the command requests input, it's the data supplied here that will be returned. This applies most commonly to commands of the form "p4 cmd -i". Note that typically commands of that form are invoked using the P4#save_* methods which call P4#input() internally. So there is no need to call this method when using the save_* shortcuts.

You may pass a string, a hash or (for commands that take multiple inputs from the user) an array of strings/hashes. You may only pass hashes when working in parse_forms mode. If you pass an array, note that the array will be 'shifted' each time Perforce asks the user for input.
    p4 = P4.new
    p4.parse_forms
    p4.connect

    change = p4.run_change( "-o" ).shift
    change[ "Description" ] = "Autosubmitted changelist"

    p4.input( change )
    p4.run_submit( "-i" )

    p4.disconnect
      
Note that P4#input cannot predict whether or not the supplied input will be acceptable to the next command the user runs so it always returns true - regardless of the validity of the input.
maxresults= p4.maxresults = aNumber -> aNumber
Limit the number of results Perforce will permit for subsequent commands. Commands that produce more than this number of results will be aborted. The limit remains in force until you disable it by setting it to zero. See p4 help maxresults for information on the commands that support this limit.
    p4 = P4.new
    begin
      p4.connect
      p4.maxresults = 100
      files = p4.run_sync
    rescue P4Exception => ex
      p4.errors.each { |e| $stderr.puts( e ) }
    ensure
      p4.disconnect
    end
      
maxscanrows= p4.maxscanrows = aNumber -> aNumber
Limit the number of database records Perforce will scan for subsequent commands. Commands that attempt to scan more than this number of records will be aborted. The limit remains in force until you disable it by setting it to zero. See p4 help maxresults for information on the commands that support this limit.
    p4 = P4.new
    begin
      p4.connect
      p4.maxscanrows = 100
      files = p4.run_sync
    rescue P4Exception => ex
      p4.errors.each { |e| $stderr.puts( e ) }
    ensure
      p4.disconnect
    end
      
output p4.output -> anArray
Get the results of the previous command. Returns an array containing the output of the command. Useful in a rescue block when a command has partially worked, and you still need to look at the command output.
    p4 = P4.new
    begin
      p4.connect
      p4.exception_level( P4::RAISE_ERRORS ) # to ignore "File(s) up-to-date"
      files = p4.run_sync
    rescue P4Exception => ex
      files = p4.output
      if files.length
	puts( "Sync succeeded with errors" )
      else
        puts( "Sync failed!" )
      end
    ensure
      p4.disconnect
    end
      
parse_forms p4.parse_forms -> true
Extends the capabilities of tagged output to include Perforce forms. Forms returned by Perforce in response to commands such as "p4 client -o" will be parsed and returned to the caller as a Ruby hash containing keys for each of the fields on the form. Where a form element may contain more than one value, the hash value is an array containing the form elements. parse_forms implies the use of tagged.
    p4 = P4.new
    p4.parse_forms
    p4.connect
    clientspec = p4.run_client( "-o" ).shift
    puts( clientspec[ "Options" ] )
    p4.disconnect
      
Such parsed forms are also acceptable as input to commands of the form "p4 XXXX -i". For example, to change the root of a clientspec you could use:
    p4 = P4.new
    p4.parse_forms
    p4.connect
    spec = p4.run_client( "-o" ).shift
    spec[ "Root" ] = "/home/my/new/root" 
    p4.input( spec )
    p4.run_client( "-i" )
    p4.disconnect
      
parse_spec p4.parse_spec( <spec type>, aString )-> aHash
Parses a Perforce form (spec) in text form into a Ruby hash using the spec definition obtained from the server. Requires parse_forms() mode.

The first argument is the type of spec to parse: "client", "branch", "label" etc. The second is the raw buffer to parse.

Note that there are shortcuts available for this method.

    p4.parse_<spec type>( buf )
      
instead of
    p4.parse_spec( <spec type>, buf )
      
Where <spec type> is 'client'/'branch'/'label' etc. etc.
password= p4.password = aString -> true
Set your Perforce password, in plain text. If not used, takes the value of P4PASSWD from any P4CONFIG file in effect, or from the environment according to the normal Perforce conventions. This password will also be used if you later call p4.run_login to login using the 2003.2 and later ticket system.
    p4 = P4.new
    p4.password = "mypass"
    p4.connect
    p4.run_login
      
password? p4.password? -> aString
Get the current password. This may be the password in plain text, or if you've used p4.run_login, it'll be the value of the ticket you've been allocated by the server.
    p4 = P4.new
    puts( p4.password? )
      
prog= p4.prog = aString -> true
Set the name of your 'program'. This value is visible to Perforce system administrators running 'p4 monitor show -e' in Perforce 2004.2 or later releases.
    p4 = P4.new
    p4.prog = "sync-script"
    p4.connect
    ...
    p4.disconnect
      
port= p4.port = aString -> true
Set the host and port address of the Perforce server you want to connect to. If not called, defaults to the value of P4PORT in any P4CONFIG file in effect and then to the value of P4PORT taken from the environment.
    p4 = P4.new
    p4.port = "localhost:1666"
    p4.connect
    ...
    p4.disconnect
      
port? p4.port? -> aString
Get the address of the current Perforce server.
    p4 = P4.new
    puts( p4.port? )
      
run p4.run( aCommand, arguments... ) -> anArray
Base interface to all the run methods in this API. Runs the specified Perforce command with the arguments supplied. Arguments may be in any form you like as long as it responds nicely to to_s.

If the command succeeds without errors or warnings, then run returns an array of results. Whether the elements of the array are strings or hashes depends on (a) the command executed and (b) whether tagged() or parse_forms() have been called.

The array that is returned is equivalent to that returned by p4.output.

In the event of errors or warnings, and depending on the exception level in force at the time, run will raise a P4Exception. If the current exception level is below the threshold for the error/warning, then run returns the output as normal and the caller must explicitly review p4.errors and p4.warnings to check for errors or warnings.

    p4 = P4.new
    p4.connect
    spec = p4.run( "client", "-o" ).shift
    p4.disconnect
      
Through the magic of Object#method_missing, you can save yourself some typing as
    p4.run_XXX( args )
      
is translated into
    p4.run( "XXX", args )
      
There are also some shortcuts for common commands such as editing Perforce forms and submitting. So this:
    p4 = P4.new
    p4.parse_forms
    p4.connect
    clientspec = p4.run_client( "-o" ).shift
    clientspec[ "Description" ] = "Build client"
    p4.input( clientspec )
    p4.run_client( "-i" )
    p4.disconnect
      
May be shortened to
    p4 = P4.new
    p4.parse_forms
    p4.connect
    clientspec = p4.fetch_client
    clientspec[ "Description" ] = "Build client"
    p4.save_client( clientspec )
    p4.disconnect
      
In fact, the following are equivalent:

p4.delete_xxx p4.run_xxx( "-d ").shift
p4.fetch_xxx p4.run_xxx( "-o ").shift
p4.save_xxx( spec ) p4.input( spec )
p4.run_xxx( "-i" ).shift

Note that the fetch_xxx methods do not return an array as typically there is only one result item from such commands. Accordingly, they return the first result element.

There is also a special shortcut for submitting

    p4 = P4.new
    p4.parse_forms
    p4.connect
    spec = p4.fetch_change
    spec[ "Description" ] = "Automated change"
    p4.submit_spec( spec )
    p4.disconnect
      
run_filelog p4.run_filelog(fileSpec) -> anArray
Runs a p4 filelog on the fileSpec provided and returns an array of
P4DepotFile results when executed in tagged mode. The raw output of p4 filelog in tagged mode is difficult to work with so this method restructures the output into a more user-friendly (and object-oriented) form.
    p4 = P4.new
    p4.parse_forms
    begin
      p4.connect
      p4.run_filelog( "index.html" ).shift.each_revision do
          |r|
	  r.each_integration do
	      |i|
	      # Do something
	  end
      end
    rescue P4Exception 
      p4.errors.each { |e| puts( e ) }
    ensure
      p4.disconnect
    end
      
run_password p4.run_password(oldpass, newpass) -> anArray
A thin wrapper to make it easy to change your password. This method is (literally) equivalent to the following code:
	p4.input( [ oldpass, newpass, newpass ] )
	p4.run( "password" )
      
For example:
    p4 = P4.new
    p4.password = "myoldpass"
    begin
      p4.connect
      p4.run_password( "myoldpass", "mynewpass" )
    rescue P4Exception 
      p4.errors.each { |e| puts( e ) }
    ensure
      p4.disconnect
    end
      
run_resolve p4.run_resolve( args ) [ block ] -> anArray
Interface to 'p4 resolve'. Without a block, simply runs a non-interactive resolve - typically an automatic resolve.
	p4.run_resolve( "-at" )
      

When a block is supplied, the block is invoked once for each merge scheduled by Perforce. For each merge, a P4::MergeData object is passed to the block. This object contains the context of the merge.

Note that this interface is evolving and is subject to change in future versions of P4Ruby.

The block decides the outcome of the merge by evaluating to one of the following strings

  • "ay" - Accept Yours
  • "at" - Accept Theirs
  • "am" - Accept Merge result
  • "ae" - Accept Edited result
  • "s" - Skip this merge
  • "q" - Abort the merge
	p4.run_resolve() do
	    |md|
	    puts( "Merging..." )
	    puts( "Yours: #{md.your_name}" )
	    puts( "Theirs: #{md.their_name}" )
	    puts( "Base: #{md.base_name}" )
	    puts( "Yours file: #{md.your_path}" )
	    puts( "Theirs file: #{md.their_path}" )
	    puts( "Base file: #{md.base_path}" )
	    puts( "Result file: #{md.result_path}" )
	    puts( "Merge Hint: #{md.merge_hint}" )

	    result = md.merge_hint
	    if( result == "e" && ENV.has_key?( "P4MERGE" ) )
		puts( "Invoking external merge application" )
		result = "s"	# If the merge doesn't work, we'll skip
		result = "am" if md.run_merge()
	    end
	    result
	end
      
save_<spec type> p4.save_<spec type>( [options], hashOrString ) -> anArray
The save_* methods are simply shortcut methods that allow you to quickly update the definitions of clients, labels, branches, etc. They're equivalent to p4.run( <spec type>, '-i', [options,] hashOrString ).shift
    p4 = P4.new
    begin
      p4.connect
      client       	= p4.fetch_client()
      client[ "Owner" ] = p4.user?
      p4.save_client( client )
    rescue P4Exception 
      p4.errors.each { |e| puts( e ) }
    ensure
      p4.disconnect
    end
      
tagged p4.tagged -> true
Enables tagged output. Responses to Perforce commands which support tagged output will be converted into Ruby hashes. Must be called before connecting to the server.
    p4 = P4.new
    p4.tagged
    p4.connect
    ...
    p4.disconnect
      
user= p4.user = aString -> true
Set your Perforce username. If not set defaults to the value of P4USER taken from any P4CONFIG file in effect, then the value of P4USER in your environment and lastly your operating system user name.
    p4 = P4.new
    p4.user = "tony"
    p4.connect
    ...
    p4.disconnect
      
user? p4.user? -> aString
Returns your current Perforce user name
    p4 = P4.new
    puts( p4.user? )
      
warnings p4.warnings -> anArray
Returns the array of warnings which arose during execution of the last command.
    p4 = P4.new
    begin
      p4.connect
      p4.exception_level( P4::RAISE_ALL ) # "File(s) up-to-date" is a warning
      files = p4.run_sync
    rescue P4Exception => ex
      p4.warnings.each { |w| puts( w ) }
    ensure
      p4.disconnect
    end
      

See Also

P4DepotFile P4Exception P4Integration P4Revision P4::MergeData P4::Spec