Deltas/Create-DeltaBetweenVersions.ps1

function Create-DeltaBetweenVersions
{
    Param(
        [Parameter(Mandatory=$true)]
        [string]$BranchPath,
        [Parameter(Mandatory=$true)]
        [int]$OldVersion,
        [Parameter(Mandatory=$true)]
        [int]$NewVersion,
        [Parameter(Mandatory=$true)]
        [ValidateSet('Replace','Compare')][string]$BespokeObjects = 'Replace',
        [Parameter(Mandatory=$false)]
        [string]$DeltaPath,
        [Parameter(Mandatory=$false)]
        [switch]$NoContent,
        [Parameter(Mandatory=$false)]
        [switch]$Reverse
    )  

    #download the list of items at both versions
    $url = '_apis/tfvc/items?scopePath={0}&recursionLevel=OneLevel&versionType=Changeset&version={1}' -f $BranchPath, $OldVersion

    $OldItems = Invoke-TFSAPI -Url $url

    $url = '_apis/tfvc/items?scopePath={0}&recursionLevel=OneLevel&versionType=Changeset&version={1}' -f $BranchPath, $NewVersion

    $NewItems = Invoke-TFSAPI -Url $url

    if ($DeltaPath -eq '')
    {
        $DeltaPath = Join-Path ([Environment]::GetFolderPath('Desktop')) ('{0} - {1}' -f $OldVersion, $NewVersion)
    }

    $OldItemsFolder = Join-Path $DeltaPath $OldVersion
    $NewItemsFolder = Join-Path $DeltaPath $NewVersion    
    $DeltasFolder = Join-Path $DeltaPath 'Deltas'
    $ReplacementFolder = Join-Path $DeltaPath 'Replacement Objects'
    $DeletedItemsFolder = Join-Path $DeltaPath 'Deleted Items'

    $ResultObject = New-Object System.Object
    $ResultObject | Add-Member -Type NoteProperty -Name 'DeltasPath' -Value $DeltasFolder 
    $ResultObject | Add-Member -Type NoteProperty -Name 'ReplacementsPath' -Value $ReplacementFolder
    $ResultObject | Add-Member -Type NoteProperty -Name 'DeletedItemsPath' -Value $DeletedItemsFolder

    Create-EmptyDirectory $OldItemsFolder
    Create-EmptyDirectory $NewItemsFolder
    Create-EmptyDirectory $DeltasFolder

    $progressName = "Comparing changesets {0} and {1}" -f $OldVersion, $NewVersion

    Write-Progress $progressName

    [int]$itemCounter = 0

    $DeletedItems = Compare-Object -ReferenceObject $olditems.value -DifferenceObject $newitems.value -Property path | Where-Object -property SideIndicator -EQ "<="
    $OldItems = $OldItems.Value | Sort-Object -Property Version -Descending    
    $NewItems = $NewItems.Value | Where-Object -Property Version -gt $OldItems[0].Version    

    $itemCounter = 0

    foreach ($NewItem in $NewItems)
    {
        $itemCounter += 1
        if ($NewItems.Count)
        {
            Write-Progress $progressName -PercentComplete (($itemCounter / $NewItems.Count) * 100)
        }

        if (!$NewItem.isFolder)
        {
            if ($NoContent)
            {
                if (![IO.Directory]::Exists($ReplacementFolder))
                {
                    [IO.Directory]::CreateDirectory($ReplacementFolder)
                }

                New-Item -ItemType File -Path (Join-Path -Path $ReplacementFolder -ChildPath (Split-Path -Leaf $NewItem.Path)) | Out-Null
            }
            else
            {
                Add-Content -Path (Join-Path -Path $NewItemsFolder -ChildPath (Split-Path -Leaf $NewItem.Path)) -Value (Invoke-TFSAPI -Url $NewItem.url)
            
                if ((IsStandardObject -ObjectName (Split-Path -Leaf $NewItem.Path)) -or ($BespokeObjects -eq 'Compare'))
                {
                    $OldItem = $OldItems | Where-Object -Property Path -EQ -Value $NewItem.Path

                    if ($OldItem.Path -ne $null)
                    {
                        Add-Content -Path (Join-Path -Path $OldItemsFolder -ChildPath (Split-Path -Leaf $OldItem.Path)) -Value (Invoke-TFSAPI -Url $OldItem.url)
                    }
                }
                else
                {
                    if (![IO.Directory]::Exists($ReplacementFolder))
                    {
                        [IO.Directory]::CreateDirectory($ReplacementFolder)
                    }

                    [IO.File]::Move((Join-Path -Path $NewItemsFolder -ChildPath (Split-Path -Leaf $NewItem.Path)),(Join-Path -Path $ReplacementFolder (Split-Path -Leaf $NewItem.Path)))
                }
            }
        }
    }   

     
    foreach ($DeletedItem in $DeletedItems)
    {    
        if (!$NoContent)
        {  
            if (![IO.Directory]::Exists($DeletedItemsFolder))
            {
                [IO.Directory]::CreateDirectory($DeletedItemsFolder)
            }   
                   
            $OldItem = $OldItems | Where-Object -Property Path -EQ -Value $DeletedItem.Path
           
            if ($OldItem.Path -ne $null)
            {
                Add-Content -Path (Join-Path -Path $DeletedItemsFolder -ChildPath (Split-Path -Leaf $OldItem.Path)) -Value (Invoke-TFSAPI -Url $OldItem.url)
            }
      
        }
    }


    if ($Reverse)
    {
        Compare-NAVApplicationObject -OriginalPath $NewItemsFolder -ModifiedPath $OldItemsFolder -DeltaPath $DeltasFolder -Force
    }
    else
    {
        Compare-NAVApplicationObject -OriginalPath $OldItemsFolder -ModifiedPath $NewItemsFolder -DeltaPath $DeltasFolder -Force
    }

    if ([IO.Directory]::Exists($ReplacementFolder))
    {
        Join-NAVApplicationObjectFile -Source $ReplacementFolder -Destination (Join-Path $ReplacementFolder -ChildPath '_Replacement Objects.TXT')        
    }    

    $ResultObject
}

function IsStandardObject
(    
    [Parameter(Mandatory=$true)]
    [string]$ObjectName    
)
{
    [bool]$Result = $false

    #read the numerical part of the file name
    [int]$ObjectNumber = [int32]::Parse($ObjectName.Substring(3,$ObjectName.Length - 7))

    if (($ObjectNumber -lt 50000) -or ($ObjectNumber -gt 90000000))
    {
        $Result = $true
    }

    #special rules for menusuites
    if ($ObjectName.Substring(0,3) -eq "MEN")
    {
        if ($ObjectNumber -le 1050)
        {
            $Result = $true
        }
        else
        {
            $Result = $false
        }
    }

    $Result
}

Export-ModuleMember -Function Create-DeltaBetweenVersions