present in scottl's public_html... The bad thing about svnweb is that it doesn't expand the FreeBSD keyword unlike on checkout, so people using this d/l link won't have it..
		
			
				
	
	
		
			910 lines
		
	
	
	
		
			38 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
			
		
		
	
	
			910 lines
		
	
	
	
		
			38 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
| <?xml version="1.0" encoding="iso-8859-1"?>
 | |
| <!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
 | |
| 	"http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
 | |
| <article xmlns="http://docbook.org/ns/docbook"
 | |
|   xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
 | |
|   xml:lang="en">
 | |
| 
 | |
|   <info>
 | |
|     <title>Perforce in &os; Development</title>
 | |
| 
 | |
|     <authorgroup>
 | |
|       <author>
 | |
| 	<personname>
 | |
| 	  <firstname>Scott</firstname>
 | |
| 	  <surname>Long</surname>
 | |
| 	</personname>
 | |
| 	<affiliation>
 | |
| 	  <address>
 | |
| 	    <email>scottl@FreeBSD.org</email>
 | |
| 	  </address>
 | |
| 	</affiliation>
 | |
|       </author>
 | |
|     </authorgroup>
 | |
| 
 | |
|     <legalnotice xml:id="trademarks" role="trademarks">
 | |
|       &tm-attrib.freebsd;
 | |
|       &tm-attrib.general;
 | |
|     </legalnotice>
 | |
| 
 | |
|     <pubdate>$FreeBSD$</pubdate>
 | |
| 
 | |
|     <releaseinfo>$FreeBSD$</releaseinfo>
 | |
|   </info>
 | |
| 
 | |
|   <sect1 xml:id="intro">
 | |
|     <title>Introduction</title>
 | |
| 
 | |
|     <para>The &os; project uses the
 | |
|       <application>Perforce</application> version control system to
 | |
|       manage experimental projects that are not ready for the main
 | |
|       Subversion repository.</para>
 | |
| 
 | |
|     <sect2 xml:id="resources">
 | |
|       <title>Availability, Documentation, and Resources</title>
 | |
| 
 | |
|       <para>While <application>Perforce</application> is a commercial
 | |
| 	product, the client software for interacting with the server
 | |
| 	is freely available from Perforce.  It can be easily installed
 | |
| 	on &os; via the <package>devel/p4</package> port or can be
 | |
| 	downloaded from the <application>Perforce</application> web
 | |
| 	site at <uri
 | |
| 	  xlink:href="http://www.perforce.com/perforce/loadprog.html">http://www.perforce.com/perforce/loadprog.html</uri>,
 | |
| 	which also offers client applications for other OS's.</para>
 | |
| 
 | |
|       <para>While there is a GUI client available, most people use the
 | |
| 	command line application called <command>p4</command>.  This
 | |
| 	document is written from the point of view of using this
 | |
| 	command.</para>
 | |
| 
 | |
|       <para>Detailed documentation is available online at <uri
 | |
| 	  xlink:href="http://www.perforce.com/perforce/technical.html">http://www.perforce.com/perforce/technical.html</uri>.</para>
 | |
| 
 | |
|       <para>Reading the <quote>Perforce User's Guide</quote> and
 | |
| 	<quote>Perforce Command Reference</quote> is highly
 | |
| 	recommended.  The <application>p4</application> application
 | |
| 	also contains an extensive amount of online help accessible
 | |
| 	via <command>p4 help</command>.</para>
 | |
| 
 | |
|       <para>The &os; <application>Perforce</application> server is
 | |
| 	hosted on <systemitem
 | |
| 	  class="fqdomainname">perforce.freebsd.org</systemitem>, port
 | |
| 	<literal>1666</literal>.  The repository is browsable online
 | |
| 	at <uri
 | |
| 	  xlink:href="http://p4web.freebsd.org">http://p4web.freebsd.org</uri>.</para>
 | |
|     </sect2>
 | |
|   </sect1>
 | |
| 
 | |
|   <sect1 xml:id="start">
 | |
|     <title>Getting Started</title>
 | |
| 
 | |
|     <para>The first step to using <application>Perforce</application>
 | |
|       is to obtain an account on the server.  If you already have a
 | |
|       <systemitem class="fqdomainname">FreeBSD.org</systemitem>
 | |
|       account, log into <systemitem
 | |
| 	class="fqdomainname">freefall</systemitem>, run the following
 | |
|       command, and enter a password that is not the same as your &os;
 | |
|       login or any other SSH passphrase:</para>
 | |
| 
 | |
|     <screen>&prompt.user; <userinput>/usr/local/bin/p4newuser</userinput></screen>
 | |
| 
 | |
|     <para>Of course if you do not have a <systemitem
 | |
| 	class="fqdomainname">FreeBSD.org</systemitem> account, you
 | |
|       will need to coordinate with your sponsor.</para>
 | |
| 
 | |
|     <warning>
 | |
|       <para>An email will be sent to your &os; address that contains
 | |
| 	the password you specified above in cleartext.  Be sure to
 | |
| 	change the password once your
 | |
| 	<application>Perforce</application> account has been
 | |
| 	created!</para>
 | |
|     </warning>
 | |
| 
 | |
|     <para>The next step is to set the environment variables that
 | |
|       <command>p4</command> needs, and verify that it can connect to
 | |
|       the server.  The <envar>P4PORT</envar> variable is required to
 | |
|       be set for all operations, and specifies the appropriate
 | |
|       <application>Perforce</application> server to talk to.  For the
 | |
|       &os; project, set it like so:</para>
 | |
| 
 | |
|     <screen>&prompt.user; <userinput>export P4PORT=perforce.freebsd.org:1666</userinput></screen>
 | |
| 
 | |
|     <note>
 | |
|       <para>Users with shell access on the <systemitem
 | |
