Skip to content

Instantly share code, notes, and snippets.

@rfennell
Created April 20, 2018 12:19
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save rfennell/dc9e49a40d98d77c26698574d298dc53 to your computer and use it in GitHub Desktop.
Save rfennell/dc9e49a40d98d77c26698574d298dc53 to your computer and use it in GitHub Desktop.
param
(
[Parameter(Mandatory = $true)]
[string]$pat,
[Parameter(Mandatory = $true)]
[string]$instance,
[Parameter(Mandatory = $true)]
[string]$backuppath
)
function Get-WebClient
{
param
(
[string]$pat,
[string]$contentType = "application/json"
)
$wc = New-Object System.Net.WebClient
$wc.Headers["Content-Type"] = $contentType
$pair = ":${pat}"
$bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
$base64 = [System.Convert]::ToBase64String($bytes)
$wc.Headers.Add("Authorization","Basic $base64");
$wc
}
function Get-AuthenticatedGitUri
{
param
(
$uri,
$token
)
$colonSlashSlash = "://";
$protocol = $uri.substring(0, $uri.indexOf($colonSlashSlash))
$address = $uri.substring($uri.indexOf($colonSlashSlash) + $colonSlashSlash.length)
return $protocol + $colonSlashSlash + $token + "@" + $address
}
function Get-TeamProjectList
{
param
(
$tfsUri ,
$pat
)
write-host "Getting team project details for $tfsUri " -ForegroundColor Green
$wc = Get-WebClient -pat $pat
$uri = "$($tfsUri)/_apis/projects?api-version=1.0"
$jsondata = $wc.DownloadString($uri) | ConvertFrom-Json
$jsondata.value | select-object -property @{Name="Name"; Expression = {$_.name}}
}
function Get-GitRepo
{
param
(
$name,
$uri,
$backuppath,
$pat
)
write-host "Cloning Git Repo $name into $backuppath"
Set-Location -Path $backuppath
$fixeduri = Get-AuthenticatedGitUri -uri $uri -token $pat
# Git send info to stderr it should not, redirecting it
& git clone $fixeduri 2>&1 | % { $_.ToString() }
}
function Get-TfvcContent
{
param
(
$instance ,
$pat,
$projectname,
$backuppath
)
Write-Host " Downloading TFVC ZIP for project $projectname"
$url = "https://$instance.visualstudio.com/$projectname/_apis/tfvc/Items?path=%24%2F$projectname&versionDescriptor%5BversionType%5D=5&%24format=zip&api-version=4.1-preview.1"
$file = "$backuppath\TFVC-$projectname.zip"
$wc = Get-WebClient -pat $pat
try
{
$wc.DownloadFile($url,$file)
Write-Host " Finished TFVC content download"
} catch
{
Write-Host " No TFVC content for project"
}
}
function Get-GitBranchesForRepo
{
param
(
$instance ,
$pat,
$projectname,
$repo
)
Write-Host " Getting branches repo $repo in project $projectname"
$url = "https://$instance.visualstudio.com/$projectname/_apis/git/repositories/$repo/stats/branches?api-version=4.1"
try
{
$wc = Get-WebClient -pat $pat
$jsondata = $wc.DownloadString($url) | ConvertFrom-Json
$jsondata.value | select-object -property @{Name="Name"; Expression = {$_.name}}
} catch
{
Write-Host " No Repos for project"
}
}
function Get-GitContent
{
param
(
$instance ,
$pat,
$projectname,
$repo,
$backuppath,
$branch
)
Write-Host " Downloading GIT ZIP for branch $branch in repo $repo in project $projectname"
# A branch name may have a / in it which is not a valid file name
$fixedbranch = $branch -replace "/", "-"
$url = "https://$instance.visualstudio.com/$projectname/_apis/git/repositories/$repo/Items?path=%2F&versionDescriptor%5BversionOptions%5D=0&versionDescriptor%5BversionType%5D=0&versionDescriptor%5Bversion%5D=$branch&%24format=zip&api-version=4.1-preview.1"
$file = "$backuppath\GIT-$projectname-$repo-$fixedbranch.zip"
$wc = Get-WebClient -pat $pat
$wc.DownloadFile($url,$file)
Write-Host " Finished GIT content download"
}
function Git-GetRepos
{
param
(
$instance,
$pat,
$projectname
)
$url = "https://$instance.visualstudio.com/$projectname/_apis/git/repositories?api-version=4.1"
$wc = Get-WebClient -pat $pat
$jsondata = $wc.DownloadString($url) | ConvertFrom-Json
$jsondata.value | select-object -property @{Name="Name"; Expression = {$_.name}},@{Name="RemoteUrl"; Expression = {$_.remoteUrl}}
}
function Add-Folder
{
param
(
$path
)
if ((Test-Path($path)) -eq $false)
{
Write-Host " Creating folder $path"
New-Item -ItemType directory -Path $path -force | Out-Null
} else
{
Write-Host " Cleaning folder $path"
Remove-Item "$path" -Force -Recurse
}
}
$projects = Get-TeamProjectList -pat $pat -tfsUri "https://$instance.visualstudio.com"
$instancepath = Join-Path -Path $backuppath -ChildPath $instance
Add-Folder -path $instancepath
foreach ($project in $projects)
{
$name = $project.Name
Write-Host "Procesing project $name" -ForegroundColor Green
$projectpath = Join-Path -Path $instancepath -ChildPath $name
Add-Folder -path $projectpath
$repos = Git-GetRepos -instance $instance -pat $pat -projectname $name
if ($repos.count -eq 0)
{
Write-Host " No GIT content for project"
} else
{
foreach ($repo in $repos)
{
Get-GitRepo -name $repo.Name -uri $repo.remoteurl -backuppath $projectpath -pat $pat
# If you wish to get the repo's as simple ZIPs
# $branches = Get-GitBranchesForRepo -instance $instance -pat $pat -projectname $name -repo $repo.Name
# foreach ($branch in $branches)
# {
# Get-GitContent -instance $instance -pat $pat -projectname $name -path $projectpath -repo $repo.Name -branch $branch.Name
# }
}
}
Get-TfvcContent -instance $instance -pat $pat -projectname $name -path $projectpath
}
Write-Host "`n"
@HoLengZai
Copy link

Line 232, it should be -backuppath instead of -path
Otherwise Get-TfvcContent and Get-GitRepo will get an issue to save the backup.

With the new rebranding to Azure DevOPS... all URL should be changed with this syntax:
Replace All
"https://$instance.visualstudio.com"
By
"https://dev.azure.com/$instance"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment