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

Boostrapper download without nuget exe and switch bootstrapper to .net 4.5 #734

Merged
merged 4 commits into from
Apr 8, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/content/bootstrapper.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
Downloads the latest stable paket.exe from github.com.

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

Options:

`prerelease`: Downloads the latest paket.exe from github.com and includes prerelease versions.

`version`: Downloads the given version of paket.exe from github.com.

`--prefer-nuget`: Downloads the given version of paket.exe from nuget.org instead of github.com.
18 changes: 18 additions & 0 deletions src/Paket.Bootstrapper/DownloadArguments.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace Paket.Bootstrapper
{
internal class DownloadArguments
{
public string Folder { get; private set; }
public string Target { get; private set; }
public string LatestVersion { get; private set; }
public bool IgnorePrerelease { get; private set; }

public DownloadArguments(string latestVersion, bool ignorePrerelease, string folder, string target)
{
LatestVersion = latestVersion;
IgnorePrerelease = ignorePrerelease;
Folder = folder;
Target = target;
}
}
}
73 changes: 73 additions & 0 deletions src/Paket.Bootstrapper/GitHubDownloadStrategy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System;
using System.IO;
using System.Net;

namespace Paket.Bootstrapper
{
internal class GitHubDownloadStrategy : IDownloadStrategy
{
private PrepareWebClientDelegate PrepareWebClient { get; set; }
private GetDefaultWebProxyForDelegate GetDefaultWebProxyFor { get; set; }
public string Name { get { return "Github"; } }
public IDownloadStrategy FallbackStrategy { get; set; }

public GitHubDownloadStrategy(PrepareWebClientDelegate prepareWebClient, GetDefaultWebProxyForDelegate getDefaultWebProxyFor)
{
PrepareWebClient = prepareWebClient;
GetDefaultWebProxyFor = getDefaultWebProxyFor;
}

public string GetLatestVersion(bool ignorePrerelease)
{
string latestVersion = "";
using (WebClient client = new WebClient())
{
const string releasesUrl = "https://github.com/fsprojects/Paket/releases";
PrepareWebClient(client, releasesUrl);

var data = client.DownloadString(releasesUrl);
var start = 0;
while (latestVersion == "")
{
start = data.IndexOf("Paket/tree/", start) + 11;
var end = data.IndexOf("\"", start);
latestVersion = data.Substring(start, end - start);
if (latestVersion.Contains("-") && ignorePrerelease)
latestVersion = "";
}
}
return latestVersion;
}

public void DownloadVersion(string latestVersion, string target)
{
var url = String.Format("https://github.com/fsprojects/Paket/releases/download/{0}/paket.exe", latestVersion);

Console.WriteLine("Starting download from {0}", url);

var request = (HttpWebRequest)HttpWebRequest.Create(url);

request.UseDefaultCredentials = true;
request.Proxy = GetDefaultWebProxyFor(url);
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

using (HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse())
{
using (Stream httpResponseStream = httpResponse.GetResponseStream())
{
const int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
int bytesRead = 0;

using (FileStream fileStream = File.Create(target))
{
while ((bytesRead = httpResponseStream.Read(buffer, 0, bufferSize)) != 0)
{
fileStream.Write(buffer, 0, bytesRead);
}
}
}
}
}
}
}
15 changes: 15 additions & 0 deletions src/Paket.Bootstrapper/IDownloadStrategy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Net;

namespace Paket.Bootstrapper
{
internal interface IDownloadStrategy
{
string Name { get; }
IDownloadStrategy FallbackStrategy { get; set; }
string GetLatestVersion(bool ignorePrerelease);
void DownloadVersion(string latestVersion, string target);
}

public delegate void PrepareWebClientDelegate(WebClient client, string url);
public delegate IWebProxy GetDefaultWebProxyForDelegate(string url);
}
195 changes: 195 additions & 0 deletions src/Paket.Bootstrapper/NugetDownloadStrategy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;

