AreaIteration/AreaIteration.psm1

<#
.SYNOPSIS
    Get an specific Area of one Team Project.
 
.PARAMETER Collection
    Specifies either�a�URL�or�the�name�of�the�Team�Project�Collection�to�connect�to,�or�a�previously�initialized�TfsTeamProjectCollection�object.
    For�more�details,�see�the�-Collection�argument�in�the�Get-TfsTeamProjectCollection�cmdlet.
 
.PARAMETER Project
    Specifies either the�name of the Team Project or a previously initialized Microsoft.TeamFoundation.WorkItemTracking.Client.Project object to connect to.�
    For�more�details,�see�the�-Project�argument�in�the�Get-TfsTeamProject�cmdlet.
 
.EXAMPLE
    xxxx.
#>

Function Get-TfsArea
{
    [CmdletBinding()]
    [OutputType([Microsoft.TeamFoundation.Server.NodeInfo])]
    Param
    (
        [Parameter(Position=0)]
        [Alias("Path")]
        [ValidateScript({($_ -is [string]) -or ($_ -is [uri]) -or ($_ -is [Microsoft.TeamFoundation.Server.NodeInfo])})] 
        [SupportsWildcards()]
        [object]
        $Area = '\**',

        [Parameter(ValueFromPipeline=$true)]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

    Process
    {
        return _GetCssNodes -Node $Area -Scope Area -Project $Project -Collection $Collection
    }
}
<#
.SYNOPSIS
    Get an specific Iteration of one Team Project.
 
.PARAMETER Collection
    Specifies either�a�URL�or�the�name�of�the�Team�Project�Collection�to�connect�to,�or�a�previously�initialized�TfsTeamProjectCollection�object.
    For�more�details,�see�the�-Collection�argument�in�the�Get-TfsTeamProjectCollection�cmdlet.
 
.PARAMETER Project
    Specifies either the�name of the Team Project or a previously initialized Microsoft.TeamFoundation.WorkItemTracking.Client.Project object to connect to.�
    For�more�details,�see�the�-Project�argument�in�the�Get-TfsTeamProject�cmdlet.
 
.EXAMPLE
    xxxx.
#>

Function Get-TfsIteration
{
    [CmdletBinding()]
    [OutputType([Microsoft.TeamFoundation.Server.NodeInfo])]
    Param
    (
        [Parameter(Position=0)]
        [Alias("Path")]
        [ValidateScript({($_ -is [string]) -or ($_ -is [uri]) -or ($_ -is [Microsoft.TeamFoundation.Server.NodeInfo])})] 
        [object]
        $Iteration = '\**',

        [Parameter(ValueFromPipeline=$true)]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

    Process
    {
        return _GetCssNodes -Node $Iteration -Scope Iteration -Project $Project -Collection $Collection
    }
}
<#
#>

Function Move-TfsArea
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
        [Alias("Path")]
        [ValidateScript({($_ -is [string]) -or ($_ -is [uri]) -or ($_ -is [Microsoft.TeamFoundation.Server.NodeInfo])})] 
        [object]
        $Area,

        [Parameter(Position=1l)]
        [ValidateScript({($_ -is [string]) -or ($_ -is [uri]) -or ($_ -is [Microsoft.TeamFoundation.Server.NodeInfo])})] 
        [object]
        $Destination,

        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

    Process
    {
        $node = Get-TfsArea -Area $Area -Project $Project -Collection $Collection

        if (-not $node)
        {
            throw "Invalid or non-existent area $Area"
        }

        $destinationNode = Get-TfsArea -Area $Destination -Project $Project -Collection $Collection

        if (-not $node)
        {
            throw "Invalid or non-existent destination area $Destination"
        }

        $cssService = _GetCssService -Project $Project -Collection $Collection

        $cssService.MoveBranch($node.Uri, $destinationNode.Uri)

        return $cssService.GetNode($node.Uri)
    }
}
<#
#>

Function Move-TfsIteration
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
        [Alias("Path")]
        [ValidateScript({($_ -is [string]) -or ($_ -is [uri]) -or ($_ -is [Microsoft.TeamFoundation.Server.NodeInfo])})] 
        [object]
        $Iteration,

        [Parameter(Position=1)]
        [ValidateScript({($_ -is [string]) -or ($_ -is [uri]) -or ($_ -is [Microsoft.TeamFoundation.Server.NodeInfo])})] 
        [object]
        $Destination,

        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

    Process
    {
        $node = Get-TfsIteration -Iteration $Iteration -Project $Project -Collection $Collection

        if (-not $node)
        {
            throw "Invalid or non-existent iteration $Iteration"
        }

        $destinationNode = Get-TfsIteration -Iteration $Destination -Project $Project -Collection $Collection

        if (-not $node)
        {
            throw "Invalid or non-existent destination iteration $Destination"
        }

        $cssService = _GetCssService -Project $Project -Collection $Collection

        $cssService.MoveBranch($node.Uri, $destinationNode.Uri)

        return $cssService.GetNode($node.Uri)
    }
}
<#
.SYNOPSIS
    Create a new Area on Team Project.
 