| 	  class="fqdomainname">FreeBSD.org</systemitem> cluster may
 | |
| 	wish to tunnel the <application>Perforce</application>
 | |
| 	client-server protocol via an SSH tunnel, in which case the
 | |
| 	above string should be set to
 | |
| 	<literal>localhost</literal>.</para>
 | |
|     </note>
 | |
| 
 | |
|     <para>The &os; server also requires that the <envar>P4USER</envar>
 | |
|       and <envar>P4PASSWD</envar> variables be set.  Use the username
 | |
|       and password from above, like so:</para>
 | |
| 
 | |
|     <screen>&prompt.user; <userinput>export P4USER=<replaceable>username</replaceable></userinput>
 | |
| &prompt.user; <userinput>export P4PASSWD=<replaceable>password</replaceable></userinput></screen>
 | |
| 
 | |
|     <para>Test that this works by running the following
 | |
|       command:</para>
 | |
| 
 | |
|     <screen>&prompt.user; <userinput>p4 info</userinput></screen>
 | |
| 
 | |
|     <para>This should return a list of information about the server.
 | |
|       If it does not, check that you have the <envar>P4PORT</envar>
 | |
|       variable set correctly.</para>
 | |
|   </sect1>
 | |
| 
 | |
|   <sect1 xml:id="clients">
 | |
|     <title>Clients</title>
 | |
| 
 | |
|     <para><application>Perforce</application> provides access to the
 | |
|       repository and tracks state on a per-client basis.  In
 | |
|       <application>Perforce</application> terms, a client is a
 | |
|       specification that maps files and directories from the
 | |
|       repository to the local machine.  Each user can have multiple
 | |
|       clients, and each client can access different or overlapping
 | |
|       parts of the repository.  The client also specifies the root
 | |
|       directory of the file tree that it maps, and it specifies the
 | |
|       machine that the tree lives on.  Thus, working on multiple
 | |
|       machines requires that multiple clients be used.</para>
 | |
| 
 | |
|     <para>Clients may be accessed via <command>p4 client</command>.
 | |
|       Running this command with no arguments will bring up a client
 | |
|       template in an editor, allowing you to create a new client for
 | |
|       your work.  The important fields in this template are explained
 | |
|       below:</para>
 | |
| 
 | |
|     <variablelist>
 | |
|       <varlistentry>
 | |
| 	<term><literal>Client:</literal></term>
 | |
| 
 | |
| 	<listitem>
 | |
| 	  <para>This is the name of the client spec.  It can be
 | |
| 	    anything you want, but it must be unique within the
 | |
| 	    <application>Perforce</application> server.  A naming
 | |
| 	    convention that is commonly used is
 | |
| 	    <literal><replaceable>username</replaceable>_<replaceable>machinename</replaceable></literal>,
 | |
| 	    which makes it easy to identify clients when browsing
 | |
| 	    them.  A default name will be filled in that is just the
 | |
| 	    machine name.</para>
 | |
| 	</listitem>
 | |
|       </varlistentry>
 | |
| 
 | |
|       <varlistentry>
 | |
| 	<term><literal>Description:</literal></term>
 | |
| 
 | |
| 	<listitem>
 | |
| 	  <para>This can contain a simple text description to help
 | |
| 	    identify the client.</para>
 | |
| 	</listitem>
 | |
|       </varlistentry>
 | |
| 
 | |
|       <varlistentry>
 | |
| 	<term><literal>Root:</literal></term>
 | |
| 
 | |
| 	<listitem>
 | |
| 	  <para>This is the local directory that will serve as the
 | |
| 	    root directory of all the files in the client mapping.
 | |
| 	    This should be a unique location in your filesystem that
 | |
| 	    does not overlap with other files or
 | |
| 	    <application>Perforce</application> clients.</para>
 | |
| 	</listitem>
 | |
|       </varlistentry>
 | |
| 
 | |
|       <varlistentry>
 | |
| 	<term><literal>Options:</literal></term>
 | |
| 
 | |
| 	<listitem>
 | |
| 	  <para>Most of the default options are fine, though it is
 | |
| 	    usually a good idea to make sure that the
 | |
| 	    <option>compress</option> and <option>rmdir</option>
 | |
| 	    options are present and do not have a
 | |
| 	    <literal>no</literal> prefix on them.  Details about each
 | |
| 	    option are in the <application>Perforce</application>
 | |
| 	    docs.</para>
 | |
| 	</listitem>
 | |
|       </varlistentry>
 | |
| 
 | |
|       <varlistentry>
 | |
| 	<term><literal>LineEnd:</literal></term>
 | |
| 
 | |
| 	<listitem>
 | |
| 	  <para>This handles CR-LF conversions and should be left to
 | |
| 	    the default unless you have special needs for it.</para>
 | |
| 	</listitem>
 | |
|       </varlistentry>
 | |
| 
 | |
|       <varlistentry>
 | |
| 	<term><literal>View:</literal></term>
 | |
| 
 | |
| 	<listitem>
 | |
| 	  <para>This is where the server-to-local file mappings go.
 | |
| 	    The default is</para>
 | |
| 
 | |
| 	  <programlisting>//depot/... //<replaceable>client</replaceable>/...</programlisting>
 | |
| 
 | |
| 	  <para>This will map the entire
 | |
| 	    <application>Perforce</application> repository to the
 | |
| 	    <filename>Root</filename> directory of your client.
 | |
| 	    <emphasis>DO NOT USE THIS DEFAULT!</emphasis>  The &os;
 | |
| 	    repo is huge, and trying to map and sync it all will take
 | |
| 	    an enormous amount of resources.  Instead, only map the
 | |
| 	    section of the repo that you intend to work on.  For
 | |
| 	    example, there is the smpng project tree at
 | |
| 	    <filename>//depot/projects/smpng</filename>.  A mapping
 | |
