After the previous posts describing selectors in detail, it's now time to enter the last selector frontier: multi repository selectors.
As you know plastic can manage multiple repositories. You can map each one of your projects inside a plastic repository, or go for more advanced practices like component oriented development.
Repositories can be totally independent from each other, but there're also situations in which they can be tightly related. For instance you can have shared libraries you’ve developed and you reuse between different projects. If this is the case, it can be useful to have one repository for each project, and one repository for the libraries.
But then, how can developers use the code from the libraries and the project at the same time?
Let's take a look at a very simple repository like the one on the figure. It has just a couple of files and an empty directory. Probably none of your projects looks so simple. Suppose this is the repository named “proj00”.
Then you have another repository containing your library code. It looks like the one at the following figure. This repository is named “lib_repos”.
Now we need to make the lib_repos repository available to the “proj00” developers.
Please note we’ve created an empty “lib” directory which will be used as mount point in “proj00” to plug “lib_repos”.
Take a look at the following selector:
repository "lib_repos" mount "/lib"
path "/"
branch "/main"
checkout "/main"
repository "proj00"
path "/"
branch "/main"
checkout "/main"
Remember how selector rules work:
from top to bottom, and you’ll see how we’re telling plastic: take everything from lib_repos at the main branch, but mount it at /lib. Later on it will need to resolve the /lib path, and it will be solved using the next repository rule (proj00).
If you run the following ls (with a format modifier to show the repository information) you’ll see the following.
>cm ls
br:/main#1@rep:proj00@local:8084 .
br:/main#0@rep:proj00@local:8084 file00.txt
br:/main#0@rep:proj00@local:8084 file01.txt
br:/main#1@rep:lib_repos@local:8084 lib
Note:
We used the following PLASTIC_LS_FORMAT environment variable:
LS_FORMAT="{3}@{8,-26} {4,-5} {5}"
Right, the lib directory is being loaded from the lib_repos repository.
Of course if you move inside the directory you’ll check that everything inside is from the same repos. Look at the following plastic screenshot showing the repository details of the files and directories.
Implementing a real working environment
The selector above showed how to go for main branch development on a multi-repository scenario. But you’ll probably need to implement a whole branching strategy. If so, then consider the following selector:
repository "lib_repos" mount "/lib"
path "/"
label “lib_00”
repository "proj00"
path "/"
branch "/main/task001" label “BL010”
checkout "/main/task001"
This resembles a branch per task pattern on a multi-rep scenario.
Please note we’re now mounting “lib_repos” as read-only because we’re just specifying a label and not a check out rule.
The way to use the mounted repository will vary depending on your project’s needs. It can happen than a different dev group completely manages “lib_repos”, then is ok to mount it read-only because developers at “proj00” will only use it as a “library”. Lib_repos will go through its own release cycle and the team at proj00 will only have to take care of changing the label of the mounted repository when a new release is available and approved for their project.
It can also happen that your team is responsible of both repositories. You’ve decided to split them because they’re clearly different components but there is only one release cycle for them.
Then it makes sense to follow a combined “branch and merge cycle” for the two repositories. If you’re working on task001 then it can happen you need to change code at both lib_repos and proj00. You’ll be probably using a selector like:
repository "lib_repos" mount "/lib"
path "/"
branch "/main/task001" label “BL010”
checkout "/main/task001"
repository "proj00"
path "/"
branch "/main/task001" label “BL010”
checkout "/main/task001"
Please note that:
There’re two branches /main/task001, one at each repos, and the same for labels, but you can use a naming convention (using the same name as I’m doing here) to enforce their relationship.
Going really advanced, configuring what you mount
So far we’ve seen typical mount scenarios. But, what if you need to mount inside the “/lib” directory at “proj00” something which is not at the root of “lib_repos”?
Then we’ll use the power of plastic branch inheritance to actually get the desired result.
Suppose we want to mount inside “lib” the content of the “/bin” directory. So, we want to use “/bin” as the root of the lib_repos repository. To make things easier we’ll assume there’s a “release” subdirectory inside “bin”. Check the following figure.

Let’s go to the lib_repos repository and create a branch named “/main/mount-point”.
Then let’s use regular rm and mv commands to correctly configure the “mount-point” branch as we need.
>cm co .
Checking out . ... Done
>cm rm doc src
Item doc has been removed.
Item src has been removed.
>cm co bin
Checking out bin ... Done
>cm mv bin\release .
bin\release has been moved to .
>cm ls
0 07/04/08 dir br:/main/mount-point#CO CO .
0 07/04/08 dir br:/main/mount-point#CO CO bin
0 07/04/08 dir br:/main#0 release
>cm ci bin
Checking in bin ... Done
Created changeset
cs:3@rep:lib_repos@repserver:CONRAD:8084
>cm rm bin
Item bin has been removed.
>cm ls
0 07/04/08 dir br:/main/mount-point#CO CO .
0 07/04/08 dir br:/main#0 release
>cm ci .
Checking in . ... Done
Created changeset
cs:4@rep:lib_repos@repserver:CONRAD:8084
Then we can set the following selector:
repository "lib_repos" mount "/lib"
path "/?"
branch "/main"
checkout "/main"
path "/" norecursive
branch "/main/mount-point"
repository "proj00"
path "/"
branch "/main"
checkout "/main"
Please note the following:
We’re using the /main/mount-point branch just as a way to “refactor” the directory structure, but all the contents will be loaded from the main branch of the “lib_repos” repository. Of course instead of the main branch we could be using a different one.
The purpose of the /main/mount-point branch is not being merged back into “/main”
but just hold a project reorganization. In fact we can even prevent it to be merged denying the merge permission.

Let’s set the following selector:
repository "lib_repos" mount "/lib"
path "/?"
branch "/main/task001" label “BL010”
checkout "/main/task001"
path "/" norecursive
branch "/main/mount-point"
repository "proj00"
path "/"
branch "/main/task001" label “BL010”
checkout "/main/task001"
And a little explanation:
Whenever you make changes to your code inside the “lib” directory, you’ll be placing the changes directly inside “/main/task001”, but using the directory reorganization from “/main/mount-point”.
When you merge back /main/task001 in lib_repos, you’ll be only getting the changes made on the task, and not the entire reorganization made inside “mount-point”.
That’s why plastic branch inheritance is so powerful and allows many different scenarios to be implemented.
Future work
We’re currently working on the design of new selector rules to allow different repositories to be mounted on different locations directly. Some people will find the “mount-point” branch solution helpful, but other will prefer to be able to do something equivalent just using selector rules.
We’re introducing new selector rules to be able to specify which one is the root item to be used in a mount point, for instance. This way you could specify that /bin is now the root at lib_repos.
Also we’re working on creating “workspace selector directories”, which are local directories not under source control but managed by the tool (created by the update process) and able to hold controlled code…
So, we’re open to suggestions… feel free to contact me by email if you have ideas about possible selector evolution.









