Cm find by example


Chapter 1: "cm find"

In every version control system we frequently need to get information about usage, about what files are being changed or just searching for a specific change or a specific branch.

The best way of achieving this is by using queries, so when we created Plastic SCM we added a very powerful query system called cm find, a command that allows you to get specific information involving changesets, branches, labels, merges and code reviews.

The find can also be used to customize views in the GUI.

This article covers by examples some scenarios that can be handled with the cm find command; they are a small subset of what you can do in your Plastic SCM installation. Each sample includes a question, a step-by-step solution and the expected output to help you to understand what kind information is returned.

Note: You can use both singular and plural to find an object. For instance, you can use both cm find branch or cm find branches.
Note: All cm find queries are case-sensitive.
Note: When you run queries using comparison operators (>, <, >=, <=) from the command line, remember that the shell considers these operators as IO redirections, so you will need to enclose the queries with quotation marks:
cm find "branches where owner='pablo' and changesets >= '2013/03/01'"
Or you can enclose only the comparison operators:
cm find branches where owner='pablo' and changesets ">=" '2013/03/01'
Note about Powershell: The powershell console will escape the "double" quotes by default (but not the "simple"), so we must put an extra pair of quotes to specify we want them inside our command:
cm find replicationlog where branch = "'/semanticmain'" --format="{date}" --nototal | select -Last 1
Or you and enclose all the query:
cm find replicationlog "where branch = '/semanticmain'" --format="{date}" --nototal | select -Last 1

Chapter 2: Branches

Can I find all the branches that have passed tests before a specific date?

We can retrieve the branches that were created by a user on a time span, and then we can filter by a specific attribute.


Find all branches

We start retrieving all the branches available:

cm find branches 301186 09/01/2013 8:18:51 /main/Fix-4.1/SCM12154 borja codice T 378467 12/02/2013 12:43:24 /main/scm12336 violeta codice T 379892 12/02/2013 17:52:14 /main/scm12336/scm12013 pablo codice T 407817 22/04/2013 16:32:31 /main/scm12636/scm12666 pablo codice T 426648 29/05/2013 17:36:04 /main/scm12313 pablo codice T Total: 5

Find our branches

We only want our branches, so we filter by user:

cm find branches where owner='pablo' 379892 12/02/2013 17:52:14 /main/scm12336/scm12013 pablo codice T 407817 22/04/2013 16:32:31 /main/scm12636/scm12666 pablo codice T 426648 29/05/2013 17:36:04 /main/scm12313 pablo codice T Total: 3

Find branches filtered by date

After filtering by user, we now want only the branches related to this sprint, so we are looking for the ones created after a specific date:

cm find "branches where owner='pablo' and date >= '2013/03/01'" 407817 22/04/2013 16:32:31 /main/scm12636/scm12666 pablo codice T 426648 29/05/2013 17:36:04 /main/scm12313 pablo codice T Total: 2

You can use a formatted output:

cm find "branches where owner='pablo' and date >= '2013/03/01'" --format="{name,-30} {date}" /main/scm12636/scm12666 22/04/2013 16:32:31 /main/scm12313 29/05/2013 17:36:04 Total: 2

Find branches by attribute value

Finally, we look for a specific attribute. According to our internal feature lifecycle each branch must pass tests before integrating it on the main branch.

When a branch passes the test the "test" attribute will be set to "passed", and so, we filter by attribute name and by attribute value:

cm find "branches where owner='pablo' and date>= '2012/01/01' and attribute ='test' and attrvalue = 'passed'" 426648 29/05/2013 17:36:04 /main/scm12313 pablo codice T Total: 1

Filtering and Output options

The following table displays the different filtering options that are currently available to be used with cm find branch command:

Filtering options ( where... )
attribute attrvalue changesets comment date guid
id item name owner parent repllogid
replsrcdate replsrcid replsrcrepository replsrcserver

* Condition date corresponds to Creation date column in the Branches view.



This other table displays the different output options that are currently available to be used with cm find branch command:

Output options ( --format... )
comment date id name owner parent

Chapter 3: Changesets


Show changeset's comments

Can I find that comment I wrote in some checkin? I'm sure that is has to be somewhere in this branch and that is related to "solution".