| 	    for this might look like:</para>
 | |
| 
 | |
| 	  <programlisting>//depot/projects/smpng/... //<replaceable>client</replaceable>/...</programlisting>
 | |
| 
 | |
| 	  <para>The <literal>...</literal> should be taken literally.
 | |
| 	    It is a <application>Perforce</application> idiom for
 | |
| 	    saying <quote>this directory and all files and directories
 | |
| 	      below it.</quote></para>
 | |
| 
 | |
| 	  <para>A Perforce <quote>view</quote> can contain multiple
 | |
| 	    mappings.  Say you want to map in both the SMPng tree and
 | |
| 	    the NFS tree.  Your View might look like:</para>
 | |
| 
 | |
| 	  <programlisting>//depot/projects/smpng/... //<replaceable>client</replaceable>/smpng/...
 | |
| 	  //depot/projects/nfs/... //<replaceable>client</replaceable>/nfs/...</programlisting>
 | |
| 
 | |
| 	  <para>Remember that the <replaceable>client</replaceable> is
 | |
| 	    the name of the client that was specified in the
 | |
| 	    <literal>Client</literal> section, but in the
 | |
| 	    <literal>View</literal> it also resolves to the directory
 | |
| 	    that was specified in the <literal>Root</literal>
 | |
| 	    section.</para>
 | |
| 
 | |
| 	  <para>Also note that the same file or directory cannot be
 | |
| 	    mapped multiple times in a single view.  The following is
 | |
| 	    illegal and will produce undefined results:</para>
 | |
| 
 | |
| 	  <programlisting>//depot/projects/smpng/... //<replaceable>client</replaceable>/smpng-foo/...
 | |
| 	  //depot/projects/smpng/... //<replaceable>client</replaceable>/smpng-bar/...</programlisting>
 | |
| 
 | |
| 	  <para>Views are a tricky part of the learning experience
 | |
| 	    with <application>Perforce</application>, so do not be
 | |
| 	    afraid to ask questions.</para>
 | |
| 	</listitem>
 | |
|       </varlistentry>
 | |
|     </variablelist>
 | |
| 
 | |
|     <para>Existing clients can be listed via <command>p4
 | |
| 	clients</command>.  They can be viewed without being modified
 | |
|       via <command>p4 client -o
 | |
| 	<replaceable>clientname</replaceable></command>.</para>
 | |
| 
 | |
|     <para>Whenever you are interacting with files in
 | |
|       <application>Perforce</application>, the <envar>P4CLIENT</envar>
 | |
|       environment variable must be set to the name of the client that
 | |
|       you are using, like so:</para>
 | |
| 
 | |
|     <screen>&prompt.user; <userinput>export P4CLIENT=<replaceable>myclientname</replaceable></userinput></screen>
 | |
| 
 | |
|     <para>Note that client mappings in the repository are not
 | |
|       exclusive; multiple clients can map in the same part of the
 | |
|       repository.  This allows multiple people to access and modify
 | |
|       the same parts of the repository, allowing a team of people to
 | |
|       work together on the same code.</para>
 | |
|   </sect1>
 | |
| 
 | |
|   <sect1 xml:id="syncing">
 | |
|     <title>Syncing</title>
 | |
| 
 | |
|     <para>Once you have a client specification defined and the
 | |
|       <envar>P4CLIENT</envar> variable set, the next step is to pull
 | |
|       the files for that client down to your local machine.  This is
 | |
|       done with <command>p4 sync</command>, which instructs
 | |
|       <application>Perforce</application> to synchronize the local
 | |
|       files in your client with the repository.  The first time it
 | |
|       runs, it will download all of the files.  Subsequent runs will
 | |
|       only download files that have changed since the previous run.
 | |
|       This allows you to stay in sync with others whom you might be
 | |
|       working with.</para>
 | |
| 
 | |
|     <para>Sync operations only work on files that the
 | |
|       <application>Perforce</application> server knows has changed.
 | |
|       If you change or delete a file locally without informing the
 | |
|       server, doing a sync will not bring it back.  However, doing a
 | |
|       <command>p4 sync -f</command> will unconditionally sync all
 | |
|       files, regardless of their state.  This is useful for resolving
 | |
|       problems where you think that your tree might be corrupt.</para>
 | |
| 
 | |
|     <para>You can sync a subset of your tree or client by specifying a
 | |
|       relative path to the sync command.  For example, to only sync
 | |
|       the <filename>ufs</filename> directory of the
 | |
|       <literal>smpng</literal> project, you might do the
 | |
|       following:</para>
 | |
| 
 | |
|     <screen>&prompt.user; <userinput>cd <replaceable>projectroot</replaceable>/smpng</userinput>
 | |
| &prompt.user; <userinput>p4 sync src/sys/ufs/...</userinput></screen>
 | |
| 
 | |
|     <para>Specifying a local relative path works for many other
 | |
|       <command>p4</command> commands.</para>
 | |
|   </sect1>
 | |
| 
 | |
|   <sect1 xml:id="branches">
 | |
|     <title>Branches</title>
 | |
| 
 | |
|     <para>One of the strongest features of
 | |
|       <application>Perforce</application> is branching.  Branches are
 | |
|       very cheap to create, and moving changes between related
 | |
|       branches is very easy (as will be explained later).  Branches
 | |
|       also allow you to do very experimental work in a sandbox-like
 | |
|       environment, without having to worry about colliding with others
 | |
|       or destabilizing the main tree.  They also provide insulation
 | |
|       against mistakes while learning the
 | |
|       <application>Perforce</application> system.  With all of these
 | |
|       benefits, it makes sense for each project to have its own
 | |
|       branch, and we strongly encourage that with &os;.  Frequent
 | |
|       submits of changes to the server are also encouraged.</para>
 | |
| 
 | |
