Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Local paket.exe cache #1400

Merged
merged 10 commits into from
Jan 19, 2016
8 changes: 6 additions & 2 deletions docs/content/bootstrapper.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# paket.bootstrapper.exe

Downloads the latest stable paket.exe from github.com. If the download from github.com fails it tries to download the version from nuget.org instead.
Downloads the latest stable paket.exe. By default, the bootstrapper caches downloaded versions of paket.exe for the current user across all projects. If the requested version is not present in the cache, it is downloaded from github.com. If the download from github.com fails it tries to download the version from nuget.org instead.

Cached paket.exe versions are removed when the NuGet cache folder is [cleared](paket-clear-cache.html).

`Ctrl+C` interrupts the download process. The return value of the bootstrapper is 0 when a paket.exe already exists, so that any subsequent scripts can continue.

[lang=batchfile]
$ paket.bootstrapper.exe [prerelease|version] [--prefer-nuget] [--self] [-s]
$ paket.bootstrapper.exe [prerelease|version] [--prefer-nuget] [--self] [-s] [-f]

Options:

Expand All @@ -23,6 +25,8 @@ Options:

`-s`: If this flag is set the bootstrapper will not perform any output.

`-f`: Forces the bootstrapper to ignore any cached paket.exe versions and go directly to github.com or nuget.org based on other flags.

Environment Variables:

`PAKET.VERSION`: The requested version can also be set using this environment variable. Above options take precedence over the environment variable
Expand Down
111 changes: 111 additions & 0 deletions src/Paket.Bootstrapper/CacheDownloadStrategy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
using System;
using System.IO;
using System.Linq;
using System.Net;

namespace Paket.Bootstrapper
{
internal class CacheDownloadStrategy : IDownloadStrategy
{
public string Name { get { return "Cache"; } }

private readonly string _paketCacheDir =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "NuGet", "Cache", "Paket");

private IDownloadStrategy _fallbackStrategy;
public IDownloadStrategy FallbackStrategy
{
get
{
return _fallbackStrategy;
}
set
{
if (value == null)
throw new ArgumentException("CacheDownloadStrategy needs a non-null FallbackStrategy");
_fallbackStrategy = value;
}
}

public CacheDownloadStrategy(IDownloadStrategy fallbackStrategy)
{
FallbackStrategy = fallbackStrategy;
}

public string GetLatestVersion(bool ignorePrerelease, bool silent)
{
try
{
return FallbackStrategy.GetLatestVersion(ignorePrerelease, silent);
}
catch (WebException)
{
if (FallbackStrategy.FallbackStrategy != null)
{
FallbackStrategy = FallbackStrategy.FallbackStrategy;
return GetLatestVersion(ignorePrerelease, silent);
}

var latestVersion = GetLatestVersionInCache(ignorePrerelease);

if (!silent)
Console.WriteLine("Unable to look up the latest version online, the cache contains version {0}.", latestVersion);

return latestVersion;
}
}

public void DownloadVersion(string latestVersion, string target, bool silent)
{
var cached = Path.Combine(_paketCacheDir, latestVersion, "paket.exe");

if (!File.Exists(cached))
{
if (!silent)
Console.WriteLine("Version {0} not found in cache.", latestVersion);

FallbackStrategy.DownloadVersion(latestVersion, target, silent);
Directory.CreateDirectory(Path.GetDirectoryName(cached));
File.Copy(target, cached);
}
else
{
if (!silent)
Console.WriteLine("Copying version {0} from cache.", latestVersion);

File.Copy(cached, target, true);
}
}

public void SelfUpdate(string latestVersion, bool silent)
{
FallbackStrategy.SelfUpdate(latestVersion, silent);
}

private string GetLatestVersionInCache(bool ignorePrerelease)
{
Directory.CreateDirectory(_paketCacheDir);
var zero = new SemVer();

return Directory.GetDirectories(_paketCacheDir)
.Select(Path.GetFileName)
.OrderByDescending(x =>
{
try
{
var version = SemVer.Create(x);

if (ignorePrerelease && version.PreRelease != null)
return zero;
else
return version;
}
catch (Exception)
{
return zero;
}
})
.FirstOrDefault() ?? "0";
}
}
}
4 changes: 3 additions & 1 deletion src/Paket.Bootstrapper/DownloadArguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ internal class DownloadArguments
public bool DoSelfUpdate { get; set; }
public string LatestVersion { get; private set; }
public bool IgnorePrerelease { get; private set; }
public bool IgnoreCache { get; private set; }

