PSDependScripts/Git.ps1
<# .SYNOPSIS Clone a git repository .DESCRIPTION Clone a git repository Note: We require git.exe in your path Relevant Dependency metadata: DependencyName (Key): Git URL You can override this with the 'Name'. If you specify only an Account/Repository, we assume GitHub is the source Name: Optional override for the Git URL, same rules as DependencyName (key) Version: Used with git checkout. Specify a branch name, commit hash, or tags/<tag name>, for example. Defaults to master Target: Path to clone this repository. e.g C:\Temp would result in C:\Temp\RepoName. Defaults to nothing (current path/repo name) AddToPath: Prepend the Target to ENV:PATH and ENV:PSModulePath .PARAMETER Force If specified and target does not exist, create directory tree up to the target folder .PARAMETER PSDependAction Test, Install, or Import the module. Defaults to Install Test: Return true or false on whether the dependency is in place (Note: Currently only checks if path exists) Install: Install the dependency Import: Import the dependency 'Target'. Override with ImportPath .PARAMETER ImportPath If specified with PSDependAction Import, we import this path, instead of Target, the default .EXAMPLE @{ 'buildhelpers' = @{ Name = 'https://github.com/RamblingCookieMonster/BuildHelpers.git' Version = 'd32a9495c39046c851ceccfb7b1a85b17d5be051' Target = 'C:\git' } } # Full syntax # DependencyName (key) uses (unique) name 'buildhelpers' # Override DependencyName as URL the name https://github.com/RamblingCookieMonster/BuildHelpers.git # Specify a commit to checkout (version) # Clone in C:\git .EXAMPLE @{ 'https://github.com/RamblingCookieMonster/PSDeploy.git' = 'master' 'https://internal.gitlab.fqdn/jdoe/BuildHelpers.git' = 'd32a9495c39046c851ceccfb7b1a85b17d5be051' } # Simple syntax # First example shows cloning PSDeploy from ramblingcookiemonster's GitHub repo # Second example shows clonging BuildHelpers from jdoe's internal GitLab account and checking out a specific commit # Both are cloned to the current path (e.g. .\<repo name>) # This syntax assumes git as a source. The right hand side is the version (branch, commit, tags/<tag name>, etc.) #> [cmdletbinding()] param( [PSTypeName('PSDepend.Dependency')] [psobject[]]$Dependency, [switch]$Force, [ValidateSet('Test', 'Install')] [string[]]$PSDependAction = @('Install'), [string]$ImportPath, [bool]$ExtractProject = $False ) # Extract data from Dependency $DependencyName = $Dependency.DependencyName $Name = $Dependency.Name if(-not $Name) { $Name = $DependencyName } #Name is in account/repo format, default to GitHub as source #This likely needs work, and will need to change if GitHub changes valid characters for usernames if($Name -match "^[a-zA-Z0-9]+/[a-zA-Z0-9_-]+$") { $Name = "https://github.com/$Name.git" } $GitName = $Name.trimend('/').split('/')[-1] -replace "\.git$", '' if($Dependency.Target -and ($Target = (Get-Item $Dependency.Target -ErrorAction SilentlyContinue).FullName)) { Write-Debug "Target resolved to $Target" } else { $Target = $PWD.Path Write-Debug "Target defaulted to current dir: $Target" } $RepoPath = Join-Path $Target $GitName $GottaInstall = $True if(-not (Test-Path $Target) -and $PSDependAction -contains 'Install') { Write-Verbose "Creating folder [$Target] for git dependency [$Name]" $null = mkdir $Target -Force } if(-not (Test-Path $RepoPath)) { # Nothing found, return test output if( $PSDependAction -contains 'Test' -and $PSDependAction.count -eq 1) { return $False } } else # Target exists { $GottaTest = $True } if(-not (Get-Command git.exe -ErrorAction SilentlyContinue)) { Write-Error "Git dependency type requires git.exe. Ensure this is in your path, or explicitly specified in $ModuleRoot\PSDepend.Config's GitPath. Skipping [$DependencyName]" } $Version = $Dependency.Version if(-not $Version) { $Version = 'master' } if($GottaTest) { Push-Location Set-Location $RepoPath $Branch = Invoke-ExternalCommand git -Arguments (Write-Output rev-parse --abbrev-ref HEAD) -Passthru $Commit = Invoke-ExternalCommand git -Arguments (Write-Output rev-parse HEAD) -Passthru Pop-Location if($Version -eq $Branch -or $Version -eq $Commit) { Write-Verbose "[$RepoPath] exists and is already at version [$Version]" if($PSDependAction -contains 'Test' -and $PSDependAction.count -eq 1) { return $true } $GottaInstall = $False } elseif($PSDependAction -contains 'Test' -and $PSDependAction.count -eq 1) { Write-Verbose "[$RepoPath] exists and is at branch [$Branch], commit [$Commit].`nWe don't currently support moving to the requested version [$Version]" return $false } else { Write-Verbose "[$RepoPath] exists and is at branch [$Branch], commit [$Commit].`nWe don't currently support moving to the requested version [$Version]" $GottaInstall = $False } } if($PSDependAction -notcontains 'Install') { return } if($GottaInstall -and !$ExtractProject) { Push-Location Set-Location $Target Write-Verbose -Message "Cloning dependency [$Name] with git from [$($Target)]" Invoke-ExternalCommand git 'clone', $Name #TODO: Should we do a fetch, once existing repo is found? Set-Location $RepoPath Write-Verbose -Message "Checking out [$Version] of [$Name] from [$RepoPath]" Invoke-ExternalCommand git 'checkout', $Version Pop-Location } elseif($GottaInstall -and $ExtractProject) { $OutPath = Join-Path ([System.IO.Path]::GetTempPath()) ([guid]::NewGuid().guid) $RepoFolder = Join-Path -Path $OutPath -ChildPath $GitName $null = New-Item -ItemType Directory -Path $OutPath -Force Push-Location $OutPath Write-Verbose -Message "Cloning dependency [$GitName] with git from [$($Target)]" Invoke-ExternalCommand git 'clone', $Name Push-Location $GitName Write-Verbose -Message "Checking out [$Version] of [$GitName] from [$RepoFolder]" Invoke-ExternalCommand git 'checkout', $Version Pop-Location $ProjectDetails = Get-ProjectDetail -Path $RepoFolder [string[]]$ToCopy = $ProjectDetails.Path Pop-Location #TODO: Implement test and import PSDependActions. if(-not (Test-Path $Target)) { $null = New-Item -ItemType Directory -Path $Target -Force } foreach($Item in $ToCopy) { Write-Verbose "Copy From: $ToCopy To: $Target" Copy-Item -Path $Item -Destination $Target -Force -Confirm:$False -Recurse } Remove-Item $OutPath -Force -Recurse } if($Dependency.AddToPath) { Write-Verbose "Setting PSModulePath to`n$($Target, $env:PSModulePath -join ';' | Out-String)" Add-ToItemCollection -Reference Env:\PSModulePath -Item (Get-Item $Target).FullName Write-Verbose "Setting PATH to`n$($RepoPath, $env:PATH -join ';' | Out-String)" Add-ToItemCollection -Reference Env:\Path -Item (Get-Item $Target).FullName } $ToImport = $Target if($ImportPath) { $ToImport = $ImportPath } Import-PSDependModule $ToImport |