|     <para>Similar to <application>Subversion</application>, the
 | |
|       <application>Perforce</application> repository (the
 | |
|       <quote>depot</quote>)  is a single flat tree.  Every file,
 | |
|       whether a unique creation or a derivative from a branch, is
 | |
|       accessible via a simple path under the server
 | |
|       <filename>//depot</filename> directory.  When you create a
 | |
|       branch, all you are doing is creating a new path under the
 | |
|       <filename>//depot</filename>.  This is in sharp contrast to
 | |
|       systems like CVS, where each branch lives in the same path as
 | |
|       its parent.  With <application>Perforce</application>, the
 | |
|       server tracks the relationship between the files in the parent
 | |
|       and child, but the files themselves live under their own
 | |
|       paths.</para>
 | |
| 
 | |
|     <para>The first step to creating a branch is to create a branch
 | |
|       specification.  This is similar to a client specification, but
 | |
|       is created via the command <command>p4 branch
 | |
| 	<replaceable>branchname</replaceable></command>.</para>
 | |
| 
 | |
|     <para>The following important fields are explained:</para>
 | |
| 
 | |
|     <variablelist>
 | |
|       <varlistentry>
 | |
| 	<term><literal>Branch</literal></term>
 | |
| 
 | |
| 	<listitem>
 | |
| 	  <para>The name of the branch.  It can be any name, but must
 | |
| 	    be unique within the repository.  The common convention in
 | |
| 	    &os; is to use
 | |
| 	    <replaceable>username</replaceable>_<replaceable>projectname</replaceable>.</para>
 | |
| 	</listitem>
 | |
|       </varlistentry>
 | |
| 
 | |
|       <varlistentry>
 | |
| 	<term><literal>Description</literal></term>
 | |
| 
 | |
| 	<listitem>
 | |
| 	  <para>This can hold a simple text description to describe
 | |
| 	    the branch.</para>
 | |
| 	</listitem>
 | |
|       </varlistentry>
 | |
| 
 | |
|       <varlistentry>
 | |
| 	<term><literal>View</literal></term>
 | |
| 
 | |
| 	<listitem>
 | |
| 	  <para>This is the branch mapping.  Instead of mapping from
 | |
| 	    the depot to the local machine like a client map, it maps
 | |
| 	    between the branch parent and branch child in the depot.
 | |
| 	    For example, you might want to create a branch of the
 | |
| 	    smpng project.  The mapping might look like:</para>
 | |
| 
 | |
| 	  <programlisting>//depot/projects/smpng/... //depot/projects/my-super-smpng/...</programlisting>
 | |
| 
 | |
| 	  <para>Or, you might want to create a brand new branch off of
 | |
| 	    the stock &os; sources:</para>
 | |
| 
 | |
| 	  <programlisting>//depot/vendor/freebsd/... //depot/projects/my-new-project/...</programlisting>
 | |
| 
 | |
| 	  <para>This will map the &os; HEAD tree to your new
 | |
| 	    branch.</para>
 | |
| 	</listitem>
 | |
|       </varlistentry>
 | |
|     </variablelist>
 | |
| 
 | |
|     <para>Creating the branch spec only saves the spec itself in the
 | |
|       server, it does not modify the depot or change any files.  The
 | |
|       directory that you specified in the branch is empty on the
 | |
|       server until you populate it.</para>
 | |
| 
 | |
|     <para>To populate your branch, first edit your client with
 | |
|       <command>p4 client</command> and make sure that the branch
 | |
|       directory is mapped in your client.  You might need to add a
 | |
|       <literal>View</literal> line like:</para>
 | |
| 
 | |
|     <programlisting>//depot/projects/my-new-project/... //<replaceable>myclient</replaceable>/my-new-project/...</programlisting>
 | |
| 
 | |
|     <para>The next step is to run <command>p4 integrate</command>, as
 | |
|       described in the next section.</para>
 | |
|   </sect1>
 | |
| 
 | |
|   <sect1 xml:id="Integrations">
 | |
|     <title>Integrations</title>
 | |
| 
 | |
|     <para><quote>Integration</quote> is the term used by
 | |
|       <application>Perforce</application> to describe the action of
 | |
|       moving changes from one part of the depot to another.  It is
 | |
|       most commonly done in conjunction with creating and maintaining
 | |
|       branches.  An integration is done when you want to initially
 | |
|       populate a branch, and it is done when you want to move
 | |
|       subsequent changes in the branch from the parent to the child,
 | |
|       or from the child to the parent.  A common example of this is
 | |
|       periodically integrating changes from the vendor &os; tree to
 | |
|       your child branch tree, allowing you to keep up to date with
 | |
|       changes in the &os; tree.  The
 | |
|       <application>Perforce</application> server tracks the changes in
 | |
|       each tree and knows when there are changes that can be
 | |
|       integrated from one tree to another.</para>
 | |
| 
 | |
|     <para>The common way to do an integration is with the following
 | |
|       command:</para>
 | |
| 
 | |
|     <screen>&prompt.user; <userinput>p4 integrate -b <replaceable>branchname</replaceable></userinput></screen>
 | |
| 
 | |
|     <para><replaceable>branchname</replaceable> is the name given to a
 | |
|       branch spec, as discussed in the previous section.  This command
 | |
|       will instruct <application>Perforce</application> to look for
 | |
|       changes in the branch parent that are not yet in the child.
 | |
|       From those changes it will prepare a list of diffs to move.  If
 | |
|       the integration is being done for the first time on a branch
 | |
|       (for example doing an initial population operation), then the
 | |
|       parent files will simply be copied to the child location on the
 | |
|       local machine.</para>
 | |
| 
 | |
|     <para>Once the integration operation is done, you must run
 | |
|       <command>p4 resolve</command> to accept the changes and resolve
 | |
|       possible conflicts.  Conflicts can arise from overlapping
 | |