public DownloadArguments(string latestVersion, bool ignorePrerelease, string folder, string target, bool doSelfUpdate, string nugetSource)
public DownloadArguments(string latestVersion, bool ignorePrerelease, string folder, string target, bool doSelfUpdate, string nugetSource, bool ignoreCache)
{
LatestVersion = latestVersion;
IgnorePrerelease = ignorePrerelease;
Folder = folder;
Target = target;
DoSelfUpdate = doSelfUpdate;
NugetSource = nugetSource;
IgnoreCache = ignoreCache;
}
}
}
2 changes: 1 addition & 1 deletion src/Paket.Bootstrapper/GitHubDownloadStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public GitHubDownloadStrategy(PrepareWebClientDelegate prepareWebClient, Prepare
GetDefaultWebProxyFor = getDefaultWebProxyFor;
}

public string GetLatestVersion(bool ignorePrerelease)
public string GetLatestVersion(bool ignorePrerelease, bool silent)
{
using (var client = new WebClient())
{
Expand Down
2 changes: 1 addition & 1 deletion src/Paket.Bootstrapper/IDownloadStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ internal interface IDownloadStrategy
{
string Name { get; }
IDownloadStrategy FallbackStrategy { get; set; }
string GetLatestVersion(bool ignorePrerelease);
string GetLatestVersion(bool ignorePrerelease, bool silent);
void DownloadVersion(string latestVersion, string target, bool silent);
void SelfUpdate(string latestVersion, bool silent);
}
Expand Down
6 changes: 3 additions & 3 deletions src/Paket.Bootstrapper/NugetDownloadStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public string Name

public IDownloadStrategy FallbackStrategy { get; set; }

public string GetLatestVersion(bool ignorePrerelease)
public string GetLatestVersion(bool ignorePrerelease, bool silent)
{
if (Directory.Exists(NugetSource))
{
Expand Down Expand Up @@ -130,7 +130,7 @@ public void DownloadVersion(string latestVersion, string target, bool silent)

if (Directory.Exists(NugetSource))
{
if (String.IsNullOrWhiteSpace(latestVersion)) latestVersion = this.GetLatestVersion(false);
if (String.IsNullOrWhiteSpace(latestVersion)) latestVersion = this.GetLatestVersion(false, silent);
var sourcePath = Path.Combine(NugetSource, String.Format(paketNupkgFileTemplate, latestVersion));

if (!silent)
Expand Down Expand Up @@ -185,7 +185,7 @@ public void SelfUpdate(string latestVersion, bool silent)

if (Directory.Exists(NugetSource))
{
if (String.IsNullOrWhiteSpace(latestVersion)) latestVersion = this.GetLatestVersion(false);
if (String.IsNullOrWhiteSpace(latestVersion)) latestVersion = this.GetLatestVersion(false, silent);
var sourcePath = Path.Combine(NugetSource, String.Format(paketNupkgFileTemplate, latestVersion));

if (!silent)
Expand Down
1 change: 1 addition & 0 deletions src/Paket.Bootstrapper/Paket.Bootstrapper.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="BootstrapperHelper.cs" />
<Compile Include="CacheDownloadStrategy.cs" />
<Compile Include="DownloadArguments.cs" />
<Compile Include="EnvProxy.cs" />
<Compile Include="GitHubDownloadStrategy.cs" />
Expand Down
27 changes: 21 additions & 6 deletions src/Paket.Bootstrapper/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Program
const string SelfUpdateCommandArg = "--self";
const string SilentCommandArg = "-s";
const string NugetSourceArgPrefix = "--nuget-source=";
const string IgnoreCacheCommandArg = "-f";

static void Main(string[] args)
{
Expand All @@ -30,6 +31,7 @@ static void Main(string[] args)
var commandArgs = args;
var preferNuget = false;
var forceNuget = false;

if (commandArgs.Contains(PreferNugetCommandArg))
{
preferNuget = true;
Expand All @@ -54,7 +56,8 @@ static void Main(string[] args)
silent = true;
commandArgs = args.Where(x => x != SilentCommandArg).ToArray();
}
var dlArgs = EvaluateCommandArgs(commandArgs, silent);

var dlArgs = EvaluateCommandArgs(commandArgs);

var effectiveStrategy = GetEffectiveDownloadStrategy(dlArgs, preferNuget, forceNuget);

Expand Down Expand Up @@ -102,10 +105,13 @@ private static void StartPaketBootstrapping(IDownloadStrategy downloadStrategy,

var localVersion = BootstrapperHelper.GetLocalFileVersion(dlArgs.Target);

var specificVersionRequested = true;
var latestVersion = dlArgs.LatestVersion;

if (latestVersion == String.Empty)
{
latestVersion = downloadStrategy.GetLatestVersion(dlArgs.IgnorePrerelease);
latestVersion = downloadStrategy.GetLatestVersion(dlArgs.IgnorePrerelease, silent);
specificVersionRequested = false;
}

if (dlArgs.DoSelfUpdate)
Expand All @@ -118,7 +124,9 @@ private static void StartPaketBootstrapping(IDownloadStrategy downloadStrategy,
{
var currentSemVer = String.IsNullOrEmpty(localVersion) ? new SemVer() : SemVer.Create(localVersion);
var latestSemVer = SemVer.Create(latestVersion);
if (currentSemVer.CompareTo(latestSemVer) != 0)
var comparison = currentSemVer.CompareTo(latestSemVer);

if ((comparison > 0 && specificVersionRequested) || comparison < 0)
{
downloadStrategy.DownloadVersion(latestVersion, dlArgs.Target, silent);
if (!silent)
Expand Down Expand Up @@ -176,10 +184,11 @@ private static IDownloadStrategy GetEffectiveDownloadStrategy(DownloadArguments
effectiveStrategy = gitHubDownloadStrategy;
gitHubDownloadStrategy.FallbackStrategy = nugetDownloadStrategy;
}
return effectiveStrategy;

return dlArgs.IgnoreCache ? effectiveStrategy : new CacheDownloadStrategy(effectiveStrategy);
}

private static DownloadArguments EvaluateCommandArgs(string[] args, bool silent)
private static DownloadArguments EvaluateCommandArgs(string[] args)
{
var folder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var target = Path.Combine(folder, "paket.exe");
Expand All @@ -188,6 +197,7 @@ private static DownloadArguments EvaluateCommandArgs(string[] args, bool silent)
var latestVersion = ConfigurationManager.AppSettings[PaketVersionAppSettingsKey] ?? Environment.GetEnvironmentVariable(PaketVersionEnv) ?? String.Empty;
var ignorePrerelease = true;
bool doSelfUpdate = false;
var ignoreCache = false;
var commandArgs = args;

if (commandArgs.Contains(SelfUpdateCommandArg))
Expand All @@ -201,6 +211,11 @@ private static DownloadArguments EvaluateCommandArgs(string[] args, bool silent)
commandArgs = commandArgs.Where(x => !x.StartsWith(NugetSourceArgPrefix)).ToArray();
nugetSource = nugetSourceArg.Substring(NugetSourceArgPrefix.Length);
}
if (commandArgs.Contains(IgnoreCacheCommandArg))
{
commandArgs = commandArgs.Where(x => x != IgnoreCacheCommandArg).ToArray();
ignoreCache = true;
}
if (commandArgs.Length >= 1)
{
if (commandArgs[0] == PrereleaseCommandArg)
Expand All @@ -214,7 +229,7 @@ private static DownloadArguments EvaluateCommandArgs(string[] args, bool silent)
}
}

return new DownloadArguments(latestVersion, ignorePrerelease, folder, target, doSelfUpdate, nugetSource);
return new DownloadArguments(latestVersion, ignorePrerelease, folder, target, doSelfUpdate, nugetSource, ignoreCache);
}
}
}