从私有 NuGet feed 下载所有软件包

5
我想从我的私有NuGet源中下载所有版本的所有软件包。我可以使用PowerShell、Bash或其他包管理器,没有任何问题。
我不能使用一个占位符项目来引用所有软件包并复制我的缓存,因为我需要所有版本。
你有什么想法吗?
我正在使用私有的NuGet源。该源有点故障,但不在我手上修复。所以我必须这样做...

这个私有 feed 是如何实现的?如果是文件共享,你可以简单地复制文件夹内容。即使 NuGet feed 作为服务实现,也通常会将包存储在文件夹中。 - Panagiotis Kanavos
我只有IP和凭据,如何访问文件夹?实际上不知道背后是什么 - 这就是问题所在。我想可能会有一个很酷的命令或一些PowerShell脚本的可能性。 - Peter
有一些链接/工具,但其中一些看起来比较老旧。https://www.nuget.org/packages/Nuget.Downloader https://gist.github.com/bevand/e5325035a31c281f4532e330005216cc#file-ps-download-all-nuget-packages - lastr2d2
感谢,我会去查看的。 - Peter
4个回答

10

我在这里创建了一个更好的PowerShell,可以下载所有版本的所有包

Find-Package -AllVersions -Source NuGet-Source | ForEach-Object {
   Install-Package -Name $_.Name -MaximumVersion $_.Version -Destination 'C:\Temp\Nuget\' -Source NuGet-Source -SkipDependencies
}

你如何安装所有版本? “无法安装,有多个匹配的软件包。请指定一个确切的-Name和-RequiredVersion。” - Enrico
它已经在Find-Package中迭代了所有版本,因此结果应该是安装的所有软件包版本。 - Sergey Nikitin

4

以下是我采取的措施,因为这些解决方案对我没有用。 我正在尝试将TFS 2017 feed迁移到Azure DevOps托管的feed。

首先,在Powershell ISE中使用以下脚本下载来自本地自托管feed的所有软件包:

# --- settings ---
# use nuget v2 feed for this script
# v2 feed is sometimes same url as v3, just change /v3/index.json to /v2/ 
$feedUrlBase = "http://servername:8080/tfs/MOMCollection/_packaging/bbd0bd78-205f-48af-ac25-6eef6470adb4/nuget/v2/"  # be sure to include trailing slash 
# the rest will be params when converting to funclet
$latest = $false
$overwrite = $true
$top = $null #use $top = $null to grab all , otherwise use number
$destinationDirectory = join-path ([Environment]::GetFolderPath("MyDocuments")) "NuGetLocal"

# --- locals ---
$webClient = New-Object System.Net.WebClient

# following is required if authenticating to TFS using integrated credentials
$webClient.UseDefaultCredentials=$true


# --- functions ---

# download entries on a page, recursively called for page continuations
function DownloadEntries {
 param ([string]$feedUrl) 
 $feed = [xml]$webClient.DownloadString($feedUrl)
 $entries = $feed.feed.entry 
 $progress = 0
            
 foreach ($entry in $entries) {
    $url = $entry.content.src
    $fileName = $entry.properties.id + "." + $entry.properties.version + ".nupkg"
    $saveFileName = join-path $destinationDirectory $fileName
    $pagepercent = ((++$progress)/$entries.Length*100)
    if ((-not $overwrite) -and (Test-Path -path $saveFileName)) 
    {
        write-progress -activity "$fileName already downloaded" `
                       -status "$pagepercent% of current page complete" `
                       -percentcomplete $pagepercent
        continue
    }
    write-progress -activity "Downloading $fileName" `
                   -status "$pagepercent% of current page complete" `
                   -percentcomplete $pagepercent

    [int]$trials = 0
    do {
        try {
            $trials +=1
            $webClient.DownloadFile($url, $saveFileName)
            break
        } catch [System.Net.WebException] {
            write-host "Problem downloading $url `tTrial $trials `
                       `n`tException: " $_.Exception.Message
        }
    }
    while ($trials -lt 3)
  }

  $link = $feed.feed.link | where { $_.rel.startsWith("next") } | select href
  if ($link -ne $null) {
    # if using a paged url with a $skiptoken like 
    # http:// ... /Packages?$skiptoken='EnyimMemcached-log4net','2.7'
    # remember that you need to escape the $ in powershell with `
    return $link.href
  }
  return $null
}  

