Andy
Andy

Reputation: 646

Trying to download a file from an Azure DevOps Git repo using Powershell

So I have a Git repo in Azure DevOps, with a URL like

https://[$server]/tfs/[$company]/[$project]/_git/[$repoName]

And I can get to individual files in that repo by appending to that something like this:

?path=/[$folder]/[$fileName]

I am trying to use Powershell to download a specific file from this repo to the corresponding location and filename on my computer, like this:

$sourcePath = "https://[$server]/tfs/[$company]/[$project]/_git/[$repoName]?path=/[$folder]/[$fileName]&download=true"
$filePath = "C:\Documents\[$folder]\[$fileName]"
Invoke-RestMethod -Uri $sourcePath -Method Get -Headers @{Authorization=("Basic {0}" -f [$AuthInfo])} -OutFile $filePath

What this is doing is instead of replacing the local file with the file from the repo, it is replacing the contents of the local file with the contents of the response body. I find it odd that all the googling I've been doing says to do it this way, even though the Microsoft article on Invoke-RestMethod actually explains that this is what -OutFile does.

Note I've also tried Invoke-WebRequest....same thing.

So how do I download the actual file from the repo to the local destination I want (or replace the contents of the local destination file with the contents of the repo file)?

In addition, is there a way to specify which branch to get the file from? Maybe I should be using Git powershell commands with this as well somehow? All the other googling I've done about downloading from a git repo comes up with results about GitHub.

Thank you!

Upvotes: 3

Views: 10746

Answers (2)

Dan Hoeger
Dan Hoeger

Reputation: 31

I needed to do this and what I saw here didn't work so I wrote my own:

param( 
    [Parameter(Mandatory=$true)] 
    [string] $GitFilePath,
    [Parameter(Mandatory=$true)] 
    [string] $OutFilePath,
    [Parameter(Mandatory=$true)] 
    [string] $RepoName,
    [string] $token,
    [string] $orgUrl,
    [string] $teamProject
)

if([String]::IsNullOrEmpty($token))
{
    if($env:SYSTEM_ACCESSTOKEN -eq $null)
    {
        Write-Error "you must either pass the -token parameter or use the BUILD_TOKEN environment variable"
        exit 1;
    }
    else
    {
        $token = $env:SYSTEM_ACCESSTOKEN;
    }
}


if([string]::IsNullOrEmpty($teamProject)){
    if($env:SYSTEM_TEAMPROJECT -eq $null)
    {
        Write-Error "you must either pass the -teampProject parameter or use the SYSTEM_TEAMPROJECT environment variable"
        exit 1;
    }
    else
    {
        $teamProject = $env:SYSTEM_TEAMPROJECT
    }
}

if([string]::IsNullOrEmpty($orgUrl)){
    if($env:SYSTEM_COLLECTIONURI -eq $null)
    {
        Write-Error "you must either pass the -orgUrl parameter or use the SYSTEM_COLLECTIONURI environment variable"
        exit 1;
    }
    else
    {
        $teamProject = $env:SYSTEM_COLLECTIONURI
    }
}

# Base64-encodes the Personal Access Token (PAT) appropriately  
$User='' 
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $User,$token)));  
$header = @{Authorization=("Basic {0}" -f $base64AuthInfo)};  
#---------------------------------------------------------------------- 

Write-Host "Download file" $GitFilePath "to" $OutFilePath
     
$uriGetFile = "$orgUrl/$teamProject/_apis/git/repositories/$repoName/items?scopePath=$GitFilePath&download=true&api-version=6.1-preview.1"
    
Write-Host "Url:" $uriGetFile
    
$filecontent = Invoke-RestMethod -ContentType "application/json" -UseBasicParsing -Headers $header -Uri $uriGetFile
$filecontent | Out-File -Encoding utf8 $OutFilePath

Upvotes: 0

Shamrai Aleksander
Shamrai Aleksander

Reputation: 16058

Use the rest api with the following template:

GET https://{tfs_url}/{collection_name}/{project}/_apis/git/repositories/{repositoryId}/items?path={path}

Check the documentation: Items - Get, Example - Download

I use the following code to copy files (with System.Net.WebClient) in build pipelines:

$user = ""
$token = $env:SYSTEM_ACCESSTOKEN
$teamProject = $env:SYSTEM_TEAMPROJECT
$orgUrl = $env:SYSTEM_COLLECTIONURI
$repoName = "REPO_NAME"

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))

    function InvokeGetFileRequest ($GitFilePath, $OutFilePath)
    {
        Write-Host "Download file" $GitFilePath "to" $OutFilePath
     
        $uriGetFile = "$orgUrl/$teamProject/_apis/git/repositories/$repoName/items?scopePath=$GitFilePath&download=true&api-version=6.1-preview.1"
    
       Write-Host "Url:" $uriGetFile
    
        $wc = New-Object System.Net.WebClient
        $wc.Headers["Authorization"] = "Basic {0}" -f $base64AuthInfo
        $wc.Headers["Content-Type"] = "application/json";
        $wc.DownloadFile($uriGetFile, $OutFilePath)
    }

Upvotes: 3

Related Questions