dotnet / dotnet/arcade-services

darc vmr diff should not clone the comparison repo

Open
#5,089 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
C#
Stars
86
Forks
86
Avg merge
1d 8h
Merged PRs (30d)
35

Description

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 ""

```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.