|       changes that happened in both the parent and child copy of a
 | |
|       file.  Usually, however, there are no conflicts, and
 | |
|       <application>Perforce</application> can quickly figure out how
 | |
|       to merge the changes together.  Use the following commands to do
 | |
|       a resolve operation:</para>
 | |
| 
 | |
|     <screen>&prompt.user; <userinput>p4 resolve -as</userinput>
 | |
| &prompt.user; <userinput>p4 resolve</userinput></screen>
 | |
| 
 | |
|     <para>The first invocation will instruct
 | |
|       <application>Perforce</application> to automatically merge the
 | |
|       changes together and accept files that have no conflicts.  The
 | |
|       second invocation will allow you to inspect each file that has a
 | |
|       possible conflict and resolve it by hand if needed.</para>
 | |
| 
 | |
|     <para>Once all of the integrated files have been resolved, they
 | |
|       need to be committed back to the repository.  This is done via
 | |
|       <command>p4 submit</command>, explained in the next
 | |
|       section.</para>
 | |
|   </sect1>
 | |
| 
 | |
|   <sect1 xml:id="submit">
 | |
|     <title>Submit</title>
 | |
| 
 | |
|     <para>Changes that are made locally should be committed back to
 | |
|       the <application>Perforce</application> server for safe keeping
 | |
|       and so that others can access them.  This is done via
 | |
|       <command>p4 submit</command>.  When you run this command, it
 | |
|       will open up a submit template in an editor.  &os; has a custom
 | |
|       template, and the important fields are described below:</para>
 | |
| 
 | |
|     <programlisting>Description:
 | |
|         <enter description here>
 | |
|         PR:
 | |
|         Submitted by:
 | |
|         Reviewed by:
 | |
|         Approved by:
 | |
|         Obtained from:
 | |
|         MFP4 after:</programlisting>
 | |
| 
 | |
|     <para>It is good practice to provide at least 2-3 sentences that
 | |
|       describe what the changes are that you are submitting.  You
 | |
|       should say what the change does, why it was done that way or
 | |
|       what problem is solves, and what APIs it might change or other
 | |
|       side effects it might have.  This text should replace the
 | |
|       <literal><enter description here></literal> line in the
 | |
|       template.  You should wrap your lines and start each line with a
 | |
|       TAB.  The tags below it are &os;-specific and can be removed if
 | |
|       not needed.</para>
 | |
| 
 | |
|     <programlisting>Files:</programlisting>
 | |
| 
 | |
|     <para>This is automatically populated with all of the files in
 | |
|       your client that were marked in the add, delete, integrate, or
 | |
|       edit states on the server.  It is always a very good idea to
 | |
|       review this list and remove files that might not be ready
 | |
|       yet.</para>
 | |
| 
 | |
|     <para>Once you save the editor session, the submit will happen to
 | |
|       the server.  This also means that the local copies of the
 | |
|       submitted files will be copied back to the server.  If anything
 | |
|       goes wrong during this process, the submit will be aborted, and
 | |
|       you will be notified that the submit has been turned into a
 | |
|       changelist that must be corrected and re-submitted.  Submits are
 | |
|       atomic, so if one file fails, the entire submit is
 | |
|       aborted.</para>
 | |
| 
 | |
|     <para>Submits cannot be reverted, but they can be aborted while in
 | |
|       the editor by exiting the editor without changing the
 | |
|       <literal>Description</literal> text.
 | |
|       <application>Perforce</application> will complain about this the
 | |
|       first time you do it and will put you back in the editor.
 | |
|       Exiting the editor the second time will abort the operation.
 | |
|       Reverting a submitted change is very difficult and is best
 | |
|       handled on a case-by-case basis.</para>
 | |
|   </sect1>
 | |
| 
 | |
|   <sect1 xml:id="editing">
 | |
|     <title>Editing</title>
 | |
| 
 | |
|     <para>The state of each file in the client is tracked and saved on
 | |
|       the server.  In order to avoid collisions from multiple people
 | |
|       working on the same file at once,
 | |
|       <application>Perforce</application> tracks which files are
 | |
|       opened for edit, and uses this to help with submit, sync, and
 | |
|       integration operations later on.</para>
 | |
| 
 | |
|     <para>To open a file for editing, use <command>p4 edit</command>
 | |
|       like so:</para>
 | |
| 
 | |
|     <screen>&prompt.user; <userinput>p4 edit <replaceable>filename</replaceable></userinput></screen>
 | |
| 
 | |
|     <para>This marks the file on the server as being in the
 | |
|       <emphasis>edit</emphasis> state, which then allows it to be
 | |
|       submitted after changes are made, or marks it for special
 | |
|       handling when doing an integration or sync operation.  Note that
 | |
|       editing is not exclusive in <application>Perforce</application>.
 | |
|       Multiple people can have the same file in the edit state (you
 | |
|       will be informed of others when you run
 | |
|       <command>edit</command>), and you can submit your changes even
 | |
|       when others are still editing the file.</para>
 | |
| 
 | |
|     <para>When someone else submits a change to a file that you are
 | |
|       editing, you will need to resolve his changes with yours before
 | |
|       your submit will succeed.  The easiest way to do this is to
 | |
|       either run a <command>p4 sync</command> or <command>p4
 | |
| 	submit</command> and let it fail with the conflict, then run
 | |
|       <command>p4 resolve</command> to manually resolve and accept his
 | |
|       changes into your copy, then run <command>p4 submit</command> to
 | |
|       commit your changes to the repository.</para>
 | |
| 
 | |
|     <para>If you have a file open for edit and you want to throw away
 | |
|       your changes and revert it to its original state, run
 | |
|       <command>p4 revert</command> like so:</para>
 | |
| 
 | |
