forked from MethodsAndPractices/vsteam
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix Get-VSTeamWiql MethodsAndPractices#314
- Loading branch information
James O'Neill
authored and
James O'Neill
committed
May 14, 2020
1 parent
fd9f922
commit 9feee71
Showing
6 changed files
with
139 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
using namespace System.Collections | ||
using namespace System.Collections.Generic | ||
using namespace System.Management.Automation | ||
|
||
class QueryCompleter : IArgumentCompleter { | ||
[IEnumerable[CompletionResult]] CompleteArgument( | ||
[string] $CommandName, | ||
[string] $ParameterName, | ||
[string] $WordToComplete, | ||
[Language.CommandAst] $CommandAst, | ||
[IDictionary] $FakeBoundParameters) { | ||
|
||
$results = [List[CompletionResult]]::new() | ||
|
||
|
||
# If the user has explictly added the -ProjectName parameter | ||
# to the command use that instead of the default project. | ||
$projectName = $FakeBoundParameters['ProjectName'] | ||
|
||
# Only use the default project if the ProjectName parameter was | ||
# not used | ||
if (-not $projectName) { | ||
$projectName = _getDefaultProject | ||
} | ||
|
||
# If there is no projectName by this point just return a empty | ||
# list. | ||
if ($projectName) { | ||
|
||
foreach ( $q in [vsteamquerycache]::GetCurrent() ) { | ||
if ($q.name -like "*$WordToComplete*" -and $q.name -notmatch '\w') { | ||
$results.Add([CompletionResult]::new($q.name)) | ||
} | ||
elseif ($q.name -like "*$WordToComplete*") { | ||
$results.Add([CompletionResult]::new("'$($q.name.replace("'","''"))'", $q.name, 0, $q.name)) | ||
} | ||
} | ||
} | ||
return $results | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using namespace System.Management.Automation | ||
|
||
class QueryTransformToIDAttribute : ArgumentTransformationAttribute { | ||
[object] Transform( | ||
[EngineIntrinsics]$EngineIntrinsics, | ||
[object] $InputData | ||
) { | ||
#If input data is not a GUID, and it is found as a name in the cache, | ||
#then replace it with the match ID from the cache | ||
if ($InputData -notmatch "[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}" -and | ||
[VSTeamQueryCache]::queries.where({$_.name -eq $InputData}).count) { | ||
$InputData = [VSTeamQueryCache]::queries.where({$_.name -eq $InputData}).id | ||
} | ||
return ($InputData) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
class VSTeamQueryCache { | ||
static [int] $timestamp = -1 | ||
static [object] $queries = $null | ||
static [Void] Update () { | ||
$projectName = (_getDefaultProject) | ||
if ($projectName) { | ||
[VSTeamQueryCache]::queries = (_callAPi -ProjectName $projectName -Area wit -Resource queries -version (_getApiVersion core ) -QueryString @{'$depth'=1} | ||
).value.children | Where-Object -property isfolder -ne "True" | Select-Object Name,ID | Sort-Object Name | ||
[VSTeamQueryCache]::timestamp = (Get-Date).TimeOfDay.TotalMinutes | ||
} | ||
} | ||
static [void] Invalidate () { | ||
[VSTeamQueryCache]::timestamp = -1 | ||
} | ||
static [object] GetCurrent () { | ||
if ([VSTeamQueryCache]::timestamp -lt 0 -or | ||
[VSTeamQueryCache]::timestamp -lt [datetime]::Now.TimeOfDay.TotalMinutes -5) { | ||
[VSTeamQueryCache]::Update() | ||
} | ||
return ([VSTeamQueryCache]::queries) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,80 +1,73 @@ | ||
function Get-VSTeamWiql { | ||
[CmdletBinding(DefaultParameterSetName = 'ByID')] | ||
param( | ||
[QueryTransformToID()] | ||
[ArgumentCompleter([QueryCompleter])] | ||
[Parameter(ParameterSetName = 'ByID', Mandatory = $true, Position = 0)] | ||
[string] $Id, | ||
|
||
[Parameter(ParameterSetName = 'ByQuery', Mandatory = $true, Position = 0)] | ||
[Parameter(ParameterSetName = 'ByQuery', Mandatory = $true)] | ||
[string] $Query, | ||
|
||
[Parameter(Mandatory = $true, Position = 1)] | ||
[string] $Team, | ||
|
||
[int] $Top = 100, | ||
[Parameter(Position = 2)] | ||
[ProjectValidateAttribute()] | ||
[ArgumentCompleter([ProjectCompleter])] | ||
$ProjectName, | ||
|
||
[int] $Top = 100, | ||
[Switch] $TimePrecision, | ||
|
||
[Switch] $Expand | ||
) | ||
DynamicParam { | ||
#$arrSet = Get-VSTeamProject | Select-Object -ExpandProperty Name | ||
_buildProjectNameDynamicParam -mandatory $true #-arrSet $arrSet | ||
} | ||
|
||
Process { | ||
|
||
# Bind the parameter to a friendly variable | ||
$ProjectName = $PSBoundParameters["ProjectName"] | ||
|
||
$QueryString = @{ | ||
'$top' = $Top | ||
timePrecision = $TimePrecision | ||
process { | ||
#build paramters for _callAPI | ||
$params = @{ | ||
ProjectName = $ProjectName | ||
Area = 'wit' | ||
Resource = 'wiql' | ||
Version = [VSTeamVersions]::Core | ||
QueryString = @{ | ||
'$top' = $Top | ||
timePrecision = $TimePrecision | ||
} | ||
} | ||
|
||
# Call the REST API | ||
if ($Query) { | ||
|
||
$body = (@{ | ||
query = $Query | ||
}) | ConvertTo-Json | ||
|
||
$resp = _callAPI -ProjectName $ProjectName -Team $Team -Area 'wit' -Resource 'wiql' ` | ||
-method "POST" -ContentType "application/json" ` | ||
-Version $(_getApiVersion Core) ` | ||
-Querystring $QueryString ` | ||
-Body $body | ||
$params['body'] = @{query = $Query} | ConvertTo-Json | ||
$params['method'] = 'POST' | ||
$params['ContentType'] = 'application/json' | ||
} | ||
else { | ||
$resp = _callAPI -ProjectName $ProjectName -Team $Team -Area 'wit' -Resource 'wiql' ` | ||
-Version $(_getApiVersion Core) -id "$Id" ` | ||
-Querystring $QueryString | ||
$params['id']= $Id | ||
$params['Team']= $Team | ||
} | ||
$resp = _callAPI @params | ||
|
||
if ($Expand) { | ||
#Handle queries for work item links | ||
if ($resp.queryResultType -eq 'workItemLink') { | ||
Add-Member -InputObject $resp -MemberType NoteProperty -Name Workitems -Value @() | ||
$Ids = $resp.workItemRelations.Target.id | ||
} | ||
else { $Ids = $resp.workItems.id } | ||
|
||
[array]$Ids = $resp.workItems.id | ||
$Fields = $resp.columns.referenceName | ||
|
||
$resp.workItems = @() | ||
#splitting id array by 200, since a maximum of 200 ids are allowed per call | ||
$countIds = $Ids.Count | ||
$resp.workItems = for ($beginRange = 0; $beginRange -lt $countIds; $beginRange += 200) { | ||
|
||
$endRange = ($beginRange + 199) | ||
|
||
if ($endRange -gt $countIds) { | ||
$idArray = $Ids[$beginRange..($countIds - 1)] | ||
#in case strict mode is on,pick lesser of 0..199 and 0..count-1 | ||
$endRange = [math]::Min(($beginRange + 199),($countIds - 1)) | ||
#if query contains "*" don't specify fields, otherwise use fields returned. | ||
if ($Query -match "\*") { | ||
Get-VSTeamWorkItem -Id $Ids[$beginRange..$endRange] | ||
} | ||
else { | ||
$idArray = $Ids[$beginRange..($endRange)] | ||
Get-VSTeamWorkItem -Id $Ids[$beginRange..$endRange] -Fields $resp.columns.referenceName | ||
} | ||
|
||
(Get-VSTeamWorkItem -Fields $Fields -Id $idArray).value | ||
} | ||
} | ||
|
||
_applyTypesToWiql -item $resp | ||
|
||
return $resp | ||
} | ||
} | ||
} |