Invoke-GitCheckout.ps1 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. function Set-GitConfig {
  2. <#
  3. .SYNOPSIS
  4. Sets a git config value.
  5. .DESCRIPTION
  6. Allows setting single or multiple config values in a PowerShell-friendly fashion.
  7. .EXAMPLE
  8. Set-GitConfig advice.detachedHead false
  9. #>
  10. if ( $args.Count -lt 2 ) {
  11. throw 'Set-GitConfig called without required arguments <OPTION> <VALUE>.'
  12. }
  13. Invoke-External git config @args
  14. }
  15. function Invoke-GitCheckout {
  16. <#
  17. .SYNOPSIS
  18. Checks out a specified git repository.
  19. .DESCRIPTION
  20. Wraps the git executable with PowerShell syntax to check out
  21. a specified Git repository with a given commit hash and branch,
  22. or a GitHub pull request ID.
  23. .EXAMPLE
  24. Invoke-GitCheckout -Uri "My-Repo-Uri" -Commit "My-Commit-Hash"
  25. Invoke-GitCheckout -Uri "My-Repo-Uri" -Commit "My-Commit-Hash" -Branch "main"
  26. Invoke-GitCheckout -Uri "My-Repo-Uri" -Commit "My-Commit-Hash" -PullRequest 250
  27. #>
  28. param(
  29. [Parameter(Mandatory)]
  30. [string] $Uri,
  31. [Parameter(Mandatory)]
  32. [string] $Commit,
  33. [string] $Path,
  34. [string] $Branch = "master",
  35. [string] $PullRequest
  36. )
  37. if ( ! ( $Uri -like "*github.com*" ) -and ( $PullRequest -ne "" ) ) {
  38. throw 'Fetching pull requests is only supported with GitHub-based repositories.'
  39. }
  40. if ( ! ( Test-Path function:Log-Information ) ) {
  41. . $PSScriptRoot/Utils-Logger.ps1
  42. }
  43. if ( ! ( Test-Path function:Invoke-External ) ) {
  44. . $PSScriptRoot/Invoke-External.ps1
  45. }
  46. $RepositoryName = [System.IO.Path]::GetFileNameWithoutExtension($Uri)
  47. if ( $Path -eq "" ) {
  48. $Path = "$(Get-Location | Convert-Path)\${RepositoryName}"
  49. }
  50. Push-Location -Stack GitCheckoutTemp
  51. if ( Test-Path $Path/.git ) {
  52. Write-Information "Repository ${RepositoryName} found in ${Path}"
  53. Set-Location $Path
  54. Set-GitConfig advice.detachedHead false
  55. Set-GitConfig remote.origin.url $Uri
  56. Set-GitConfig remote.origin.tapOpt --no-tags
  57. $Ref = "+refs/heads/{0}:refs/remotes/origin/{0}" -f $Branch
  58. Set-GitConfig --replace-all remote.origin.fetch $Ref
  59. if ( $PullRequest -ne "" ) {
  60. try {
  61. Invoke-External git show-ref --quiet --verify refs/heads/pr-$PullRequest
  62. } catch {
  63. Invoke-External git fetch origin $("pull/{0}/head:pull-{0}" -f $PullRequest)
  64. } finally {
  65. Invoke-External git checkout -f "pull-${PullRequest}"
  66. }
  67. }
  68. try {
  69. $null = Invoke-External git rev-parse -q --verify "${Commit}^{commit}"
  70. } catch {
  71. Invoke-External git fetch origin
  72. }
  73. Invoke-External git checkout -f $Commit -- | Log-Information
  74. } else {
  75. Invoke-External git clone $Uri $Path
  76. Set-Location $Path
  77. Set-GitConfig advice.detachedHead false
  78. if ( $PullRequest -ne "" ) {
  79. $Ref = "pull/{0}/head:pull-{0}" -f $PullRequest
  80. $Branch = "pull-${PullRequest}"
  81. Invoke-External git fetch origin $Ref
  82. Invoke-External git checkout $Branch
  83. }
  84. Invoke-External git checkout -f $Commit
  85. }
  86. Log-Information "Checked out commit ${Commit} on branch ${Branch}"
  87. if ( Test-Path ${Path}/.gitmodules ) {
  88. Invoke-External git submodule foreach --recursive git submodule sync
  89. Invoke-External git submodule update --init --recursive
  90. }
  91. Pop-Location -Stack GitCheckoutTemp
  92. }