|     <screen>&prompt.user; <userinput>p4 revert <replaceable>filename</replaceable></userinput></screen>
 | |
| 
 | |
|     <para>This resyncs the file to the contents of the server, and
 | |
|       removes the edit attribute from the server.  Any local changes
 | |
|       that you had will be lost.  This is quite useful when you have a
 | |
|       made changes to a file but later decide that you do not want to
 | |
|       keep them.</para>
 | |
| 
 | |
|     <para>When a file is synced, it is marked read-only in the
 | |
|       filesystem.  When you tell the server to open it for editing, it
 | |
|       is changed to read-write on the filesystem.  While these
 | |
|       permissions can easily be overridden by hand, they are meant to
 | |
|       gently remind you that you should being using <command>p4
 | |
| 	edit</command>.  Files that have local changes but are not in
 | |
|       the edit state may get overwritten when doing a <command>p4
 | |
| 	sync</command>.</para>
 | |
|   </sect1>
 | |
| 
 | |
|   <sect1 xml:id="changes">
 | |
|     <title>Changes, Descriptions, and History</title>
 | |
| 
 | |
|     <para>Changes to the <application>Perforce</application> depot can
 | |
|       be listed via <command>p4 changes</command>.  This will provide
 | |
|       a brief description of each change, who made the change, and
 | |
|       what its change number was.  A change can be examined in detail
 | |
|       via <command>p4 describe
 | |
| 	<replaceable>changenumber</replaceable></command>.  This will
 | |
|       provide the submit log and the diffs of the actual
 | |
|       change.</para>
 | |
| 
 | |
|     <para>Commonly, <command>p4 describe</command> is used in one
 | |
|       of three ways:</para>
 | |
| 
 | |
|     <variablelist>
 | |
|       <varlistentry>
 | |
| 	<term><command>p4 describe -s
 | |
| 	  <replaceable>CHANGE</replaceable></command></term>
 | |
| 
 | |
| 	<listitem>
 | |
| 	  <para>List a short description of changeset
 | |
| 	    <emphasis>CHANGE</emphasis>, including the commit log of
 | |
| 	    the particular changeset and a list of the files it
 | |
| 	    affected.</para>
 | |
| 	</listitem>
 | |
|       </varlistentry>
 | |
| 
 | |
|       <varlistentry>
 | |
| 	<term><command>p4 describe -du
 | |
| 	  <replaceable>CHANGE</replaceable></command></term>
 | |
| 
 | |
| 	<listitem>
 | |
| 	  <para>List a description of changeset
 | |
| 	    <emphasis>CHANGE</emphasis>, including the commit log of
 | |
| 	    the particular changeset, a list of the files it affected
 | |
| 	    and a patch for each modified file, in a format similar to
 | |
| 	    <quote>unified diff</quote> patches (but not exactly the
 | |
| 	    same).</para>
 | |
| 	</listitem>
 | |
|       </varlistentry>
 | |
| 
 | |
|       <varlistentry>
 | |
| 	<term><command>p4 describe -dc
 | |
| 	  <replaceable>CHANGE</replaceable></command></term>
 | |
| 
 | |
| 	<listitem>
 | |
| 	  <para>List a description of changeset
 | |
| 	    <emphasis>CHANGE</emphasis>, including the commit log of
 | |
| 	    the particular changeset, a list of the files it affected
 | |
| 	    and a patch for each modified file, in a format similar to
 | |
| 	    <quote>context diff</quote> patches (but not exactly the
 | |
| 	    same).</para>
 | |
| 	</listitem>
 | |
|       </varlistentry>
 | |
|     </variablelist>
 | |
| 
 | |
|     <para>The history of a file, including all submits, integrations,
 | |
|       and branches of it will be shown by <command>p4 filelog
 | |
| 	<replaceable>filename</replaceable></command>.</para>
 | |
|   </sect1>
 | |
| 
 | |
|   <sect1 xml:id="diffs">
 | |
|     <title>Diffs</title>
 | |
| 
 | |
|     <para>There are two methods of producing file diffs in
 | |
|       <application>Perforce</application>, either against local
 | |
|       changes that have not been submitted yet, or between two trees
 | |
|       (or within a branch) in the depot.  These are done with
 | |
|       different commands, <option>diff</option> and
 | |
|       <option>diff2</option>:</para>
 | |
| 
 | |
|     <variablelist>
 | |
|       <varlistentry>
 | |
| 	<term><command>p4 diff</command></term>
 | |
| 
 | |
| 	<listitem>
 | |
| 	  <para>This generates a diff of the local changes to files in
 | |
| 	    the edit state.  The <option>-du</option> and
 | |
| 	    <option>-dc</option> flags can be used to create unified
 | |
| 	    or context diffs, respectively, or the
 | |
| 	    <envar>P4DIFF</envar> environment variable can be set to a
 | |
| 	    local diff command to be used instead.  It is a very good
 | |
| 	    idea to use this command to review your changes before
 | |
| 	    submitting them.</para>
 | |
| 	</listitem>
 | |
|       </varlistentry>
 | |
| 
 | |
|       <varlistentry>
 | |
| 	<term><command>p4 diff2</command></term>
 | |
| 
 | |
| 	<listitem>
 | |
| 	  <para>This creates a diff between arbitrary files in the
 | |
| 	    depot, or between files specified in a branch spec.  The
 | |
| 	    diff operation takes place on the server, so
 | |
| 	    <envar>P4DIFF</envar> variable has no effect, though the
 | |
| 	    <option>-du</option> and <option>-dc</option> flags do
 | |
| 	    work.  The two forms of this command are:</para>
 | |
| 
 | |
| 	  <screen>&prompt.user; <userinput>p4 diff2 -b <replaceable>branchname</replaceable></userinput></screen>
 | |
| 
 | |
| 	  <para>and</para>
 | |
| 
 | |