.PARAMETER Collection
    Specifies either�a�URL�or�the�name�of�the�Team�Project�Collection�to�connect�to,�or�a�previously�initialized�TfsTeamProjectCollection�object.
    For�more�details,�see�the�-Collection�argument�in�the�Get-TfsTeamProjectCollection�cmdlet.
 
.PARAMETER Project
    Specifies either the�name of the Team Project or a previously initialized Microsoft.TeamFoundation.WorkItemTracking.Client.Project object to connect to.�
    For�more�details,�see�the�-Project�argument�in�the�Get-TfsTeamProject�cmdlet.
 
.EXAMPLE
    xxxx.
#>

Function New-TfsArea
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true, Position=0)]
        [Alias("Path")]
        [string]
        $Area,

        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

    Process
    {
        return _NewCssNode -Path $Area -Scope Area -Project $Project -Collection $Collection
    }
}
<#
.SYNOPSIS
    Create a new Iteration on Team Project.
 
.PARAMETER Collection
    Specifies either�a�URL�or�the�name�of�the�Team�Project�Collection�to�connect�to,�or�a�previously�initialized�TfsTeamProjectCollection�object.
    For�more�details,�see�the�-Collection�argument�in�the�Get-TfsTeamProjectCollection�cmdlet.
 
.PARAMETER Project
    Specifies either the�name of the Team Project or a previously initialized Microsoft.TeamFoundation.WorkItemTracking.Client.Project object to connect to.�
    For�more�details,�see�the�-Project�argument�in�the�Get-TfsTeamProject�cmdlet.
 
.EXAMPLE
    xxxx.
#>

Function New-TfsIteration
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true, Position=0)]
        [ValidateScript({($_ -is [string]) -or ($_ -is [Microsoft.TeamFoundation.Server.NodeInfo])})] 
        [Alias("Path")]
        [object]
        $Iteration,

        [Parameter()]
        [DateTime]
        $StartDate,
    
        [Parameter()]
        [DateTime]
        $FinishDate,

        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

    Process
    {
        return _NewCssNode -Path $Iteration -Scope Iteration -Project $Project -Collection $Collection -StartDate $StartDate -FinishDate $FinishDate
    }
}
<#
#>