# the NuGet feed uses a fwlink which redirects
# using this to follow the redirect
function GetPackageUrl {
 param ([string]$feedUrlBase) 
 $resp = [xml]$webClient.DownloadString($feedUrlBase)
 return $resp.service.GetAttribute("xml:base")
}

# --- do the actual work ---

# if dest dir doesn't exist, create it
if (!(Test-Path -path $destinationDirectory)) { 
    New-Item $destinationDirectory -type directory 
}

# set up feed URL
$serviceBase = $feedUrlBase
$feedUrl = $serviceBase + "Packages"
if($latest) {
    $feedUrl = $feedUrl + "?`$filter=IsLatestVersion eq true"
    if($top -ne $null) {
        $feedUrl = $feedUrl + "&`$orderby=DownloadCount desc&`$top=$top"
    }
}

while($feedUrl -ne $null) {
    $feedUrl = DownloadEntries $feedUrl
}

接下来,我验证了每个包的每个版本都以 .nupkg 格式下载,并且它们已经下载完成。然后,我使用 PowerShell 将其上传到新的源:

$destinationDirectory = join-path ([Environment]::GetFolderPath("MyDocuments")) "NuGetLocal"

Get-ChildItem $destinationDirectory -Recurse -Filter *.nupkg | 
Foreach-Object {
    nuget push -Source "YOUR NUGEFEED NAME HERE" -ApiKey az $_.FullName
}

我希望这篇文章能够帮助那些正在进行NuGet源迁移的人。

1
顺便说一下,我不必在结尾处放置 vN,只需以 nuget 结束即可,因为该 URL 在我的 Nuget 包管理器中列出,并且似乎可以工作。值得注意的是,它保存到 join-path ([Environment]::GetFolderPath("MyDocuments")) "NuGetLocal",而不是本地路径,在你复制并粘贴代码后发现什么都没有发生之后,这是显而易见的,然后再仔细阅读代码。 (还不要在未阅读代码的情况下复制并粘贴 PowerShell)。但是,哇,太棒了;谢谢! - ruffin
1
可能默认情况下你的nuget路径已经是v2了,但我尝试了v3,在许多地方都遇到了脚本失败的问题,所以在注释中指出,如果有任何问题,请确保指定v2。很高兴帮忙,我从不同的位置借鉴了不同的脚本片段,更多的话ChatGPT可能只需编写它,但这是一个很好的选项来迁移feeds,因为没有太多的工具可以历史性地抓取每个单独的包并将其移动到新的feed中。 - Kyle Burkett

4

使用PowerShell,您可以实现以下操作:

>Find-Package -Name='Package_Name'  -AllVersions -Source Local | Install-Package -Destination 'C:\SOME_PATH'

该命令将在源Local(必须在NuGet.config中指定)中查找所有名称类似于“Package_Name”的软件包版本,并将它们安装到“C:\SOME_PATH”文件夹中。如果要从该源获取所有软件包,请删除-Name参数。
然后,您可以从各自的文件夹中获取每个.nupkg文件。

请为以下参数提供值: Name[0]: " - Enrico

1
如果您只想下载,那么save-package比install-package更合适。
此脚本将从NuGet服务器(NuGet-Source)保存所有NuGet软件包到当前目录中。
Find-Package -AllVersions -Source NuGet-Source | ForEach-Object {
  Save-Package -Name $_.Name -RequiredVersion $_.Version -Source NuGet-Source -Path '.'
}

你是怎么让它工作的?我一直收到“查询url.index.json无效”的错误信息。 - Enrico
很久没看过这个了,也没有碰它。检查一下管道的第一个位是否正常工作。'Find-Package -AllVersions -Source NuGet-Source`我怀疑你的 'NugGet-Source' 是不正确的。 - Thomas Hallam
出于某些原因,我必须使用v2 API。 - Enrico

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接