<?xml version="1.0" encoding="UTF-8"?> <?xml-model href="http://www.oasis-open.org/docbook/xml/5.0/rng/docbookxi.rng" schematypens="http://relaxng.org/ns/structure/1.0"?> <?xml-model href="http://www.oasis-open.org/docbook/xml/5.0/rng/docbook.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?> <!-- vim: set ts=2 sw=2 tw=80 ai si: --> <book xmlns="http://docbook.org/ns/docbook" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" ><?dbhtml filename="copyright.html"?> <title>P4Ruby 3000.0.0</title> <subtitle>October 2014</subtitle> <info> <publishername>Perforce</publishername> <xi:include href="@common-xml@/legalnotice.xml"/> <copyright> <year>2014</year> <holder>Perforce Software.</holder> </copyright> </info> <chapter xml:id="ruby.intro"> <title>Introduction</title> <para> P4Ruby is an extension to the Ruby programming language that allows you to run Perforce commands from within Ruby scripts, and get the results in a Ruby-friendly format. </para> <para> The main features are: </para> <itemizedlist> <listitem> <para> Get Perforce data and forms in hashes and arrays. </para> </listitem> <listitem> <para> Edit Perforce forms by modifying hashes. </para> </listitem> <listitem> <para> Exception based error handling. </para> </listitem> <listitem> <para> Controllable handling of warnings such as "File(s) up-to-date." on a sync. </para> </listitem> <listitem> <para> Run as many commands on a connection as required. </para> </listitem> <listitem> <para> The output of a command is returned as a Ruby array. For non-tagged output, the elements of the array are strings. For tagged output, the elements of the array are Ruby hashes. For forms, the output is an array of <literal>P4::Spec</literal> objects. </para> </listitem> <listitem> <para> Thread-safe and thread-friendly; you can have multiple instances of the <literal>P4</literal> class running in different threads. </para> </listitem> <listitem> <para> Exception-based error handling. Trap <exceptionname>P4Exception</exceptionname>s for complete, high-level error handling. </para> </listitem> </itemizedlist> <para> The most recent release of P4Ruby is 2014.1. </para> </chapter> <chapter xml:id="ruby.requirements"> <title>System Requirements</title> <para> P4Ruby is supported on Windows, Linux, Solaris, OS X, and FreeBSD. </para> <para> To build P4Ruby, your development machine must also have: </para> <itemizedlist> <listitem> <para> Ruby 1.8 or 1.9 development files. </para> </listitem> <listitem> <para> <command>make</command> (or <command>nmake</command> on Windows). </para> </listitem> <listitem> <para> The 2014.1 Perforce C/C++ API for your target platform. Older releases might work, but are not supported. </para> </listitem> <listitem> <para> The same C++ compiler used to build the Perforce C++ API on your target platform. </para> <para> (If you get "unresolved symbol" errors when building or running P4Ruby, you probably used the wrong compiler or the wrong Perforce API build.) </para> </listitem> </itemizedlist> </chapter> <chapter xml:id="ruby.installation"> <title>Installing P4Ruby</title> <para> You can download P4Ruby from the Perforce web site: </para> <para> <link xlink:href="http://www.perforce.com/product/components/apis">http://www.perforce.com/product/components/apis</link> </para> <para> After downloading, you can either run the installer or build the interface from source, as described in the release notes. </para> </chapter> <chapter xml:id="ruby.programming"> <title>Programming with P4Ruby</title> <para> The following example shows how to create a new client workspace based on an existing template: </para> <programlisting language="ruby"> require "P4" template = "my-client-template" client_root = 'c:\p4-work' p4 = P4.new p4.connect begin # Run a "p4 client -t template -o" and convert it into a Ruby hash spec = p4.fetch_client( "-t", template, "my-new-client") # Now edit the fields in the form spec[ "Root" ] = client_root spec[ "Options" ] = spec[ "Options" ].sub( "normdir", "rmdir" ) # Now save the updated spec p4.save_client( spec ) # Point to the newly-created client p4.client="my-new-client" # And sync it. p4.run_sync rescue P4Exception # If any errors occur, we'll jump in here. Just log them # and raise the exception up to the higher level p4.errors.each { |e| $stderr.puts( e ) } raise end </programlisting> <section xml:id="ruby.programming.ssl"> <title>Connecting to SSL-enabled servers</title> <para> Scripts written with P4Ruby use any existing <envar>P4TRUST</envar> file present in their operating environment (by default, <filename>.p4trust</filename> in the home directory of the user that runs the script). </para> <para> If the fingerprint returned by the server fails to match the one installed in the <envar>P4TRUST</envar> file associated with the script's run-time environment, your script will (and should!) fail to connect to the server. </para> </section> </chapter> <chapter xml:id="ruby.classes"> <title>P4Ruby classes</title> <para> The P4 module consists of several public classes: </para> <itemizedlist> <listitem><para><xref linkend="ruby.classes.p4"/></para></listitem> <listitem><para><xref linkend="ruby.classes.p4exception"/></para></listitem> <listitem><para><xref linkend="ruby.classes.p4_depotfile"/></para></listitem> <listitem><para><xref linkend="ruby.classes.p4_revision"/></para></listitem> <listitem><para><xref linkend="ruby.classes.p4_integration"/></para></listitem> <listitem><para><xref linkend="ruby.classes.p4_map"/></para></listitem> <listitem><para><xref linkend="ruby.classes.p4_mergedata"/></para></listitem> <listitem><para><xref linkend="ruby.classes.p4_message"/></para></listitem> <listitem><para><xref linkend="ruby.classes.p4_outputhandler"/></para></listitem> <listitem><para><xref linkend="ruby.classes.p4_progress"/></para></listitem> <listitem><para><xref linkend="ruby.classes.p4_spec"/></para></listitem> </itemizedlist> <para> The following tables provide brief details about each public class. </para> <section xml:id="ruby.classes.p4"> <title>P4</title> <para> The main class used for executing Perforce commands. Almost everything you do with P4Ruby will involve this class. </para> <informaltable> <tgroup cols="2"> <colspec colname="method" colwidth="*"/> <colspec colname="description" colwidth="3*"/> <thead> <row> <entry> <para> Method </para> </entry> <entry> <para> Description </para> </entry> </row> </thead> <tbody> <row> <entry> <para> <link linkend="ruby.p4.identify"><methodname>identify</methodname></link> </para> </entry> <entry> <para> Return the version of P4Ruby in use (class method). </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.new"><methodname>new</methodname></link> </para> </entry> <entry> <para> Construct a new <classname>P4</classname> object (class method). </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.api_level.eq"><methodname>api_level=</methodname></link> </para> </entry> <entry> <para> Set desired API compatibility level. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.api_level"><methodname>api_level</methodname></link> </para> </entry> <entry> <para> Return current API compatibility level. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.at_exception_level"><methodname>at_exception_level</methodname></link> </para> </entry> <entry> <para> Execute the associated block under a specific exception level, returning to previous exception level when block returns. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.charset.eq"><methodname>charset=</methodname></link> </para> </entry> <entry> <para> Set character set when connecting to Unicode servers. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.charset"><methodname>charset</methodname></link> </para> </entry> <entry> <para> Get character set when connecting to Unicode servers. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.client.eq"><methodname>client=</methodname></link> </para> </entry> <entry> <para> Set client workspace (<envar>P4CLIENT</envar>). </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.client"><methodname>client</methodname></link> </para> </entry> <entry> <para> Get current client workspace (<envar>P4CLIENT</envar>). </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.connect"><methodname>connect</methodname></link> </para> </entry> <entry> <para> Connect to the Perforce Server, raise <exceptionname>P4Exception</exceptionname> on failure. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.connected"><methodname>connected?</methodname></link> </para> </entry> <entry> <para> Test whether or not session has been connected and/or has been dropped. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.cwd.eq"><methodname>cwd=</methodname></link> </para> </entry> <entry> <para> Set current working directory. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.cwd"><methodname>cwd</methodname></link> </para> </entry> <entry> <para> Get current working directory. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.delete_spectype"><methodname>delete_<replaceable><spectype></replaceable></methodname></link> </para> </entry> <entry> <para> Shortcut methods for deleting clients, labels, etc. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.disconnect"><methodname>disconnect</methodname></link> </para> </entry> <entry> <para> Disconnect from the Perforce Server. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.each_spectype"><methodname>each_<replaceable><spectype></replaceable></methodname></link> </para> </entry> <entry> <para> Shortcut methods for iterating through clients, labels, etc. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.env"><methodname>env</methodname></link> </para> </entry> <entry> <para> Get the value of a Perforce environment variable, taking into account <envar>P4CONFIG</envar> files and (on Windows or OS X) the registry or user preferences. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.errors"><methodname>errors</methodname></link> </para> </entry> <entry> <para> Return the array of errors that occurred during execution of previous command. </para> </entry> </row> <row> <entry> <para> <methodname> <link linkend="ruby.p4.exception_level.eq">exception_level=</link> </methodname> </para> </entry> <entry> <para> Control which types of events give rise to exceptions (<exceptionname>P4::RAISE_NONE</exceptionname>, <exceptionname>RAISE_ERRORS</exceptionname>, or <exceptionname>RAISE_ALL</exceptionname>). </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.exception_level"><methodname>exception_level</methodname></link> </para> </entry> <entry> <para> Return the current exception level. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.fetch_spectype"><methodname>fetch_<replaceable><spectype></replaceable></methodname></link> </para> </entry> <entry> <para> Shortcut methods for retrieving the definitions of clients, labels, etc. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.format_spec"><methodname>format_spec</methodname></link> </para> </entry> <entry> <para> Convert fields in a hash containing the elements of a Perforce form (spec) into the string representation familiar to users. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.format_spectype"><methodname>format_<replaceable><spectype></replaceable></methodname></link> </para> </entry> <entry> <para> Shortcut method; equivalent to: </para> <programlisting> p4.format_spec( "<replaceable><spectype></replaceable>", aHash ) </programlisting> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.handler.eq"><methodname>handler=</methodname></link> </para> </entry> <entry> <para> Set output handler. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.handler"><methodname>handler</methodname></link> </para> </entry> <entry> <para> Get output handler. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.host.eq"><methodname>host=</methodname></link> </para> </entry> <entry> <para> Set the name of the current host (<envar>P4HOST</envar>). </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.host"><methodname>host</methodname></link> </para> </entry> <entry> <para> Get the current hostname. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.input.eq"><methodname>input=</methodname></link> </para> </entry> <entry> <para> Store input for next command. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.maxlocktime.eq"><methodname>maxlocktime=</methodname></link> </para> </entry> <entry> <para> Set MaxLockTime used for all following commands. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.maxlocktime"><methodname>maxlocktime</methodname></link> </para> </entry> <entry> <para> Get MaxLockTime used for all following commands. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.maxresults.eq"><methodname>maxresults=</methodname></link> </para> </entry> <entry> <para> Set MaxResults used for all following commands. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.maxresults"><methodname>maxresults</methodname></link> </para> </entry> <entry> <para> Get MaxResults used for all following commands. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.maxscanrows.eq"><methodname>maxscanrows=</methodname></link> </para> </entry> <entry> <para> Set MaxScanRows used for all following commands. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.maxscanrows"><methodname>maxscanrows</methodname></link> </para> </entry> <entry> <para> Get MaxScanRows used for all following commands. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.messages"><methodname>messages</methodname></link> </para> </entry> <entry> <para> Returns all messages from the server as <classname>P4::Message</classname> objects. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.p4config_file"><methodname>p4config_file</methodname></link> </para> </entry> <entry> <para> Get the location of the configuration file used (<envar>P4CONFIG</envar>). </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.parse_spectype"><methodname>parse_<replaceable><spectype></replaceable></methodname></link> </para> </entry> <entry> <para> Shortcut method; equivalent to: </para> <programlisting language="ruby"> p4.parse_spec( "<replaceable><spectype></replaceable>", aString ) </programlisting> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.parse_spec"><methodname>parse_spec</methodname></link> </para> </entry> <entry> <para> Parses a Perforce form (spec) in text form into a Ruby hash using the spec definition obtained from the server. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.password.eq"><methodname>password=</methodname></link> </para> </entry> <entry> <para> Set Perforce password (<envar>P4PASSWD</envar>). </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.password"><methodname>password</methodname></link> </para> </entry> <entry> <para> Get the current password or ticket. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.port.eq"><methodname>port=</methodname></link> </para> </entry> <entry> <para> Set host and port (<envar>P4PORT</envar>). </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.port"><methodname>port</methodname></link> </para> </entry> <entry> <para> Get host and port (<envar>P4PORT</envar>) of the current Perforce server. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.prog.eq"><methodname>prog=</methodname></link> </para> </entry> <entry> <para> Set program name as shown by <command>p4 monitor show -e</command>. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.prog"><methodname>prog</methodname></link> </para> </entry> <entry> <para> Get program name as shown by <command>p4 monitor show -e</command>. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.progress.eq"><methodname>progress=</methodname></link> </para> </entry> <entry> <para> Set progress indicator. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.progress"><methodname>progress</methodname></link> </para> </entry> <entry> <para> Get progress indicator. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.run_cmd"><methodname>run_<replaceable>cmd</replaceable></methodname></link> </para> </entry> <entry> <para> Shortcut method; equivalent to: </para> <programlisting language="ruby"> p4.run( "<replaceable>cmd</replaceable>", <replaceable>arguments</replaceable>... ) </programlisting> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.run"><methodname>run</methodname></link> </para> </entry> <entry> <para> Runs the specified Perforce command with the arguments supplied. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.run_filelog"><methodname>run_filelog</methodname></link> </para> </entry> <entry> <para> Runs a <command>p4 filelog</command> on the fileSpec provided, returns an array of <classname>P4::DepotFile</classname> objects. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.run_login"><methodname>run_login</methodname></link> </para> </entry> <entry> <para> Runs <command>p4 login</command> using a password or ticket set by the user. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.run_password"><methodname>run_password</methodname></link> </para> </entry> <entry> <para> A thin wrapper to make it easy to change your password. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.run_resolve"><methodname>run_resolve</methodname></link> </para> </entry> <entry> <para> Interface to <command>p4 resolve</command>. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.run_submit"><methodname>run_submit</methodname></link> </para> </entry> <entry> <para> Submit a changelist to the server. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.run_tickets"><methodname>run_tickets</methodname></link> </para> </entry> <entry> <para> Get a list of tickets from the local tickets file. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.save_spectype"><methodname>save_<replaceable><spectype></replaceable></methodname></link> </para> </entry> <entry> <para> Shortcut method; equivalent to: </para> <programlisting language="ruby"> p4.input = hashOrString p4.run( "<replaceable><spectype></replaceable>", "-i" ) </programlisting> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.server_case_sensitive"><methodname>server_case_sensitive?</methodname></link> </para> </entry> <entry> <para> Detects whether or not the server is case sensitive. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.server_level"><methodname>server_level</methodname></link> </para> </entry> <entry> <para> Returns the current Perforce server level. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.server_unicode"><methodname>server_unicode?</methodname></link> </para> </entry> <entry> <para> Detects whether or not the server is in unicode mode. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.set_env"><methodname>set_env</methodname></link> </para> </entry> <entry> <para> On Windows or OS X, set a variable in the registry or user preferences. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.streams.eq"><methodname>streams=</methodname></link> </para> </entry> <entry> <para> Enable or disable support for streams. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.streams"><methodname>streams?</methodname></link> </para> </entry> <entry> <para> Test whether or not the server supports streams </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.tagged"><methodname>tagged</methodname></link> </para> </entry> <entry> <para> Toggles tagged output (true or false). By default, tagged output is on. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.tagged.eq"><methodname>tagged=</methodname></link> </para> </entry> <entry> <para> Sets tagged output. By default, tagged output is on. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.tagged.q"><methodname>tagged?</methodname></link> </para> </entry> <entry> <para> Detects whether or not tagged output is enabled. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.ticketfile.eq"><methodname>ticketfile=</methodname></link> </para> </entry> <entry> <para> Set the location of the <envar>P4TICKETS</envar> file. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.ticketfile"><methodname>ticketfile</methodname></link> </para> </entry> <entry> <para> Get the location of the <envar>P4TICKETS</envar> file. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.track.eq"><methodname>track=</methodname></link> </para> </entry> <entry> <para> Activate or disable server performance tracking. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.track"><methodname>track?</methodname></link> </para> </entry> <entry> <para> Detect whether server performance tracking is active. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.track_output"><methodname>track_output</methodname></link> </para> </entry> <entry> <para> Returns server tracking output. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.user.eq"><methodname>user=</methodname></link> </para> </entry> <entry> <para> Set the Perforce username (<envar>P4USER</envar>). </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.user"><methodname>user</methodname></link> </para> </entry> <entry> <para> Get the Perforce username (<envar>P4USER</envar>). </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.version.eq"><methodname>version=</methodname></link> </para> </entry> <entry> <para> Set your script's version as reported to the server. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.version"><methodname>version</methodname></link> </para> </entry> <entry> <para> Get your script's version as reported by the server. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4.warnings"><methodname>warnings</methodname></link> </para> </entry> <entry> <para> Returns the array of warnings that arose during execution of the last command. </para> </entry> </row> </tbody> </tgroup> </informaltable> </section> <section xml:id="ruby.classes.p4exception"> <title>P4Exception</title> <para> Used as part of error reporting and is derived from the Ruby <classname>RuntimeError</classname> class. </para> </section> <section xml:id="ruby.classes.p4_depotfile"> <title>P4::DepotFile</title> <para> Utility class allowing access to the attributes of a file in the depot. Returned by <methodname>P4#run_filelog()</methodname>. </para> <informaltable> <tgroup cols="2"> <colspec colname="method" colwidth="*"/> <colspec colname="description" colwidth="3*"/> <thead> <row> <entry> <para> Method </para> </entry> <entry> <para> Description </para> </entry> </row> </thead> <tbody> <row> <entry> <para> <link linkend="ruby.p4_depotfile.depot_file"><methodname>depot_file</methodname></link> </para> </entry> <entry> <para> Name of the depot file to which this object refers. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_depotfile.each_revision"><methodname>each_revision</methodname></link> </para> </entry> <entry> <para> Iterates over each revision of the depot file. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_depotfile.revisions"><methodname>revisions</methodname></link> </para> </entry> <entry> <para> Returns an array of revision objects for the depot file. </para> </entry> </row> </tbody> </tgroup> </informaltable> </section> <section xml:id="ruby.classes.p4_revision"> <title>P4::Revision</title> <para> Utility class allowing access to the attributes of a revision <classname>P4::DepotFile</classname> object. Returned by <methodname>P4#run_filelog()</methodname>. </para> <informaltable> <tgroup cols="2"> <colspec colname="method" colwidth="*"/> <colspec colname="description" colwidth="3*"/> <thead> <row> <entry> <para> Method </para> </entry> <entry> <para> Description </para> </entry> </row> </thead> <tbody> <row> <entry> <para> <link linkend="ruby.p4_revision.action"><methodname>action</methodname></link> </para> </entry> <entry> <para> Action that created the revision. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_revision.change"><methodname>change</methodname></link> </para> </entry> <entry> <para> Changelist number. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_revision.client"><methodname>client</methodname></link> </para> </entry> <entry> <para> Client workspace used to create this revision. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_revision.depot_file"><methodname>depot_file</methodname></link> </para> </entry> <entry> <para> Name of the file in the depot. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_revision.desc"><methodname>desc</methodname></link> </para> </entry> <entry> <para> Short changelist description. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_revision.digest"><methodname>digest</methodname></link> </para> </entry> <entry> <para> MD5 digest of this revision. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_revision.filesize"><methodname>filesize</methodname></link> </para> </entry> <entry> <para> Returns the size of this revision. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_revision.integrations"><methodname>integrations</methodname></link> </para> </entry> <entry> <para> Array of <classname>P4::Integration</classname> objects. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_revision.rev"><methodname>rev</methodname></link> </para> </entry> <entry> <para> Revision number. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_revision.time"><methodname>time</methodname></link> </para> </entry> <entry> <para> Timestamp. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_revision.type"><methodname>type</methodname></link> </para> </entry> <entry> <para> Perforce file type. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_revision.user"><methodname>user</methodname></link> </para> </entry> <entry> <para> User that created this revision. </para> </entry> </row> </tbody> </tgroup> </informaltable> </section> <section xml:id="ruby.classes.p4_integration"> <title>P4::Integration</title> <para> Utility class allowing access to the attributes of an integration record for a <classname>P4::Revision</classname> object. Returned by <methodname>P4#run_filelog()</methodname>. </para> <informaltable> <tgroup cols="2"> <colspec colname="method" colwidth="*"/> <colspec colname="description" colwidth="3*"/> <thead> <row> <entry> <para> Method </para> </entry> <entry> <para> Description </para> </entry> </row> </thead> <tbody> <row> <entry> <para> <link linkend="ruby.p4_integration.how"><methodname>how</methodname></link> </para> </entry> <entry> <para> Integration method (merge/branch/copy/ignored). </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_integration.file"><methodname>file</methodname></link> </para> </entry> <entry> <para> Integrated file. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_integration.srev"><methodname>srev</methodname></link> </para> </entry> <entry> <para> Start revision. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_integration.erev"><methodname>erev</methodname></link> </para> </entry> <entry> <para> End revision. </para> </entry> </row> </tbody> </tgroup> </informaltable> </section> <section xml:id="ruby.classes.p4_map"> <title>P4::Map</title> <para> A class that allows users to create and work with Perforce mappings without requiring a connection to the Perforce Server. </para> <informaltable> <tgroup cols="2"> <colspec colname="method" colwidth="*"/> <colspec colname="description" colwidth="3*"/> <thead> <row> <entry> <para> Method </para> </entry> <entry> <para> Description </para> </entry> </row> </thead> <tbody> <row> <entry> <para> <link linkend="ruby.p4_map.new"><methodname>new</methodname></link> </para> </entry> <entry> <para> Construct a new map object (class method). </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_map.join"><methodname>join</methodname></link> </para> </entry> <entry> <para> Joins two maps to create a third (class method). </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_map.clear"><methodname>clear</methodname></link> </para> </entry> <entry> <para> Empties a map. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_map.count"><methodname>count</methodname></link> </para> </entry> <entry> <para> Returns the number of entries in a map. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_map.empty"><methodname>empty?</methodname></link> </para> </entry> <entry> <para> Tests whether or not a map object is empty. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_map.insert"><methodname>insert</methodname></link> </para> </entry> <entry> <para> Inserts an entry into the map. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_map.translate"><methodname>translate</methodname></link> </para> </entry> <entry> <para> Translate a string through a map. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_map.includes"><methodname>includes?</methodname></link> </para> </entry> <entry> <para> Tests whether a path is mapped. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_map.reverse"><methodname>reverse</methodname></link> </para> </entry> <entry> <para> Returns a new mapping with the left and right sides reversed. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_map.lhs"><methodname>lhs</methodname></link> </para> </entry> <entry> <para> Returns the left side as an array. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_map.rhs"><methodname>rhs</methodname></link> </para> </entry> <entry> <para> Returns the right side as an array. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_map.to_a"><methodname>to_a</methodname></link> </para> </entry> <entry> <para> Returns the map as an array. </para> </entry> </row> </tbody> </tgroup> </informaltable> </section> <section xml:id="ruby.classes.p4_mergedata"> <title>P4::MergeData</title> <para> Class encapsulating the context of an individual merge during execution of a <command>p4 resolve</command> command. Passed as a parameter to the block passed to <methodname>P4#run_resolve()</methodname>. </para> <informaltable> <tgroup cols="2"> <colspec colname="method" colwidth="*"/> <colspec colname="description" colwidth="3*"/> <thead> <row> <entry> <para> Method </para> </entry> <entry> <para> Description </para> </entry> </row> </thead> <tbody> <row> <entry> <para> <link linkend="ruby.p4_mergedata.your_name"><methodname>your_name</methodname></link> </para> </entry> <entry> <para> Returns the name of "your" file in the merge. (file in workspace) </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_mergedata.their_name"><methodname>their_name</methodname></link> </para> </entry> <entry> <para> Returns the name of "their" file in the merge. (file in the depot) </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_mergedata.base_name"><methodname>base_name</methodname></link> </para> </entry> <entry> <para> Returns the name of "base" file in the merge. (file in the depot) </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_mergedata.your_path"><methodname>your_path</methodname></link> </para> </entry> <entry> <para> Returns the path of "your" file in the merge. (file in workspace) </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_mergedata.their_path"><methodname>their_path</methodname></link> </para> </entry> <entry> <para> Returns the path of "their" file in the merge. (temporary file on workstation into which <methodname>their_name</methodname> has been loaded) </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_mergedata.base_path"><methodname>base_path</methodname></link> </para> </entry> <entry> <para> Returns the path of the base file in the merge. (temporary file on workstation into which <methodname>base_name</methodname> has been loaded) </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_mergedata.result_path"><methodname>result_path</methodname></link> </para> </entry> <entry> <para> Returns the path to the merge result. (temporary file on workstation into which the automatic merge performed by the server has been loaded) </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_mergedata.merge_hint"><methodname>merge_hint</methodname></link> </para> </entry> <entry> <para> Returns hint from server as to how user might best resolve merge. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_mergedata.run_merge"><methodname>run_merge</methodname></link> </para> </entry> <entry> <para> If the environment variable <envar>P4MERGE</envar> is defined, run it and return a boolean based on the return value of that program. </para> </entry> </row> </tbody> </tgroup> </informaltable> </section> <section xml:id="ruby.classes.p4_message"> <title>P4::Message</title> <para> Utility class allowing access to the attributes of a message object returned by <methodname>P4#messages()</methodname>. </para> <informaltable> <tgroup cols="2"> <colspec colname="method" colwidth="*"/> <colspec colname="description" colwidth="3*"/> <thead> <row> <entry> <para> Method </para> </entry> <entry> <para> Description </para> </entry> </row> </thead> <tbody> <row> <entry> <para> <link linkend="ruby.p4_message.severity"><methodname>severity</methodname></link> </para> </entry> <entry> <para> Returns the severity of the message. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_message.generic"><methodname>generic</methodname></link> </para> </entry> <entry> <para> Returns the generic class of the error. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_message.msgid"><methodname>msgid</methodname></link> </para> </entry> <entry> <para> Returns the unique ID of the error message. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_message.to_s"><methodname>to_s</methodname></link> </para> </entry> <entry> <para> Returns the error message as a string. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_message.inspect"><methodname>inspect</methodname></link> </para> </entry> <entry> <para> Converts the error object into a string for debugging purposes. </para> </entry> </row> </tbody> </tgroup> </informaltable> </section> <section xml:id="ruby.classes.p4_outputhandler"> <title>P4::OutputHandler</title> <para> Handler class that provides access to streaming output from the server; set <methodname>P4#handler()</methodname> to an instance of a subclass of <classname>P4::OutputHandler</classname> to enable callbacks: </para> <informaltable> <tgroup cols="2"> <colspec colname="method" colwidth="*"/> <colspec colname="description" colwidth="3*"/> <thead> <row> <entry> <para> Method </para> </entry> <entry> <para> Description </para> </entry> </row> </thead> <tbody> <row> <entry> <para> <link linkend="ruby.p4_outputhandler.outputbinary"><methodname>outputBinary</methodname></link> </para> </entry> <entry> <para> Process binary data. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_outputhandler.outputinfo"><methodname>outputInfo</methodname></link> </para> </entry> <entry> <para> Process tabular data. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_outputhandler.outputmessage"><methodname>outputMessage</methodname></link> </para> </entry> <entry> <para> Process information or errors. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_outputhandler.outputstat"><methodname>outputStat</methodname></link> </para> </entry> <entry> <para> Process tagged output. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_outputhandler.outputtext"><methodname>outputText</methodname></link> </para> </entry> <entry> <para> Process text data. </para> </entry> </row> </tbody> </tgroup> </informaltable> </section> <section xml:id="ruby.classes.p4_progress"> <title>P4::Progress</title> <para> Handler class that provides access to progress indicators from the server; set <methodname>P4#progress()</methodname> to an instance of a subclass of <classname>P4::Progress</classname> with the following methods (even if the implementations are empty) to enable callbacks: </para> <informaltable> <tgroup cols="2"> <colspec colname="method" colwidth="*"/> <colspec colname="description" colwidth="3*"/> <thead> <row> <entry> <para> Method </para> </entry> <entry> <para> Description </para> </entry> </row> </thead> <tbody> <row> <entry> <para> <link linkend="ruby.p4_progress.init"><methodname>init</methodname></link> </para> </entry> <entry> <para> Initialize progress indicator as designated type. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_progress.total"><methodname>total</methodname></link> </para> </entry> <entry> <para> Total number of units (if known). </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_progress.description"><methodname>description</methodname></link> </para> </entry> <entry> <para> Description and type of units to be used for progress reporting. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_progress.update"><methodname>update</methodname></link> </para> </entry> <entry> <para> If non-zero, user has requested a cancellation of the operation. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_progress.done"><methodname>done</methodname></link> </para> </entry> <entry> <para> If non-zero, operation has failed. </para> </entry> </row> </tbody> </tgroup> </informaltable> </section> <section xml:id="ruby.classes.p4_spec"> <title>P4::Spec</title> <para> Subclass of hash allowing access to the fields in a Perforce specification form. Also checks that the fields that are set are valid fields for the given type of spec. Returned by <methodname>P4#fetch_<replaceable><spectype></replaceable>()</methodname>. </para> <informaltable> <tgroup cols="2"> <colspec colname="method" colwidth="*"/> <colspec colname="description" colwidth="3*"/> <thead> <row> <entry> <para> Method </para> </entry> <entry> <para> Description </para> </entry> </row> </thead> <tbody> <row> <entry> <para> <link linkend="ruby.p4_spec._fieldname"><methodname>spec.<replaceable>_fieldname</replaceable></methodname></link> </para> </entry> <entry> <para> Return the value associated with the field named <replaceable>fieldname</replaceable>. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_spec._fieldname.eq"><methodname>spec._<replaceable>fieldname</replaceable>=</methodname></link> </para> </entry> <entry> <para> Set the value associated with the field named <replaceable>fieldname</replaceable>. </para> </entry> </row> <row> <entry> <para> <link linkend="ruby.p4_spec.permitted_fields"><methodname>spec.permitted_fields</methodname></link> </para> </entry> <entry> <para> Returns an array containing the names of fields that are valid in this spec object. </para> </entry> </row> </tbody> </tgroup> </informaltable> </section> </chapter> <chapter xml:id="ruby.p4"> <title>Class P4</title> <section xml:id="ruby.p4-description"> <title>Description</title> <para> Main interface to the Perforce client API. Each <classname>P4</classname> object provides you with a thread-safe API level interface to Perforce. The basic model is to: </para> <orderedlist> <listitem> <para> Instantiate your <literal>P4</literal> object. </para> </listitem> <listitem> <para> Specify your Perforce client environment. </para> <itemizedlist> <listitem> <para> <literal>client</literal> </para> </listitem> <listitem> <para> <literal>host</literal> </para> </listitem> <listitem> <para> <literal>password</literal> </para> </listitem> <listitem> <para> <literal>port</literal> </para> </listitem> <listitem> <para> <literal>user</literal> </para> </listitem> </itemizedlist> </listitem> <listitem> <para> Set any options to control output or error handling: </para> <itemizedlist> <listitem> <para> <literal>exception_level</literal> </para> </listitem> </itemizedlist> </listitem> <listitem> <para> Connect to the Perforce service. </para> <para> The Perforce protocol is not designed to support multiple concurrent queries over the same connection. Multithreaded applications that use the C++ API or derived APIs (including P4Ruby) should ensure that a separate connection is used for each thread, or that only one thread may use a shared connection at a time. </para> </listitem> <listitem> <para> Run your Perforce commands. </para> </listitem> <listitem> <para> Disconnect from the Perforce service. </para> </listitem> </orderedlist> </section> <section xml:id="ruby.p4-class_methods"> <title>Class Methods</title> <section xml:id="ruby.p4.identify"> <title>P4.identify -> aString</title> <para> Return the version of P4Ruby that you are using. Also reports the version of the OpenSSL library used for building the underlying Perforce C++ API with which P4Ruby was built. </para> <programlisting language="ruby"> ruby -rP4 -e 'puts( P4.identify )' </programlisting> <para> Some of this information is already made available through the predefined constants <literal>P4::VERSION</literal>, <literal>P4::OS</literal>, and <literal>P4::PATCHLEVEL</literal>. </para> </section> <section xml:id="ruby.p4.new"> <title>P4.new -> aP4</title> <para> Constructs a new P4 object. </para> <programlisting language="ruby"> p4 = P4.new() </programlisting> </section> </section> <section xml:id="ruby.p4-instance_methods"> <title>Instance Methods</title> <section xml:id="ruby.p4.api_level.eq"> <title>p4.api_level= anInteger -> anInteger</title> <para> 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. This method <emphasis>must</emphasis> be called prior to calling <methodname>P4#connect()</methodname>. </para> <programlisting language="ruby"> p4 = P4.new p4.api_level = 67 # Lock to 2010.1 format p4.connect ... </programlisting> <para> For the API integer levels that correspond to each Perforce release, see: </para> <para> <link xlink:href="http://kb.perforce.com/article/512">http://kb.perforce.com/article/512</link> </para> </section> <section xml:id="ruby.p4.api_level"> <title>p4.api_level -> anInteger</title> <para> Returns the current Perforce API compatibility level. Each iteration of the Perforce Server is given a level number. As part of the initial communication, the client protocol level is passed between client application and the Perforce Server. This value, defined in the Perforce API, determines the communication protocol level that the Perforce client will understand. All subsequent responses from the Perforce Server can be tailored to meet the requirements of that client protocol level. </para> <para> For more information, see: </para> <para> <link xlink:href="http://kb.perforce.com/article/512">http://kb.perforce.com/article/512</link> </para> </section> <section xml:id="ruby.p4.at_exception_level"> <title>p4.at_exception_level( lev ) { ... } -> self</title> <para> Executes the associated block under a specific exception level. Returns to the previous exception level when the block returns. </para> <programlisting language="ruby"> p4 = P4.new p4.client = "www" p4.connect p4.at_exception_level( P4::RAISE_ERRORS ) do p4.run_sync end p4.disconnect </programlisting> </section> <section xml:id="ruby.p4.charset.eq"> <title>p4.charset= aString -> aString</title> <para> Sets the character set to use when connect to a Unicode enabled server. Do not use when working with non-Unicode-enabled servers. By default, the character set is the value of the <envar>P4CHARSET</envar> environment variable. If the character set is invalid, this method raises a <exceptionname>P4Exception</exceptionname>. </para> <programlisting language="ruby"> p4 = P4.new p4.client = "www" p4.charset = "iso8859-1" p4.connect p4.run_sync p4.disconnect </programlisting> </section> <section xml:id="ruby.p4.charset"> <title>p4.charset -> aString</title> <para> Get the name of the character set in use when working with Unicode-enabled servers. </para> <programlisting language="ruby"> p4 = P4.new p4.charset = "utf8" puts( p4.charset ) </programlisting> </section> <section xml:id="ruby.p4.client.eq"> <title>p4.client= aString -> aString</title> <para> Set the name of the client workspace you wish to use. If not called, defaults to the value of <envar>P4CLIENT</envar> taken from any <envar>P4CONFIG</envar> file present, or from the environment as per the usual Perforce convention. Must be called before connecting to the Perforce server. </para> <programlisting language="ruby"> p4 = P4.new p4.client = "www" p4.connect p4.run_sync p4.disconnect </programlisting> </section> <section xml:id="ruby.p4.client"> <title>p4.client -> aString</title> <para> Get the name of the Perforce client currently in use. </para> <programlisting language="ruby"> p4 = P4.new puts( p4.client ) </programlisting> </section> <section xml:id="ruby.p4.connect"> <title>p4.connect -> aBool</title> <para> Connect to the Perforce Server. You must connect before you can execute commands. Raises a <exceptionname>P4Exception</exceptionname> if the connection attempt fails. </para> <programlisting language="ruby"> p4 = P4.new p4.connect </programlisting> </section> <section xml:id="ruby.p4.connected"> <title>p4.connected? -> aBool</title> <para> Test whether or not the session has been connected, and if the connection has not been dropped. </para> <programlisting language="ruby"> p4 = P4.newp4.connected? </programlisting> </section> <section xml:id="ruby.p4.cwd.eq"> <title>p4.cwd= aString -> aString</title> <para> Sets the current working directly. Can be called prior to executing any Perforce command. Sometimes necessary if your script executes a <function>chdir()</function> as part of its processing. </para> <programlisting language="ruby"> p4 = P4.new p4.cwd = "/home/bruno" </programlisting> </section> <section xml:id="ruby.p4.cwd"> <title>p4.cwd -> aString</title> <para> Get the current working directory. </para> <programlisting language="ruby"> p4 = P4.new puts( p4.cwd ) </programlisting> </section> <section xml:id="ruby.p4.delete_spectype"> <title>p4.delete_<spectype>( [options], name ) -> anArray</title> <para> The delete methods are simply shortcut methods that allow you to quickly delete the definitions of clients, labels, branches, etc. These methods are equivalent to: </para> <programlisting language="ruby"> p4.run( "<replaceable><spectype></replaceable>", '-d', [<replaceable>options</replaceable>], "<replaceable>spec name</replaceable>" ) </programlisting> <para> For example: </para> <programlisting language="ruby"> require "P4" require "parsedate" include ParseDate now = Time.now p4 = P4.new begin p4.connect p4.run_clients.each do |client| atime = parsedate( client[ "Access" ] ) 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 </programlisting> </section> <section xml:id="ruby.p4.disconnect"> <title>p4.disconnect -> true</title> <para> Disconnect from the Perforce Server. </para> <programlisting language="ruby"> p4 = P4.new p4.connect p4.disconnect </programlisting> </section> <section xml:id="ruby.p4.each_spectype"> <title>p4.each_<spectype<( arguments ) -> anArray</title> <para> The <methodname>each_<replaceable><spectype></replaceable></methodname> methods are shortcut methods that allow you to quickly iterate through clients, labels, branches, etc. Valid <replaceable><spectype></replaceable>s are <literal>clients</literal>, <literal>labels</literal>, <literal>branches</literal>, <literal>changes</literal>, <literal>streams</literal>, <literal>jobs</literal>, <literal>users</literal>, <literal>groups</literal>, <literal>depots</literal> and <literal>servers</literal>. Valid arguments are any arguments that would be valid for the corresponding <methodname>run_<replaceable><spectype></replaceable></methodname> command. </para> <para> For example, to iterate through clients: </para> <programlisting language="ruby"> p4.each_clients do |c| # work with the retrieved client spec end </programlisting> <para> is equivalent to: </para> <programlisting language="ruby"> clients = p4.run_clients clients.each do |c| client = p4.fetch_client( c['client'] ) # work with the retrieved client spec end </programlisting> </section> <section xml:id="ruby.p4.env"> <title>p4.env -> string</title> <para> Get the value of a Perforce environment variable, taking into account <envar>P4CONFIG</envar> files and (on Windows and OS X) the registry or user preferences. </para> <programlisting language="ruby"> p4 = P4.new puts p4.env( "P4PORT" ) </programlisting> </section> <section xml:id="ruby.p4.errors"> <title>p4.errors -> anArray</title> <para> Returns the array of errors which occurred during execution of the previous command. </para> <programlisting language="ruby"> p4 = P4.new begin p4.connect p4.exception_level( P4::RAISE_ERRORS ) # ignore "File(s) up-to-date" files = p4.run_sync rescue P4Exception p4.errors.each { |e| puts( e ) } ensure p4.disconnect end </programlisting> </section> <section xml:id="ruby.p4.exception_level.eq"> <title>p4.exception_level= anInteger -> anInteger</title> <para> Configures the events which give rise to exceptions. The following three levels are supported: </para> <itemizedlist> <listitem> <para> <literal>P4::RAISE_NONE</literal> disables all exception raising and makes the interface completely procedural. </para> </listitem> <listitem> <para> <literal>P4::RAISE_ERRORS</literal> causes exceptions to be raised only when errors are encountered. </para> </listitem> <listitem> <para> <literal>P4::RAISE_ALL</literal> causes exceptions to be raised for both errors and warnings. This is the default. </para> <programlisting language="ruby"> 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 </programlisting> </listitem> </itemizedlist> </section> <section xml:id="ruby.p4.exception_level"> <title>p4.exception_level -> aNumber</title> <para> Returns the current exception level. </para> </section> <section xml:id="ruby.p4.fetch_spectype"> <title>p4.fetch_<spectype>( [name] ) -> aP4::Spec</title> <para> The <methodname>fetch_<replaceable><spectype></replaceable></methodname> methods are shortcut methods that allow you to quickly fetch the definitions of clients, labels, branches, etc. They're equivalent to: </para> <programlisting language="ruby"> p4.run( "<replaceable><spectype></replaceable>", '-o', ... ).shift </programlisting> <para> For example: </para> <programlisting language="ruby"> 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 </programlisting> </section> <section xml:id="ruby.p4.format_spec"> <title>p4.format_spec( "<spectype>", aHash )-> aString</title> <para> Converts the fields in a hash containing the elements of a Perforce form (spec) into the string representation familiar to users. </para> <para> The first argument is the type of spec to format: for example, <literal>client</literal>, <literal>branch</literal>, <literal>label</literal>, and so on. The second argument is the hash to parse. </para> <para> There are shortcuts available for this method. You can use: </para> <programlisting language="ruby"> p4.format_<replaceable><spectype></replaceable>( hash ) </programlisting> <para> instead of: </para> <programlisting language="ruby"> p4.format_spec( "<replaceable><spectype></replaceable>", hash ) </programlisting> <para> where <replaceable><spectype></replaceable> is the name of a Perforce spec, such as <literal>client</literal>, <literal>label</literal>, etc. </para> </section> <section xml:id="ruby.p4.format_spectype"> <title>p4.format_<spectype> aHash -> aHash</title> <para> The <methodname>format_<replaceable><spectype></replaceable></methodname> methods are shortcut methods that allow you to quickly fetch the definitions of clients, labels, branches, etc. They're equivalent to: </para> <programlisting language="ruby"> p4.format_spec( "<replaceable><spectype></replaceable>", aHash ) </programlisting> </section> <section xml:id="ruby.p4.handler.eq"> <title>p4.handler= aHandler -> aHandler</title> <para> Set the current output handler. This should be a subclass of <classname>P4::OutputHandler</classname>. </para> </section> <section xml:id="ruby.p4.handler"> <title>p4.handler -> aHandler</title> <para> Get the current output handler. </para> </section> <section xml:id="ruby.p4.host.eq"> <title>p4.host= aString -> aString</title> <para> Set the name of the current host. If not called, defaults to the value of <envar>P4HOST</envar> taken from any <envar>P4CONFIG</envar> file present, or from the environment as per the usual Perforce convention. Must be called before connecting to the Perforce server. </para> <programlisting language="ruby"> p4 = P4.new p4.host = "workstation123.perforce.com" p4.connect ... p4.disconnect </programlisting> </section> <section xml:id="ruby.p4.host"> <title>p4.host -> aString</title> <para> Get the current hostname. </para> <programlisting language="ruby"> p4 = P4.new puts( p4.host ) </programlisting> </section> <section xml:id="ruby.p4.input.eq"> <title>p4.input= ( aString|aHash|anArray ) -> aString|aHash|anArray</title> <para> Store input for the next command. </para> <para> Call this method prior to running a command requiring input from the user. When the command requests input, the specified data will be supplied to the command. Typically, commands of the form <command>p4 <replaceable>cmd</replaceable> -i</command> are invoked using the <methodname>P4#save_<replaceable><spectype></replaceable>()</methodname> methods, which call <methodname>P4#input()</methodname> internally; there is no need to call <methodname>P4#input()</methodname> when using the <methodname>P4#save_<replaceable><spectype></replaceable>()</methodname> shortcuts. </para> <para> You may pass a string, a hash, or (for commands that take multiple inputs from the user) an array of strings or hashes. If you pass an array, note that the array will be shifted each time Perforce asks the user for input. </para> <programlisting language="ruby"> p4 = P4.new p4.connect change = p4.run_change( "-o" ).shift change[ "Description" ] = "Autosubmitted changelist" p4.input = change p4.run_submit( "-i" ) p4.disconnect </programlisting> </section> <section xml:id="ruby.p4.maxlocktime.eq"> <title>p4.maxlocktime= anInteger -> anInteger</title> <para> Limit the amount of time (in milliseconds) spent during data scans to prevent the server from locking tables for too long. Commands that take longer than the limit will be aborted. The limit remains in force until you disable it by setting it to zero. See <command>p4 help maxlocktime</command> for information on the commands that support this limit. </para> <programlisting language="ruby"> p4 = P4.new begin p4.connect p4.maxlocktime = 10000 # 10 seconds files = p4.run_sync rescue P4Exception => ex p4.errors.each { |e| $stderr.puts( e ) } ensure p4.disconnectend </programlisting> </section> <section xml:id="ruby.p4.maxlocktime"> <title>p4.maxlocktime -> anInteger</title> <para> Get the current <literal>maxlocktime</literal> setting. </para> <programlisting language="ruby"> p4 = P4.new puts( p4.maxlocktime ) </programlisting> </section> <section xml:id="ruby.p4.maxresults.eq"> <title>p4.maxresults= anInteger -> anInteger</title> <para> Limit the number of results Perforce permits 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 <command>p4 help maxresults</command> for information on the commands that support this limit. </para> <programlisting language="ruby"> 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 </programlisting> </section> <section xml:id="ruby.p4.maxresults"> <title>p4.maxresults -> anInteger</title> <para> Get the current <literal>maxresults</literal> setting. </para> <programlisting language="ruby"> p4 = P4.new puts( p4.maxresults ) </programlisting> </section> <section xml:id="ruby.p4.maxscanrows.eq"> <title>p4.maxscanrows= anInteger -> anInteger</title> <para> 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 <command>p4 help maxscanrows</command> for information on the commands that support this limit. </para> <programlisting language="ruby"> 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.disconnectend </programlisting> </section> <section xml:id="ruby.p4.maxscanrows"> <title>p4.maxscanrows -> anInteger</title> <para> Get the current <literal>maxscanrows</literal> setting. </para> <programlisting language="ruby"> p4 = P4.new puts( p4.maxscanrows ) </programlisting> </section> <section xml:id="ruby.p4.messages"> <title>p4.messages -> aP4::Message</title> <para> Returns a message from the Perforce Server in the form of a <classname>P4::Message</classname> object. </para> <programlisting language="ruby"> p4 = P4.new p4.exception_level = P4::RAISE_NONE p4.run_sync p4.run_sync # this second sync should return "File(s) up-to-date." w = p4.messages[0] puts ( w.to_s ) </programlisting> </section> <section xml:id="ruby.p4.p4config_file"> <title>p4.p4config_file -> aString</title> <para> Get the path to the current <envar>P4CONFIG</envar> file. </para> <programlisting language="ruby"> p4 = P4.new puts( p4.p4config_file ) </programlisting> </section> <section xml:id="ruby.p4.parse_spectype"> <title>p4.parse_<spectype>( aString ) -> aP4::Spec</title> <para> This is equivalent to: </para> <programlisting language="ruby"> p4.parse_spec( "<replaceable><spectype></replaceable>", aString ) </programlisting> </section> <section xml:id="ruby.p4.parse_spec"> <title>p4.parse_spec( "<spectype>", aString ) -> aP4::Spec</title> <para> Parses a Perforce form (spec) in text form into a Ruby hash using the spec definition obtained from the server. </para> <para> The first argument is the type of spec to parse: <literal>client</literal>, <literal>branch</literal>, <literal>label</literal>, and so on. The second argument is the string buffer to parse. </para> <para> Note that there are shortcuts available for this method. You can use: </para> <programlisting language="ruby"> p4.parse_<replaceable><spectype></replaceable>( buf ) </programlisting> <para> instead of: </para> <programlisting language="ruby"> p4.parse_spec( "<replaceable><spectype></replaceable>", buf ) </programlisting> <para> Where <replaceable><spectype></replaceable> is one of <literal>client</literal>, <literal>branch</literal>, <literal>label</literal>, and so on. </para> </section> <section xml:id="ruby.p4.password.eq"> <title>p4.password= aString -> aString</title> <para> Set your Perforce password, in plain text. If not used, takes the value of <envar>P4PASSWD</envar> from any <envar>P4CONFIG</envar> file in effect, or from the environment according to the normal Perforce conventions. This password will also be used if you later call <methodname>p4.run_login</methodname> to login using the 2003.2 and later ticket system. </para> <programlisting language="ruby"> p4 = P4.new p4.password = "mypass" p4.connect p4.run_login </programlisting> </section> <section xml:id="ruby.p4.password"> <title>p4.password -> aString</title> <para> Get the current password or ticket. This may be the password in plain text, or if you've used <methodname>P4#run_login()</methodname>, it'll be the value of the ticket you've been allocated by the server. </para> <programlisting language="ruby"> p4 = P4.new puts( p4.password ) </programlisting> </section> <section xml:id="ruby.p4.port.eq"> <title>p4.port= aString -> aString</title> <para> Set the host and port of the Perforce server you want to connect to. If not called, defaults to the value of <envar>P4PORT</envar> in any <envar>P4CONFIG</envar> file in effect, and then to the value of <envar>P4PORT</envar> taken from the environment. </para> <programlisting language="ruby"> p4 = P4.new p4.port = "localhost:1666" p4.connect ... p4.disconnect </programlisting> </section> <section xml:id="ruby.p4.port"> <title>p4.port -> aString</title> <para> Get the host and port of the current Perforce server. </para> <programlisting language="ruby"> p4 = P4.new puts( p4.port ) </programlisting> </section> <section xml:id="ruby.p4.prog.eq"> <title>p4.prog= aString -> aString</title> <para> Set the name of the program, as reported to Perforce system administrators running <command>p4 monitor show -e</command> in Perforce 2004.2 or later releases. </para> <programlisting language="ruby"> p4 = P4.new p4.prog = "sync-script" p4.connect ... p4.disconnect </programlisting> </section> <section xml:id="ruby.p4.prog"> <title>p4.prog -> aString</title> <para> Get the name of the program as reported to the Perforce Server. </para> <programlisting language="ruby"> p4 = P4.new p4.prog = "sync-script" puts( p4.prog ) </programlisting> </section> <section xml:id="ruby.p4.progress.eq"> <title>p4.progress= aProgress -> aProgress</title> <para> Set the current progress indicator. This should be a subclass of <classname>P4::Progress</classname>. </para> </section> <section xml:id="ruby.p4.progress"> <title>p4.progress -> aProgress</title> <para> Get the current progress indicator. </para> </section> <section xml:id="ruby.p4.run_cmd"> <title>p4.run_<cmd>( arguments ) -> anArray</title> <para> This is equivalent to: </para> <programlisting language="ruby"> p4.run( "<replaceable>cmd</replaceable>", arguments... ) </programlisting> </section> <section xml:id="ruby.p4.run"> <title>p4.run( aCommand, arguments... ) -> anArray</title> <para> 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 as long as they can be converted to strings by <literal>to_s</literal>. </para> <para> The <methodname>P4#run()</methodname> method returns an array of results whether the command succeeds or fails; the array may, however, be empty. Whether the elements of the array are strings or hashes depends on (a) server support for tagged output for the command, and (b) whether tagged output was disabled by calling <literal>p4.tagged = false</literal>. </para> <para> In the event of errors or warnings, and depending on the exception level in force at the time, <methodname>P4#run()</methodname> will raise a <exceptionname>P4Exception</exceptionname>. If the current exception level is below the threshold for the error/warning, <methodname>P4#run()</methodname> returns the output as normal and the caller must explicitly review <methodname>P4#errors()</methodname> and <methodname>P4#warnings()</methodname> to check for errors or warnings. </para> <programlisting language="ruby"> p4 = P4.new p4.connect spec = p4.run( "client", "-o" ).shift p4.disconnect </programlisting> <para> Shortcuts are available for <methodname>P4#run()</methodname>. For example: </para> <programlisting language="ruby"> p4.run_<replaceable>command</replaceable>( args ) </programlisting> <para> is equivalent to: </para> <programlisting language="ruby"> p4.run( "<replaceable>command</replaceable>", args ) </programlisting> <para> There are also some shortcuts for common commands such as editing Perforce forms and submitting. Consequently, this: </para> <programlisting language="ruby"> p4 = P4.new p4.connect clientspec = p4.run_client( "-o" ).shift clientspec[ "Description" ] = "Build client" p4.input = clientspec p4.run_client( "-i" ) p4.disconnect </programlisting> <para> may be shortened to: </para> <programlisting language="ruby"> p4 = P4.new p4.connect clientspec = p4.fetch_client clientspec[ "Description" ] = "Build client" p4.save_client( clientspec ) p4.disconnect </programlisting> <para> The following are equivalent: </para> <informaltable> <tgroup cols="2"> <colspec colname="method" colwidth="*"/> <colspec colname="description" colwidth="3*"/> <tbody> <row> <entry> <para> <code>p4.delete_<replaceable><spectype></replaceable>()</code> </para> </entry> <entry> <para> <code>p4.run( "<replaceable><spectype></replaceable>", "-d" )</code> </para> </entry> </row> <row> <entry> <para> <code>p4.fetch_<replaceable><spectype></replaceable>()</code> </para> </entry> <entry> <para> <code>p4.run( "<replaceable><spectype></replaceable>", "-o" ).shift</code> </para> </entry> </row> <row> <entry> <para> <code>p4.save_<replaceable><spectype></replaceable>( spec )</code> </para> </entry> <entry> <para> <code>p4.input = specp4.run( "<replaceable><spectype></replaceable>", "-i" )</code> </para> </entry> </row> </tbody> </tgroup> </informaltable> <para> As the commands associated with <methodname>P4#fetch_<replaceable><spectype></replaceable>()</methodname> typically return only one item, these methods do not return an array, but instead return the first result element. </para> <para> For convenience in submitting changelists, changes returned by <methodname>P4#fetch_change()</methodname> can be passed to <methodname>P4#run_submit</methodname>. For example: </para> <programlisting language="ruby"> p4 = P4.new p4.connect spec = p4.fetch_changespec[ "Description" ] = "Automated change" p4.run_submit( spec ) p4.disconnect </programlisting> </section> <section xml:id="ruby.p4.run_filelog"> <title>p4.run_filelog( fileSpec ) -> anArray</title> <para> Runs a <command>p4 filelog</command> on the <literal>fileSpec</literal> provided and returns an array of <classname>P4::DepotFile</classname> results when executed in tagged mode, and an array of strings when executed in non-tagged mode. By default, the raw output of <command>p4 filelog</command> is tagged; this method restructures the output into a more user-friendly (and object-oriented) form. </para> <programlisting language="ruby"> p4 = P4.new 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 </programlisting> </section> <section xml:id="ruby.p4.run_login"> <title>p4.run_login( arg... ) -> anArray</title> <para> Runs <command>p4 login</command> using a password or ticket set by the user. </para> </section> <section xml:id="ruby.p4.run_password"> <title>p4.run_password( oldpass, newpass ) -> anArray</title> <para> A thin wrapper to make it easy to change your password. This method is (literally) equivalent to the following code: </para> <programlisting language="ruby"> p4.input( [ oldpass, newpass, newpass ] ) p4.run( "password" ) </programlisting> <para> For example: </para> <programlisting language="ruby"> 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 </programlisting> </section> <section xml:id="ruby.p4.run_resolve"> <title>p4.run_resolve( args ) [ block ] -> anArray</title> <para> Interface to <command>p4 resolve</command>. Without a block, simply runs a non-interactive resolve (typically an automatic resolve). </para> <programlisting language="ruby"> p4.run_resolve( "-at" ) </programlisting> <para> When a block is supplied, the block is invoked once for each merge scheduled by Perforce. For each merge, a <classname>P4::MergeData</classname> object is passed to the block. This object contains the context of the merge. </para> <para> The block determines the outcome of the merge by evaluating to one of the following strings: </para> <informaltable> <tgroup cols="2"> <colspec colname="string" colwidth="*"/> <colspec colname="meaning" colwidth="6*"/> <thead> <row> <entry> <para> Block string </para> </entry> <entry> <para> Meaning </para> </entry> </row> </thead> <tbody> <row> <entry> <para> <literal>ay</literal> </para> </entry> <entry> <para> Accept Yours. </para> </entry> </row> <row> <entry> <para> <literal>at</literal> </para> </entry> <entry> <para> Accept Theirs. </para> </entry> </row> <row> <entry> <para> <literal>am</literal> </para> </entry> <entry> <para> Accept Merge result. </para> </entry> </row> <row> <entry> <para> <literal>ae</literal> </para> </entry> <entry> <para> Accept Edited result. </para> </entry> </row> <row> <entry> <para> <literal>s</literal> </para> </entry> <entry> <para> Skip this merge. </para> </entry> </row> <row> <entry> <para> <literal>q</literal> </para> </entry> <entry> <para> Abort the merge. </para> </entry> </row> </tbody> </tgroup> </informaltable> <para> For example: </para> <programlisting language="ruby"> 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" ) 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 </programlisting> </section> <section xml:id="ruby.p4.run_submit"> <title>p4.run_submit( [aHash], [arg...] ) -> anArray</title> <para> Submit a changelist to the server. To submit a changelist, set the fields of the changelist as required and supply any flags:. </para> <programlisting language="ruby"> change = p4.fetch_change change._description = "Some description" p4.run_submit( "-r", change ) </programlisting> <para> You can also submit a changelist by supplying the arguments as you would on the command line: </para> <programlisting language="ruby"> p4.run_submit( "-d", "Some description", "somedir/..." ) </programlisting> </section> <section xml:id="ruby.p4.run_tickets"> <title>p4.run_tickets( ) -> anArray</title> <para> Get a list of tickets from the local tickets file. Each ticket is a hash object with fields for <literal>Host</literal>, <literal>User</literal>, and <literal>Ticket</literal>. </para> </section> <section xml:id="ruby.p4.save_spectype"> <title>p4.save_<spectype>( hashOrString, [options] ) -> anArray</title> <para> The <methodname>save_<replaceable><spectype></replaceable></methodname> methods are shortcut methods that allow you to quickly update the definitions of clients, labels, branches, etc. They are equivalent to: </para> <programlisting language="ruby"> p4.input = hashOrStringp4.run( "<replaceable><spectype></replaceable>", "-i" ) </programlisting> <para> For example: </para> <programlisting language="ruby"> 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 </programlisting> </section> <section xml:id="ruby.p4.server_case_sensitive"> <title>p4.server_case_sensitive? -> aBool</title> <para> Detects whether or not the server is case-sensitive. </para> </section> <section xml:id="ruby.p4.server_level"> <title>p4.server_level -> anInteger</title> <para> Returns the current Perforce server level. Each iteration of the Perforce Server is given a level number. As part of the initial communication this value is passed between the client application and the Perforce Server. This value is used to determine the communication that the Perforce Server will understand. All subsequent requests can therefore be tailored to meet the requirements of this Server level. </para> <para> For more information, see: </para> <para> <link xlink:href="http://kb.perforce.com/article/571">http://kb.perforce.com/article/571</link> </para> </section> <section xml:id="ruby.p4.server_unicode"> <title>p4.server_unicode? -> aBool</title> <para> Detects whether or not the server is in unicode mode. </para> </section> <section xml:id="ruby.p4.set_env"> <title>p4.set_env= ( aString, aString ) -> aBool</title> <para> On Windows or OS X, set a variable in the registry or user preferences. To unset a variable, pass an empty string as the second argument. On other platforms, an exception is raised. </para> <programlisting language="ruby"> p4 = P4.new p4.set_env = ( "P4CLIENT", "my_workspace" ) p4.set_env = ( "P4CLIENT", "" ) </programlisting> </section> <section xml:id="ruby.p4.streams.eq"> <title>p4.streams= -> aBool</title> <para> Enable or disable support for streams. By default, streams support is enabled at 2011.1 or higher (<methodname>P4#api_level()</methodname> >= 70). Raises a <exceptionname>P4Exception</exceptionname> if you attempt to enable streams on a pre-2011.1 server. You can enable or disable support for streams both before and after connecting to the server. </para> <programlisting language="ruby"> p4 = P4.new p4.streams = false </programlisting> </section> <section xml:id="ruby.p4.streams"> <title>p4.streams? -> aBool</title> <para> Detects whether or not support for Perforce Streams is enabled. </para> <programlisting language="ruby"> p4 = P4.new puts ( p4.streams? ) p4.tagged = false puts ( p4.streams? ) </programlisting> </section> <section xml:id="ruby.p4.tagged"> <title>p4.tagged( aBool ) { block }</title> <para> Temporarily toggles the use of tagged output for the duration of the block, and then resets it when the block terminates. </para> </section> <section xml:id="ruby.p4.tagged.eq"> <title>p4.tagged= aBool -> aBool</title> <para> Sets tagged output. By default, tagged output is on. </para> <programlisting language="ruby"> p4 = P4.new p4.tagged = false </programlisting> </section> <section xml:id="ruby.p4.tagged.q"> <title>p4.tagged? -> aBool</title> <para> Detects whether or not you are in tagged mode. </para> <programlisting language="ruby"> p4 = P4.new puts ( p4.tagged? ) p4.tagged = false puts ( p4.tagged? ) </programlisting> </section> <section xml:id="ruby.p4.ticketfile.eq"> <title>p4.ticketfile= aString -> aString</title> <para> Sets the location of the <envar>P4TICKETS</envar> file. </para> <programlisting language="ruby"> p4 = P4.new p4.ticketfile = "/home/bruno/tickets" </programlisting> </section> <section xml:id="ruby.p4.ticketfile"> <title>p4.ticketfile -> aString</title> <para> Get the path to the current <envar>P4TICKETS</envar> file. </para> <programlisting language="ruby"> p4 = P4.new puts( p4.ticketfile ) </programlisting> </section> <section xml:id="ruby.p4.track.eq"> <title>p4.track= -> aBool</title> <para> Instruct the server to return messages containing performance tracking information. By default, server tracking is disabled. </para> <programlisting language="ruby"> p4 = P4.new p4.track = true </programlisting> </section> <section xml:id="ruby.p4.track"> <title>p4.track? -> aBool</title> <para> Detects whether or not performance tracking is enabled. </para> <programlisting language="ruby"> p4 = P4.new p4.track = true puts ( p4.track? ) p4.track = false puts ( p4.track? ) </programlisting> </section> <section xml:id="ruby.p4.track_output"> <title>p4.track_output -> anArray</title> <para> If performance tracking is enabled with <literal>p4.track=</literal>, returns a list of strings corresponding to the performance tracking output for the most recently-executed command. </para> <programlisting language="ruby"> p4 = P4.new p4.track = true p4.run_info puts ( p4.track_output[0].slice(0,3) ) # should be "rpc" </programlisting> </section> <section xml:id="ruby.p4.user.eq"> <title>p4.user= aString -> aString</title> <para> Set the Perforce username. If not called, defaults to the value of <envar>P4USER</envar> taken from any <envar>P4CONFIG</envar> file present, or from the environment as per the usual Perforce convention. Must be called before connecting to the Perforce server. </para> <programlisting language="ruby"> p4 = P4.new p4.user = "bruno" p4.connect ... p4.disconnect </programlisting> </section> <section xml:id="ruby.p4.user"> <title>p4.user -> aString</title> <para> Returns the current Perforce username. </para> <programlisting language="ruby"> p4 = P4.new puts( p4.user ) </programlisting> </section> <section xml:id="ruby.p4.version.eq"> <title>p4.version= aString -> aString</title> <para> Set the version of your script, as reported to the Perforce Server. </para> </section> <section xml:id="ruby.p4.version"> <title>p4.version -> aString</title> <para> Get the version of your script, as reported to the Perforce Server. </para> </section> <section xml:id="ruby.p4.warnings"> <title>p4.warnings -> anArray</title> <para> Returns the array of warnings that arose during execution of the last command. </para> <programlisting language="ruby"> 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 </programlisting> </section> </section> </chapter> <chapter xml:id="ruby.p4_exception"> <title>Class P4Exception</title> <para> Shallow subclass of <exceptionname>RuntimeError</exceptionname> to be used for catching Perforce-specific errors. Doesn't contain any extra information. See <methodname>P4#errors()</methodname> and <methodname>P4#warnings</methodname> for details of the errors giving rise to the exception. </para> <section xml:id="ruby.p4_exception-class_methods"> <title>Class Methods</title> <para> None. </para> </section> <section xml:id="ruby.p4_exception-instance_methods"> <title>Instance Methods</title> <para> None. </para> </section> </chapter> <chapter xml:id="ruby.p4_depotfile"> <title>Class P4::DepotFile</title> <section xml:id="ruby.p4_depotfile-description"> <title>Description</title> <para> Utility class providing easy access to the attributes of a file in a Perforce depot. Each <classname>P4::DepotFile</classname> object contains summary information about the file, and a list of revisions (<classname>P4::Revision</classname> objects) of that file. Currently, only the <methodname>P4#run_filelog()</methodname> method returns an array of <classname>P4::DepotFile</classname> objects. </para> </section> <section xml:id="ruby.p4_depotfile-class_methods"> <title>Class Methods</title> <para> None. </para> </section> <section xml:id="ruby.p4_depotfile-instance_methods"> <title>Instance Methods</title> <section xml:id="ruby.p4_depotfile.depot_file"> <title>df.depot_file -> aString</title> <para> Returns the name of the depot file to which this object refers. </para> </section> <section xml:id="ruby.p4_depotfile.each_revision"> <title>df.each_revision { |rev| block } -> revArray</title> <para> Iterates over each revision of the depot file. </para> </section> <section xml:id="ruby.p4_depotfile.revisions"> <title>df.revisions -> aArray</title> <para> Returns an array of revisions of the depot file. </para> </section> </section> </chapter> <chapter xml:id="ruby.p4_revision"> <title>Class P4::Revision</title> <section xml:id="ruby.p4_revision-description"> <title>Description</title> <para> Utility class providing easy access to the revisions of a file in a Perforce depot. <classname>P4::Revision</classname> objects can store basic information about revisions and a list of the integrations for that revision. Created by <methodname>P4#run_filelog()</methodname>. </para> </section> <section xml:id="ruby.p4_revision-class_methods"> <title>Class Methods</title> <para> None. </para> </section> <section xml:id="ruby.p4_revision-instance_methods"> <title>Instance Methods</title> <section xml:id="ruby.p4_revision.action"> <title>rev.action -> aString</title> <para> Returns the name of the action which gave rise to this revision of the file. </para> </section> <section xml:id="ruby.p4_revision.change"> <title>rev.change -> aNumber</title> <para> Returns the change number that gave rise to this revision of the file. </para> </section> <section xml:id="ruby.p4_revision.client"> <title>rev.client -> aString</title> <para> Returns the name of the client from which this revision was submitted. </para> </section> <section xml:id="ruby.p4_revision.depot_file"> <title>rev.depot_file -> aString</title> <para> Returns the name of the depot file to which this object refers. </para> </section> <section xml:id="ruby.p4_revision.desc"> <title>rev.desc -> aString</title> <para> Returns the description of the change which created this revision. Note that only the first 31 characters are returned unless you use <command>p4 filelog -L</command> for the first 250 characters, or <command>p4 filelog -l</command> for the full text. </para> </section> <section xml:id="ruby.p4_revision.digest"> <title>rev.digest -> aString</title> <para> Returns the MD5 digest for this revision of the file. </para> </section> <section xml:id="ruby.p4_revision.each_integration"> <title>rev.each_integration { |integ| block } -> integArray</title> <para> Iterates over each the integration records for this revision of the depot file. </para> </section> <section xml:id="ruby.p4_revision.filesize"> <title>rev.filesize -> aNumber</title> <para> Returns size of this revision. </para> </section> <section xml:id="ruby.p4_revision.integrations"> <title>rev.integrations -> integArray</title> <para> Returns the list of integrations for this revision. </para> </section> <section xml:id="ruby.p4_revision.rev"> <title>rev.rev -> aNumber</title> <para> Returns the number of this revision of the file. </para> </section> <section xml:id="ruby.p4_revision.time"> <title>rev.time -> aTime</title> <para> Returns the date/time that this revision was created. </para> </section> <section xml:id="ruby.p4_revision.type"> <title>rev.type -> aString</title> <para> Returns this revision's Perforce filetype. </para> </section> <section xml:id="ruby.p4_revision.user"> <title>rev.user -> aString</title> <para> Returns the name of the user who created this revision. </para> </section> </section> </chapter> <chapter xml:id="ruby.p4_integration"> <title>Class P4::Integration</title> <section xml:id="ruby.p4_integration-description"> <title>Description</title> <para> Utility class providing easy access to the details of an integration record. Created by <methodname>P4#run_filelog()</methodname>. </para> </section> <section xml:id="ruby.p4_integration-class_methods"> <title>Class Methods</title> <para> None. </para> </section> <section xml:id="ruby.p4_integration-instance_methods"> <title>Instance Methods</title> <section xml:id="ruby.p4_integration.how"> <title>integ.how -> aString</title> <para> Returns the type of the integration record - how that record was created. </para> </section> <section xml:id="ruby.p4_integration.file"> <title>integ.file -> aPath</title> <para> Returns the path to the file being integrated to/from. </para> </section> <section xml:id="ruby.p4_integration.srev"> <title>integ.srev -> aNumber</title> <para> Returns the start revision number used for this integration. </para> </section> <section xml:id="ruby.p4_integration.erev"> <title>integ.erev -> aNumber</title> <para> Returns the end revision number used for this integration. </para> </section> </section> </chapter> <chapter xml:id="ruby.p4_map"> <title>Class P4::Map</title> <section xml:id="ruby.p4_map-description"> <title>Description</title> <para> The <classname>P4::Map</classname> class allows users to create and work with Perforce mappings, without requiring a connection to a Perforce server. </para> </section> <section xml:id="ruby.p4_map-class_methods"> <title>Class Methods</title> <section xml:id="ruby.p4_map.new"> <title>Map.new ( [ anArray ] ) -> aMap</title> <para> Constructs a new <classname>P4::Map</classname> object. </para> </section> <section xml:id="ruby.p4_map.join"> <title>Map.join ( map1, map2 ) -> aMap</title> <para> Join two <classname>P4::Map</classname> objects and create a third. </para> <para> The new map is composed of the left-hand side of the first mapping, as joined to the right-hand side of the second mapping. For example: </para> <programlisting language="ruby"> # Map depot syntax to client syntax client_map = P4::Map.new client_map.insert( "//depot/main/...", "//client/..." ) # Map client syntax to local syntax client_root = P4::Map.new client_root.insert( "//client/...", "/home/bruno/workspace/..." ) # Join the previous mappings to map depot syntax to local syntax local_map = P4::Map.join( client_map, client_root ) local_path = local_map.translate( "//depot/main/www/index.html" ) # local_path is now /home/bruno/workspace/www/index.html </programlisting> </section> </section> <section xml:id="ruby.p4_map-instance_methods"> <title>Instance Methods</title> <section xml:id="ruby.p4_map.clear"> <title>map.clear -> true</title> <para> Empty a map. </para> </section> <section xml:id="ruby.p4_map.count"> <title>map.count -> anInteger</title> <para> Return the number of entries in a map. </para> </section> <section xml:id="ruby.p4_map.empty"> <title>map.empty? -> aBool</title> <para> Test whether a map object is empty. </para> </section> <section xml:id="ruby.p4_map.insert"> <title>map.insert( aString, [ aString ] ) -> aMap</title> <para> Inserts an entry into the map. </para> <para> May be called with one or two arguments. If called with one argument, the string is assumed to be a string containing either a half-map, or a string containing both halves of the mapping. In this form, mappings with embedded spaces must be quoted. If called with two arguments, each argument is assumed to be half of the mapping, and quotes are optional. </para> <programlisting language="ruby"> # called with two arguments: map.insert( "//depot/main/...", "//client/..." ) # called with one argument containing both halves of the mapping: map.insert( "//depot/live/... //client/live/..." ) # called with one argument containing a half-map: # This call produces the mapping "depot/... depot/..." map.insert( "depot/..." ) </programlisting> </section> <section xml:id="ruby.p4_map.translate"> <title>map.translate ( aString, [ aBool ] )-> aString</title> <para> Translate a string through a map, and return the result. If the optional second argument is true, translate forward, and if it is false, translate in the reverse direction. By default, translation is in the forward direction. </para> </section> <section xml:id="ruby.p4_map.includes"> <title>map.includes? ( aString ) -> aBool</title> <para> Tests whether a path is mapped or not. </para> <programlisting language="ruby"> if( map.includes?( "//depot/main/..." ) ) ... end </programlisting> </section> <section xml:id="ruby.p4_map.reverse"> <title>map.reverse -> aMap</title> <para> Return a new <classname>P4::Map</classname> object with the left and right sides of the mapping swapped. The original object is unchanged. </para> </section> <section xml:id="ruby.p4_map.lhs"> <title>map.lhs -> anArray</title> <para> Returns the left side of a mapping as an array. </para> </section> <section xml:id="ruby.p4_map.rhs"> <title>map.rhs -> anArray</title> <para> Returns the right side of a mapping as an array. </para> </section> <section xml:id="ruby.p4_map.to_a"> <title>map.to_a -> anArray</title> <para> Returns the map as an array. </para> </section> </section> </chapter> <chapter xml:id="ruby.p4_mergedata"> <title>Class P4::MergeData</title> <section xml:id="ruby.p4_mergedata-description"> <title>Description</title> <para> Class containing the context for an individual merge during execution of a <command>p4 resolve</command>. </para> </section> <section xml:id="ruby.p4_mergedata-class_methods"> <title>Class Methods</title> <para> None. </para> </section> <section xml:id="ruby.p4_mergedata-instance_methods"> <title>Instance Methods</title> <section xml:id="ruby.p4_mergedata.your_name"> <title>md.your_name() -> aString</title> <para> Returns the name of "your" file in the merge. This is typically a path to a file in the workspace. </para> <programlisting language="ruby"> p4.run_resolve() do |md| yours = md.your_name md.merge_hint # merge result end </programlisting> </section> <section xml:id="ruby.p4_mergedata.their_name"> <title>md.their_name() -> aString</title> <para> Returns the name of "their" file in the merge. This is typically a path to a file in the depot. </para> <programlisting language="ruby"> p4.run_resolve() do |md| theirs = md.their_name md.merge_hint # merge result end </programlisting> </section> <section xml:id="ruby.p4_mergedata.base_name"> <title>md.base_name() -> aString</title> <para> Returns the name of the "base" file in the merge. This is typically a path to a file in the depot. </para> <programlisting language="ruby"> p4.run_resolve() do |md| base = md.base_name md.merge_hint # merge result end </programlisting> </section> <section xml:id="ruby.p4_mergedata.your_path"> <title>md.your_path() -> aString</title> <para> Returns the path of "your" file in the merge. This is typically a path to a file in the workspace. </para> <programlisting language="ruby"> p4.run_resolve() do |md| your_path = md.your_path md.merge_hint # merge result end </programlisting> </section> <section xml:id="ruby.p4_mergedata.their_path"> <title>md.their_path() -> aString</title> <para> Returns the path of "their" file in the merge. This is typically a path to a temporary file on your local machine in which the contents of <methodname>P4::MergeData#their_name()</methodname> have been loaded. </para> <programlisting language="ruby"> p4.run_resolve() do |md| their_name = md.their_name their_file = File.open( md.their_path ) md.merge_hint # merge result end </programlisting> </section> <section xml:id="ruby.p4_mergedata.base_path"> <title>md.base_path() -> aString</title> <para> Returns the path of the base file in the merge. This is typically a path to a temporary file on your local machine in which the contents of <methodname>P4::MergeData#base_name()</methodname> have been loaded. </para> <programlisting language="ruby"> p4.run_resolve() do |md| base_name = md.base_name base_file = File.open( md.base_path ) md.merge_hint # merge result end </programlisting> </section> <section xml:id="ruby.p4_mergedata.result_path"> <title>md.result_path() -> aString</title> <para> Returns the path to the merge result. This is typically a path to a temporary file on your local machine in which the contents of the automatic merge performed by the server have been loaded. </para> <programlisting language="ruby"> p4.run_resolve() do |md| result_file = File.open( md.result_path ) md.merge_hint # merge resultend </programlisting> </section> <section xml:id="ruby.p4_mergedata.merge_hint"> <title>md.merge_hint() -> aString</title> <para> Returns the hint from the server as to how it thinks you might best resolve this merge. </para> <programlisting language="ruby"> p4.run_resolve() do |md| puts ( md.merge_hint ) # merge result end </programlisting> </section> <section xml:id="ruby.p4_mergedata.run_merge"> <title>md.run_merge() -> aBool</title> <para> If the environment variable <envar>P4MERGE</envar> is defined, <methodname>P4::MergeData#run_merge()</methodname> invokes the specified program and returns a boolean based on the return value of that program. </para> <programlisting language="ruby"> p4.run_resolve() do |md| if ( md.run_merge() ) "am" else "s" end end </programlisting> </section> </section> </chapter> <chapter xml:id="ruby.p4_message"> <title>Class P4::Message</title> <section xml:id="ruby.p4_message-description"> <title>Description</title> <para> <classname>P4::Message</classname> objects contain error or other diagnostic messages from the Perforce Server; retrieve them by using the <methodname>P4#messages()</methodname> method. </para> <para> Script writers can test the severity of the messages in order to determine if the server message consisted of command output (<literal>E_INFO</literal>), warnings, (<literal>E_WARN</literal>), or errors (<literal>E_FAILED</literal>/<literal>E_FATAL</literal>). </para> </section> <section xml:id="ruby.p4_message-class_methods"> <title>Class methods</title> <para> None. </para> </section> <section xml:id="ruby.p4_message-instance_methods"> <title>Instance methods</title> <section xml:id="ruby.p4_message.severity"> <title>message.severity() -> anInteger</title> <para> Severity of the message, which is one of the following values: </para> <informaltable> <tgroup cols="2"> <colspec colname="method" colwidth="*"/> <colspec colname="description" colwidth="5*"/> <thead> <row> <entry> <para> Value </para> </entry> <entry> <para> Meaning </para> </entry> </row> </thead> <tbody> <row> <entry> <para> <literal>E_EMPTY</literal> </para> </entry> <entry> <para> No error </para> </entry> </row> <row> <entry> <para> <literal>E_INFO</literal> </para> </entry> <entry> <para> Informational message only </para> </entry> </row> <row> <entry> <para> <literal>E_WARN</literal> </para> </entry> <entry> <para> Warning message only </para> </entry> </row> <row> <entry> <para> <literal>E_FAILED</literal> </para> </entry> <entry> <para> Command failed </para> </entry> </row> <row> <entry> <para> <literal>E_FATAL</literal> </para> </entry> <entry> <para> Severe error; cannot continue. </para> </entry> </row> </tbody> </tgroup> </informaltable> </section> <section xml:id="ruby.p4_message.generic"> <title>message.generic() -> anInteger</title> <para> Returns the generic class of the error. </para> </section> <section xml:id="ruby.p4_message.msgid"> <title>message.msgid() -> anInteger</title> <para> Returns the unique ID of the message. </para> </section> <section xml:id="ruby.p4_message.to_s"> <title>message.to_s() -> aString</title> <para> Converts the message into a string. </para> </section> <section xml:id="ruby.p4_message.inspect"> <title>message.inspect() -> aString</title> <para> To facilitate debugging, returns a string that holds a formatted representation of the entire <classname>P4::Message</classname> object. </para> </section> </section> </chapter> <chapter xml:id="ruby.p4_outputhandler"> <title>Class P4::OutputHandler</title> <section xml:id="ruby.p4_outputhandler-description"> <title>Description</title> <para> The <classname>P4::OutputHandler</classname> class is a handler class that provides access to streaming output from the server. After defining the output handler, set <methodname>P4#handler()</methodname> to an instance of a subclass of <classname>P4::OutputHandler</classname> (or use a <literal>p4.with_handler( handler )</literal> block) to enable callbacks. </para> <para> By default, <classname>P4::OutputHandler</classname> returns <literal>P4::REPORT</literal> for all output methods. The different return options are: </para> <informaltable> <tgroup cols="2"> <colspec colname="method" colwidth="*"/> <colspec colname="description" colwidth="4*"/> <thead> <row> <entry> <para> Value </para> </entry> <entry> <para> Meaning </para> </entry> </row> </thead> <tbody> <row> <entry> <para> <literal>P4::REPORT</literal> </para> </entry> <entry> <para> Messages added to output. </para> </entry> </row> <row> <entry> <para> <literal>P4::HANDLED</literal> </para> </entry> <entry> <para> Output is handled by class (don't add message to output). </para> </entry> </row> <row> <entry> <para> <literal>P4::CANCEL</literal> </para> </entry> <entry> <para> Operation is marked for cancel, message is added to output. </para> </entry> </row> </tbody> </tgroup> </informaltable> </section> <section xml:id="ruby.p4_outputhandler-class_methods"> <title>Class Methods</title> <section xml:id="ruby.p4_outputhandler.new"> <title>new P4::MyHandler.new -> aP4::OutputHandler</title> <para> Constructs a new subclass of <classname>P4::OutputHandler</classname>. </para> </section> </section> <section xml:id="ruby.p4_outputhandler-instance_methods"> <title>Instance Methods</title> <section xml:id="ruby.p4_outputhandler.outputbinary"> <title>outputBinary -> int</title> <para> Process binary data. </para> </section> <section xml:id="ruby.p4_outputhandler.outputinfo"> <title>outputInfo -> int</title> <para> Process tabular data. </para> </section> <section xml:id="ruby.p4_outputhandler.outputmessage"> <title>outputMessage -> int</title> <para> Process informational or error messages. </para> </section> <section xml:id="ruby.p4_outputhandler.outputstat"> <title>outputStat -> int</title> <para> Process tagged data. </para> </section> <section xml:id="ruby.p4_outputhandler.outputtext"> <title>outputText -> int</title> <para> Process text data. </para> </section> </section> </chapter> <chapter xml:id="ruby.p4_progress"> <title>Class P4::Progress</title> <section xml:id="ruby.p4_progress-description"> <title>Description</title> <para> The <classname>P4::Progress</classname> class is a handler class that provides access to progress indicators from the server. After defining the output handler, set <methodname>P4#progress()</methodname> to an instance of a subclass of <classname>P4::Progress</classname> (or use a <literal>p4.with_progress( progress )</literal> block) to enable callbacks. </para> <para> You must implement all five of the following methods: <methodname>init()</methodname>, <methodname>description()</methodname>, <methodname>update()</methodname>, <methodname>total()</methodname>, and <methodname>done()</methodname>, even if the implementation consists of trivially returning <literal>0</literal>. </para> </section> <section xml:id="ruby.p4_progress-class_methods"> <title>Class Methods</title> <section xml:id="ruby.p4_progress.new"> <title>new P4::MyProgress.new -> aP4::Progress</title> <para> Constructs a new subclass of <classname>P4::Progress</classname>. </para> </section> </section> <section xml:id="ruby.p4_progress-instance_methods"> <title>Instance Methods</title> <section xml:id="ruby.p4_progress.init"> <title>init -> int</title> <para> Initialize progress indicator. </para> </section> <section xml:id="ruby.p4_progress.description"> <title>description -> int</title> <para> Description and type of units to be used for progress reporting. </para> </section> <section xml:id="ruby.p4_progress.update"> <title>update -> int</title> <para> If non-zero, user has requested a cancellation of the operation. </para> </section> <section xml:id="ruby.p4_progress.total"> <title>total -> int</title> <para> Total number of units expected (if known). </para> </section> <section xml:id="ruby.p4_progress.done"> <title>done -> int</title> <para> If non-zero, operation has failed. </para> </section> </section> </chapter> <chapter xml:id="ruby.p4_spec"> <title>Class P4::Spec</title> <section xml:id="ruby.p4_spec-description"> <title>Description</title> <para> The <classname>P4::Spec</classname> class is a hash containing key/value pairs for all the fields in a Perforce form. It provides two things over and above its parent class (Hash): </para> <itemizedlist> <listitem> <para> Fieldname validation. Only valid field names may be set in a <classname>P4::Spec</classname> object. Note that only the field name is validated, not the content. </para> </listitem> <listitem> <para> Accessor methods for easy access to the fields. </para> </listitem> </itemizedlist> </section> <section xml:id="ruby.p4_spec-class_methods"> <title>Class Methods</title> <section xml:id="ruby.p4_spec.new"> <title>new P4::Spec.new( anArray ) -> aP4::Spec</title> <para> Constructs a new <classname>P4::Spec</classname> object given an array of valid fieldnames. </para> </section> </section> <section xml:id="ruby.p4_spec-instance_methods"> <title>Instance Methods</title> <section xml:id="ruby.p4_spec._fieldname"> <title>spec._<fieldname> -> aValue</title> <para> Returns the value associated with the field named <replaceable><fieldname></replaceable>. This is equivalent to <code>spec[ "<<replaceable>fieldname</replaceable>>" ]</code> with the exception that when used as a method, the fieldnames may be in lowercase regardless of the actual case of the fieldname. </para> <programlisting language="ruby"> client = p4.fetch_client() root = client._root desc = client._description </programlisting> </section> <section xml:id="ruby.p4_spec._fieldname.eq"> <title>spec._<fieldname>= aValue -> aValue</title> <para> Updates the value of the named field in the spec. Raises a <exceptionname>P4Exception</exceptionname> if the fieldname is not valid for specs of this type. </para> <programlisting language="ruby"> client = p4.fetch_client() client._root = "/home/bruno/new-client" client._description = "My new client spec" p4.save_client( client ) </programlisting> </section> <section xml:id="ruby.p4_spec.permitted_fields"> <title>spec.permitted_fields -> anArray</title> <para> Returns an array containing the names of fields that are valid in this spec object. This does not imply that values for all of these fields are actually set in this object, merely that you may choose to set values for any of these fields if you want to. </para> <programlisting language="ruby"> client = p4.fetch_client() spec.permitted_fields.each do | field | printf ( "%14s = %s\n", field, client[ field ] ) end </programlisting> </section> </section> </chapter> <xi:include href="aa_license.xml" /> </book>
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#2 | 14695 | tjuricek |
Restructure the p4ruby docbook source to allow for a standalone HTML site, and update installation notes. Removed obsolete framemaker files. P4RUBY-173 Imported from Git Author: Tristan Juricek <tjuricek@perforce.com> 1418335025 -0800 Committer: Tristan Juricek <tjuricek@perforce.com> 1418335025 -0800 sha1: d772f6517f080ed1b5969c8954e7c7431449969d push-state: complete parent-changes: 141f8b9f65b4c56ce5a42144d8c185285effaa12=[974373] |
||
#1 | 14682 | Git Fusion |
Git Fusion branch management Imported from Git ghost-of-change-num: 960958 ghost-of-sha1: 005052ae424bd69f426f7209e741ca1c8c3253c7 ghost-precedes-sha1: ad052c71a568ef12165e143a6866ad9ceffbb4a1 parent-branch: None@960958 push-state: incomplete |