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 |
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 |
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 |
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 |
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:
- Find all the branches from this sprint.
- Find all the merges from this sprint, and return only the source branches.
- Change the format of the $allbranches output so both lists have the same format.
- 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:
- Finds every branch belonging to this sprint.
- Finds every merge belonging to this sprint, returning only their source branches.
- Print all branches from this sprint that weren't on the merged branches list.
Branches not fully integrated
We are looking for this 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:
- Get all the merges and the source changeset done after a specific date.
- Filter those merges that have the same origin and destination.
- Get a list only with the merges for discarding those already merged.
- Changes the format of the find branches output so it matches the find merge format.
- 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:
- 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.
- 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).
- Finally, delete the temporary files.
Branches integrated on this release
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:
- You get the list and remove the duplicates as before.
- 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.
- Inside the ListAll function, you try to find a merge which target matches the target window.
- If it matches, you add the item to the visited list, and you call ListAll recursively, the time with our merge source.
- 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:
- You get the list of merges, remove duplicate entries, and store it into a file.
- You prepare two auxiliary files:
- old_targets, which will save every target branch you find
- targets, which will contain the target branches whose sources you are looking for
- 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.
- 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.
- 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 |
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:
Excel includes a very useful utility called PivotTable that allows us to get more statistics.
Using the filtering and sorting features available in Excel, you can get the group the changesets user and convert those stats into 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.
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:
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.