eng/common/scripts/TypeSpec-Project-Sync.ps1 (129 lines of code) (raw):
# For details see https://github.com/Azure/azure-sdk-tools/blob/main/doc/common/TypeSpec-Project-Scripts.md
[CmdletBinding()]
param (
[Parameter(Position = 0)]
[ValidateNotNullOrEmpty()]
[string] $ProjectDirectory,
[Parameter(Position = 1)]
[string] $LocalSpecRepoPath
)
$ErrorActionPreference = "Stop"
. $PSScriptRoot/Helpers/PSModule-Helpers.ps1
Install-ModuleIfNotInstalled "powershell-yaml" "0.4.7" | Import-Module
$sparseCheckoutFile = ".git/info/sparse-checkout"
function AddSparseCheckoutPath([string]$subDirectory) {
if (!(Test-Path $sparseCheckoutFile) -or !((Get-Content $sparseCheckoutFile).Contains($subDirectory))) {
Write-Output $subDirectory >> .git/info/sparse-checkout
}
}
function CopySpecToProjectIfNeeded([string]$specCloneRoot, [string]$mainSpecDir, [string]$dest, [string[]]$specAdditionalSubDirectories) {
$source = Join-Path $specCloneRoot $mainSpecDir
Copy-Item -Path $source -Destination $dest -Recurse -Force
Write-Host "Copying spec from $source to $dest"
foreach ($additionalDir in $specAdditionalSubDirectories) {
$source = Join-Path $specCloneRoot $additionalDir
Write-Host "Copying spec from $source to $dest"
Copy-Item -Path $source -Destination $dest -Recurse -Force
}
}
function UpdateSparseCheckoutFile([string]$mainSpecDir, [string[]]$specAdditionalSubDirectories) {
AddSparseCheckoutPath $mainSpecDir
foreach ($subDir in $specAdditionalSubDirectories) {
Write-Host "Adding $subDir to sparse checkout"
AddSparseCheckoutPath $subDir
}
}
function GetGitRemoteValue([string]$repo) {
Push-Location $ProjectDirectory
$result = ""
try {
$gitRemotes = (git remote -v)
foreach ($remote in $gitRemotes) {
Write-Host "Checking remote $remote"
if ($remote.StartsWith("origin") -or $remote.StartsWith("main")) {
if ($remote -match 'https://(.*)?github.com/\S+') {
$result = "https://github.com/$repo.git"
break
}
elseif ($remote -match "(.*)?git@github.com:\S+") {
$result = "git@github.com:$repo.git"
break
}
else {
throw "Unknown git remote format found: $remote"
}
}
}
}
finally {
Pop-Location
}
Write-Host "Found git remote $result"
return $result
}
function InitializeSparseGitClone([string]$repo) {
git clone --no-checkout --filter=tree:0 $repo .
if ($LASTEXITCODE) { exit $LASTEXITCODE }
git sparse-checkout init
if ($LASTEXITCODE) { exit $LASTEXITCODE }
Remove-Item $sparseCheckoutFile -Force
}
function GetSpecCloneDir([string]$projectName) {
Push-Location $ProjectDirectory
try {
$root = git rev-parse --show-toplevel
}
finally {
Pop-Location
}
$sparseSpecCloneDir = "$root/../sparse-spec/$projectName"
New-Item $sparseSpecCloneDir -Type Directory -Force | Out-Null
$createResult = Resolve-Path $sparseSpecCloneDir
return $createResult
}
$typespecConfigurationFile = Resolve-Path "$ProjectDirectory/tsp-location.yaml"
Write-Host "Reading configuration from $typespecConfigurationFile"
$configuration = Get-Content -Path $typespecConfigurationFile -Raw | ConvertFrom-Yaml
$pieces = $typespecConfigurationFile.Path.Replace("\", "/").Split("/")
$projectName = $pieces[$pieces.Count - 2]
$specSubDirectory = $configuration["directory"]
# use local spec repo if provided
if ($LocalSpecRepoPath) {
$specCloneDir = $LocalSpecRepoPath
}
elseif ($configuration["repo"] -and $configuration["commit"]) {
# use sparse clone if repo and commit are provided
$specCloneDir = GetSpecCloneDir $projectName
$gitRemoteValue = GetGitRemoteValue $configuration["repo"]
Write-Host "from tsplocation.yaml 'repo' is:"$configuration["repo"]
Write-Host "Setting up sparse clone for $projectName at $specCloneDir"
Push-Location $specCloneDir.Path
try {
if (!(Test-Path ".git")) {
Write-Host "Initializing sparse clone for repo: $gitRemoteValue"
InitializeSparseGitClone $gitRemoteValue
}
Write-Host "Updating sparse checkout file with directory:$specSubDirectory"
UpdateSparseCheckoutFile $specSubDirectory $configuration["additionalDirectories"]
$commit = $configuration["commit"]
Write-Host "git checkout commit: $commit"
git checkout $configuration["commit"]
if ($LASTEXITCODE) { exit $LASTEXITCODE }
}
finally {
Pop-Location
}
}
else {
# write error if neither local spec repo nor repo and commit are provided
Write-Error "Must contain both 'repo' and 'commit' in tsp-location.yaml or input 'localSpecRepoPath' parameter."
exit 1
}
$tempTypeSpecDir = "$ProjectDirectory/TempTypeSpecFiles"
New-Item $tempTypeSpecDir -Type Directory -Force | Out-Null
CopySpecToProjectIfNeeded `
-specCloneRoot $specCloneDir `
-mainSpecDir $specSubDirectory `
-dest $tempTypeSpecDir `
-specAdditionalSubDirectories $configuration["additionalDirectories"]
exit 0