UpdateSubmodules.ps1 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #!/usr/bin/env pwsh -c
  2. <#
  3. .SYNOPSIS
  4. Updates git submodules and generates a commit message with the list of changes
  5. .PARAMETER GitAuthorName
  6. The author name to use in the commit message. (Optional)
  7. .PARAMETER GitAuthorEmail
  8. The author email to use in the commit message. (Optional)
  9. .PARAMETER GitCommitArgs
  10. Additional arguments to pass into git-commit
  11. .PARAMETER NoCommit
  12. Make changes without executing git-commit
  13. .PARAMETER Force
  14. Specified this to make a commit with any changes
  15. .PARAMETER IgnoredRepos
  16. Repos to not update (likely because they are temporarily broken).
  17. #>
  18. [cmdletbinding(SupportsShouldProcess = $true)]
  19. param(
  20. [string]$GitAuthorName = $null,
  21. [string]$GitAuthorEmail = $null,
  22. [string[]]$GitCommitArgs = @(),
  23. [switch]$NoCommit,
  24. [switch]$Force,
  25. [string[]]$IgnoredRepos = @()
  26. )
  27. $ErrorActionPreference = 'Stop'
  28. Set-StrictMode -Version 2
  29. $RepoRoot = Resolve-Path "$PSScriptRoot\.."
  30. $ModuleDirectory = Join-Path $RepoRoot "modules"
  31. Import-Module "$PSScriptRoot/common.psm1" -Scope Local -Force
  32. function Get-GitChanges([string]$Path) {
  33. Write-Verbose "git diff --cached --quiet $Path"
  34. & git diff --cached --quiet $Path | Out-Null
  35. if ($LastExitCode -ne 0) {
  36. return $true
  37. }
  38. Write-Verbose "git diff --quiet $Path"
  39. & git diff --quiet $Path | Out-Null
  40. return $LastExitCode -ne 0
  41. }
  42. Push-Location $RepoRoot | Out-Null
  43. try {
  44. Assert-Git
  45. Write-Host "Checking that submodules are in a clean state first..."
  46. if (Get-GitChanges $ModuleDirectory) {
  47. Write-Error "$RepoRoot/modules is in an unclean state. Reset submodules first by running ``git submodule update``"
  48. exit 1
  49. }
  50. $submodules = Get-Submodules $RepoRoot -Verbose:$VerbosePreference
  51. foreach ($submodule in $submodules) {
  52. $submoduleName = $submodule.module
  53. if ($IgnoredRepos.Contains($submoduleName))
  54. {
  55. Write-Host "Skipping $submoduleName due to IgnoredRepos."
  56. continue
  57. }
  58. $submodulePath = $submodule.path
  59. Write-Host "Updating $submodulePath"
  60. $vcs_name = "BUILD_VCS_NUMBER_" + ($submodule.module -replace '\.','_')
  61. $newCommit = [environment]::GetEnvironmentVariable($vcs_name)
  62. if (-not $newCommit) {
  63. if ($env:TEAMCITY_PROJECT_NAME) {
  64. throw "TeamCity env variable '$vcs_name' not found. Make sure to configure a VCS root for $submodulePath"
  65. }
  66. Invoke-Block { & git submodule update --remote $submodulePath }
  67. Push-Location $submodulePath | Out-Null
  68. try {
  69. $newCommit = $(git rev-parse HEAD)
  70. }
  71. finally {
  72. Pop-Location | Out-Null
  73. }
  74. }
  75. else {
  76. Push-Location $submodulePath | Out-Null
  77. try {
  78. Invoke-Block { & git checkout $newCommit }
  79. }
  80. finally {
  81. Pop-Location | Out-Null
  82. }
  83. }
  84. $submodule.newCommit = $newCommit
  85. if ($newCommit -ne $submodule.commit) {
  86. $submodule.changed = $true
  87. Write-Host -ForegroundColor Cyan "`t=> $($submodule.module) updated to $($submodule.newCommit)"
  88. }
  89. else {
  90. Write-Host -ForegroundColor Magenta "`t$($submodule.module) did not change"
  91. }
  92. }
  93. $changes = $submodules `
  94. | ? { $_.changed } `
  95. | % {
  96. Invoke-Block { & git add $_.path }
  97. "$($_.module) => $($_.newCommit)"
  98. }
  99. if ($changes) {
  100. $shortMessage = "Updating submodule(s) `n`n$( $changes -join "`n" )"
  101. # add this to the commit message to make it possible to filter commit triggers based on message
  102. $message = "$shortMessage`n`n[auto-updated: submodules]"
  103. if (-not $NoCommit -and ($Force -or ($PSCmdlet.ShouldContinue($shortMessage, 'Create a new commit with these changes?')))) {
  104. $gitConfigArgs = @()
  105. if ($GitAuthorName) {
  106. $gitConfigArgs += '-c',"user.name=$GitAuthorName"
  107. }
  108. if ($GitAuthorEmail) {
  109. $gitConfigArgs += '-c',"user.email=$GitAuthorEmail"
  110. }
  111. Invoke-Block { & git @gitConfigArgs commit -m $message @GitCommitArgs }
  112. }
  113. else {
  114. # If composing this script with others, return the message that would have been used
  115. return @{
  116. message = $message
  117. }
  118. }
  119. }
  120. else {
  121. Write-Host -ForegroundColor Magenta 'No changes detected in git submodules'
  122. }
  123. }
  124. finally {
  125. Pop-Location
  126. }