Function Remove-TfsArea
{
    [CmdletBinding(ConfirmImpact='High', SupportsShouldProcess=$true)]
    Param
    (
        [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
        [Alias("Path")]
        [ValidateScript({($_ -is [string]) -or ($_ -is [Microsoft.TeamFoundation.Server.NodeInfo])})] 
        [object]
        $Area,

        [Parameter(Position=1)]
        [Alias("NewPath")]
        [ValidateScript({ ($_ -is [string]) -or ($_ -is [Microsoft.TeamFoundation.Server.NodeInfo]) })] 
        [object]
        $MoveTo = '\',

        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

    Process
    {
        $Areas = Get-TfsArea -Area $Area -Project $Project -Collection $Collection | Sort -Property Path -Descending

        foreach($i in $Areas)
        {
            if ($PSCmdlet.ShouldProcess($i.RelativePath, "Delete Area"))
            {
                $projectName = $i.Path.Split("\")[1]
                _DeleteCssNode -Node $i -MoveToNode $MoveTo -Scope Area -Project $projectName -Collection $Collection
            }
        }
    }
}
<#
#>

Function Remove-TfsIteration
{
    [CmdletBinding(ConfirmImpact='High', SupportsShouldProcess=$true)]
    Param
    (
        [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
        [Alias("Path")]
        [ValidateScript({($_ -is [string]) -or ($_ -is [Microsoft.TeamFoundation.Server.NodeInfo])})] 
        [object]
        $Iteration,

        [Parameter(Position=1)]
        [Alias("NewPath")]
        [ValidateScript({ ($_ -is [string]) -or ($_ -is [Microsoft.TeamFoundation.Server.NodeInfo]) })] 
        [object]
        $MoveTo = '\',

        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

    Process
    {
        $iterations = Get-TfsIteration -Iteration $Iteration -Project $Project -Collection $Collection | Sort -Property Path -Descending

        foreach($i in $iterations)
        {
            if ($PSCmdlet.ShouldProcess($i.RelativePath, "Delete Iteration"))
            {
                $projectName = $i.Path.Split("\")[1]
                _DeleteCssNode -Node $i -MoveToNode $MoveTo -Scope Iteration -Project $Project -Collection $Collection
            }
        }
    }
}
<#
#>

Function Rename-TfsArea
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
        [ValidateScript({($_ -is [string]) -or ($_ -is [Microsoft.TeamFoundation.Server.NodeInfo])})] 
        [Alias("Path")]
        [object]
        $Area,

        [Parameter(Position=1)]
        [string]
        $NewName,

        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

    Process
    {
        Set-TfsArea -Area $Area -NewName $NewName -Project $Project -Collection $Collection
    }
}
<#
#>

Function Rename-TfsIteration
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
        [ValidateScript({($_ -is [string]) -or ($_ -is [Microsoft.TeamFoundation.Server.NodeInfo])})] 
        [Alias("Path")]
        [object]
        $Iteration,

        [Parameter(Position=1)]
        [string]
        $NewName,

        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

    Process
    {
        Set-TfsIteration -Iteration $Iteration -NewName $NewName -Project $Project -Collection $Collection
    }
}
<#
#>

Function Set-TfsArea
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
        [ValidateScript({($_ -is [string]) -or ($_ -is [Microsoft.TeamFoundation.Server.NodeInfo])})] 
        [Alias("Path")]
        [object]
        $Area,

        [Parameter()]
        [string]
        $NewName,

        [Parameter()]
        [int]
        $MoveBy,

        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

    Process
    {
        $node = Get-TfsArea -Area $Area -Project $Project -Collection $Collection

        if (-not $node)
        {
            throw "Invalid or non-existent area $Area"
        }

        $cssService = _GetCssService -Project $Project -Collection $Collection

        if ($NewName)
        {
            $cssService.RenameNode($node.Uri, $NewName)
        }

        if ($MoveBy)
        {
            $cssService.ReorderNode($node.Uri, $MoveBy)
        }

        return $cssService.GetNode($node.Uri)
    }
}
<#
.SYNOPSIS
    Set Iteration Dates of an specific Iteration of one Team Project.
 
.PARAMETER Collection
    Specifies either�a�URL�or�the�name�of�the�Team�Project�Collection�to�connect�to,�or�a�previously�initialized�TfsTeamProjectCollection�object.
    For�more�details,�see�the�-Collection�argument�in�the�Get-TfsTeamProjectCollection�cmdlet.
 
.PARAMETER Project
    Specifies either the�name of the Team Project or a previously initialized Microsoft.TeamFoundation.WorkItemTracking.Client.Project object to connect to.�
    For�more�details,�see�the�-Project�argument�in�the�Get-TfsTeamProject�cmdlet.
 
.EXAMPLE
    xxxx.
#>

Function Set-TfsIteration
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)]
        [Alias("Path")]
        [ValidateScript({($_ -is [string]) -or ($_ -is [Microsoft.TeamFoundation.Server.NodeInfo])})] 
        [object]
        $Iteration = '\**',

        [Parameter()]
        [string]
        $NewName,

        [Parameter()]
        [int]
        $MoveBy,

        [Parameter()]
        [Nullable[DateTime]]
        $StartDate,
    
        [Parameter()]
        [Nullable[DateTime]]
        $FinishDate,

        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

    Process
    {
        $node = Get-TfsIteration -Iteration $Iteration -Project $Project -Collection $Collection

        if (-not $node)
        {
            throw "Invalid or non-existent iteration $Iteration"
        }

        $cssService = _GetCssService -Project $Project -Collection $Collection
        $cssService4 = _GetCssService -Project $Project -Collection $Collection -Version 4

        if ($NewName)
        {
            $cssService.RenameNode($node.Uri, $NewName)
        }

        if ($MoveBy)
        {
            $cssService.ReorderNode($node.Uri, $MoveBy)
        }

        if ($StartDate -or $FinishDate)
        {
            if (-not $PSBoundParameters.ContainsKey("StartDate"))
            {
                $StartDate = $node.StartDate
            }

            if (-not $PSBoundParameters.ContainsKey("FinishDate"))
            {
                $FinishDate = $node.FinishDate
            }

            [void]$cssService4.SetIterationDates($node.Uri, $StartDate, $FinishDate)
        }

        return $cssService.GetNode($node.Uri)
    }
}
Function _GetCssNodes($Node, $Scope, $Project, $Collection)
{
    Process
    {
        if ($Node -is [Microsoft.TeamFoundation.Server.NodeInfo])
        {
            return $Node
        }

        $tp = Get-TfsTeamProject -Project $Project -Collection $Collection
        $tpc = $tp.Store.TeamProjectCollection
        $projectName = $tp.Name
        $cssService = $tpc.GetService([type]"Microsoft.TeamFoundation.Server.ICommonStructureService")
        
        if ($node -is [uri])
        {
            return $cssService.GetNode($node)
        }

        $rootPath = _NormalizePath "$projectName\$Scope"
        $fullPath = _NormalizePath "$rootPath\$Node"

        $rootNodeUri = $cssService.GetNodeFromPath("$rootPath").Uri
        $rootElement = $cssService.GetNodesXml(@($rootNodeUri), $true)
        
        $nodePaths = $rootElement.SelectNodes('//@Path') | Select -ExpandProperty '#text'
        $matchingPaths = $nodePaths | ? { $_ -like $fullPath }

        return $matchingPaths | % { $cssService.GetNodeFromPath($_) }
    }
}