We can find a lot of info for the changesets, and the comments are just one of those. For quick info we can use cm log and do our own filtering (using shell commands) or let cm find to do the job for you.

In this sample we are getting the date and comment for all the changesets that belong to a branch:

cm find changeset where branch = 'main/scm12800' --format="{date} - {comment}" 27/05/2013 13:25:53 - Updated output. 27/05/2013 13:26:45 - Changed SccPlugin with the new change. 27/05/2013 13:35:15 - Added solution. Total: 3

So here are all the changesets, now we are looking for the word "solution", here we can easily see it, but when we have a couple hundred changesets, it becomes something slow and boring. For filtering by a specific word we use the SQL-syntax LIKE and % for an approximate search, because we are not looking for the full comments:

cm find changeset where branch = 'main/scm12800' and comment like '%solution%' --format="{date} - {comment}" 27/05/2013 13:35:15 - Added solution. Total: 1

Find replicated changesets

Can I find the changesets I replicated on a specific date?

We can also query the changesets by replication date, using the following command (we will see later how to get the last replication date):

cm find changeset where branch='semanticmain' and replsrcdate ">" '2013/06/17' --nototal 427425 16794 /semanticmain 07/06/2013 11:06:38 violeta codice IntegrateMiryamtask 12838 427435 16804 /semanticmain 07/06/2013 19:25:31 violeta codice Changeassemblyversion (0.9.28.0). 427436 16805 /semanticmain 07/06/2013 19:54:35 lrodriguez codice Updatemapall

Filtering and Output options

The following table displays the different filtering options that are currently available to be used with cm find changeset command:

Filtering options ( where...)
attribute attrvalue branch changesetid comment date
guid id owner parent repllogid replsrcdate
replsrcid replsrcrepository replsrcserver returnparent

* Conditions changesetid, date and owner correspond to Name , Creation date and Created by columns respectively in the Changesets view.



This other table displays the different output options that are currently available to be used with cm find changeset command:

Output options ( --format...)
branch changesetid comment date guid id
owner parent

"returnparent" field

What is that returnparent field for?

returnparent allows us to get the parent of a specific changeset or revision. That way, if we want to know what happened before this changeset we can simply ask:

cm find changeset where changesetid = 16583 and returnparent = 'true' --nototal 423630 16582 /main/scm12800 27/05/2013 13:25:53 roberto codice Updated output.

Chapter 4: Replication log

Can I find when the last replica for a specific branch was?

Given a branch, we can get all the replication operations since the beginning of the times in chronologically order.

cm find replicationlog "where branch = '/semanticmain'" --nototal 424089 03/06/2013 12:16:42 codice@diana:9095 F pablo 426718 17/06/2013 18:46:38 codice@diana:9095 F pablo 427606 17/06/2013 18:50:47 codice@diana:9095 F pablo

If we only want the last date, we can filter the search by date and select the last row using Powershell or bash.

Powershell:

cm find replicationlog "where branch = '/semanticmain'" --format="{date}" --nototal | select -Last 1

Bash:

cm find replicationlog "where branch = '/semanticmain'" --format="{date}" --nototal | tail -n 1

Result:

17/06/2013 18:50:47

Filtering and Output options

The following table displays the different filtering options that are currently available to be used with cm find replicationlog command:

Filtering options ( where...)
branch date id owner package repositoryname
server


This other table displays the different output options that are currently available to be used with cm find replicationlog command:

Output options ( --format...)
date id owner package server

Chapter 5: Labels


Find labels in a specific branch

Can I find all the labels in a specific branch?

We can get all the labels:

cm find label --format="{name} {owner} {branch} {branchid}" --nototal on repository 'codice' BL234 lrodriguez /main 3 BL235 lrodriguez /main 3 BL236 lrodriguez /main/task001 4 BL237 lrodriguez /main 3 BL238 lrodriguez /main/task002 5 BL239 lrodriguez /main 3

And we can get all the labels that we are created in certain branch:

cm find label where branch = '/main' --format="{name} {owner}" --nototal on repository 'codice' BL234 lrodriguez BL235 lrodriguez BL237 lrodriguez BL239 lrodriguez

Find branch with specific label

Can I find the branch that contains a specific label?

