arcade-services
arcade-services copied to clipboard
darc vmr diff should not clone the comparison repo
darc vmr diff does not need to clone the repos to work. It can use a combination of the local git-tree object hashes as well as the REST APIs to quickly generate a diff. There are REST API equivalents of the local tree hash.
Here is a local version:
param (
[Parameter(Mandatory=$true)]
[string]$Dir1,
[string]$Dir1Ref = "HEAD",
[Parameter(Mandatory=$true)]
[string]$Dir2,
[string]$Dir2Ref = "HEAD",
[Parameter(Mandatory=$true)]
[string]$GlobPattern
)
function Get-GitTreeEntries {
param (
[string]$RepoPath,
[string]$TreePath,
[string]$Ref
)
Push-Location $(Join-Path $RepoPath $TreePath)
Write-Verbose "Listing tree at $RepoPath -> $Ref"
$entries = git ls-tree "$Ref" 2>$null | ForEach-Object {
if ($_ -match '(\d+)\s+(blob|tree)\s+([a-f0-9]+)\s+(.*)') {
[PSCustomObject]@{
Mode = $matches[1]
Type = $matches[2]
Hash = $matches[3]
Path = if ($TreePath) { "$TreePath/$($matches[4])" } else { $matches[4] }
}
}
}
Pop-Location
return $entries
}
function Compare-GitTrees {
param (
[string]$Repo1,
[string]$Repo2,
[string]$Ref1,
[string]$Ref2,
[string]$TreePath
)
Write-Verbose "Comparing tree: $TreePath"
$entries1 = Get-GitTreeEntries -RepoPath $Repo1 -TreePath $TreePath -Ref $Ref1
$entries2 = Get-GitTreeEntries -RepoPath $Repo2 -TreePath $TreePath -Ref $Ref2
$map1 = @{}
$entries1 | ForEach-Object { $map1[$_.Path] = $_ }
$map2 = @{}
$entries2 | ForEach-Object { $map2[$_.Path] = $_ }
$allPaths = ($map1.Keys + $map2.Keys) | Sort-Object -Unique
foreach ($path in $allPaths) {
if ($path -notlike $GlobPattern) {
Write-Verbose "Skipped $path"
}
$e1 = $map1[$path]
$e2 = $map2[$path]
if ($e1 -and $e2) {
if ($e1.Type -eq 'tree' -and $e2.Type -eq 'tree') {
if ($e1.Hash -ne $e2.Hash) {
Write-Verbose "Tree differs: $path (hash1=$($e1.Hash), hash2=$($e2.Hash))"
Compare-GitTrees -Repo1 $Repo1 -Ref1 $Ref1 -Repo2 $Repo2 -Ref2 $Ref2 -TreePath $path
} else {
Write-Verbose "Tree matches: $path (hash=$($e1.Hash))"
}
} elseif ($e1.Type -eq 'blob' -and $e2.Type -eq 'blob') {
if ($e1.Hash -ne $e2.Hash) {
$file1 = Join-Path $Repo1 $path
$file2 = Join-Path $Repo2 $path
Write-Host "`nDiff for: $path"
Write-Verbose "Blob differs: $path"
git diff --no-index --ignore-cr-at-eol $file1 $file2
} else {
Write-Verbose "Blob matches: $path (hash=$($e1.Hash))"
}
}
} elseif ($e1 -and $e1.Type -eq 'blob' -and $path -like $GlobPattern) {
Write-Host "`nOnly in ${Repo1}: $path"
Write-Verbose "Blob only in Repo1: $path"
} elseif ($e2 -and $e2.Type -eq 'blob' -and $path -like $GlobPattern) {
Write-Host "`nOnly in ${Repo2}: $path"
Write-Verbose "Blob only in Repo2: $path"
}
}
Write-Verbose "Finished comparing tree: $TreePath"
}
Compare-GitTrees -Repo1 $Dir1 -Ref1 $Dir1Ref -Repo2 $Dir2 -Ref2 $Dir2Ref -TreePath ""