-
Notifications
You must be signed in to change notification settings - Fork 235
Expand file tree
/
Copy pathsparse-checkout.yml
More file actions
143 lines (124 loc) · 5.82 KB
/
sparse-checkout.yml
File metadata and controls
143 lines (124 loc) · 5.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
parameters:
- name: Paths
type: object
default: []
- name: Repositories
type: object
default:
- Name: $(Build.Repository.Name)
Commitish: $(Build.SourceVersion)
WorkingDirectory: $(System.DefaultWorkingDirectory)
- name: SkipCheckoutNone
type: boolean
default: false
- name: TokenToUseForAuth
type: string
default: ''
steps:
- ${{ if not(parameters.SkipCheckoutNone) }}:
- checkout: none
- ${{ if ne(parameters.TokenToUseForAuth, '') }}:
- pwsh: |
$base64Token = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("nobody:${{ parameters.TokenToUseForAuth }}"))
git config set --global "http.extraheader" "AUTHORIZATION: basic $base64Token"
displayName: Setup git config auth header
- task: PowerShell@2
${{ if eq(length(parameters.Repositories), 1) }}:
displayName: 'Sparse checkout ${{ parameters.Repositories[0].Name }}'
${{ else }}:
displayName: 'Sparse checkout repositories'
inputs:
targetType: inline
# Define this inline, because of the chicken/egg problem with loading a script when nothing
# has been checked out yet.
script: |
# Setting $PSNativeCommandArgumentPassing to 'Legacy' to use PowerShell
# 7.2 behavior for command argument passing. Newer behaviors will result
# in errors from git.exe.
$PSNativeCommandArgumentPassing = 'Legacy'
function Retry()
{
Run 3 @args
}
function Run()
{
$retries, $command, $arguments = $args
if ($retries -isnot [int]) {
$command, $arguments = $args
$retries = 0
}
Write-Host "==>" $command $arguments
$attempt = 0
$sleep = 5
while ($true) {
$attempt++
& $command $arguments
if (!$LASTEXITCODE) { return }
if ($attempt -gt $retries) { exit $LASTEXITCODE }
Write-Warning "Attempt $attempt failed: $_. Trying again in $sleep seconds..."
Start-Sleep -Seconds $sleep
$sleep *= 2
}
}
function SparseCheckout([Array]$paths, [Hashtable]$repository)
{
$dir = $repository.WorkingDirectory
if (!$dir) {
$dir = "./$($repository.Name)"
}
New-Item $dir -ItemType Directory -Force | Out-Null
Push-Location $dir
if (Test-Path .git/info/sparse-checkout) {
$hasInitialized = $true
Write-Host "Repository $($repository.Name) has already been initialized. Skipping this step."
} else {
Write-Host "Repository $($repository.Name) is being initialized."
if ($repository.Commitish -match '^refs/pull/\d+/merge$') {
Retry git clone --no-checkout --filter=tree:0 -c remote.origin.fetch=''+$($repository.Commitish):refs/remotes/origin/$($repository.Commitish)'' https://github.com/$($repository.Name) .
} else {
Retry git clone --no-checkout --filter=tree:0 https://github.com/$($repository.Name) .
}
# Turn off git GC for sparse checkout. Note: The devops checkout task does this by default
Run git config gc.auto 0
Run git sparse-checkout init
# Set non-cone mode otherwise path filters will not work in git >= 2.37.0
# See https://github.blog/2022-06-27-highlights-from-git-2-37/#tidbits
# '/*' '!/*/' -> only checkout files in top level directory
# '/eng' -> checkout required eng/ scripts/configs
# '.config' -> required for files like .config/1espt/PipelineAutobaseliningConfig.yml and .config/guardian/.gdnbaselines used by 1es PT scripts
git sparse-checkout set --no-cone '/*' '!/*/' '/eng' '/.config'
}
# Prevent wildcard expansion in Invoke-Expression (e.g. for checkout path '/*')
$quotedPaths = $paths | ForEach-Object { "'$_'" }
$gitsparsecmd = "git sparse-checkout add $quotedPaths"
Write-Host $gitsparsecmd
Invoke-Expression -Command $gitsparsecmd
Write-Host "Set sparse checkout paths to:"
Get-Content .git/info/sparse-checkout
# sparse-checkout commands after initial checkout will auto-checkout again
if (!$hasInitialized) {
# Remove refs/heads/ prefix from branch names
$commitish = $repository.Commitish -replace '^refs/heads/', ''
# use -- to prevent git from interpreting the commitish as a path
# This will use the default branch if repo.Commitish is empty
Retry git -c advice.detachedHead=false checkout $commitish --
} else {
Write-Host "Skipping checkout as repo has already been initialized"
}
Pop-Location
}
# Paths may be sourced as a yaml object literal OR a dynamically generated variable json string.
# If the latter, convertToJson will wrap the 'string' in quotes, so remove them.
$paths = '${{ convertToJson(parameters.Paths) }}'.Trim('"') | ConvertFrom-Json
# Replace windows backslash paths, as Azure Pipelines default directories are sometimes formatted like 'D:\a\1\s'
$repositories = '${{ convertToJson(parameters.Repositories) }}' -replace '\\', '/' | ConvertFrom-Json -AsHashtable
foreach ($repo in $Repositories) {
SparseCheckout $paths $repo
}
pwsh: true
workingDirectory: $(System.DefaultWorkingDirectory)
- ${{ if ne(parameters.TokenToUseForAuth, '') }}:
- pwsh: |
git config unset --global "http.extraheader"
displayName: Removing git config auth header
condition: always()