At codice we keep a main branch for development and a "Fix" branch for supporting current and old versions, so we may want to find which branch contains a specific release:

cm find label where name = 'BL237' --nototal on repository 'codice' 191871 17/11/2011 16:38:06 BL237 10503 /main lrodriguez codice

As we can see, the label BL237 comes from the "main" branch.


Find changesets between 2 labels

Can I find which changesets were created between 2 labels?

We can get the labels date, and later ask for the changesets that were created in that timespan in that branch. Getting the information for two (or more) labels is very simple:

cm find label where name = 'BL237' or name='BL235' --nototal on repository 'codice' 191869 11/11/2011 14:20:02 BL235 1750 /main lrodriguez codice 191871 17/11/2011 16:38:06 BL237 10503 /main lrodriguez codice

Filtering and Output options

The following table displays the different filtering options that are currently available to be used with cm find label command:

Filtering options ( where... )
attribute attrvalue branch branchid changeset comment
date guid id name owner repllogid
replsrcdate replsrcid replsrcrepository replsrcserver

* Condition date corresponds to Creation date column in the Labels view.



This other table displays the different output options that are currently available to be used with cm find label command:

Output options ( --format... )
branch branchid changeset comment date id
name owner

Chapter 6: Attributes


Get all attributes

Can I get all the attributes of this branch?

The attributes can be applied to branches, changesets and labels, without any distinction. The first thing we need is the object Id. We can get it specifying the id when querying for a branch:

cm find branch where name = 'main' --format="{id}" --nototal 3

Once we have it, we can get the attribute list with the following commands:

cm find attributes where srcobj=3 --nototal objid:3@repid:2@repserver:localhost:8087 -- status --> PASSED

In this case, the attribute name is "status", and the attribute value is "Passed".

We can combine these two commands using some Powershell scripting:

cm find branch "where name = 'main'" --format="{id}" --nototal |Foreach-Object { cm find attributes where srcobj= $_ --nototal}

Or bash scripting:

for branch_id in 'cm find branch "where name = 'main'" --format="{id}" --nototal' ;do cm find attributes "where srcobj=$branch_id" --nototal; done

The output will be the same as before:

objid:3@repid:2@repserver:localhost:8087 -- status --> PASSED

Get all objects with specific attributes

Can I get all the objects with attribute foo and valuebar?

Let's suppose we set a specific attribute to some objects (in our case, the test "status"), we can query for these attributes, no matter the object that contains it.

cm find attributes where type = 'status' and value='PASSED' objid:253012@repid:2@repserver:localhost:8087 -- status --> PASSED objid:253013@repid:2@repserver:localhost:8087 -- status --> PASSED objid:253014@repid:2@repserver:localhost:8087 -- status --> PASSED objid:268518@repid:2@repserver:localhost:8087 -- status --> PASSED

Filtering and Output options

The following table displays the different filtering options that are currently available to be used with cm find attributes command:

Filtering options ( where... )
comment date guid id owner srcobj
type value

* Conditions date and type correspond to Creation date and Name columns respectively in the Attributes view.



This other table displays the different output options that are currently available to be used with cm find attributes command:

Output options ( --format... )
comment date id owner type value

Chapter 7: Revisions


Files changed in a changeset

Can I find what files have changed in a changeset?

With a specific changeset retrieved in the previous sample, we may want now to know more about the files that have changes in it, and for that purpose we may use find revision.

We specify a custom format, because we only want the file and folder paths:

cm find revisions where changeset=16716 --format="{path}" d:\linked_replicated\ d:\linked_replicated\01nerva d:\linked_replicated\01nerva\src d:\linked_replicated\01nerva\src\client d:\linked_replicated\01nerva\src\client\plastic d:\linked_replicated\01nerva\src\client\plastic\libplasticTranslations.es.resx d:\linked_replicated\01nerva\src\client\plastic\libplasticTranslations.resx d:\linked_replicated\01nerva\src\client\plastic\ActionMenuManager.cs Total: 8

We could also filter by folder with some command line help (grep on Linux, and where on Windows Powershell):

Powershell:

cm find revisions where changeset=16716 --format="{path}" --nototal | where {$_ -match "client\\"}

Bash:

bcm find revisions where changeset=15430 --format="{path}" --nototal | grep client\/

Then the output would be something like this:

d:\linked_replicated\01nerva\src\client\plastic d:\linked_replicated\01nerva\src\client\plastic\libplasticTranslations.es.resx d:\linked_replicated\01nerva\src\client\plastic\libplasticTranslations.resx d:\linked_replicated\01nerva\src\client\plastic\ActionMenuManager.cs

Folder changed inside a branch

Can I know if the folder foo has changed inside a branch on a specific time lapse?

We can also get the revision info for a branch, searching in all its changests. We can start by getting all the changed items from a branch and a time span:

cm find revisions "where branch = 'main/Fix-4.1/scm12814' and date<='2013/05/30' and date > '2013/05/28'" --format="{date} - {path}"

Later we can use our favourite shell tool, in our case Powershell, to filter that info.

cm find revisions "where branch = 'main/Fix-4.1/scm12814' and date<='2013/05/30' and date > '2013/05/28'" --format="{date} - {path}" | where {$_ -match "view\\"}

If you prefer bash, this is your line:

cm find revisions "where branch = 'main/Fix-4.1/scm12814' and date<='2013/05/30' and date > '2013/05/28'" --format="{date} - {path}" | grep view\/

The expected output looks like this:

28/05/2013 12:35:18 - d:\linked_replicated\01nerva\src\client\plastic\view\releasediagram 28/05/2013 12:35:18 - d:\linked_replicated\01nerva\src\client\plastic\view\releasediagram\drawingStyles 28/05/2013 12:35:18 - d:\linked_replicated\01nerva\src\client\plastic\view\releasediagram\drawingStyles\BaseDrawingStyle.cs

Filtering and Output options

The following table displays the different filtering options that are currently available to be used with cm find revisions command:

Filtering options ( where... )
archived attribute attrvalue branch changeset date
guid id item itemid label marker
owner parent repllogid replsrcdate replsrcid replsrcrepository
replsrcserver returnparent size type workspacecheckoutid


This other table displays the different output options that are currently available to be used with cm find revisions command:

Output options ( --format... )
branch changeset date id item itemid
owner parent size type

Chapter 8: Merges


Where the branch has been integrated

Can I get where has been this branch integrated?

What about merges? It's possible to track the merges done from and to a specific branch or changeset.

If we want to know where a branch has been integrated on, you can type the following command:

cm find merge where srcbranch ='main/Fix-4.1/SCM11769' br:/main/Fix-4.1/SCM11769@55613 -->br:/main/Fix-4.1/Release-4.1.10.447@55808 Total: 1

Branches integrated on a specific release

Can I find which branches have been integrated on Release 4.1.10.447?

And if we want to know which branches are integrated in a specific branch, the command is:

$ cm find merge where dstbranch ='main/Fix-4.1/Release-4.1.10.447' br:/main/Fix-4.1/SCM12835@55568 -->br:/main/Fix-4.1/Release-4.1.10.447@55801 br:/main/Fix-4.1/scm11898@55647 -->br:/main/Fix-4.1/Release-4.1.10.447@55802 br:/main/Fix-4.1/scm12839@55678 -->br:/main/Fix-4.1/Release-4.1.10.447@55803 br:/main/Fix-4.1/SCM11769@55613 -->br:/main/Fix-4.1/Release-4.1.10.447@55808 br:/main/Fix-4.1/SCM12860@55735 -->br:/main/Fix-4.1/Release-4.1.10.447@55809 Total: 5

The previous commands can also use our format flags to customize the output by returning only the branch names, that way, for example, the second command would become something like this:

$ cm find merge where dstbranch ='main/Fix-4.1/Release-4.1.10.447' --format="{srcbranch}" --nototal br:/main/Fix-4.1/SCM12835 br:/main/Fix-4.1/scm11898 br:/main/Fix-4.1/scm12839 br:/main/scm12419 br:/main/SCM4052 br:/main/Fix-4.1/SCM11769 br:/main/Fix-4.1/SCM12860

Or:

cm find merges where dstbranch='br:/main/ReleaseBL274' --format="{srcbranch}@{srcchangeset} --> {dstbranch}@{dstchangeset}({type})" --nototal br:/main/scm11148@43953 --> br:/main/ReleaseBL274@44094 (merge) br:/main/scm11181@43969 --> br:/main/ReleaseBL274@44096 (merge) br:/main/Fix-4.0/SCM11101@44010 --> br:/main/ReleaseBL274@44030 (merge) br:/main/scm11135@43980 --> br:/main/ReleaseBL274@44031 (merge) br:/main/ReleaseBL272@43914 --> br:/main/ReleaseBL274@44032 (cherrypick) br:/main/ReleaseBL268@43663 --> br:/main/ReleaseBL274@44033 (cherrypick) br:/main/scm10957@43952 --> br:/main/ReleaseBL274@44093 (merge) br:/main/SCM11195@43981 --> br:/main/ReleaseBL274@44095 (merge) br:/main/SCM10924@43942 --> br:/main/ReleaseBL274@44033 (merge)

Remember that find merge returns all types of merges: regular merges, cherrypicked merges, and subtractive merges.

So you can get interval merges to a given branch:

cm find merges where dstbranch='br:/main/Fix-4.1/ReleaseBL285' and type='intervalcherrypick' --format="({basebranch}@{basechangeset}, {srcbranch}@{srcchangeset}] --> {dstbranch}@{dstchangeset}" --nototal (br:/main@44448, br:/main/scm11318@44461] --> br:/main/Fix-4.1/ReleaseBL285@44463

Branches not integrated

Can I know which branches that were created on this sprint are not integrated?

We can answer this question with two queries (find branches, find merge) and some Powershell hacking. Place this code on a PS1 file and run it from your Powershell console:

$allBranches = cm find branches "where date >= '2013/06/20'" --format="{name}" --nototal; $allMerged = cm find merge "where date >= '2013/06/20'" --format="{srcbranch}" --nototal; for($i = 0; $i -le $allBranches.length -1; $i++) {$allBranches[$i] = 'br:' + $allBranches[$i]} $allBranches| ?{$allMerged -notcontains $_}

Here is a sample output:

br:/main/scm12619 br:/main/Fix-4.1/scm12916 br:/main/Fix-4.1/scm12899/scm12947 br:/main/Fix-4.1/scm11180 br:/main/Fix-4.1/scm8782 br:/main/Fix-4.1/scm12944 br:/semanticmain/SCM12759/scm12948

This code performs the following actions:

  1. Find all the branches from this sprint.
  2. Find all the merges from this sprint, and return only the source branches.
  3. Change the format of the $allbranches output so both lists have the same format.
  4. Check if the "merges" list contains the branches from the allBranches list. If it doesn't, the branch is not integrated.

An equivalent code in bash shell would be the following:

$ allBranches='cm find branches where "date >= '2013/06/20'" --format="{name}" --nototal' $ allMerged='cm find merge where "date >= '2013/06/20'" --format="{srcbranch}" --nototal' $ for branch in $allBranches; do [ ! 'echo $allMerged | grep 'br:$branch'' ] && print "br:$branch"; done

This code, on its side, does the following:

  1. Finds every branch belonging to this sprint.
  2. Finds every merge belonging to this sprint, returning only their source branches.
  3. Print all branches from this sprint which weren't on the merged branches list.

Branches not fully integrated

Can I know which branches are not fully integrated?

We are looking for this scenario:

Scenario

We want those branches that have been integrated into another branch (so we must discard merges into the same branch) but have changesets pending to integrate (the orange cset on the picture), and yes, we can do it with a single query, and then some post-processing with some Powershell code:

$allMergedNonFiltered = cm find merge where "date >= '2013/06/01'" --format="{srcbranch} {dstbranch} {srcchangeset}" --nototal; $allMerged = $allMergedNonFiltered | ForEach-Object {$res = $_.Split(" "); if($res[0] -ne $res[1]) {$res[0] + " " + $res[2]} }; $semiMerged = $allMerged | ForEach-Object {$_.Split(" ")[0] }; $allBranches = cm find branches where "date >= '2013/06/01'" --format="{name} {changeset}" --nototal; for($i = 0; $i -le $allBranches.length -1; $i++) {$allBranches[$i] = 'br:' + $allBranches[$i]} $allBranches| ?{$allMerged -notcontains $_ -and $semiMerged -contains $_.Split(" ")[0]}

Here is a sample output:

