diff options
author | Gabor Kovesdan <gabor@FreeBSD.org> | 2012-10-01 09:53:01 +0000 |
---|---|---|
committer | Gabor Kovesdan <gabor@FreeBSD.org> | 2012-10-01 09:53:01 +0000 |
commit | b4346b9b2dfe86a97907573086dff096850dcb1d (patch) | |
tree | 9b951977cbd22dada9b868ac83b1d56791ea3859 /en_US.ISO8859-1/articles/p4-primer/article.xml | |
parent | bee5d224febbeba11356aa848006a4f5f9e24b30 (diff) | |
download | doc-b4346b9b2dfe86a97907573086dff096850dcb1d.tar.gz doc-b4346b9b2dfe86a97907573086dff096850dcb1d.zip |
- Rename .sgml files to .xml
- Reflect the rename in referencing files
Approved by: doceng (implicit)
Notes
Notes:
svn path=/head/; revision=39631
Diffstat (limited to 'en_US.ISO8859-1/articles/p4-primer/article.xml')
-rw-r--r-- | en_US.ISO8859-1/articles/p4-primer/article.xml | 893 |
1 files changed, 893 insertions, 0 deletions
diff --git a/en_US.ISO8859-1/articles/p4-primer/article.xml b/en_US.ISO8859-1/articles/p4-primer/article.xml new file mode 100644 index 0000000000..c174348aea --- /dev/null +++ b/en_US.ISO8859-1/articles/p4-primer/article.xml @@ -0,0 +1,893 @@ +<?xml version="1.0" encoding="iso-8859-1" standalone="no"?> +<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V4.2-Based Extension//EN" + "../../../share/sgml/freebsd42.dtd" [ +<!ENTITY % entities PUBLIC "-//FreeBSD//ENTITIES DocBook FreeBSD Entity Set//EN" "../../share/sgml/entities.ent"> +%entities; +]> + +<article lang='en'> + <title>Perforce in &os; Development</title> + + <articleinfo> + + <authorgroup> + <author> + <firstname>Scott</firstname> + <surname>Long</surname> + <affiliation> + <address><email>scottl@FreeBSD.org</email> + </address> + </affiliation> + </author> + </authorgroup> + + <legalnotice id="trademarks" role="trademarks"> + &tm-attrib.freebsd; + &tm-attrib.cvsup; + &tm-attrib.general; + </legalnotice> + + <pubdate>$FreeBSD$</pubdate> + + <releaseinfo>$FreeBSD$</releaseinfo> + </articleinfo> + +<sect1 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 CVS repository.</para> + + <sect2 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 <filename role="package">devel/p4</filename> + port or can be downloaded from the <application>Perforce</application> + web site at <ulink + url="http://www.perforce.com/perforce/loadprog.html"></ulink>, + 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 <ulink + url="http://www.perforce.com/perforce/technical.html"></ulink>.</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 the <command>p4 + help</command> command.</para> + + <para>The &os; <application>Perforce</application> server is + hosted on <hostid role="fqdn">perforce.freebsd.org</hostid>, + port <literal>1666</literal>. The repository is browsable + online at <ulink url="http://perforce.freebsd.org"></ulink>. + Some portions of the repository are also automatically exported + to a number of <application>CVSup</application> servers.</para> + </sect2> +</sect1> + +<sect1 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 <hostid + role="domainname">FreeBSD.org</hostid> account, log into <hostid + role="hostname">freefall</hostid>, 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 <hostid + role="domainname">FreeBSD.org</hostid> 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 <hostid + role="domainname">FreeBSD.org</hostid> 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 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 the <command>p4 client</command> + 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 class="directory">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 + class="directory">//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. Let's 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 the <command>p4 + clients</command> command. They can be viewed without being + modified via the <command>p4 client -o + <replaceable>clientname</replaceable></command> 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 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 the <command>p4 sync</command> 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 class="directory">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 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>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 + class="directory">//depot</filename> directory. When you create a + branch, all you are doing is creating a new path under the + <filename class="directory">//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 the + <command>p4 client</command> 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 the <command>p4 integrate</command> + command, as described in the next section.</para> +</sect1> + +<sect1 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 (i.e. + 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 the + <command>p4 submit</command> command, explained in the next + section.</para> +</sect1> + +<sect1 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 the <command>p4 + submit</command> 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 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 the <command>p4 edit</command> + 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 the <command>edit</command> 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 the + <command>p4 revert</command> 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 the <command>p4 + edit</command> 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 id="changes"> + <title>Changes, Descriptions, and History</title> + + <para>Changes to the <application>Perforce</application> depot can + be listed via the <command>p4 changes</command> 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 the <command>p4 describe + <replaceable>changenumber</replaceable></command> command. This + will provide the submit log and the diffs of the actual change.</para> + + <para>Commonly, the <command>p4 describe</command> 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 <command>p4 filelog + <replaceable>filename</replaceable></command> command will show + the history of a file, including all submits, integrations, and + branches of it.</para> +</sect1> + +<sect1 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 + the <command>p4 diff</command> 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: <ulink + url="http://people.freebsd.org/~scottl/awkdiff"></ulink>.</para> +</sect1> + +<sect1 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 + the <command>p4 add</command> 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 don't 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 the + <command>p4 obliterate</command> command. This command is + irreversible and expensive, so it is only available to those with + admin access.</para> +</sect1> + +<sect1 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 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 id="freebsd-cvs-and-p4"> + <title>Interactions between &os; CVS and Perforce</title> + + <para>The &os; <application>Perforce</application> and CVS + repositories are completely separate. However, changes to CVS are + tracked at near-real-time in <application>Perforce</application>. + Every 2 minutes, the CVS server is polled for updates in the HEAD + branch, and those updates are committed to + <application>Perforce</application> in the <filename + class="directory">//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 CVS and <application>Perforce</application> + is one-way; changes to CVS will be reflected in + <application>Perforce</application>, but changes in Perforce will + not be reflected in CVS. On request, some parts of the + <application>Perforce</application> repo can be exported to + <application>CVSup</application> and made available for + distribution that way. Contact the &os; + <application>Perforce</application> administrators if this is + something that you are interested in.</para> +</sect1> + +<sect1 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 CVS/<application>CVSup</application>. 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 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 + class="directory">//depot/projects/soc2005/<replaceable>project-name</replaceable>/...</filename></para> + </listitem> + <listitem> + <para><filename + class="directory">//depot/projects/soc2006/<replaceable>project-name</replaceable>/...</filename></para> + </listitem> + <listitem> + <para><filename + class="directory">//depot/projects/soc2007/<replaceable>project-name</replaceable>/...</filename></para> + </listitem> + <listitem> + <para><filename + class="directory">//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 membership in the &os; CVS committer community, + though we happily encourage all students to consider joining the + project when the time is appropriate.</para> +</sect1> +</article> |