Types/OpenPackage.Source/Repository.ps1
|
<# .SYNOPSIS Gets a repository as a package .DESCRIPTION Gets a repository as an open package #> param( # A Repository to package. # This can be the root of a repo or a link to a portion of the tree. # If a portion of the tree is provided, will perform a sparse clone of the repository [Parameter(ValueFromPipelineByPropertyName)] [Alias('clone_url')] [string] $Repository, # The github branch name. [Parameter(ValueFromPipelineByPropertyName)] [string] $Branch, # One or more optional sparse filters to a repository. # If these are provided, only files matching these filters will be downloaded. [Parameter(ValueFromPipelineByPropertyName)] [string[]] $SparseFilter, # A list of file wildcards to include. [Parameter(ValueFromPipelineByPropertyName)] [SupportsWildcards()] [string[]] $Include, # A list of file wildcards to exclude. [Parameter(ValueFromPipelineByPropertyName)] [SupportsWildcards()] [string[]] $Exclude, # The base path within the package. # Content should be added beneath this base path. [string] $BasePath = '/', # A content type map. # This maps extensions and URIs to a content type. [Collections.IDictionary] $TypeMap = $( ([PSCustomObject]@{PSTypeName='OpenPackage.ContentTypeMap'}).TypeMap ), # The compression option. [IO.Packaging.CompressionOption] [Alias('CompressionLevel')] $CompressionOption = 'Superfast', # If set, will force the redownload of various resources and remove existing files or directories [switch] $Force, # If set, will include hidden files and folders, except for files beneath `.git` [Alias('IncludeDotFiles')] [switch] $IncludeHidden, # If set, will include the `.git` directory contents if found. # By default, this content will be excluded. [Alias('IncludeGitFile','IncludeGitFiles','IncludeGitDirectory')] [switch] $IncludeGit, # If set, will include any content found in `/node_modules`. # By default, this content will be excluded. [Alias('IncludeNodeModules')] [switch] $IncludeNodeModule, # If set, will include any content found in `/_site`. # By default, this content will be excluded. [Alias('IncludeWebsite')] [switch] $IncludeSite ) if (-not $repository) { throw "No repository" } $gitApp = $ExecutionContext.SessionState.InvokeCommand.GetCommand('git', 'Application') if (-not $gitApp) { throw "No git" } if (-not $env:OpenPackagePath) { throw "No Open Package Path" } $myAppData = $env:OpenPackagePath -split $( if ($IsLinux -or $IsMacOS) { ':' } else { ';' } ) $namedParameters = [Ordered]@{} foreach ($key in $MyInvocation.MyCommand.Parameters.Keys) { $var = $ExecutionContext.SessionState.PSVariable.Get($key) if (-not [string]::IsNullOrEmpty($var.value)) { $namedParameters[$key] = $var.value } } $namedParameters.Remove('Repository') $namedParameters.Remove('Branch') $namedParameters.Remove('SparseFilter') $repositoryUrl = $Repository # See if we are matching a repo or a tree or blob. $treePattern = '/(?>tree|blob)/(?<branch>[^/]+)/' if ($Repository -match $treePattern -and -not $NamedParameters.SparseFilter) { # If we are matching a tree, turn the file portion into a sparse filter $branch = $matches.branch $NamedParameters.SparseFilter = $SparseFilter = $RepositoryUrl -replace "^.+?$treePattern" -replace '^/?', '/' -replace '/?$', '/' -replace '(?<!:)//', '/' $Repository = $RepositoryUrl -replace "$treePattern.+?$" if ($SparseFilter -notmatch '/[^\.]+\.[^\.]+?$') { $sparseFilter = $SparseFilter -replace '/$','/**' } } # Pick out the owner and repository $owner, $repositoryName = ($Repository -as [uri]).Segments[1,2] -replace '/$' if (-not $owner -or -not $repositoryName) { Write-Error "Could not identifier owner and repository $reposityUrl" return } $repoDir = if ( ($Repository -as [uri]).DnsSafeHost ) { ($Repository -as [uri]).DnsSafeHost } else { 'repos' } # Get the path to our repos $reposPaths = Join-Path $myAppData $repoDir if (-not (Test-Path $reposPaths)) { # (create it if it did not exist) $null = New-Item -ItemType Directory $reposPaths -Force if (-not $?) { return } } # Get the path to repos of that owner $ownerDirectory = Join-Path $reposPaths $owner if (-not (Test-Path $ownerDirectory)) { $null = New-Item -ItemType Directory $ownerDirectory -Force if (-not $?) { return } } # Finally, get the path to the repo itself. $repoDirectory = Join-Path $ownerDirectory $repositoryName # If we are using `-Force`, remove the directory if ($Force -and (Test-path $repoDirectory)) { Remove-Item -Path $repoDirectory -Recurse -Force } $namedParameters.Remove('Repository') # and get read to turn our git activity into progress bars $gitProgress = @{Id=Get-Random;Status="Cloning $repository"} $writeGitProgress = { process { $gitProgress.Activity = "$_" Write-Progress @gitProgress } } $checkoutBranch = @() if ($branch) { $checkoutBranch += $branch} # If the directory did not exist if (-not (Test-Path $repoDirectory)) { # push to the owner directory and clone it Push-Location $ownerDirectory # If sparse filters were provided if ($SparseFilter) { # Perform a sparse clone & $gitApp clone --depth 1 --no-checkout --sparse --filter=tree:0 $Repository "$repositoryName" *>&1 | . $writeGitProgress # and push into the location Push-Location -LiteralPath $repoDirectory # then set our sparse filter $SparseArgs = @($SparseFilter) & $gitApp sparse-checkout set --no-cone @SparseArgs *>&1 | . $writeGitProgress # and checkout. & $gitApp checkout @checkoutBranch *>&1 | . $writeGitProgress # we should now have the files, so prepare an -Include filter if (-not $namedParameters.Include) { $namedParameters.Include = foreach ($sparse in $SparseFilter) { "*$sparse" } } # clean up our progress $gitProgress.Completed = $true Write-Progress @gitProgress # and call ourselves with the repoDirectory Get-OpenPackage -FilePath $pwd @namedParameters Pop-Location } else { # If no sparse filters were provided, just clone & $gitApp clone $Repository *>&1 | . $writeGitProgress $gitProgress.Completed = $true Write-Progress @gitProgress if ($?) { Push-Location $repoDirectory # and call ourself Get-OpenPackage -FilePath $pwd @namedParameters Pop-Location } } Pop-Location if (-not $?) { return } } else { # If the directory already exists, go there Push-Location $repoDirectory # and checkout & $gitApp checkout @checkoutBranch | . $writeGitProgress # and if a sparse filter was provided if ($SparseFilter) { if (-not $namedParameters.Include) { # try to only include those files $namedParameters.Include = foreach ($sparse in $SparseFilter) { "*$sparse" } } } $gitProgress.Completed = $true Write-Progress @gitProgress # Call get-openpackage and make a package from this directory Get-OpenPackage -FilePath $repoDirectory @namedParameters Pop-Location } |