br:/main/Fix-4.1/scm12861 56049 br:/main/Fix-4.1/SCM12817 56300 br:/main/Fix-4.1/scm12899 56270

This code performs the following actions:

  1. Get all the merges, and the source changeset done after a specific date.
  2. Filter those merges that have the same origin and destination.
  3. Get a list only with the merges, for discarding those already merged.
  4. Changes the format of the find branches output, so it matches the find merge format.
  5. Compare, and filter those branches that have been merged on that interval, but have pending changesets to merge.

If you are using bash, here's an alternative:

$ cm find merge where "date >= '2013/06/01'" --format="{srcbranch}#{dstbranch}#{srcchangeset}" --nototal |awk -F "#" '{if($1 != $2) print $1 "#" $3}' | tee allMerges | cut -d'#' -f1 | sort -u > mergedBranches $ for branch in 'cm find branches where "date >= '2013/06/01'" --format="br:{name}#{changeset}" --nototal;'; do [ ! "'grep $branch allMerges'" ] && [ "'echo $branch | grep -f mergedBranches'" ] && echo $branch; done $ rm allMerges mergedBranches

What we are doing is:

  1. Write all merges on a file, indicating source changeset, performed after a specific date; at the same time, write all source merge branches on a different file.
  2. Iterating on all existing branches by branch name and changeset, print only those that don't appear on the first file (merge source branch and changeset) but do appear on the second one (meaning that there are pending changesets to merge).
  3. Finally, delete the temporary files.

Branches integrated on this release

Can I know which branches have been (directly or indirectly) integrated on this release?

We are looking for this scenario:

Scenario

We want to know which branches have been integrated into version 1.0, directly or indirectly. As before, we only need one single query to the server, and some more powershell to filter the data. In this specific sample we want to get all the branches that have been integrated in /main.

function ListAll($list, $visited, $targetBranch, $depth) { $visited += $targetBranch; $list | ForEach-Object { $res = $_.Split(" "); if(($res[1] -eq $targetBranch) -and ($visited -notcontains $res[0])) { Write-Host $depth $res[0]; $visited += $res[0]; $temp_visited = ListAll $list $visited $res[0] ($depth + "-"); $temp_visited | ForEach-Object{ if($visited -notcontains $_) { $visited += $_; } } } } return $visited; } $targetBranch = "br:/main"; $allMergedNonFiltered = cm find merge where "date >= '2013/01/01'" --format="{srcbranch} {dstbranch}" --nototal; $allMerged = $allMergedNonFiltered | ForEach-Object {$res =$_.Split(" "); if($res[0] -ne $res[1]) {$res[0] + " " + $res[1]} } $visited = @(); $targetBranch ListAll $allMerged $visited $targetBranch "-" | Out-Null;

Here is a sample output, we can see that the branch 12299 is indirectly integrated in the release 4.3.39.406

br:/main br:/main/Release-4.2.29.406 br:/main/SCM12356 br:/main/scm12238 br:/main/Release-4.2.28.387/SCM12169/scm12230 br:/main/SCM12243/scm12280/scm12277/scm12293 br:/main/scm12238/scm12299

A brief explanation of the script:

  1. We get the list and remove the duplicates as before.
  2. We call the ListAll function with the target branch, an empty visited list and a marker that will help us to display the depth. The output of this function is piped to null because we won't use this value in our code, and otherwise it would display.
  3. Inside the ListAll function we try to find a merge which target matches the target window.
  4. If it matches, we add the item to our visited list, and we call ListAll recursively, the time with our merge source.
  5. After the recursive function returns, we update our visited list based on the return value of the function.

An equivalence under bash can be done with the following script:

cm find merge where "date >= '2013/01/01'" --format="{srcbranch}#{dstbranch}" --nototal | awk -F "#" '{if($1 != $2) print $1 "#" $2}' > list touch old_targets touch next_targets echo "br:/main" | tee targets depth=">" while [ -s targets ]; do for merge in 'grep -f targets list'; do src_branch=${merge%#*} was_already_target="'grep ${src_branch} old_targets 2>/dev/null'" already_on_next_targets="'grep ${src_branch} next_targets 2>/dev/null'" if [ ! "$was_already_target" ] && [ ! "$already_on_next_targets" ]; then echo ${src_branch} >> next_targets echo ${depth}${src_branch} fi done depth="-${depth}" cat targets >> old_targets [ -s next_targets ] && mv next_targets targets || rm -f targets done rm -f list old_targets

A brief explanation for this script:

  1. We get the list of merges, removing duplicate entries, and we store it into a file.
  2. We prepare two auxiliary files:
    1. old_targets, which will save every target branch we find
    2. targets, which will contain the target branches whose sources we are looking for
  3. We now proceed to look if the target branches exist on the list file as destinations. If so, we will store the merge source branch for the next round if it has not been affected before. Also, we will print it on screen.
  4. We increase the depth level and we switch the target list: the new list of targets became the current list of targets, and the current list is added to the "already used" list.
  5. Finally, only a clean-up operation remains to leave the environment as it was.

Filtering and Output options

The following table displays the different filtering options that are currently available to be used with cm find merge command:

Filtering options ( where... )
date dstbranch dstchangeset guid id owner
srcbranch srcchangeset type

This other table displays the different output options that are currently available to be used with cm find merge command:

Output options ( --format... )
date dstbranch dstchangeset id owner srcbranch
srcchangeset type

Chapter 9: Code reviews

Can I get the reviews that have been assigned to me and that are not closed?

The integrated code review feature allows us to get information about the reviews status. In this sample we start getting my reviews (that is, the ones assigned literally to 'me' where 'me' is the current user). We can also put a user's name as we did before.

cm find reviews where assignee = 'me' 399982 08/03/2013 10:43:30 danipen Status1 pablo "scm12563" Branch id:399570 419067 20/05/2013 9:59:49 asalim Status0 pablo "scm12411" Branch id:416824 8424078 29/05/2013 14:50:35 borja Status1 pablo "Review scm12816" Branch id:424073 425830 05/06/2013 17:04:37 jesusmg Status0 pablo "Review scm11179" Branch id:413120 426717 14/06/2013 14:01:14 roberto Status1 pablo "Code review 1" Branch id:426648 Total: 5

Afterwards, we can scope the result to those reviews that have a specific status (1 = approved):

cm find reviews where assignee = 'me' and status = 1 399982 08/03/2013 10:43:30 danipen Status1 pablo "scm12563" Branch id:399570 8424078 29/05/2013 14:50:35 borja Status1 pablo "Review scm12816" Branch id:424073 426717 14/06/2013 14:01:14 roberto Status1 pablo "Code review 1" Branch id:426648 Total: 3

Finally we get the reviews done in a specific time frame:

cm find "review where assignee = 'me' and date > '2013/05/01' and date < '2013/06/29'" 419067 20/05/2013 9:59:49 asalim Status0 pablo "scm12411" Branch id:416824 8424078 29/05/2013 14:50:35 borja Status1 pablo "Review scm12816" Branch id:424073 425830 05/06/2013 17:04:37 jesusmg Status0 pablo "Review scm11179" Branch id:413120 426717 14/06/2013 14:01:14 roberto Status1 pablo "Code review 1" Branch id:426648 Total: 4

So we want to compare it with the ones that have this specific span and this specific condition:

cm find "review where assignee = 'me' and date > '2013/06/14' and date < '2013/06/15'" and status = 1 8424078 29/05/2013 14:50:35 borja Status1 pablo "Review scm12816" Branch id:424073 426717 14/06/2013 14:01:14 roberto Status1 pablo "Code review 1" Branch id: 426648 Total: 2
Note: the Total value we see at the end of every command can be omitted with the --nototal option, as you've seen in previous chapters.

With these two queries we could get a ratio of approved/all reviews on this sprint.

In the previous examples we have set the date to a specific value, but we can also use "yesterday" or even "3 months ago". This can be very useful if you want to check timespans related with the current date:

cm find "review where assignee = 'me' and date >= '4 days ago'" and status = 1 8424078 29/05/2013 14:50:35 borja Status1 pablo "Review scm12816" Branch id:424073 Total: 1

Filtering and Output options

The following table displays the different filtering options that are currently available to be used with cm find review command:

Filtering options ( where... )
assignee comment date guid id owner
status targetid

* Conditions date and targetid correspond to Creation date and Reviewed object columns respectively in the Code reviews view.



This other table displays the different output options that are currently available to be used with cm find review command:

Output options ( --format... )
assignee date id owner status target
targettype title

Chapter 10: Output and post-processing options

In this article we have seen how to customize the output, but we can also set the output as XML and save it to a file for later analysis. This way the following command:

cm find revisions where changeset=16716 --xml --file=output.xml

Generates the following XML content:

<?xml version="1.0" encoding="utf-8" ?>
<PLASTICQUERY>
  <REVISION>
    <ID>426098</ID>
    <COMMENT></COMMENT>
    <DATE>07/06/2013 16:00:09</DATE>
    <OWNER>roberto</OWNER>
    <TYPE>dir</TYPE>
    <SIZE>0</SIZE>
    <CHANGESET>16716</CHANGESET>
    <PARENT>426069</PARENT>
    <ITEM>d:\linked_replicated\</ITEM>
    <ITEMID>2</ITEMID>
    <BRANCH>br:/main/Fix-4.1/scm12863</BRANCH>
    <PATH>d:\linked_replicated\</PATH>
    <REPOSITORY>codice</REPOSITORY>
    <REPNAME>codice</REPNAME>
    <REPSERVER>localhost:8087</REPSERVER>
    <HASH>kWJO1fm+7RCiZZcgSjM4/Q==</HASH>
  </REVISION>
  <REVISION>
    <ID>426092</ID>
    <COMMENT></COMMENT>
    <DATE>07/06/2013 16:00:09</DATE>
    <OWNER>roberto</OWNER>
    <TYPE>txt</TYPE>
    <SIZE>78238</SIZE>
    <CHANGESET>16716</CHANGESET>
    <PARENT>426056</PARENT>
    <ITEM>d:\linked_replicated\01nerva\src\client\plastic\ActionMenuManager.cs</ITEM>
    <ITEMID>37736</ITEMID>
    <BRANCH>br:/main/Fix-4.1/scm12863</BRANCH>
    <PATH>d:\linked_replicated\01nerva\src\client\plastic\ActionMenuManager.cs</PATH>
    <REPOSITORY>codice</REPOSITORY>
    <REPNAME>codice</REPNAME>
    <REPSERVER>localhost:8087</REPSERVER>
    <HASH>FXmLNV7B9Et1wTGqULWpgQ==</HASH>
  </REVISION>
</PLASTICQUERY>
  

This content can be later imported into tools like Excel, and get stats from it in a beautiful way.


Chapter 11: Stats

Let's assume we want to get the information of all the changesets in our repository; then we can execute the following command:

cm find changeset --xml --file=output.xml

We can then load the output in Excel; this is the result:

Output

Excel includes a very useful utility called PivotTable that allows us to get more statistics.

PivotTable

Using the filtering and sorting features available in Excel we can get group the changesets user, and convert those stats into graphs:

Graphs

We can also group by branch, and we could get, grouping by branch, how many users have contributed, and how many changesets have been created by each user, on each branch.

Groups


Chapter 12: Syntax rules

The find command has a default output for each object, but we can define our custom output options as seen before, retrieve the result using XML format with the --xml attribute, and save the result in a file with the --file attribute for later analysis.

The general syntax is the following:

cm find object [where conditions] [on repositories] [options]

Where:

  • object can be almost every object in the system, having branch, attribute, changeset, label, merge, review, revision, user and the like.
  • the conditions depend on the object, you can get the conditions (and all the objects we can use) typing the command: cm showfindobjects.
  • on repositories can be used to get information from a repository that may, or may not, match the current workspace. We can go to any folder (inside our workspace, in another workspace or in a folder without workspace) and type: cm find revisions where branch = 'main/scm12800' on repositories 'codice@localhost:8087' --nototal 423620 27/05/2013 13:25:53 dirRoberto d:\linked_replicated\#br:/main/scm12800#16582 423621 27/05/2013 13:25:53 dirRoberto d:\linked_replicated\01nerva#br:/main/scm12800#16582 423622 27/05/2013 13:25:53 dirRoberto d:\linked_replicated\01nerva\src#br:/main/scm12800#16582

    This will work as long as we have authorization to query that repository.

  • options allows us to specify the output options specified before, --format , --xml or --file.

Last updated July 1, 2014