forked from Azure/azure-sdk-for-java
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Set-ComponentRegistrations.ps1
266 lines (213 loc) · 8.35 KB
/
Set-ComponentRegistrations.ps1
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
#!/usr/bin/env pwsh
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
#Requires -Version 6.0
#Requires -PSEdition Core
<#
.Synopsis
Updates or adds a cgmanifest.json for all pom.xmls in a directory based on its maven dependency tree.
.Parameter Directory
Name of the service being built. For example, "C:\git\azure-sdk-for-java\sdk\eventhubs".
.Parameter ExcludeRegex
A regular expression of directory names to skip generating cgmanifest.json for.
.Parameter Overwrite
Indicates whether or not to overwrite an existing "cgmanifest.json". If the cgmanifest.json exists, then the program
stops.
.Parameter KeepTemporaryFile
Indicates whether or not to keep the temporary file containing the maven dependency tree. By default, it is deleted.
.Example
pwsh Set-ComponentRegistrations.ps1 D:\git\azure-sdk-for-java\sdk\eventhubs\ -ExcludeRegex "mgmt-*"
Excludes any pom.xml in folders that match "mgmt-*"
.Example
pwsh Set-ComponentRegistrations.ps1 D:\git\azure-sdk-for-java\sdk\eventhubs\ -ExcludeRegex "mgmt-*" -KeepTemporaryFile
Excludes pom.xmls in folders that match "mgmt-*" and will keep the temporary maven dependency file.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 0)]
[ValidateScript({ Test-Path $_ })]
[string]$Directory,
[string]$ExcludeRegex,
[switch]$KeepTemporaryFile
)
# By default stop for any error.
$ErrorActionPreference = "Stop"
$IsVerbose = $false
if ($PSBoundParameters.ContainsKey("Verbose")) {
$IsVerbose = $PsBoundParameters.Get_Item("Verbose")
}
class MavenReference {
[string]$GroupId
[string]$ArtifactId
[string]$Version
MavenReference([string]$groupId, [string]$artifactId, [string]$version) {
$this.GroupId = $groupId
$this.ArtifactId = $artifactId
$this.Version = $version
}
[string]ToString() {
return ("{0}:{1}:{2}" -f $this.GroupId, $this.ArtifactId, $this.Version)
}
}
class MavenComponent {
[string]$Type
[MavenReference]$Maven
MavenComponent([MavenReference]$maven) {
$this.Type = "Maven"
$this.Maven = $maven
}
}
function Get-Dependencies($mavenExecutable, $pomFile) {
$transitiveDependencies = @{}
$temp = New-TemporaryFile
Write-Host "Writing dependencies to file: $($pomFile.FullName) -> $($temp.FullName)"
Write-Host "Command: $mavenExecutable -DoutputFile=$($temp.FullName) -q -DoutputType=dot -f $($pomFile.FullName) dependency:tree"
Invoke-Expression "$mavenExecutable -DoutputFile=$($temp.FullName) -q -DoutputType=dot -f $($pomFile.FullName) dependency:tree"
$contents = Get-Content $temp
if ($contents.Length -eq 0) {
Write-Warning "Maven did not successfully generate dependency tree."
$temp.Delete()
return $null
}
Write-Host "--- START: DEPENDENCY TREE ---"
Write-Verbose "$contents"
Write-Host "--- END: DEPENDENCY TREE ---"
if (!$KeepTemporaryFile) {
Write-Host "Removing temp file: '$($temp.FullName)'"
$temp.Delete()
}
foreach ($line in $contents) {
$split = $line -replace '"','' -replace ';','' -split "->"
if ($split.Length -eq 1) {
Write-Verbose "'$line' does not contain ->."
continue
}
$referencedBy = $split[0].Trim()
$dependency = $split[1].Trim()
$referencedByParts = $referencedBy -split ":"
# Transitive dependencies are expressed with a :compile, :test, etc notation.
if ($referencedByParts.Length -eq 4) {
Write-Verbose "'$dependency' is a direct dependency. Skipping."
continue
}
$dependencyParts = $dependency -split ":"
if (!$dependencyParts[2].Equals("jar")) {
Write-Host "'$dependency' is not a jar reference from '$referencedBy'. Skipping."
continue
}
[MavenReference]$reference = [MavenReference]::new($dependencyParts[0], $dependencyParts[1], $dependencyParts[3])
$key = $reference.ToString()
if (!$transitiveDependencies.ContainsKey($key)) {
Write-Host "[$key]: $reference"
$transitiveDependencies.Add($key, $reference) | Out-Null
} else {
Write-Warning "$key already exists. Skipping."
}
}
return $transitiveDependencies
}
function Write-Table($header, $table) {
if (!$IsVerbose) {
return
}
Write-Host "--- START: $header ---"
foreach ($key in $($table.Keys | Sort-Object)) {
$value = $table[$key];
Write-Verbose " [$key]: $value"
}
Write-Host "--- END: $header ---"
}
<# Locates maven installation using algorithm from Azure tasks.
https://github.com/microsoft/azure-pipelines-tasks/blob/master/Tasks/MavenV3/maventask.ts#L68 #>
function Get-Maven() {
if (!($env:M2_HOME -eq $mavenHome)) {
Write-Verbose "Using maven from: '$($env:M2_HOME)'"
$mavenBin = Join-Path $(Join-Path $env:M2_HOME "bin") "mvn"
# On Windows, append .cmd or .bat to the executable as necessary
# Maven 3 uses mvn.cmd. Maven 2 uses mvn.bat
$lowercaseBin = $mavenBin.ToLowerInvariant()
if ($IsWindows -and !$lowercaseBin.EndsWith(".bat") -and !$lowercaseBin.EndsWith(".cmd")) {
if (Test-Path "$($mavenBin).cmd") {
$mavenBin += ".cmd"
} elseif (Test-Path "$($mavenBin).bat") {
$mavenBin += ".bat"
}
}
return $mavenBin
} else {
Write-Verbose "Finding maven in path."
$allMavenInstallations = @(Get-Command mvn -CommandType Application -ErrorAction Ignore)
if ($allMavenInstallations.Length -eq 0) {
Write-Error "mvn is not in path and M2_HOME is not set. Cannot continue."
}
$maven = $allMavenInstallations[0]
return $maven.Path
}
}
$maven = Get-Maven
Write-Host "Using maven at: '$maven'"
Invoke-Expression "$maven --version"
$pomFiles = Get-ChildItem -Path $Directory -Filter pom.xml -Recurse -File | Where-Object {
($null -eq $ExcludeRegex) -or ($ExcludeRegex.Length -eq 0) -or ($_.Directory.Name -notmatch $ExcludeRegex)
}
$pomFiles | ForEach-Object {
Write-Host "pom: [$($_.FullName)]"
}
if (@($pomFiles).Count -eq 0) {
Write-Warning "No pom.xml files were found."
}
foreach ($file in $pomFiles) {
$manifestFile = Join-Path $file.DirectoryName "cgmanifest.json"
$existingComponents = @{}
$incrementVersion = $false
if (Test-Path $manifestFile) {
$json = Get-Content $manifestFile | ConvertFrom-Json
$incrementVersion = $true
foreach ($c in $json.Registrations) {
if (!($c.Component.Type -ieq "Maven")) {
Write-Host "$($c.Component) is not type Maven. Skipping."
continue
}
$m = $c.Component.Maven
[MavenReference]$mavenReference = [MavenReference]::new($m.GroupId, $m.ArtifactId, $m.Version)
$existingComponents.Add($mavenReference.ToString(), $mavenReference) | Out-Null
}
} else {
Write-Verbose "$manifestFile does not exist."
$json = [PSCustomObject]@{
Registrations = @()
Version = 1
}
}
[hashtable]$dependencies = Get-Dependencies $maven $file
if (($null -eq $dependencies) -or ($null -eq $dependencies.Keys)) {
Write-Host "Skipping $($file.FullName)"
continue
}
Write-Table "csmanifest.json components" $existingComponents
Write-Table "Transitive dependencies" $dependencies
$isUpdated = $false
foreach ($key in $($dependencies.Keys | Sort-Object)) {
if ($existingComponents.ContainsKey($key)) {
Write-Verbose "'$key' already exists."
continue
}
if (!$isUpdated -and $incrementVersion) {
$isUpdated = $true
$json.Version++
}
$value = $dependencies[$key]
Write-Host "Adding: $value"
$mavenComponent = [MavenComponent]::new($value)
$json.Registrations += @{ Component = $mavenComponent }
}
Write-Host "Writing to: '$manifestFile'"
if (Test-Path $manifestFile) {
Write-Host "Overwriting existing cgmanifest.json."
}
$jsonOutput = ConvertTo-Json -InputObject $json -Depth 15
if ($IsVerbose) {
Write-Host $jsonOutput
}
$jsonOutput | Set-Content $manifestFile
}