Function _DeleteCssNode($Node, $Scope, $MoveToNode, $Project, $Collection)
{
    Process
    {
        $newNode = _GetCssNodes -Node $MoveToNode -Scope $Scope -Project $Project -Collection $Collection
        $cssService = _GetCssService -Project $Project -Collection $Collection

        $cssService.DeleteBranches($Node.Uri, $newNode.Uri)        
    }
}

Function _NewCssNode ($Project, $Path, $Scope, $Collection, $StartDate, $FinishDate)
{
    Process
    {
        $tp = Get-TfsTeamProject -Project $Project -Collection $Collection
        $tpc = $tp.Store.TeamProjectCollection
        $projectName = $tp.Name
        $cssService = $tpc.GetService([type]"Microsoft.TeamFoundation.Server.ICommonStructureService")

        try
        {
            $fullPath = _NormalizePath "$projectName\$Scope\$Path"
            $parentPath = Split-Path $fullPath -Parent
            $nodeName = Split-Path $fullPath -Leaf
            $parentNode = $cssService.GetNodeFromPath($parentPath)
        }
        catch
        {
            $parentNode = _NewCssNode -Project $Project -Path $parentPath -Scope $Scope -Collection $Collection
        }

        if ($StartDate -or $FinishDate)
        {
            $cssService = $tpc.GetService([type]"Microsoft.TeamFoundation.Server.ICommonStructureService4")
            $nodeUri = $cssService.CreateNode($nodeName, $parentNode.Uri, $StartDate, $FinishDate)
        }
        else
        {
            $nodeUri = $cssService.CreateNode($nodeName, $parentNode.Uri)
        }

        return $cssService.GetNode($nodeUri)
    }
}

Function _NormalizePath($Path)
{
    if([string]::IsNullOrWhiteSpace($Path))
    {
        return [string]::Empty
    }

    $newPath = [System.Text.RegularExpressions.Regex]::Replace($Path, '\\{2,}', '\')

    if (-not $newPath.StartsWith("\"))
    {
        $newPath = "\$newPath"
    }

    if ($newPath.EndsWith("\"))
    {
        $newPath = $newPath.Substring(0, $newPath.Length-1)
    }

    return $newPath
}

Function _GetCssService($Project, $Collection, $Version)
{
    $tp = Get-TfsTeamProject -Project $Project -Collection $Collection
    $tpc = $tp.Store.TeamProjectCollection
    $projectName = $tp.Name

    return $tpc.GetService([type]"Microsoft.TeamFoundation.Server.ICommonStructureService$Version")
}