| 	  <screen>&prompt.user; <userinput>p4 diff2 //depot/<replaceable>path1</replaceable> //depot/<replaceable>path2</replaceable></userinput></screen>
 | |
| 	</listitem>
 | |
|       </varlistentry>
 | |
|     </variablelist>
 | |
| 
 | |
|     <para>In all cases the diff will be written to the standard
 | |
|       output.  Unfortunately, <application>Perforce</application>
 | |
|       produces a diff format that is slightly incompatible with the
 | |
|       traditional Unix diff and patch tools.  Using the
 | |
|       <envar>P4DIFF</envar> variable to point to the real &man.diff.1;
 | |
|       tool can help this, but only for <command>p4 diff</command>.
 | |
|       The output of <option>diff2</option> command must be
 | |
|       post-processed to be useful (the <option>-u</option> flag of
 | |
|       <option>diff2</option> will produce unified diffs that are
 | |
|       somewhat compatible, but it does not include files that have
 | |
|       been added or deleted).  There is a post-processing script at:
 | |
|       <uri
 | |
| 	xlink:href="https://svnweb.freebsd.org/base/head/tools/tools/perforce/awkdiff?view=co">https://svnweb.freebsd.org/base/head/tools/tools/perforce/awkdiff?view=co</uri>.</para>
 | |
|   </sect1>
 | |
| 
 | |
|   <sect1 xml:id="add-rm-files">
 | |
|     <title>Adding and Removing Files</title>
 | |
| 
 | |
|     <para>Integrating a branch will bring existing files into your
 | |
|       tree, but you may still want to add new files or remove existing
 | |
|       ones.  Adding files is easily done be creating the file and then
 | |
|       running <command>p4 add</command> like so:</para>
 | |
| 
 | |
|     <screen>&prompt.user; <userinput>p4 add <replaceable>filename</replaceable></userinput></screen>
 | |
| 
 | |
|     <para>If you want to add a whole tree of files, run a command
 | |
|       like:</para>
 | |
| 
 | |
|     <screen>&prompt.user; <userinput>find . -type f | xargs p4 add</userinput></screen>
 | |
| 
 | |
|     <note>
 | |
|       <para><application>Perforce</application> can track UNIX
 | |
| 	symlinks too, so you can probably use
 | |
| 	<quote><command>\! -type d</command></quote> as the
 | |
| 	matching expression in &man.find.1; above.  We do not commit
 | |
| 	symlinks into the source tree of &os; though, so this should
 | |
| 	not be necessary.</para>
 | |
|     </note>
 | |
| 
 | |
|     <para>Doing a <command>p4 submit</command> will then copy the file
 | |
|       to the depot on the server.  It is very important to only add
 | |
|       files, not directories.  Explicitly adding a directory will
 | |
|       cause <application>Perforce</application> to treat it like a
 | |
|       file, which is not what you want.</para>
 | |
| 
 | |
|     <para>Removing a file is just as easy with the
 | |
|       <command>p4</command> delete command like so:</para>
 | |
| 
 | |
|     <screen>&prompt.user; <userinput>p4 delete <replaceable>filename</replaceable></userinput></screen>
 | |
| 
 | |
|     <para>This will mark the file for deletion from the depot the next
 | |
|       time that a submit is run.  It will also remove the local copy
 | |
|       of the file, so beware.</para>
 | |
| 
 | |
|     <para>Of course, deleting a file does not actually remove it from
 | |
|       the repository.</para>
 | |
| 
 | |
|     <para>Deleted files can be resurrected by syncing them to a prior
 | |
|       version.  The only way to permanently remove a file is to use
 | |
|       <command>p4 obliterate</command>.  This command is irreversible
 | |
|       and expensive, so it is only available to those with admin
 | |
|       access.</para>
 | |
|   </sect1>
 | |
| 
 | |
|   <sect1 xml:id="working-with-diffs">
 | |
|     <title>Working with Diffs</title>
 | |
| 
 | |
|     <para>Sometimes you might need to apply a diff from another source
 | |
|       to a tree under <application>Perforce</application> control.  If
 | |
|       it is a large diff that affects lots of files, it might be
 | |
|       inconvenient to manually run <command>p4 edit</command> on each
 | |
|       file.  There is a trick for making this easier.  First, make
 | |
|       sure that no files are open on your client and that your tree is
 | |
|       synced and up to date.  Then apply the diff using the normal
 | |
|       tools, and coerce the permissions on the files if needed.  Then
 | |
|       run the following commands:</para>
 | |
| 
 | |
|     <screen>&prompt.user; <userinput>p4 diff -se ... | xargs p4 edit</userinput>
 | |
| &prompt.user; <userinput>p4 diff -sd ... | xargs p4 delete</userinput>
 | |
| &prompt.user; <userinput>find . -type f | xargs p4 add</userinput></screen>
 | |
| 
 | |
|     <para>The first command tells <application>Perforce</application>
 | |
|       to look for files that have changed, even if they are not open.
 | |
|       The second command tells <application>Perforce</application> to
 | |
|       look for files that no longer exist on the local machine but do
 | |
|       exist on the server.  The third command then attempts to add all
 | |
|       of the files that it can find locally.  This is a very
 | |
|       brute-force method, but it works because
 | |
|       <application>Perforce</application> will only add the files that
 | |
|       it does not already know about.  The result of running these
 | |
|       commands will be a set of files that are opened for edit,
 | |
|       removal, or add, as appropriate.</para>
 | |
| 
 | |
|     <para>Verify the active changelist with:</para>
 | |
| 
 | |
|     <screen>&prompt.user; <userinput>p4 changelist</userinput>
 | |
| &prompt.user; <userinput>p4 diff -du</userinput></screen>
 | |
| 
 | |
|     <para>and just do a <command>p4 submit</command> after
 | |
|       that.</para>
 | |
