3
votes

Why is the TFS Rest API for fetching the TFVC changesets returning only 256 items. I tried using the $Top to get more than 256 results. But no use.

The API for getting Git repository commits is working fine.

I am referring to https://www.visualstudio.com/en-us/docs/integrate/api/tfvc/changesets

Sample request https://tfs.domain.com/tfs/defaultcollection/projectname/_apis/tfvc/changesets?$searchCriteria.fromDate=2016-07-12T17:49:01&$skip=0&$top=500

I tried without $skip and $searchcriteria.fromdate also. Please help me understand how to get all the results.

2

2 Answers

4
votes

I managed to resolve this strange logic (thank you MSFT guys you rock :/). In my case I want to get all changesets.

1) you need to get first 256 changesets (I used orderby in case of different order in responses):

<projectName>/_apis/tfvc/changesets?$top=256&orderby=id desc&searchCriteria.itemPath=<your_path>&api-version=1.0

2) if you have more then 0 items in response get last value of changesetNumber from response. If 0 - you got all changesets.

3) get next 256 items starting from changesetNumber:

  <projectName>/_apis/tfvc/changesets?searchCriteria.toId=<changesetNumber>&$top=256&orderby=id desc&searchCriteria.itemPath=<your_path>&api-version=1.0

You need to skip first changeset (you already have this value) in response.

4) go to Step 2

So you need to replace changesetId with createdDate and searchCriteria.toId with searchCriteria.fromDate. I hope my solution will help you.

P.S. I was unable to find any feedback on connect website.

0
votes

Based on @Vitaly comments above, I've implemented the solution in posh here. ALso extracted the script below:

function Get-MaxChangeset($Project, $LastChngset)
{
    $projectUri = "$rootTfsUri/$($Project.name)/_apis/tfvc/changesets?api-version=3.1&`$top=256&orderby=id desc"
    $lastchangeset = $LastChngset
    if($lastchangeset -ne $null){
        $projectUri += "&searchCriteria.toId=$($lastchangeset.changesetId)"
    }

    $nestedsubresponse = Invoke-WebRequest -Uri $projectUri -UseDefaultCredentials -Method Get -Verbose -UseBasicParsing
    $nestedsubresponseObject = $nestedsubresponse.Content | ConvertFrom-Json
    if($nestedsubresponseObject.count -ge 1)
    {
        # exclude false positives.
        $lastchangeset = $nestedsubresponseObject.value | `
                    where-object {
                        ($_.checkedInBy.displayName -notlike "*Project Collection Service Accounts*") } | `
                    Sort-Object changesetId -Descending | Select-Object -First 1

        if( ($lastchangeset -eq $null) -and ($nestedsubresponseObject.count -ge 256) )
        {
            # More records to search. Pick the bottom from current list and send it back for next batch api call.
            $lastchangeset = $nestedsubresponseObject.value | Sort-Object changesetId | Select-Object -First 1
            $lastchangeset = Get-MaxChangeset $Project $lastchangeset
        }
    }

    return $lastchangeset
}

$rootTfsUri = "http://tfs:8080/tfs/DefaultCollection"
$allProjectsUri = "$rootTfsUri/_apis/projects?api-version=3.1&`$top=256"
$projectStats = @{}
$response = Invoke-WebRequest -Uri $allProjectsUri -UseDefaultCredentials -Method Get -Verbose -UseBasicParsing
$responseObject = $response.Content | ConvertFrom-Json
if($responseObject.count -ge 1)
{
    foreach($prj in $responseObject.value)
    {
        $lastchangeset = Get-MaxChangeset $prj $null
        if($lastchangeset -ne $null)
        {
            $projectStats.Add("$($prj.name)", $lastchangeset.createdDate)
        }
        else
        {
            $projectStats.Add("$($prj.name)", $lastchangeset)
        }
    }

    $projectStats.GetEnumerator() | Export-Csv "CheckInHistory.csv"
}

HTH, Sam