functions/New-GitRepo.ps1
function New-GitRepo { <# .SYNOPSIS Creates a new git repository and returns the repository or directory object. .DESCRIPTION Creates a new git repository and returns the repository or directory object. .PARAMETER Repo The name, or a relative or absolute path, to the git repository to create. If the directory does not exist, it will be created. If RepoPath is not specified, the repository is created at the current location. If the UseDefaultDir switch is used, then Repo allows a repository name or relative path. .PARAMETER UseDefaultDir Uses the directory stored in the $Powdrgit.DefaultDir variable as the parent directory. .PARAMETER Bare Create a bare repository. .PARAMETER InitialBranchName Name of the initial branch. If not specified, the git default will be used. .PARAMETER InitialCommit Make an initial commit against the new repo using the given text. This commit will associate any existing files in the repository with it and will be the parent to all subsequent commits. Until an initial commit has been made, the initial branch will not be visible in git. If multiple strings are passed in, the first string is used as the commit subject. All remaining strings are used as the commit body. .PARAMETER UseDefaultInitialCommit Same behavior as the InitialCommit parameter, but the commit message will use the value in $Powdrgit.DefaultInitialCommit. .PARAMETER TemplateDir Path to the template directory. Files and directories in the template directory whose name do not start with a dot will be copied to the new repository after it is created. .PARAMETER AppendPowdrgitPath Appends the path of the new repository to the $Powdrgit.Path module variable. .PARAMETER SetLocation Sets the location to the top-level directory of the new repository. .EXAMPLE ## Call with no parameters ## PS C:\> New-Item -ItemType Directory -Path 'C:\MyEmptyFolder' PS C:\> Set-Location 'C:\MyEmptyFolder' PS C:\MyEmptyFolder> $r = New-GitRepo PS C:\MyEmptyFolder> Get-ChildItem -Hidden | Select-Object -ExpandProperty FullName C:\MyEmptyFolder\.git # A repository was created at the current location .EXAMPLE ## Call with an absolute path ## PS C:\> $r = New-GitRepo -Repo 'C:\MyNewRepo' PS C:\> Get-ChildItem -Path 'C:\MyNewRepo' -Hidden | Select-Object -ExpandProperty FullName C:\MyNewRepo\.git # A repository was created at the specified location .EXAMPLE ## Call with a relative path ## PS C:\> New-Item -ItemType Directory -Path 'C:\MyEmptyFolder' PS C:\> Set-Location 'C:\MyEmptyFolder' PS C:\MyEmptyFolder> $r = New-GitRepo -Repo 'MyRepos\MyNewRepo' PS C:\MyEmptyFolder> Get-ChildItem -Hidden -Recurse | Select-Object -ExpandProperty FullName C:\MyEmptyFolder\MyRepos\MyNewRepo\.git # A repository was created relative to the current location .EXAMPLE ## Call with a repository name ## PS C:\> New-Item -ItemType Directory -Path 'C:\MyEmptyFolder' PS C:\> Set-Location 'C:\MyEmptyFolder' PS C:\MyEmptyFolder> $r = New-GitRepo -Repo 'MyNewRepo' PS C:\MyEmptyFolder> Get-ChildItem -Hidden -Recurse | Select-Object -ExpandProperty FullName C:\MyEmptyFolder\MyNewRepo\.git # A repository with the specified name was created at the current location .EXAMPLE ## Call with UseDefaultDir ## PS C:\> $Powdrgit.DefaultDir = 'C:\PowdrgitExamples' PS C:\> $Powdrgit.ShowWarnings = $true # to ensure warnings are visible PS C:\> $r = New-GitRepo -Repo 'C:\PowdrgitExamples\MyNewRepo' -UseDefaultDir WARNING: [New-GitRepo]The UseDefaultDir switch cannot be used with an absolute path for Repo: C:\PowdrgitExamples\MyNewRepo. # A warning is generated for the incompatible parameter values. PS C:\> $r = New-GitRepo -Repo 'MyNewRepo' -UseDefaultDir PS C:\> Get-ChildItem -Path "$($Powdrgit.DefaultDir)\MyNewRepo" -Hidden -Recurse | Select-Object -ExpandProperty FullName C:\PowdrgitExamples\MyNewRepo\.git # A repository was created in the default directory. .EXAMPLE ## Call with SetLocation ## PS C:\> $r = New-GitRepo -Repo 'C:\PowdrgitExamples\MyNewRepo' -SetLocation PS C:\PowdrgitExamples\MyNewRepo> # The location changed to the new repository. .EXAMPLE ## Call with Bare ## PS C:\> $r = New-GitRepo -Repo 'C:\PowdrgitExamples\MyNewRepo' -Bare PS C:\> Get-ChildItem -Path 'C:\PowdrgitExamples\MyNewRepo*' -Directory | Select-Object -ExpandProperty FullName C:\PowdrgitExamples\MyNewRepo.git # The name of the repository was automatically appended with ".git" to indicate a bare repository. .EXAMPLE ## Call with AppendPowdrgitPath ## PS C:\> $Powdrgit.Path = $null PS C:\> $r = New-GitRepo -Repo 'C:\PowdrgitExamples\MyNewRepo' -AppendPowdrgitPath PS C:\> $Powdrgit.Path C:\PowdrgitExamples\MyNewRepo PS C:\> $r.GetType().FullName GitRepo # The name of the repository was appended with ".git" to indicate a bare repository. # Because the repository exists in the $Powdrgit.Path module variable, New-GitRepo returns a GitRepo object. .EXAMPLE ## Call with InitialBranchName and InitialCommit ## PS C:\> $r = New-GitRepo -Repo 'C:\PowdrgitExamples\MyNewRepo' -AppendPowdrgitPath -InitialBranchName 'MyBranch' -InitialCommit 'Initial commit' # AppendPowdrgitPath is used to make the repo visible to Powdrgit. # InitialCommit is used to make the branch visible in git. PS C:\> $r | Get-GitBranch | Select-Object RepoName,BranchName RepoName BranchName -------- ---------- MyNewRepo MyBranch PS C:\> $r | Get-GitLog | Select-Object RepoName,SHA1Hash,Subject RepoName SHA1Hash Subject -------- -------- ------- MyNewRepo 6ef6fab1a36bd165a898e06e053515ce114a4390 Initial commit .EXAMPLE ## Call with TemplateDir ## PS C:\> $t = New-GitRepo -Repo 'C:\PowdrgitExamples\TemplateRepo' # create a template repository PS C:\> $f = New-Item -Path "$($t.FullName)\TemplateFile.txt" -ItemType File -Value 'This is a template file.' # add a file to the template repository PS C:\> $r = New-GitRepo -Repo 'C:\PowdrgitExamples\NewRepoFromTemplateRepo' -TemplateDir $t.FullName # create a new repository from the template repository PS C:\> Get-ChildItem -Path 'C:\PowdrgitExamples\NewRepoFromTemplateRepo' -Force -Recurse -Filter *.txt | Select-Object -ExpandProperty FullName C:\PowdrgitExamples\NewRepoFromTemplateRepo\.git\TemplateFile.txt # Note that git copies files from with working directory of the template repository to the git directory of the new repository. .INPUTS [System.String[]] Accepts string objects via the Repo parameter. .OUTPUTS [GitRepo] [System.IO.DirectoryInfo] If the AppendPowdrgitPath switch was used, then a [GitRepo] object is returned. Otherwise a [System.IO.DirectoryInfo] object is returned. .NOTES Author : nmbell .LINK Find-GitRepo .LINK Get-GitRepo .LINK Set-GitRepo .LINK Remove-GitRepo .LINK Invoke-GitClone .LINK Add-PowdrgitPath .LINK Remove-PowdrgitPath .LINK Test-PowdrgitPath .LINK about_powdrgit .LINK https://github.com/nmbell/powdrgit/blob/main/help/about_powdrgit.md #> # Function alias [Alias('ngr')] # Use cmdlet binding [CmdletBinding( DefaultParameterSetName = 'InitialCommit' , SupportsShouldProcess = $true , ConfirmImpact = 'Medium' , HelpURI = 'https://github.com/nmbell/powdrgit/blob/main/help/New-GitRepo.md' )] # Declare output type [OutputType('GitRepo' , ParameterSetName = ('Bare','InitialCommit','UseDefaultInitialCommit'))] [OutputType([System.IO.DirectoryInfo], ParameterSetName = ('Bare','InitialCommit','UseDefaultInitialCommit'))] # Declare parameters Param( [Parameter( Mandatory = $false , Position = 0 , ValueFromPipeline = $true , ValueFromPipelineByPropertyName = $true )] [Alias('FullName','Path','RepoName','RepoPath')] [ValidateNotNullOrEmpty()] [String[]] $Repo , [Switch] $UseDefaultDir , [Parameter( ParameterSetName = 'Bare' )] [Switch] $Bare , [Parameter( Mandatory = $false , Position = 1 , ValueFromPipeline = $false , ValueFromPipelineByPropertyName = $true )] [ValidateNotNullOrEmpty()] [String] $InitialBranchName , [Parameter( Mandatory = $false , Position = 2 , ValueFromPipeline = $false , ValueFromPipelineByPropertyName = $true , ParameterSetName = 'InitialCommit' )] [ValidateNotNullOrEmpty()] [String[]] $InitialCommit , [Parameter( ParameterSetName = 'UseDefaultInitialCommit' )] [Switch] $UseDefaultInitialCommit , [Parameter( Mandatory = $false , Position = 3 , ValueFromPipeline = $false , ValueFromPipelineByPropertyName = $true )] [ValidateNotNullOrEmpty()] [String] $TemplateDir , [Switch] $AppendPowdrgitPath , [Switch] $SetLocation ) BEGIN { $bk = 'B' # Common BEGIN: Set-StrictMode -Version 3.0 $thisFunctionName = $MyInvocation.MyCommand $start = Get-Date $indent = ($Powdrgit.DebugIndentChar[0]+' ')*($PowdrgitCallDepth++) $PSDefaultParameterValues += @{ '*:Verbose' = $(If ($DebugPreference -notin 'Ignore','SilentlyContinue') { $DebugPreference } Else { $VerbosePreference }) } # turn on Verbose with Debug $warn = $Powdrgit.ShowWarnings -and !($PSBoundParameters.ContainsKey('WarningAction') -and $PSBoundParameters.WarningAction -eq 'Ignore') # because -WarningAction:Ignore is not implemented correctly Write-Debug " $(ts)$indent[$thisFunctionName][$bk]Start: $($start.ToString('yyyy-MM-dd HH:mm:ss.fff'))" # Function BEGIN: Write-Debug " $(ts)$indent[$thisFunctionName][$bk]Storing current location" $startLocation = $PWD.Path } PROCESS { $bk = 'P' # Use the current path if none was supplied If (!$Repo) { $Repo = $PWD.Path } ForEach ($_Repo in $Repo) { # Validate Repo parameter <# Repo UseDefaultDir=True UseDefaultDir=False ---- ------------------ ------------------- Absolute Warning;NoOp $Repo Relative DefaultDir+$Repo $PWD+$Repo NotPresent DefaultDir $PWD #> $repoPath = $null If ($PSBoundParameters.ContainsKey('Repo')) { If ($_Repo -like '[A-Z]:\*' -or $_Repo -like '\\*') # if absolute path { If ($UseDefaultDir) { If ($warn) { Write-Warning "[$thisFunctionName]The UseDefaultDir switch cannot be used with an absolute path for Repo: $_Repo." } } Else { $repoPath = $_Repo } } Else { If ($UseDefaultDir) { If (Test-PowdrgitDefaultDir) { $repoPath = Join-Path -Path $Powdrgit.DefaultDir -ChildPath $_Repo } } Else { $repoPath = Join-Path -Path $PWD.Path -ChildPath $_Repo } } } Else { If ($UseDefaultDir) { If (Test-PowdrgitDefaultDir) { $repoPath = $Powdrgit.DefaultDir } } Else { $repoPath = $PWD.Path } } If ($repoPath) { Write-Debug " $(ts)$indent[$thisFunctionName][$bk]Repository path: $repoPath" # Construct git command $gitCommand = "git init" If ($Bare) { $gitCommand += ' --bare' If ($repoPath -notlike '*.git') { $repoPath += '.git' } } If ($InitialBranchName) { $gitCommand += " --initial-branch=`"$InitialBranchName`"" } If ($TemplateDir ) { $gitCommand += " --template=`"$TemplateDir`"" } $gitCommand += " `"$repoPath`"" # Determine procession $shouldText = ("Creating repository: $repoPath") If ($WhatIfPreference) { Write-Host } $shouldProcess = $PSCmdlet.ShouldProcess($shouldText,$null,$null) # Create the repo # If ($WhatIfPreference) { Write-Host "What if: $shouldText" } # handled by ShouldProcess If ($shouldProcess) { Write-Verbose "$(ts)$indent[$thisFunctionName][$bk]$shouldText" $gitResults = Invoke-GitExpression -Command $gitCommand If ($gitResults -like 'fatal:*') { If ($warn) { Write-Warning "[$thisFunctionName]$gitResults" } } } # Process remaining parameters and return the repository $shouldText = "Setting location: $repoPath" # If ($WhatIfPreference) { Write-Host "What if: $shouldText" } # moved to END block If ($shouldProcess) { Write-Debug " $(ts)$indent[$thisFunctionName][$bk]$shouldText" Set-Location -Path $repoPath -ErrorAction Ignore } If ($repoPath -eq $PWD.Path -or $WhatIfPreference) { If ($UseDefaultInitialCommit) { $InitialCommit = @($Powdrgit.DefaultInitialCommit) } If ($InitialCommit) { $commitSubject = "-m `"$($InitialCommit[0])`"" $commitBody = '' If ($InitialCommit.Count -gt 1) { $commitBody = "-m `"$($InitialCommit[1..($InitialCommit.Count-1)] -join "`r`n")`"" } $shouldText = "Making initial commit: $($InitialCommit[0])" If ($WhatIfPreference) { Write-Host "What if: $shouldText" } If ($shouldProcess) { Write-Debug " $(ts)$indent[$thisFunctionName][$bk]$shouldText" Invoke-GitExpression -Command 'git add .' -SuppressGitSuccessStream -SuppressGitErrorStream Invoke-GitExpression -Command "git commit --allow-empty $commitSubject $commitBody" -SuppressGitSuccessStream -SuppressGitErrorStream } } If ($AppendPowdrgitPath) { $shouldText = 'Adding path to `$Powdrgit.Path' If ($WhatIfPreference) { Write-Host "What if: $shouldText" } If ($shouldProcess) { Write-Debug " $(ts)$indent[$thisFunctionName][$bk]$shouldText" Add-PowdrgitPath -Path $repoPath -WhatIf:$false -Confirm:$false } $shouldText = 'Returning [GitRepo]' If ($WhatIfPreference) { Write-Host "What if: $shouldText" } If ($shouldProcess) { Write-Debug " $(ts)$indent[$thisFunctionName][$bk]$shouldText" Get-GitRepo -Repo $repoPath } } Else { $shouldText = 'Returning [System.IO.DirectoryInfo]' If ($WhatIfPreference) { Write-Host "What if: $shouldText" } If ($shouldProcess) { Write-Debug " $(ts)$indent[$thisFunctionName][$bk]$shouldText" Get-Item -Path $repoPath } } } ElseIf ($repoPath -and $shouldProcess) { If ($warn) { Write-Warning "[$thisFunctionName]Could not move to repository location: $repoPath. Check the repository has been created." } } } } } END { $bk = 'E' # Function END: If (!$SetLocation) { Write-Debug " $(ts)$indent[$thisFunctionName][$bk]Setting location to original directory" Set-Location -Path $startLocation } Else { $shouldText = "Setting location: $repoPath" If ($WhatIfPreference) { Write-Host; Write-Host "What if: $shouldText" } } If ($WhatIfPreference) { Write-Host } # Common END: $end = Get-Date $duration = New-TimeSpan -Start $start -End $end Write-Debug " $(ts)$indent[$thisFunctionName][$bk]Finish: $($end.ToString('yyyy-MM-dd HH:mm:ss.fff')) ($($duration.ToString('d\d\ hh\:mm\:ss\.fff')))" $PowdrgitCallDepth-- } } |