namespace Paket.Bootstrapper
{
internal class NugetDownloadStrategy : IDownloadStrategy
{
private PrepareWebClientDelegate PrepareWebClient { get; set; }
private GetDefaultWebProxyForDelegate GetDefaultWebProxyFor { get; set; }
private string Folder { get; set; }

public NugetDownloadStrategy(PrepareWebClientDelegate prepareWebClient, GetDefaultWebProxyForDelegate getDefaultWebProxyFor, string folder)
{
PrepareWebClient = prepareWebClient;
GetDefaultWebProxyFor = getDefaultWebProxyFor;
Folder = folder;
}

public string Name
{
get { return "Nuget"; }
}

public IDownloadStrategy FallbackStrategy { get; set; }

public string GetLatestVersion(bool ignorePrerelease)
{
using (WebClient client = new WebClient())
{
const string getVersionsFromNugetUrl = "https://www.nuget.org/api/v2/package-versions/Paket";
const string withPrereleases = "?includePrerelease=true";

var versionRequestUrl = getVersionsFromNugetUrl;
if (!ignorePrerelease)
versionRequestUrl += withPrereleases;
PrepareWebClient(client, versionRequestUrl);
var versions = client.DownloadString(versionRequestUrl);
var latestVersion = versions.
Trim('[', ']').
Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).
Select(x => x.Trim('"')).
Select(x => GetSemVer(x)).
OrderBy(x => x).
LastOrDefault(x => !String.IsNullOrWhiteSpace(x.Original));
return latestVersion != null ? latestVersion.Original : String.Empty;
}
}

private SemVer GetSemVer(string version)
{
var dashSplitted = version.Split('-', '+');
var splitted = dashSplitted[0].Split('.');
var l = splitted.Length;

var prereleaseBuild = dashSplitted.Length > 1 && dashSplitted[1].Split('.').Length > 1 ? dashSplitted[1].Split('.')[1] : "0";

return new SemVer
{
Major = l > 0 ? Int32.Parse(splitted[0]) : 0,
Minor = l > 1 ? Int32.Parse(splitted[1]) : 0,
Patch = l > 2 ? Int32.Parse(splitted[2]) : 0,
PreRelease = PreRelease.TryParse(dashSplitted.Length > 1 ? dashSplitted[1].Split('.')[0] : String.Empty),
Build = l > 3 ? splitted[3] : "0",
PreReleaseBuild = prereleaseBuild,
Original = version
};
}

public void DownloadVersion(string latestVersion, string target)
{
using (WebClient client = new WebClient())
{
const string getLatestFromNugetUrl = "https://www.nuget.org/api/v2/package/Paket";
const string getSpecificFromNugetUrlTemplate = "https://www.nuget.org/api/v2/package/Paket/{0}";
const string paketNupkgFile = "paket.latest.nupkg";
const string paketNupkgFileTemplate = "paket.{0}.nupkg";

var paketDownloadUrl = getLatestFromNugetUrl;
var paketFile = paketNupkgFile;
if (latestVersion != "")
{
paketDownloadUrl = String.Format(getSpecificFromNugetUrlTemplate, latestVersion);
paketFile = String.Format(paketNupkgFileTemplate, latestVersion);
}

var randomFullPath = Path.Combine(Folder, Path.GetRandomFileName());
Directory.CreateDirectory(randomFullPath);
var paketPackageFile = Path.Combine(randomFullPath, paketFile);
Console.WriteLine("Starting download from {0}", paketDownloadUrl);
PrepareWebClient(client, paketDownloadUrl);
client.DownloadFile(paketDownloadUrl, paketPackageFile);

ZipFile.ExtractToDirectory(paketPackageFile, randomFullPath);
var paketSourceFile = Path.Combine(randomFullPath, "Tools", "Paket.exe");
File.Copy(paketSourceFile, target, true);
Directory.Delete(randomFullPath, true);
}
}

private class SemVer : IComparable
{
public int Major { get; set; }
public int Minor { get; set; }
public int Patch { get; set; }
public PreRelease PreRelease { get; set; }
public string Original { get; set; }
public string PreReleaseBuild { get; set; }
public string Build { get; set; }

public int CompareTo(object obj)
{
var y = obj as SemVer;
if (y == null)
throw new ArgumentException("cannot compare values of different types", "obj");
var x = this;
if (x.Major != y.Major) return x.Major.CompareTo(y.Major);
else if (x.Minor != y.Minor) return x.Minor.CompareTo(y.Minor);
else if (x.Patch != y.Patch) return x.Patch.CompareTo(y.Patch);
else if (x.Build != y.Build)
{
int buildx, buildy;
var parseResultx = Int32.TryParse(x.Build, out buildx);
var parseResulty = Int32.TryParse(y.Build, out buildy);
if (parseResultx && parseResulty)
return buildx.CompareTo(buildy);
return x.Build.CompareTo(y.Build);
}
else if (x.PreRelease == y.PreRelease && x.PreReleaseBuild == y.PreReleaseBuild) return 0;
else if (x.PreRelease == null && y.PreRelease != null && x.PreReleaseBuild == "0") return 1;
else if (y.PreRelease == null && x.PreRelease != null && y.PreReleaseBuild == "0") return -1;
else if (x.PreRelease != y.PreRelease) return x.PreRelease.CompareTo(y.PreRelease);
else if (x.PreReleaseBuild != y.PreReleaseBuild)
{
int prereleaseBuildx, prereleaseBuildy;
var parseResultx = Int32.TryParse(x.PreReleaseBuild, out prereleaseBuildx);
var parseResulty = Int32.TryParse(y.PreReleaseBuild, out prereleaseBuildy);
if (parseResultx && parseResulty)
return prereleaseBuildx.CompareTo(prereleaseBuildy);
return x.PreReleaseBuild.CompareTo(y.PreReleaseBuild);
}
else return 0;
}

public override bool Equals(object obj)
{
var y = obj as SemVer;
if (y == null)
return false;
return Major == y.Major && Minor == y.Minor && Patch == y.Patch && PreRelease == y.PreRelease && Build == y.Build && PreReleaseBuild == y.PreReleaseBuild;
}
}

private class PreRelease : IComparable
{
public string Origin { get; set; }
public string Name { get; set; }
public long? Number { get; set; }

public static PreRelease TryParse(string str)
{
var m = new Regex(@"^(?<name>[a-zA-Z]+)(?<number>\d*)$").Match(str);
if (m.Success)
{
long? number = null;
if (m.Groups["number"].Value != "")
number = long.Parse(m.Groups["number"].Value);

return new PreRelease { Origin = str, Name = m.Groups["name"].Value, Number = number };
}
return null;
}

public int CompareTo(object obj)
{
var yObj = obj as PreRelease;
if (yObj == null)
throw new ArgumentException("cannot compare values of different types", "obj");
var x = this;
if (x.Name != yObj.Name) return x.Name.CompareTo(yObj.Name);
else if (!x.Number.HasValue && yObj.Number.HasValue)
return 1;
else if (x.Number.HasValue && !yObj.Number.HasValue)
return -1;
else if (!x.Number.HasValue && !yObj.Number.HasValue)
return 0;
else
return x.Number.Value.CompareTo(yObj.Number.Value);
}
}
}
}
7 changes: 6 additions & 1 deletion src/Paket.Bootstrapper/Paket.Bootstrapper.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Paket.Bootstrapper</RootNamespace>
<AssemblyName>paket.bootstrapper</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
Expand All @@ -35,9 +35,14 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="DownloadArguments.cs" />
<Compile Include="GitHubDownloadStrategy.cs" />
<Compile Include="IDownloadStrategy.cs" />
<Compile Include="NugetDownloadStrategy.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
Expand Down
Loading