March 24, 2011

Streams: A Tiny Tutorial


I promised to post a tutorial on using Perforce streams, so let's just dive right in. Here’s the short synopsis of what we’ll do:

  • Create a stream depot.
  • Create a mainline rooted in that depot.
  • Import files from an existing depot into our mainline.
  • Branch a development stream from the mainline.
  • Merge files from the mainline to the dev stream.
  • Promote the dev stream to the mainline.

As I mentioned in the first blog in this series, streams will be supported in the upcoming release of Perforce. This tutorial will give you a peek at the commands and operations that will be available. You can't try this yourself, because the Perforce Server version you need hasn't been released yet.

There will be visual tools for streams, but I’m going to use the command line for this tutorial. And I'm not going to dwell on syntax or command arguments at this point -- there's plenty of time for that later.

Let's assume our local environment is already configured to connect to a stream-savvy Perforce Server. Before we get started, we need to bootstrap a new client workspace. My trick for this is to create a new local directory, and in that directory, run:

% p4 workspace -o | p4 workspace -i

Okay, let's roll!

1. Creating a stream depot

Streams live in stream depots, so the first thing we need is a stream depot. Let’s define one called Ace:

% p4 depot Ace

We edit the default definition to make this a stream depot:

Depot: Ace
Type:  localstream

(Note that the “we” in this step is a user with 'super' privileges. But from here on out, non-privileged users can run the commands I’ll demonstrate.)

2. Creating a new mainline

Now we define a stream called //Ace/MAIN:

% p4 stream -t mainline //Ace/MAIN

3. Importing files into the mainline

Having defined the stream, we can now switch our workspace to it:

% p4 workspace -s -S //Ace/MAIN

Our client view is now a view of the //Ace/MAIN stream. There aren't any files in that stream yet, so let's branch some from another depot location:

% p4 copy -v //depot/projects/ace/trunk/... //Ace/MAIN/...
% p4 submit -d ”Seeding the Ace mainline”

Now our mainline is full of files, ready for us and our colleagues to start working on them. Anyone who wants to work in the mainline can create their own workspace and switch it to the stream, just as we just did. Then they can run the usual p4 sync, p4 edit, and p4 submit comands, the same as in a non-stream workspace.

4. Branching a development stream from the mainline

Oh, but wait -- let’s say we don’t want to do feature development work in the mainline. Instead, we want to work in a development stream. So let's branch a development stream from the mainline. We’ll call it //Ace/DEV. First we define it, with //Ace/MAIN as its parent:

% p4 stream -t development -P //Ace/MAIN //Ace/DEV

We now switch our workspace to //Ace/DEV:

% p4 workspace -s -S //Ace/DEV

And we populate the stream by branching its parent's files:

% p4 merge -S //Ace/DEV -r
% p4 submit -d ”Branching from mainline”

This leaves our local workspace in sync with the //Ace/DEV branch, ready for us to start working on files.

5. Merging files from the mainline

While we’re working on features in //Ace/DEV, other changes are being submitted to //Ace/MAIN. Here’s how we merge those changes into the //Ace/DEV branch:

% p4 merge -S //Ace/DEV -r
% p4 resolve
% p4 submit -d ”Merged latest changes”

(Yes, p4 merge is a new command. It does pretty much the same thing p4 integ does, but only after validating the relationship between a stream and its parent. This is another topic I'll be blogging about soon.)

6. Promoting our development work to the mainline

Let’s say we’ve completed a development task in the //Ace/DEV stream. Now we’d like to promote our work to the parent stream.

“Promote” is simply another way of saying “copy up after merging everything down”. So let’s make sure we’ve merged everything down first:

% p4 merge -n -S //Ace/DEV -r
All revisions already integrated.

Looks good. Now let's switch our workspace back to //Ace/MAIN:

% p4 workspace -s -S //Ace/MAIN
% p4 sync

We run p4 sync after switching the workspace, because both streams have files in them at this point. (You'll be happy to know that p4 sync will be smart enough to swap out only the files that aren't the same in both streams.)

Finally, we copy content from the //Ace/DEV stream to its parent:

% p4 copy -S //Ace/DEV
% p4 submit -d ”Here’s our new feature”

Et voilà -- our work in the //Ace/DEV stream has just been promoted to //Ace/MAIN.

What you see in this tiny tutorial is just the tip of the iceberg. I didn’t touch on stream views, view inheritance, or controlling the flow of change. I’ll get to them in future blogs. Nor did I show you how easy it is to use streams in P4V. For that you'll want to come to the Perforce User Conference and see the demo!

Meanwhile, I'll get to work on my next blog installment. If you joined late, here are the posts that preceded this one:

We thank those of you who have offered comments and questions about the previous posts. Randy DeFauw has already answered one or two, and I'm going to address more of them directly in an upcoming post. So please keep them coming, and we'll do our best to respond.