<!--
Copyright (c) Perforce Software, Inc., 1997-2010. All rights reserved
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE
SOFTWARE, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
User contributed content on the Perforce Public Depot is not supported by Perforce,
although it may be supported by its author. This applies to all contributions
even those submitted by Perforce employees.
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>PDS</title>
<link rel="stylesheet" type="text/css" href="applets.css" />
<script type="text/javascript">
var mainColor = "#000000";
var highColor = "#0000FF";
var loColor = "#FF0000";
var mergeColor = "#009966";
var promoteColor = "#CC3399";
var lineHeight = 2;
var radius = 5;
// Draw all canvases
function drawCanvases() {
drawFgsCanvas();
drawWebCanvas();
drawToolkitCanvas();
} // drawCanvases
function drawWebCanvas() {
var canvas = document.getElementById("webCanvas");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
// main
ctx.fillStyle = mainColor;
ctx.fillText("//web/main/...", 25, 85);
ctx.beginPath();
ctx.fillRect(50, 100, 350, lineHeight);
ctx.closePath();
ctx.fill();
// live
ctx.beginPath();
ctx.fillStyle = highColor;
ctx.fillText("//web/live/...", 100, 35);
ctx.fillRect(150, 50, 250, lineHeight);
ctx.closePath();
ctx.fill();
// live - start branch
ctx.beginPath();
ctx.fillStyle = highColor;
ctx.fillRect(150, 50, lineHeight, 50);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(150, 50, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
// live - promotes from main
ctx.beginPath();
ctx.fillStyle = promoteColor;
ctx.fillRect(250, 50, lineHeight, 50);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(250, 50, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.fillRect(350, 50, lineHeight, 50);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(350, 50, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
// latest
ctx.beginPath();
ctx.fillStyle = loColor;
ctx.fillText("//web/dev/latest/...", 100, 135);
ctx.fillRect(200, 150, 200, lineHeight);
ctx.closePath();
ctx.fill();
// latest - start branch
ctx.beginPath();
ctx.fillStyle = loColor;
ctx.fillRect(200, 100, lineHeight, 50);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(200, 150, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
// latest - promote
ctx.beginPath();
ctx.fillStyle = promoteColor;
ctx.fillRect(225, 100, lineHeight, 50);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(225, 100, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.fillRect(325, 100, lineHeight, 50);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(325, 100, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
} // got canvas
} // drawWebCanvas
function drawToolkitCanvas() {
var canvas = document.getElementById("toolkitCanvas");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
// main
ctx.fillStyle = mainColor;
ctx.fillText("//toolkit/main/...", 0, 160);
ctx.beginPath();
ctx.fillRect(50, 175, 350, lineHeight);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(150, 175, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(225, 175, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
// cust1
ctx.beginPath();
ctx.fillStyle = highColor;
ctx.fillText("//toolkit/svcs/Army/main/...", 75, 35);
ctx.fillRect(100, 50, 300, lineHeight);
ctx.closePath();
ctx.fill();
// cust1 - start branch
ctx.beginPath();
ctx.fillStyle = highColor;
ctx.fillRect(100, 50, lineHeight, 125);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(100, 50, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
// cust1 - merge from main
ctx.beginPath();
ctx.fillStyle = mergeColor;
ctx.fillRect(350, 50, lineHeight, 125);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(350, 50, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
// cust2
ctx.beginPath();
ctx.fillStyle = highColor;
ctx.fillText("//toolkit/svcs/Navy/main/...", 150, 85);
ctx.fillRect(175, 100, 225, lineHeight);
ctx.closePath();
ctx.fill();
// cust2 - start branch
ctx.beginPath();
ctx.fillStyle = highColor;
ctx.fillRect(175, 100, lineHeight, 75);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(175, 100, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
// cust2 - merge from main
ctx.beginPath();
ctx.fillStyle = mergeColor;
ctx.fillRect(250, 100, lineHeight, 75);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(250, 100, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
} // got canvas
} // drawToolkitCanvas
function drawFgsCanvas() {
var canvas = document.getElementById("fgsCanvas");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
// main
ctx.fillStyle = mainColor;
ctx.fillText("//fgs/main/...", 25, 85);
ctx.beginPath();
ctx.fillRect(50, 100, 350, lineHeight);
ctx.closePath();
ctx.fill();
// rel
ctx.beginPath();
ctx.fillStyle = highColor;
ctx.fillText("//fgs/rel/2.0-R/...", 100, 35);
ctx.fillRect(150, 50, 250, lineHeight);
ctx.closePath();
ctx.fill();
// rel - start branch
ctx.beginPath();
ctx.fillStyle = highColor;
ctx.fillRect(150, 50, lineHeight, 50);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(150, 50, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
// rel - bug merge
ctx.beginPath();
ctx.fillStyle = mergeColor;
ctx.fillRect(250, 50, lineHeight, 50);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(250, 100, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
// dev
ctx.beginPath();
ctx.fillStyle = loColor;
ctx.fillText("//fgs/dev/FGS218/...", 100, 325);
ctx.fillRect(200, 150, 200, lineHeight);
ctx.closePath();
ctx.fill();
// dev - start branch
ctx.beginPath();
ctx.fillStyle = loColor;
ctx.fillRect(200, 100, lineHeight, 50);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(200, 150, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
// dev - merge
ctx.beginPath();
ctx.fillStyle = mergeColor;
ctx.fillRect(300, 100, lineHeight, 50);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(300, 150, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
// dev - promote
ctx.beginPath();
ctx.fillStyle = promoteColor;
ctx.fillRect(400, 100, lineHeight, 50);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(400, 100, radius, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
} // got canvas
} // drawFgsCanvas
</script>
</head>
<body class="applet" onload="drawCanvases();">
<h2>Perforce Directory Structure</h2>
This page is an overview of the PDS, which is captured fully in <a href="http://www.perforce.com/perforce/doc.current/manuals/p4web/help/index.html">PDS Guide (P4Web)</a>.
<br><br>
<a href="#dirlevels">Directory Levels</a><br>
<a href="#patterns">Branching Patterns</a><br>
<a href="#methods">Branch Methods</a><br>
<a href="#diagrams">Branch Diagrams</a><br>
<a href="#diagram_fgs">...fgs</a><br>
<a href="#diagram_web">...web</a><br>
<a href="#diagram_toolkit">...toolkit</a>
<h3><a name="dirlevels">Directory Levels</a></h3>
Our PDS indicates the use of a product level and container level in the branch model. Directories below that are determined by the needs of the product. The basic structure is:
<br>
<div class="info"><i>//<product>/<container>[/<version>]/<module>/...</i></div>
<p>For example, the <i>fgs</i> product's main line has two modules, <i>src</i> and <i>doc</i>, and is located at:
<br>
<div class="info">
<i>//fgs/main/src/...</i>
<br>
<i>//fgs/main/doc/...</i>
</div>
<br>
<h3><a name="patterns">Branching Patterns</a></h3>
Branching patterns determine what container levels are used, and the integration paths between these levels. The table below lists the branching patterns and directory container levels for our products.
<table class="applet eighty">
<tr>
<th scope="col" class="applet">Product</th>
<th scope="col" class="applet">Branching Patterns</th>
<th scope="col" class="applet">Container Levels</th>
<th scope="col" class="applet">Other SCM Areas</th>
</tr>
<tr>
<td class="applet">fgs</td>
<td class="applet">Basic Maintenance<br>Basic Planned Development</td>
<td class="applet">main<br>dev<br>rel<br>sb</td>
<td class="applet"><i>//fgs-bld</i> and <i>fgs-rel</i> depots for builds and releases</td>
</tr>
<tr>
<td class="applet">web</td>
<td class="applet">Standard Hosted</td>
<td class="applet">live<br>main<br>latest</td>
<td class="applet"></td>
</tr>
<tr>
<td class="applet">toolkit</td>
<td class="applet">Organic Development<br>Customization</td>
<td class="applet">main<br>svcs</td>
<td class="applet">Uses libraries from <i>//3rdparty</i> depot</td>
</tr>
</table>
<br>
<h3><a name="methods">Branch Methods</a></h3>
The two main types of branching methods are <i>merge</i> and <i>promotion</i>.
<p>
A regular <i>merge</i>, also called a <i>merge down</i>, is typically done from a more stable to a less stable branch. For example, we would <i>merge down</i> from <i>//fgs/main/...</i> to <i>//fgs/dev/FGS218/...</i> in order to pick up the latest bug fixes on <i>main</i>. Any resolves are started using <a href="http://www.perforce.com/perforce/doc.current/manuals/cmdref/resolve.html#1040665">p4 resolve -am</a>. A <i>merge</i> may result in a conflicts.
<p>
A <i>promotion</i> is done when a less stable branch is fully tested and ready to be pushed to its more stable parent branch. The goal is to make the parent branch an exact copy of the less stable branch. For example, when work is stable on <i>//fgs/dev/FGS218/...</i>, we would <i>promote</i> it to <i>//fgs/main/...</i>. A last <i>merge down</i> is done immediately before a promotion. A promotion is done using <i>p4 resolve -at</i>, followed by a <i>diff-driven merge</i> to account for any divergence.
<p>
<i>Selective integrations</i> are special cases where a specific revision, or set of revisions, is cherry-picked. Selective integrations introduce complexity into the integration history, and should be avoided if possible.
<br>
<h3><a name="diagrams">Branch Diagrams</a></h3>
Putting this all together gives us the sample branch diagrams below.
<br>
<div class="info">
<b>Legend</b><br>
<font style="color: #000000;"><i>main line</i></font><br>
<font style="color: #FF0000;"><i>less stable branches</i></font><br>
<font style="color: #0000FF;"><i>more stable branches</i></font><br>
<font style="color: #009966;"><i>merge paths</i></font><br>
<font style="color: #CC3399;"><i>promotion paths</i></font>
</div>
<br>
<h4><a name="diagram_fgs">fgs</a></h4>
Note that the <i>sandbox</i> branches do not have a defined relationship to other branches, and so are not shown in this diagram. <i>Sandbox</i> branches are located under <i>//fgs/sb/...</i>.<br>
<canvas id="fgsCanvas" width="500" height="200"></canvas>
<h4><a name="diagram_web">web</a></h4>
<canvas id="webCanvas" width="500" height="200"></canvas>
<h4><a name="diagram_toolkit">toolkit</a></h4>
<canvas id="toolkitCanvas" width="500" height="200"></canvas>
</body>
</html>