api - Azure DevOps API : Get all files (source and target) of Pull Request

标签 api azure-devops pull-request

我搜索了很多,在这里找到了几个线程(例如 thisthat 等),但我找不到以下任务的答案: 使用 Azure DevOps API 检索特定 PR 的所有文件的内容更改(基本上是之前和之后的文件)。

我可以找到一个 PR,可以循环更改、迭代、提交(以各种组合),但我无法下载每个文件的第一个和最后一个版本(应该有一种方法因为我可以在 DevOps 的 PR 中查看之前和之后的情况)。

任何提示我可以在哪里/如何检索某个提交/更改/迭代的文件的两个版本?

非常感谢!

干杯, 乌多

最佳答案

感谢所有的提示。看来我找到了一个笏来拉它。请随时纠正我的方法。

这是完整的 PowerShell 文件:

[CmdletBinding()]
param (
    [int]
    $pullRequestId,
    [string]
    $repoName
)

# --- your own values ---
$pat = 'your-personal access token for Azure DevOps'
$urlOrganization = 'your Azure DevOps organization'
$urlProject = 'your Azure DevOps project'
$basePath = "$($env:TEMP)/pullRequest/" # a location to store all the data
# --- your own values ---

if (!$repoName)
{
    $userInput = Read-Host "Please enter the repository name"
    if (!$userInput)
    {
        Write-Error "No repository name given."
        exit
    }
    $repoName = $userInput
}

if (!$pullRequestId)
{
    $userInput = Read-Host "Please enter the PullRequest ID for $($repoName)"
    if (!$userInput)
    {
        Write-Error "No PullRequest ID given."
        exit
    }
    $pullRequestId = $userInput
}

$prPath = "$($basePath)$($pullRequestId)"
$sourcePath = "$($basePath)$($pullRequestId)/before"
$targetPath = "$($basePath)$($pullRequestId)/after"

# --- helper methods ---
function CleanLocation([string]$toBeCreated)
{
    RemoveLocation $toBeCreated
    CreateLocation $toBeCreated
    if (!(Test-Path $toBeCreated))
    {
        Write-Error "Path '$toBeCreated' could not be created"
    }
}

function CreateLocation([string]$toBeCreated)
{
    if (!(Test-Path $toBeCreated)) { New-Item -ErrorAction Ignore -ItemType directory -Path $toBeCreated > $null }
}

function RemoveLocation([string]$toBeDeleted)
{
    if (Test-Path $toBeDeleted) { Remove-Item -Path $toBeDeleted -Recurse -Force }
}

function DeleteFile([string]$toBeDeleted)
{
    if (Test-Path $toBeDeleted) { Remove-Item -Path $toBeDeleted -Force }
}
# --- helper methods ---

# --- Azure DevOps helper methods ---
function GetFromDevOps($url)
{
    $patToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($pat)"))
    $repoHeader = @{ "Authorization" = "Basic $patToken" }
    $response = $(Invoke-WebRequest $url -Headers $repoHeader)
    if ($response.StatusCode -ne 200)
    {
        Write-Error "FAILED: $($response.StatusDescription)"
    }
    return $response
}

function JsonFromDevOps($url)
{
    $response = GetFromDevOps $url
    return ConvertFrom-Json -InputObject $response.Content
}

function DownloadFromDevOps($url, $filename)
{
    $patToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($pat)"))
    $repoHeader = @{ "Authorization" = "Basic $patToken" }
    $ProgressPreference = 'SilentlyContinue'
    Invoke-WebRequest $url -Headers $repoHeader -OutFile $filename
    $ProgressPreference = 'Continue'
}

function DownloadAndSaveFile($itemUrl, $outputPath, $path, $overwrite)
{
    $outFile = "$outputPath$($path)"
    $fileExists = Test-Path $outFile
    if (!$fileExists -or $overwrite)
    {
        $outPath = [System.IO.Path]::GetDirectoryName($outFile)
        CreateLocation $outPath
        if ($fileExists)
        {
            Write-Host "    overwriting to $outputPath"
        }
        else
        {
            Write-Host "    downloading to $outputPath"
        }
        DownloadFromDevOps $itemUrl $outFile
    }
}

