quickstarts/microsoft.devcenter/devbox-ready-to-code-image/tools/artifacts/windows-clone-update-repo/windows-clone-update-repo.ps1 (603 lines of code) (raw):
<#
.DESCRIPTION
Allows cloning a new or updating an existing repo (important for updating a chained image).
#>
param(
# Url of the repository to clone/sync.
[Parameter(Mandatory = $true)]
[string] $repoUrl,
[ValidateNotNullOrEmpty()]
[Parameter(Mandatory = $true)]
[String] $repository_TargetDirectory,
# The repository Source Control options are git (default) or gvfs
[Parameter(Mandatory = $false)]
[String] $repository_SourceControl,
[Parameter(Mandatory = $false)]
[bool] $repository_cloneIfNotExists = $false,
[Parameter(Mandatory = $false)]
[string] $repoName,
# The commit id to fetch/check out for the repo. $commitId is ignored if $branchName is provided.
[Parameter(Mandatory = $false)]
[string] $commitId = 'latest',
# When provided, this is the branch to clone/fetch. Otherwise the default branch is cloned/pulled.
[Parameter(Mandatory = $false)]
[string] $branchName,
[Parameter(Mandatory = $false)]
[string] $repository_optionalCloningParameters,
[Parameter(Mandatory = $false)]
[string] $repository_optionalFetchParameters,
[Parameter(Mandatory = $false)]
[bool] $enableGitCommitGraph = $false,
# Optional comma separated list of folders for sparse checkout. When provided, only these folders will be set and sparse-checkout is used for the repo
[Parameter(Mandatory = $false)]
[string] $sparseCheckoutFolders,
# Optional MSI client ID which is required if the VM has multiple user-assigned managed identities. This will be used to access Azure DevOps.
[Parameter(Mandatory = $false)]
[string] $repository_MSIClientId = $null
)
enum SourceControl {
git = 0 # default
gvfs
}
$logfilepath = $null
$global:varLogArray = New-Object -TypeName "PSCustomObject"
Function ProcessRunner(
[string]$command,
[string]$arguments,
[string]$argumentsToLog = '',
[bool] $checkForSuccess = $true,
[bool] $waitForDependents = $true
) {
<#
.DESCRIPTION
Run a process and validate that the process started and completed without any errors
.PARAMETER command
The command that will be run
.PARAMETER arguments
The arguments required to run the supplied command. Do not use in logging as the string may contains a secret.
.PARAMETER argumentsToLog
The arguments representation that is safe to log
.PARAMETER checkForSuccess
If $false then do not check whether the command succeeded
#>
if (!$argumentsToLog) {
$argumentsToLog = $arguments
}
$errLog = [System.IO.Path]::GetTempFileName()
if ($waitForDependents) {
$process = Start-Process -FilePath $command -ArgumentList $arguments -RedirectStandardError $errLog -Wait -PassThru -NoNewWindow
}
else {
$process = Start-Process -FilePath $command -ArgumentList $arguments -RedirectStandardError $errLog -PassThru -NoNewWindow
}
# If $process variable is null, something is wrong
if (!$process) {
Write-Error "ERROR command failed to start: $command $argumentsToLog"
return;
}
if ($waitForDependents) {
$ExitCode = $process.ExitCode
}
else {
# This will wait for the process to exit as Start-Process above will not block for the process to exit
$process.WaitForExit()
# There is a defect where the $process.ExitCode is empty.
# The full details is at https://stackoverflow.com/questions/10262231/obtaining-exitcode-using-start-process-and-waitforexit-instead-of-wait
# The below is the workaround for the defect
$process.HasExited # This will calculate the exitCode
$ExitCode = $process.GetType().GetField("exitCode", "NonPublic,Instance").GetValue($process) # Get the ExitCode from the hidden field but it is not publicly available
}
if ($ExitCode -ne 0) {
Write-Output "Error running: $command $argumentsToLog"
Write-Output "Exit code: $ExitCode"
Write-Output "**ERROR**"
Get-Content -Path $errLog
# if logfilepath is set, write that out too if the process exited
if ([System.String]::IsNullOrWhiteSpace($logfilepath) -ne $true -and [System.IO.File]::Exists($logfilepath) -eq $true) {
Write-Host "Logfile output from '$logfilepath':"
Get-Content $logfilepath
}
if ($checkForSuccess) {
throw "Exit code from process was nonzero"
}
else {
Write-Output "==Ignored the error"
}
}
}
<#
.DESCRIPTION
Gvfs clones the repository and checks out to the specified gitBranchName
#>
function GvfsCloneGitRepo {
Param(
[ValidateNotNullOrEmpty()] $gitExeLocation,
[ValidateNotNullOrEmpty()] $gvfsExeLocation,
[ValidateNotNullOrEmpty()] $gvfsRepoLocation,
[ValidateNotNullOrEmpty()] $gvfsLocalRepoLocation,
[string] $gitBranchName,
[string] $msiClientId
)
# pre-condition checks
if ($false -eq $gvfsRepoLocation.ToLowerInvariant().StartsWith("https://")) {
$errMsg = $("Error! The specified Gvfs repo url is not a valid HTTPS clone url : " + $gvfsRepoLocation)
Write-Host $errMsg
Throw $errMsg
}
if ($false -eq ($gvfsRepoLocation.Length -gt 8)) {
$errMsg = $("Error! The specified Git repo url is not valid : " + $gvfsRepoLocation)
Write-Host $errMsg
Throw $errMsg
}
$cmdArgs = $(" " + $gvfsRepoLocation + " `"" + $gvfsLocalRepoLocation + "`"")
# Known Issue: gvfs clone does not work with -b <branch> option.
# So, first gvfs clone without -b <branch> option
# then, next git checkout <branch>
Write-Host $("Gvfs cloning the git repo...")
# Limitation: gvfs clone doesn't take a -c parameter like git clone.
# So, the workaround is to configure and Unconfigure a custom credential.helper using "git config"
$prevCredentialHelper = &$gitExeLocation config --system credential.helper
# Configure credential.helper using "git config"
$GitAccessToken = Get-GitAccessToken -MsiClientID $msiClientId
$CredentialHelper = "`"!f() { test `"`$1`" = get && echo username=AzureManagedIdentity; echo password=$GitAccessToken; }; f`""
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "config" -gitCmdArgs "--system credential.helper $CredentialHelper" -argumentsToLog "--system credential.helper CUSTOM_AUTH_SCRIPT"
$runBlock = {
# gvfs clone
ExecuteGvfsCmd -gvfsExeLocation $gvfsExeLocation -gvfsCmd "clone" -gvfsCmdArgs $cmdArgs
}
RunWithRetries -runBlock $runBlock -retryAttempts 5 -waitBeforeRetrySeconds 30 -onFailureBlock {}
# Unconfigure credential.helper using "git config"
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "config" -gitCmdArgs "--system credential.helper $prevCredentialHelper"
}
function Get-CanUseManagedIdentityForRepo {
param(
[Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String] $RepoUrl
)
return ($RepoUrl -Match '^https://[a-zA-Z][\w\-_]*\.visualstudio\.com/.*' -or $RepoUrl -Match '^https://dev\.azure\.com/.*')
}
<#
.DESCRIPTION
Clones the repository and checks out to the specified CommitId
#>
function CloneGitRepo {
Param(
[ValidateNotNullOrEmpty()] $gitExeLocation,
[ValidateNotNullOrEmpty()] $gitRepoLocation,
[ValidateNotNullOrEmpty()] $gitLocalRepoLocation,
[string] $gitBranchName,
[Parameter(Mandatory = $false)] $optionalGitCloneArgs,
[Parameter(Mandatory = $false)] $formattedSparseCheckoutFolders,
[Parameter(Mandatory = $false)][string] $msiClientId
)
# pre-condition checks
if ($false -eq $gitRepoLocation.ToLowerInvariant().StartsWith("https://")) {
$errMsg = $("Error! The specified Git repo url is not a valid HTTPS clone url : " + $gitRepoLocation)
Write-Host $errMsg
Throw $errMsg
}
if ($false -eq ($gitRepoLocation.Length -gt 8)) {
$errMsg = $("Error! The specified Git repo url is not valid : " + $gitRepoLocation)
Write-Host $errMsg
Throw $errMsg
}
# Using specified credentials, create the actual repo url to clone from.
$authorizationHeader = ''
if (Get-CanUseManagedIdentityForRepo -RepoUrl $gitRepoLocation) {
$authorizationHeader = Get-GitAuthorizationHeader -MsiClientID $msiClientId
}
# Prep to start git.exe
# Add optional git clone parameters
$optionalArgs = ""
if (!([System.String]::IsNullOrWhiteSpace($optionalGitCloneArgs))) {
$optionalArgs = $optionalGitCloneArgs
}
if (![string]::IsNullOrEmpty($gitBranchName)) {
$optionalArgs = "-b $gitBranchName " + $optionalArgs
}
if (-not [string]::IsNullOrEmpty($formattedSparseCheckoutFolders)) {
# Clone the repo without checking out any files. Sparse checkout folders will be set after clone, and then checked out.
$optionalArgs = $optionalArgs + " --no-checkout"
}
$cmdArgs = $($optionalArgs + " " + $gitRepoLocation + " `"" + $gitLocalRepoLocation + "`"")
Write-Host $("Cloning the git repo...")
$runBlock = {
# Remove existing repo folder in case it was created by the previous clone attempt
if (Test-Path $gitLocalRepoLocation) {
Remove-Item $gitLocalRepoLocation -Recurse -Force
}
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "clone" -authHeader $authorizationHeader -gitCmdArgs $cmdArgs
}
RunWithRetries -runBlock $runBlock -retryAttempts 5 -waitBeforeRetrySeconds 30 -onFailureBlock {}
Write-Host Changing to repo location: $("'$gitLocalRepoLocation'")
Set-Location $gitLocalRepoLocation
# If sparse checkout, repo was cloned with --no-checkout option. Set folders desired for checkout, then check them out.
if (-not [string]::IsNullOrEmpty($formattedSparseCheckoutFolders)) {
$sparseGitCmd = "set $formattedSparseCheckoutFolders"
# Set sparse-checkout folders for checkout, then check them out
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "sparse-checkout" -authHeader $authorizationHeader -gitCmdArgs $sparseGitCmd -argumentsToLog $sparseGitCmd
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "checkout" -authHeader $authorizationHeader
}
}
<#
.DESCRIPTION
Updates the local repository to the commit ID specified
#>
function UpdateGitRepo {
param(
[ValidateNotNullOrEmpty()] $gitExeLocation,
[ValidateNotNullOrEmpty()] $gitRepoLocation,
[ValidateNotNullOrEmpty()] $gitLocalRepoLocation,
[string] $gitBranchName,
[string] $commitId,
[string] $optionalFetchArgs,
[string] $formattedSparseCheckoutFolders,
[Parameter(Mandatory = $false)][string] $msiClientId
)
# pre-condition checks
if ($false -eq $gitRepoLocation.ToLowerInvariant().StartsWith("https://")) {
$errMsg = $("Error! The specified Git repo url is not a valid HTTPS url : " + $gitRepoLocation)
Write-Error $errMsg
Throw $errMsg
}
if ($false -eq $gitRepoLocation.Length -gt 8) {
$errMsg = $("Error! The specified Git repo url is not valid : " + $gitRepoLocation)
Write-Error $errMsg
Throw $errMsg
}
# Using specified credentials, create the actual repo url to update
$authorizationHeader = ''
if (Get-CanUseManagedIdentityForRepo -RepoUrl $gitRepoLocation) {
$authorizationHeader = Get-GitAuthorizationHeader -MsiClientID $msiClientId
}
$baseRepoSparseCheckout = Invoke-Expression -Command '&$gitExeLocation config --get core.sparseCheckout'
if ([string]::IsNullOrEmpty($baseRepoSparseCheckout)) {
$baseRepoSparseCheckout = $false
}
$repoSparseCheckout = $false
if (-not [string]::IsNullOrEmpty($formattedSparseCheckoutFolders)) {
$repoSparseCheckout = $true
}
if ($repoSparseCheckout -ne $baseRepoSparseCheckout) {
Write-Host "Base image sparse checkout configuration: $baseRepoSparseCheckout"
Write-Host "Image sparse checkout configuration: $repoSparseCheckout"
throw "Sparse checkout configuration misaligned with base image"
}
$optionalArgs = ""
if (!([System.String]::IsNullOrWhiteSpace($optionalFetchArgs))) {
$optionalArgs = $optionalFetchArgs
}
# Explicitly specified branch takes precedence over commitId
if (![string]::IsNullOrEmpty($gitBranchName)) {
# Check out a temporary branch to be able to delete the requested one in case it is currently checked out
$tempBranch = (New-Guid).Guid
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "checkout" -authHeader $authorizationHeader -gitCmdArgs "-b $tempBranch"
# Delete local branch in case it already exists
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "branch" -gitCmdArgs "-D $gitBranchName" -checkForSuccess $false
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "fetch" -authHeader $authorizationHeader -gitCmdArgs "origin $($gitBranchName):$($gitBranchName) $optionalArgs"
# (Re)create the local branch
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "checkout" -authHeader $authorizationHeader -gitCmdArgs "$gitBranchName"
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "branch" -gitCmdArgs "-D $tempBranch"
}
elseif ($commitId -ne 'latest') {
Write-Host "Fetching commit $commitId"
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "fetch" -authHeader $authorizationHeader -gitCmdArgs "origin $commitId $optionalArgs"
# Reset command may need to reach out to ADO when GIT LFS is used
Write-Host "Resetting branch to $commitId"
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "reset" -authHeader $authorizationHeader -gitCmdArgs "$commitId --hard"
}
else {
Write-Host "Pulling the latest commit"
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "pull" -authHeader $authorizationHeader -gitCmdArgs $optionalArgs
}
$logExpression = '&$gitExeLocation log -1 --quiet --format=%H'
$updateCommitID = Invoke-Expression -Command $logExpression
Add-VarForLogging -varName 'CommitID' -varValue $updateCommitID
}
<#
.DESCRIPTION
Executes a git command with arguments
#>
function ExecuteGitCmd {
param(
[ValidateNotNullOrEmpty()][string] $gitExeLocation,
[ValidateNotNullOrEmpty()][string] $gitCmd,
[string] $gitCmdArgs,
[string] $authHeader = '',
[bool] $checkForSuccess = $true,
# If $gitCmdArgs contain secrets the caller is responsible for providing the alternative string to log
[string]$argumentsToLog = ''
)
if (!$argumentsToLog) {
$argumentsToLog = $gitCmdArgs
}
Write-Host $("Running: ""$gitExeLocation"" $gitCmd $argumentsToLog")
$arguments = "$($authHeader)$gitCmd $gitCmdArgs"
ProcessRunner -command $gitExeLocation -arguments $arguments -argumentsToLog "$gitCmd $argumentsToLog" -checkForSuccess $checkForSuccess
}
<#
.DESCRIPTION
Executes a gvfs command with arguments
#>
function ExecuteGvfsCmd {
param(
[ValidateNotNullOrEmpty()][string] $gvfsExeLocation,
[ValidateNotNullOrEmpty()][string] $gvfsCmd,
[string] $gvfsCmdArgs,
[bool] $checkForSuccess = $true,
# If $gitCmdArgs contain secrets the caller is responsible for providing the alternative string to log
[string]$argumentsToLog = ''
)
if (!$argumentsToLog) {
$argumentsToLog = $gvfsCmdArgs
}
Write-Host $("Running: ""$gvfsExeLocation"" $gvfsCmd $argumentsToLog")
$arguments = "$gvfsCmd $gvfsCmdArgs"
# gvfs clone creates a child process (gvfs.mount.exe) which never exits. gvfs.mount.exe exits only after a gvfs unmount which is done later (if needed).
# So, dont -Wait during Start-Process for gvfs clone
ProcessRunner -command $gvfsExeLocation -arguments $arguments -argumentsToLog "$gvfsCmd $argumentsToLog" -checkForSuccess $checkForSuccess -waitForDependents $false
}
# Applies configuration that doesn't require the repo to be cloned but may be needed for the clone to succeed, e.g. core.longpaths
function ConfigureGitRepoBeforeClone {
Param(
[ValidateNotNullOrEmpty()] $gitExeLocation
)
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "config" -gitCmdArgs "--system core.safecrlf true"
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "config" -gitCmdArgs "--system push.default simple"
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "config" -gitCmdArgs "--system core.preloadindex true"
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "config" -gitCmdArgs "--system core.fscache true"
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "config" -gitCmdArgs "--system core.longpaths true"
}
# Applies configuration that requires the repo to be cloned
function ConfigureGitRepoAfterClone {
Param(
[ValidateNotNullOrEmpty()] $gitExeLocation,
[ValidateNotNullOrEmpty()][string] $gitLocalRepoLocation,
[ValidateNotNullOrEmpty()] [bool] $enableGitCommitGraph
)
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "config" -gitCmdArgs "--system --add safe.directory $($gitLocalRepoLocation -replace '\\','/')"
if ($enableGitCommitGraph -eq $true) {
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "config" -gitCmdArgs "--local core.commitGraph true"
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "config" -gitCmdArgs "--local gc.writeCommitGraph true"
ExecuteGitCmd -gitExeLocation $gitExeLocation -gitCmd "commit-graph" -gitCmdArgs "write --reachable"
}
}
<#
.DESCRIPTION
Calls update of the targetDirectory is a valid repository. Else it will attempt to clone the repository.
#>
function UpdateOrCloneRepo {
param(
[ValidateNotNullOrEmpty()][string] $repoUrl,
[ValidateNotNullOrEmpty()][string] $targetDirectory,
[SourceControl]$sourceControl,
[ValidateNotNullOrEmpty()][string] $commitId,
[string] $gitBranchName,
[string] $optionalCloneArgs,
[bool] $cloneIfNotExists,
[string] $optionalFetchArgs,
[bool] $enableGitCommitGraph,
[string] $formattedSparseCheckoutFolders,
[string] $msiClientId
)
switch ($sourceControl) {
{ ($_ -eq [SourceControl]::git) -or ($_ -eq [SourceControl]::gvfs) } {
# Get git install location
$gitexe = Get-Command git
$GitExeLocation = $gitexe.Source
}
{ $_ -eq [SourceControl]::gvfs } {
# Get gvfs install location
$gvfsexe = Get-Command gvfs
$GvfsExeLocation = $gvfsexe.Source
}
}
## Update or Clone Repo
$shouldCloneRepo = $false
# We don't need to fully url-encode the repo url. However we should replace whitespaces with '%20'.
if ($repoUrl.Contains(" ")) {
$repoUrl = $repoUrl.Replace(" ", "%20")
}
# If the Folder exists
if (!(Test-Path -Path $targetDirectory -PathType Container)) {
if ($cloneIfNotExists -eq $true) {
$shouldCloneRepo = $true
}
else {
Write-Host "folder not found at '$targetDirectory'."
throw "folder not found."
}
}
else {
Set-Location $targetDirectory
switch ($sourceControl) {
git {
Write-Host "Testing if '$targetDirectory' hosts a git repository..."
# git remote will return an error if this is not a git repository
$repo_originUrl = &$GitExeLocation remote get-url origin
}
gvfs {
Write-Host "Testing if '$targetDirectory' hosts a gvfs repository..."
# gvfs status will return an error if this is not a gvfs repository
&$GvfsExeLocation status
if ($? -eq $true) {
# gvfs repository is always at "src" folder
Set-Location (Join-Path $targetDirectory "src")
# git remote will return an error if this is not a git repository
$repo_originUrl = &$GitExeLocation remote get-url origin
}
}
}
if ($? -eq $false) {
if ($cloneIfNotExists -eq $true) {
$shouldCloneRepo = $true
}
else {
Write-Host "repository not found at '$targetDirectory'."
throw "Repository not found."
}
}
}
# If for some reason one of the checks above fails, we need to clone the repo.
if ($shouldCloneRepo -eq $true) {
# folder doesn't exist, clone into the folder
ConfigureGitRepoBeforeClone -gitExeLocation $GitExeLocation
switch ($sourceControl) {
git {
CloneGitRepo -gitExeLocation $GitExeLocation -gitRepoLocation $repoUrl -gitLocalRepoLocation $targetDirectory -gitBranchName $gitBranchName -optionalGitCloneArgs $optionalCloneArgs -formattedSparseCheckoutFolders $formattedSparseCheckoutFolders -msiClientId $msiClientId
}
gvfs {
GvfsCloneGitRepo -gitExeLocation $GitExeLocation -gvfsExeLocation $GvfsExeLocation -gvfsRepoLocation $repoUrl -gvfsLocalRepoLocation $targetDirectory -gitBranchName $gitBranchName -msiClientId $msiClientId
# git repository is always at "src" folder
$targetDirectory = Join-Path $targetDirectory "src"
}
}
Write-Host Changing to repo location: $("'$targetDirectory'")
Set-Location $targetDirectory
# update repo_originUrl to the new location
$repo_originUrl = &$GitExeLocation remote get-url origin
ConfigureGitRepoAfterClone -gitExeLocation $GitExeLocation -gitLocalRepoLocation $targetDirectory -enableGitCommitGraph $enableGitCommitGraph
}
if ($shouldCloneRepo -and $commitId -eq 'latest') {
Write-Host "Skip pulling latest updates for just cloned repo: $repo_originUrl"
}
else {
Write-Host Updating repo with Url: $repo_originUrl
UpdateGitRepo -gitExeLocation $GitExeLocation -gitRepoLocation $repo_originUrl -gitLocalRepoLocation $targetDirectory -gitBranchName $gitBranchName -commitId $commitId -optionalFetchArgs $optionalFetchArgs -msiClientId $msiClientId
}
}
function Add-VarForLogging ($varName, $varValue) {
<#
.DESCRIPTION
Add a row to the logging array but only if the value is not null or whitespace
.PARAMETER varName
Name of the variable
.PARAMETER varValue
Value of the variable
#>
if (!([string]::IsNullOrWhiteSpace($varValue))) {
$global:varLogArray | Add-Member -MemberType NoteProperty -Name $varName -Value $varValue
}
}
function RunScriptSyncRepo(
$repoUrl,
$repository_TargetDirectory,
[SourceControl]$repository_SourceControl,
$repository_cloneIfNotExists = $false,
$repoName,
$commitId,
$branchName,
$repository_optionalCloningParameters,
$repository_optionalFetchParameters,
$enableGitCommitGraph,
$sparseCheckoutFolders,
$repository_MSIClientId
) {
$logfilepath = $null
$global:varLogArray = New-Object -TypeName "PSCustomObject"
Set-StrictMode -Version Latest
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls
# Track starting directory so we can reset it back at the end of the script
$startingDirectory = Get-Location
# Set Repo Log file path
$repoLogFilePath = 'c:\.tools\RepoLogs'
try {
# Create log file location
mkdir "$repoLogFilePath" -Force
switch ($repository_SourceControl) {
{ ($_ -eq [SourceControl]::git) -or ($_ -eq [SourceControl]::gvfs) } {
# Get git install location
$gitexe = Get-Command git
$GitExeLocation = $gitexe.Source
# confirm git is there
ProcessRunner -command $GitExeLocation -arguments "version"
if ($? -ne $true) {
Write-Error Unable to find git.exe.
exit 1
}
}
{ $_ -eq [SourceControl]::gvfs } {
# Get gvfs install location
$gvfsexe = Get-Command gvfs
$GvfsExeLocation = $gvfsexe.Source
# confirm gvfs is there
ProcessRunner -command $GvfsExeLocation -arguments "version"
if ($? -ne $true) {
Write-Error Unable to find gvfs.exe.
exit 1
}
}
}
Write-Host --------------------------------------
Write-Host "Repository name: '$repoName'"
Write-Host "Commit id: '$commitId'"
Write-Host "BranchName name: '$branchName'"
Write-Host --------------------------------------
# Add input data variables to log array
Add-VarForLogging -varName 'RepoURL' -varValue $repoUrl
Add-VarForLogging -varName 'repository_TargetDirectory' -varValue $repository_TargetDirectory
if (!([string]::IsNullOrWhiteSpace($branchName))) {
Write-Host "Use explicitly provided branch '$branchName' rather than commitId"
$commitId = 'latest'
}
if ([string]::IsNullOrWhiteSpace($repoUrl)) {
throw "RepoUrl must be known at this point"
}
$formattedSparseCheckoutFolders = ""
if (-not [string]::IsNullOrWhiteSpace($sparseCheckoutFolders)) {
$quotedFolders = $sparseCheckoutFolders -Split ',' | ForEach-Object { '"' + $_ + '"' }
$formattedSparseCheckoutFolders = $quotedFolders -Join " "
}
## Update or Clone repo
UpdateOrCloneRepo -repoUrl $repoUrl -commitId $commitId -gitBranchName $branchName -enableGitCommitGraph $enableGitCommitGraph -targetDirectory $repository_TargetDirectory -sourceControl $repository_SourceControl -optionalCloneArgs $repository_optionalCloningParameters -cloneIfNotExists $repository_cloneIfNotExists -optionalFetchArgs $repository_optionalFetchParameters -formattedSparseCheckoutFolders $formattedSparseCheckoutFolders -msiClientId $repository_MSIClientId
Write-Host "Var Log Array"
Write-Host $global:varLogArray | ConvertTo-Json
# Set the file name for logging repo sync variables
Write-Host "Derive Repo Log Name"
$repoLogFileName = [IO.Path]::GetFileName("$repository_TargetDirectory") + ".json"
# Write out file to output location
$outFile = "$repoLogFilePath\$repoLogFileName"
Write-Host "Write output file to " $outFile
$global:varLogArray | ConvertTo-Json | Out-File -FilePath $outFile
Write-Host Completed!
}
catch {
Write-Host -Object $_
Write-Host -Object $_.ScriptStackTrace
if (($null -ne $Error[0]) -and ($null -ne $Error[0].Exception) -and ($null -ne $Error[0].Exception.Message)) {
$errMsg = $Error[0].Exception.Message
Write-Host $errMsg
Write-Error $errMsg
}
if ([System.String]::IsNullOrWhiteSpace($logfilepath) -ne $true -and [System.IO.File]::Exists($logfilepath) -eq $true) {
Write-Host "Logfile output from '$logfilepath':"
Get-Content $logfilepath
}
Write-Host 'Script failed.'
Set-Location $startingDirectory
exit 1
}
Set-Location $startingDirectory
}
if ((-not (Test-Path variable:global:IsUnderTest)) -or (-not $global:IsUnderTest)) {
# If the optional parameter $repository_SourceControl is NOT passed in, default to git
[SourceControl]$sourceControl = [SourceControl]::git
# If the optional paramter $repository_SourceControl is passed in, ensure it has a valid value
if (-not [String]::IsNullOrEmpty($repository_SourceControl)) {
$sourceControl = [Enum]::Parse([SourceControl], $repository_SourceControl)
}
Import-Module -Force (Join-Path $(Split-Path -Parent $PSScriptRoot) '_common/windows-azure-managed-identity-utils.psm1')
Import-Module -Force (Join-Path $(Split-Path -Parent $PSScriptRoot) '_common/windows-retry-utils.psm1')
RunScriptSyncRepo `
-repoUrl $repoUrl `
-repository_TargetDirectory $repository_TargetDirectory `
-repository_SourceControl $sourceControl `
-repository_cloneIfNotExists $repository_cloneIfNotExists `
-repoName $repoName `
-commitId $commitId `
-branchName $branchName `
-repository_optionalCloningParameters $repository_optionalCloningParameters `
-repository_optionalFetchParameters $repository_optionalFetchParameters `
-enableGitCommitGraph $enableGitCommitGraph `
-sparseCheckoutFolders $sparseCheckoutFolders `
-repository_MSIClientId $repository_MSIClientId `
}