Cm find by example


cm find

In every version control system, we frequently need to get usage information 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, code reviews, and more.

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

This guide covers (with 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 example includes a question, a step-by-step solution, and the expected output to help you understand what kind of information is returned.

This guide will show you examples about using the cm find command with some and not all of the available objects.

You can get the complete list of objects you can find by running the cm showfindobjects command.

Note: You can use both singular and plural to find an object. For example, 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'"

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 can enclose all the query:

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

Branches

We can retrieve the branches created by a user in a specific period, 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.



Learn how to filter by date using constants.



This 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

Changesets


Show changeset's comments

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

This example shows 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

Here are all the changesets, for example, you're looking for the word "solution." Here we can easily see it, but it becomes harder to spot when you have a couple hundred changesets. For filtering by a specific word, use the SQL-syntax LIKE and % for an approximate search because you're not looking for the complete 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

You can also query the changesets by replication date, using the following command (see replication log on 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

"returnparent" field

returnparent allows you to get the parent of a specific changeset or revision. That way, if you want to know what happened before the changeset you can use:

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

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.



Learn how to filter by date using constants.



This 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

Replication log

Given a branch, you can get all the replication operations from any time chronologically.

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 you only want the last date, you can filter 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


Learn how to filter by date using constants.



This 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

Labels


Find labels in a specific branch

You can find all the labels in a specific repository:

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

And you can find all the labels that created in specific branch in a particular repository:

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

Find branch with specific label

You may want to find which branch contains a specific release:

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

In the above example, the label BL237 comes from the main branch.


Find changesets between 2 labels

You can get the label's date, and later ask for the changesets 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' on repository 'codice'" --nototal 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.



Learn how to filter by date using constants.



This 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

Attributes


Get all attributes

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

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

Once you have it, you 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".

You 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

And you will get the same output by running the following query:

cm find attributes "where srcobj='br:/main'" --nototal

Get all objects with specific attributes

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

cm find attributes "where type = 'status' and value='PASSED' and date > 'this month'" 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.



Learn how to filter by date using constants.



This 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

Revisions


Files changed in a changeset

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

You use a custom format, because you 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

You 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

You can also get the revision info for a branch, searching in all its changests. You 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 you can use our favourite shell tool, in our case PoYourshell, 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


Learn how to filter by date using constants.



This 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

Merges


Where the branch has been integrated

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

If you want to know where a branch has been integrated on, 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

And if you 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

You can do this 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 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 that weren't on the merged branches list.

Branches 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 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 you've just done:

  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

Scenario

For example, you want to know which branches have been integrated into version 1.0, directly or indirectly. As before, you only need one single query to the server and some more PowerShell to filter the data. In this specific example, you want to get all the branches that have been integrated into /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, You 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. You get the list and remove the duplicates as before.
  2. You call the ListAll function with the target branch, an empty visited list, and a marker that will help display the depth. The output of this function is piped to null because you won't use this value in the code: Otherwise it would display.
  3. Inside the ListAll function, you try to find a merge which target matches the target window.
  4. If it matches, you add the item to the visited list, and you call ListAll recursively, the time with our merge source.
  5. After the recursive function returns, you update the visited list based on the function's return value.

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. You get the list of merges, remove duplicate entries, and store it into a file.
  2. You prepare two auxiliary files:
    1. old_targets, which will save every target branch you find
    2. targets, which will contain the target branches whose sources you are looking for
  3. You now proceed to look if the target branches exist on the list file as destinations. If so, you will store the merge source branch for the next round if it has not been affected before. Also, you will print it on screen.
  4. You increase the depth level and you 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


Learn how to filter by date using constants.



This 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

Code reviews

The integrated code review feature allows you to get information about the status of a review. In this example, start getting 'my' reviews (the ones assigned literally to 'me' where 'me' is the current user). You can also put a user's name like previous examples.

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, you 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, you find reviews 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 you 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 you see at the end of every command can be omitted with the --nototal option, as you've seen in previous sections.

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

In previous examples, you set the date to a specific value, but you can also use "yesterday" or even "3 months ago". This can be very useful if you want to check timespans related to 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.



Learn how to filter by date using constants.



This 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

Shelves

You can get the shelves that are created by your team members during the last year:

cm find shelve "where owner != 'me' and date >= '1 years ago'" 3848 2 04/10/2018 5:58:22 PM pablo doom3code Shelve - temporary compilation.txt file 3860 3 06/23/2018 11:08:06 PM pablo doom3code Shelve - test with a new configuration Total: 2

Filtering and Output options

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

Filtering options ( where...)
owner date attribute attrvalue comment guid
parent shelveid id


Learn how to filter by date using constants.



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

Output options ( --format...)
id shelveid date owner repository comment

Output and post-processing options

In this guide, you've seen how to customize the output, but you can also set the output as XML and save it to a file for later analysis:

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.


Stats

Suppose you want to get the information of all the changesets in our repository. You can execute the following command:

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

You 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, you can get the group the changesets user and convert those stats into graphs:

Graphs

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

Groups


Syntax rules

The find command has a default output for each object, but you can define your 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]" [sort options] [pagination options] [format options]

Where:

  • object can be almost every object in the system, having branch, attribute, changeset, label, merge, review, revision, and user.
  • The filtering conditions depend on the object. You can get the conditions (and all the objects you can use) by typing the command cm showfindobjects.
  • The on repositories argument can be used to get information from one or more repositories that may, or may not, match the current workspace. You 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 you have the authorization to query that repository.

    You can query together from not only different repositories but also different servers. For example

    cm find "changesets where date >= '2017/11/17' on repositories 'documentation/plasticdocu@localhost:8087','codice@codice@cloud'" --nototal 68621 1451 /main/scm21135 11/20/2017 3:32:31 PM maria documentation/plasticdocu Added documentation about the EOL conversion mechanism. 4821759 132324 /main/SCM21120 11/20/2017 1:41:45 PM pablo codice Added missing config file 4821840 132326 /main/scm21149/scm21150 11/20/2017 1:54:35 PM vsanchezm@codicesoftware.com codice Fix HAL FAILED - Conflicts and user intervention required. Rebase from main. 4821941 132333 /main 11/20/2017 2:38:28 PM hal codice HAL: merged /main/scm21076/scm21084/scm21093 : GTK Gluon: add pending changes view
  • The sort options lets you get the objects ordered by the specified field. Read more about sorting.
  • The pagination options can be used to manage the result size and the starting point where retrieving the objects from. See more about pagination.
  • format options allows you to specify the output options (for example, --format , --xml or --file as you saw previously, among some other options).

Date constants

When filtering by date, you can use date formats that follow your machine localization settings. For example, if your computer displays dates in the 'MM-dd-yyyy' format, you can use dates such as '12-31-2021' in your queries.

You can also use the following constants to simplify your queries:

  • 'today': today's date.
  • yesterday': yesterday's date.
  • this week': current week's Monday date.
  • this month': current month's 1st day date.
  • this year': current year's January 1st date.
  • one day ago': one day before the current date.
  • one week ago': seven days before the current date.
  • one month ago': one month before the current date.
  • n days ago': 'n' days before the current date.
  • n months ago': 'n' months before the current date.
  • n years ago': 'n' years before the current date.

The following where clauses are valid for fields of type date:

  • (...) where date > 'today' (...)
  • (...) where date < 'yesterday' (...)
  • (...) where date > 'this week' (...)
  • (...) where date > 'this month' (...)
  • (...) where date < 'one day ago' and date > '3 days ago' (...)
  • (...) where date < 'one week ago' and date > '3 weeks ago' (...)
  • (...) where date < 'one month ago' and date > '3 months ago' (...)
  • (...) where date > '1 year ago' (...)

Pagination

Every find object complies with pagination, defining a limit and an offset to manage the result size and starting point.

For example:

  • Display 10 labels starting from the 21st where I am the owner: cm find label "where owner='me'" limit 10 offset 20
  • Display the first 10 branches created by me:
  • cm find branches "where owner='me'" limit 10
Note: When using pagination, you can get a different number of results than the one you specified in the limit value. This is because there may be some objects that have been filtered by the Plastic SCM Security system. This means that you don't have permission to see some of those objects.

For example. Let's suppose that the following command returns a total of 60 branches: cm find branch "where owner='me'"

You want to get the results in blocks of 20 branches. So you'll have to run the cm find command with the pagination options three times to get three blocks of 20 branches. First, you run: cm find branch "where owner='me'" limit 20 offset 0

If you don't have permission to see some rows in the first block, then you'll get a minor number of 20 branches. So, you'll have to run the cm find command with the pagination options more than three times to get the total of 60 branches.

Sorting

You can sort some objects by different fields. This way, the order by clause can be used with the following objects and some of its fields:

Sort object By these fields
branch date, branchname
changeset date, changesetId
label date, labelname
review date, modifiedate, status

For example:

  • Find my changesets and order the results by date in descendant order: cm find changesets "where owner='me'" order by date desc 4336 203 /main 10/8/2021 3:48:10 PM mbarriosc@codicesoftware.com battlegame reverted 4332 202 /main 10/8/2021 3:16:29 PM mbarriosc@codicesoftware.com battlegame Lighter shadow 4328 201 /main 10/8/2021 3:08:22 PM mbarriosc@codicesoftware.com battlegame Reverted
  • Find all branches between two dates, sorting by the branch name in descendant order: cm find branch "where date > '2022/01/01' and date < '2022/01/05'" order by branchname desc 28781097 1/3/2022 7:36:49 PM /main/SCM31425 borja.ruiz@unity3d.com codice T 28780726 1/3/2022 12:03:54 PM /main/scm31423 miguel.gonzalez@unity3d.com codice T 28781122 1/4/2022 4:01:09 PM /main/scm31415 jesusmg codice T 28780724 1/3/2022 10:29:24 AM /main/scm31371 alvaro.berruezo@unity3d.com codice T 28781091 1/3/2022 5:30:43 PM /main/scm30759 alvaro.berruezo@unity3d.com codice T

Last updated

March 14, 2022
  • Added a note to highlight this guide is about cm find examples with some and not all of the available objects.
  • March 14, 2022
  • The cm find command now supports pagination and sorting.
  • December 10, 2019
  • We fixed some cm find examples by adding missing double-quotes.
  • December 7, 2018
  • We added some new examples.
  • Learn how to find shelves.
  • You can use date constanst when filtering by date.
  • November 20, 2017
  • Learn how to use the on repositories argument to query from one or more repositories.
  • July 1, 2014
  • Publication date.