aboutsummaryrefslogtreecommitdiff
path: root/en_US.ISO8859-1/articles/p4-primer/article.xml
blob: c174348aeabfc81a6308aa79145244b87e34342e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
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:
        &lt;enter description here&gt;
        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>&lt;enter description here&gt;</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&nbsp;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>\!&nbsp;-type&nbsp;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>