function DownloadFiles($changes, $beforePath, $beforeCommitId, $afterPath, $afterCommitId)
{
    foreach ($change in $changes)
    {
        $item = $change.item

        if ($item.isFolder)
        {
            continue;
        }
        $path = $item.path
        $originalPath = $change.originalPath
        if (!$path)
        {
            $path = $change.originalPath
        }
        $displayPath = $path ?? $originalPath
        $changeType = $change.changeType
        Write-Host "[$($changeType)] $($displayPath)"
        if (($changeType -eq "edit, rename"))
        {
            $itemUrl = "$($urlRepository)/items?path=$($originalPath)&versionDescriptor.version=$($beforeCommitId)&versionDescriptor.versionOptions=0&versionDescriptor.versionType=2&download=true"
            DownloadAndSaveFile $itemUrl $beforePath $originalPath
        }
        # just get the source/before version
        if ($changeType -eq "delete")
        {
            $itemUrl = "$($urlRepository)/items?path=$($originalPath)&versionDescriptor.version=$($beforeCommitId)&versionDescriptor.versionOptions=0&versionDescriptor.versionType=2&download=true"
            DownloadAndSaveFile $itemUrl $beforePath $originalPath
            DeleteFile "$($afterPath)$($originalPath)"
        }
        if ($changeType -eq "edit")
        {
            $itemUrl = "$($urlRepository)/items?path=$($path)&versionDescriptor.version=$($beforeCommitId)&versionDescriptor.versionOptions=0&versionDescriptor.versionType=2&download=true"
            DownloadAndSaveFile $itemUrl $beforePath $path
        }
        if (($changeType -eq "add") -or ($changeType -eq "edit") -or ($changeType -eq "edit, rename"))
        {
            $itemUrl = "$($urlRepository)/items?path=$($path)&versionDescriptor.version=$($afterCommitId)&versionDescriptor.versionOptions=0&versionDescriptor.versionType=2&download=true"
            DownloadAndSaveFile $itemUrl $afterPath $path $true
        }
        $validChangeTypes = @('add', 'delete', 'edit', 'edit, rename')
        if (!($validChangeTypes.Contains($changeType)))
        {
            Write-Warning "Unknown change type $($changeType)"
        }
    }
}
# --- Azure DevOps helper methods ---

$urlBase = "https://dev.azure.com/$($urlOrganization)/$($urlProject)/_apis"
$urlRepository = "$($urlBase)/git/repositories/$($repoName)"
$urlPullRequests = "$($urlRepository)/pullRequests"
$urlPullRequest = "$($urlPullRequests)/$($pullRequestId)"
$urlIterations = "$($urlPullRequest)/iterations"

CleanLocation $prPath

$iterations = JsonFromDevOps $urlIterations
foreach ($iteration in $iterations.value)
{
    # the modified file
    $srcId = $iteration.sourceRefCommit.commitId
    # the original file
    $comId = $iteration.commonRefCommit.commitId
    $comId = $iteration.targetRefCommit.commitId

    $urlIterationChanges = "$($urlIterations)/$($iteration.id)/changes"
    $iterationChanges = JsonFromDevOps $urlIterationChanges

    DownloadFiles $iterationChanges.changeEntries $sourcePath $comId $targetPath $srcId
}

关于api - Azure DevOps API : Get all files (source and target) of Pull Request,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70154223/

相关文章:

python - 如何将 Trello 上传并图像到 Trello,但不将其设置为封面(这是默认设置)

javascript - 当我获取 wikipedia api 时得到错误的响应

python - 从 JSON 中提取数据并使用 python 进行迭代

json - 使用 Azure Devops 部署 Azure 策略 ARM 模板失败

ios - 平台 "android"似乎不是有效的 cordova 平台。它缺少 API.js。安卓不支持

git - 如何在 Github 中将单独的 pull 请求与 "stacking"相互叠加?

ruby-on-rails - 使用 Rails 和 HTTParty 将 JSON 发布到 API

kubernetes - 在 VSTS 中取消发布(取消部署)应用程序?

git - pull 请求完成后更改工单状态

git - 如何使用提交消息关闭 GitHub pull 请求?