|   </sect1>
 | |
| 
 | |
|   <sect1 xml:id="renaming-files">
 | |
|     <title>Renaming Files</title>
 | |
| 
 | |
|     <para><application>Perforce</application> does not have a built-in
 | |
|       way of renaming files or moving them to a different part of the
 | |
|       tree.  Simply copying a file to the new location, doing a
 | |
|       <command>p4 add</command> on it, and a <command>p4
 | |
| 	delete</command> on the old copy, works, but does not preserve
 | |
|       change history of the file.  This can make future integrations
 | |
|       with parents and children very bumpy, in fact.  A better method
 | |
|       of dealing with this is to do a one-time, in-tree integration,
 | |
|       like so:</para>
 | |
| 
 | |
|     <screen>&prompt.user; <userinput>p4 integrate -i <replaceable>oldfile</replaceable> <replaceable>newfile</replaceable></userinput>
 | |
| &prompt.user; <userinput>p4 resolve</userinput>
 | |
| &prompt.user; <userinput>p4 delete <replaceable>oldfile</replaceable></userinput>
 | |
| &prompt.user; <userinput>p4 submit</userinput></screen>
 | |
| 
 | |
|     <para>The integration will force
 | |
|       <application>Perforce</application> to keep a record of the
 | |
|       relationship between the old and new names, which will assist it
 | |
|       in future integrations.  The <option>-i</option> flag tells it
 | |
|       that it is a <quote>baseless</quote> integration, meaning that
 | |
|       there is no branch history available for it to use in the
 | |
|       integration.  That is perfect for an integration like this, but
 | |
|       should not be used for normal branch-based integrations.</para>
 | |
|   </sect1>
 | |
| 
 | |
|   <sect1 xml:id="freebsd-cvs-and-p4">
 | |
|     <title>Interactions Between &os; Subversion and Perforce</title>
 | |
| 
 | |
|     <para>The &os; <application>Perforce</application> and
 | |
|       <application>Subversion</application> repositories are
 | |
|       completely separate.  However, changes to Subversion are tracked
 | |
|       at near-real-time in <application>Perforce</application>.  Every
 | |
|       2 minutes, the Subversion server is polled for updates in the
 | |
|       HEAD branch, and those updates are committed to
 | |
|       <application>Perforce</application> in the
 | |
|       <filename>//depot/vendor/freebsd/...</filename> tree.  This tree
 | |
|       is then available for branching and integrating to derivative
 | |
|       projects.  Any project that directly modifies that &os; source
 | |
|       code should have this tree as its branch parent (or grandparent,
 | |
|       depending on the needs), and periodic integrations and syncs
 | |
|       should be done so that your tree stays up to date and avoids
 | |
|       conflicts with mainline development.</para>
 | |
| 
 | |
|     <para>The bridge between Subversion and
 | |
|       <application>Perforce</application> is one-way; changes to
 | |
|       Subversion will be reflected in
 | |
|       <application>Perforce</application>, but changes in Perforce
 | |
|       will not be reflected in Subversion.</para>
 | |
|   </sect1>
 | |
| 
 | |
|   <sect1 xml:id="offline-ops">
 | |
|     <title>Offline Operation</title>
 | |
| 
 | |
|     <para>One weakness of <application>Perforce</application> is that
 | |
|       it assumes that network access to the server is always
 | |
|       available.  Most state, history, and metadata is saved on the
 | |
|       server, and there is no provision for replicating the server
 | |
|       like there is with SVN.  It is possible to run a proxy server,
 | |
|       but it only provides very limited utility for offline
 | |
|       operation.</para>
 | |
| 
 | |
|     <para>The best way to work offline is to make sure that your
 | |
|       client has no open files and is fully synced before going
 | |
|       offline.  Then when editing a file, manually change the
 | |
|       permissions to read-write.  When you get back online, run the
 | |
|       commands listed in the <xref linkend="working-with-diffs"/> to
 | |
|       automatically identify files that have been edited, added, and
 | |
|       removed.  It is quite common to be surprised by
 | |
|       <application>Perforce</application> overwriting a locally
 | |
|       changed file that was not opened for edit, so be extra vigilant
 | |
|       with this.</para>
 | |
|   </sect1>
 | |
| 
 | |
|   <sect1 xml:id="soc">
 | |
|     <title>Notes for Google Summer of Code</title>
 | |
| 
 | |
|     <para>Most &os; projects under the Google Summer of Code program
 | |
|       are located on the &os; <application>Perforce</application>
 | |
|       server under one of the following locations:</para>
 | |
| 
 | |
|     <itemizedlist>
 | |
|       <listitem>
 | |
| 	<para><filename>//depot/projects/soc2005/<replaceable>project-name</replaceable>/...</filename></para>
 | |
|       </listitem>
 | |
|       <listitem>
 | |
| 	<para><filename>//depot/projects/soc2006/<replaceable>project-name</replaceable>/...</filename></para>
 | |
|       </listitem>
 | |
|       <listitem>
 | |
| 	<para><filename>//depot/projects/soc2007/<replaceable>project-name</replaceable>/...</filename></para>
 | |
|       </listitem>
 | |
|       <listitem>
 | |
| 	<para><filename>//depot/projects/soc2008/<replaceable>project-name</replaceable>/...</filename></para>
 | |
|       </listitem>
 | |
|     </itemizedlist>
 | |
| 
 | |
|     <para>The project mentor is responsible for choosing a suitable
 | |
|       project name and getting the student going with
 | |
|       <application>Perforce</application>.</para>
 | |
| 
 | |
|     <para>Access to the &os; <application>Perforce</application>
 | |
|       server does not imply access to subversion, though we happily
 | |
|       encourage all students to consider
 | |
|       joining the project when the time is appropriate.</para>
 | |
|   </sect1>
 | |
| </article>
 |