Ein lokales Repository für NuGet

 

Das Bereitstellen von Installationspaketen per NuGet ist schon ein echter Gewinn, allerdings muß man ständig online sein. Hier kann das Skript von Jon Galloway helfen, es kopiert das offizielle Repository auf die lokale Festplatte.

Was mir allerdings auffiel: die Konfiguration des Skriptes geschieht per Quelltextänderung. Unschön, wie ich finde. Und das gibt mir eine schöne Gelegenheit, mir einmal die Feinheiten der PowerShell anzuschauen.

Kommandozeilen-Parameter

Es ist ziemlich schwierig, alleine mit der PowerShell-Hilfe herauszubekommen wie man Parameter richtig an ein Skript übergibt bzw wie man sie dort ausliest. Zum Glück bin ich auf DevCentral fündig geworden: man gibt als erste Anweisung die bekannten Argumente an, wenn nötig mit ihren Default-Werten:

param(
[int] $top = 500, # use $top = 0 to grab all,
[string] $destination  
)

Unschön ist, daß das mit den Optionswerten, sogenannten Switches, nicht so einfach funktioniert. Der Schalter latest ist per Default true, allerdings kann man die Schalter nur setzen. Es hilft in dem Fall nur die Aussage des Schalters umzudrehen. Aus latest wurde deshalb hier notlatest.

 

Ternärer Operator

Der aus anderen Sprachen wie zB C++ bekannte ?-Operator wurde bei der PowerShell leider weggelassen. Man kann ihn aber leicht nachimplementieren, wie zB auf dieser Seite gezeigt:

function Invoke-Ternary ([bool]
$decider,[scriptblock]$iftrue,[scriptblock]$iffalse)
{
begin {}
process {
if ($decider) { &$iftrue} else { &$iffalse }
}
end {}
}
set-Alias ?: Invoke-Ternary

Das komplette Skript

Hinzu kamen noch die Ausgabe der aktuellen Einstellungen, sowie eine kleine Hilfeseite:

# the parameters when converting to funclet
param(
[switch] $help,
[switch] $notlatest,
[switch] $overwrite,
[int] $top = 500, # use $top = 0 to grab all,
[string] $destination  
)

# --- settings ---
$feedUrlBase = "http://go.microsoft.com/fwlink/?LinkID=206669"

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

# --- helpers ---
# ternary operator
function Invoke-Ternary ([bool]
$decider,[scriptblock]$iftrue,[scriptblock]$iffalse)
{
begin {}
process {
if ($decider) { &$iftrue} else { &$iffalse }
}
end {}
}
set-Alias ?: Invoke-Ternary

# download entries on a page, recursively called for page continuations
function DownloadEntries {
 param ([string]$feedUrl) 
 $feed = [xml]$webClient.DownloadString($feedUrl)
 $entries = $feed | select -ExpandProperty feed | select -ExpandProperty entry
 $progress = 0
             
 foreach ($entry in $entries) {
    $url = $entry.content.src
    $fileName = $entry.properties.id + "." + $entry.properties.version + ".nupkg"
    $saveFileName = join-path $destination $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
    $webClient.DownloadFile($url, $saveFileName)
  }
  $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 `
    $feedUrl = $link.href
    DownloadEntries $feedUrl
  }
}  

# 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")
}

if( $help ) {
    ""
    "-help               this help"
    "-notlatest          do not only pull latest version of package"
    "-overwrite          do overwrite if package already present"
    "-top [count]        Pull only <count> packages, pull all packages when count is 0"
    "-destination [path] Pull all packages to <path>. Default is ~/Documents/LocalNuGet"
    ""
    exit
}

# -- output current settings ---
""
"Current settings:"
"---------------------------------------------------"
?: ($notlatest) { "Do not take the latest packages" } { "Get the latest packages" }
?: ($overwrite) { "Overwrite existing packages" } { "Do not overwrite existing packages" }
?: ($top) { "The number of packages to pull is $top" } { "Pull all packages" }
if( !$destination ) { $destination = join-path ([Environment]::GetFolderPath("MyDocuments")) "LocalNuGet" }
"Destination directy: $destination"
""

# --- do the actual work ---
# if dest dir doesn't exist, create it
if (!(Test-Path -path $destination)) { New-Item $destination -type directory }
# set up feed URL
$serviceBase = GetPackageUrl($feedUrlBase)
$feedUrl = $serviceBase + "Packages"
if(-not $notlatest) {
    $feedUrl = $feedUrl + "?`$filter=IsLatestVersion eq true"
    if($top) {
        $feedUrl = $feedUrl + "&`$orderby=DownloadCount desc&`$top=$top"
    }
}
DownloadEntries $feedUrl

Nach dem Herunterladen der Pakete kann, wie an anderer Stelle bereits beschrieben, im Visual Studio per Tools, Options, Package Manager, Package Sources das lokale Repository eingetragen werden.

DotNetKicks-DE Image
Werbeanzeigen
Dieser Beitrag wurde unter NuGet, PowerShell veröffentlicht. Setze ein Lesezeichen auf den Permalink.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden /  Ändern )

Google Foto

Du kommentierst mit Deinem Google-Konto. Abmelden /  Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden /  Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden /  Ändern )

Verbinde mit %s