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

Automatic License restore #737

Merged
merged 3 commits into from Mar 30, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Paket.Core/Environment.fs
Expand Up @@ -63,8 +63,8 @@ module PaketEnv =

let ensureNotExists (directory : DirectoryInfo) =
match fromRootDirectory directory with
| Ok(_) -> fail (PaketEnvAlreadyExistsInDirectory directory)
| Fail(msgs) ->
| Result.Ok(_) -> fail (PaketEnvAlreadyExistsInDirectory directory)
| Result.Fail(msgs) ->
let filtered =
msgs
|> List.filter (function
Expand Down
83 changes: 74 additions & 9 deletions src/Paket.Core/NuGetV2.fs
Expand Up @@ -23,10 +23,11 @@ type NugetPackageCache =
PackageName : string
SourceUrl: string
Unlisted : bool
DownloadUrl : string;
DownloadUrl : string
LicenseUrl : string
CacheVersion: string }

static member CurrentCacheVersion = "1.0"
static member CurrentCacheVersion = "1.1"

let rec private followODataLink getUrlContents url =
async {
Expand Down Expand Up @@ -175,6 +176,11 @@ let parseODataDetails(nugetURL,packageName,version,raw) =
| Some "binary/octet-stream", Some link -> link
| _ -> failwithf "unable to find downloadLink for package %s %O" packageName version

let licenseUrl =
match entry |> getNode "properties" |> optGetNode "LicenseUrl" with
| Some node -> node.InnerText
| _ -> ""

let dependencies =
match entry |> getNode "properties" |> optGetNode "Dependencies" with
| Some node -> node.InnerText
Expand Down Expand Up @@ -203,6 +209,7 @@ let parseODataDetails(nugetURL,packageName,version,raw) =
Dependencies = Requirements.optimizeRestrictions packages
SourceUrl = nugetURL
CacheVersion = NugetPackageCache.CurrentCacheVersion
LicenseUrl = licenseUrl
Unlisted = publishDate = Constants.MagicUnlistingDate }


Expand Down Expand Up @@ -314,6 +321,7 @@ let getDetailsFromLocalFile localNugetPath package (version:SemVerInfo) =
Dependencies = Requirements.optimizeRestrictions nuspec.Dependencies
SourceUrl = localNugetPath
CacheVersion = NugetPackageCache.CurrentCacheVersion
LicenseUrl = nuspec.LicenseUrl
Unlisted = false }
}

Expand All @@ -328,7 +336,7 @@ let inline isExtracted fileName =
/// Extracts the given package to the ./packages folder
let ExtractPackage(fileName:string, targetFolder, name, version:SemVerInfo) =
async {
if isExtracted fileName then
if isExtracted fileName then
verbosefn "%s %A already extracted" name version
else
use zip = ZipFile.Read(fileName)
Expand Down Expand Up @@ -359,8 +367,24 @@ let ExtractPackage(fileName:string, targetFolder, name, version:SemVerInfo) =
return targetFolder
}

let CopyLicenseFromCache(root, cacheFileName, name, version:SemVerInfo, force) =
async {
try
if String.IsNullOrWhiteSpace cacheFileName then return () else
let cacheFile = FileInfo cacheFileName
if cacheFile.Exists then
let targetFolder = DirectoryInfo(Path.Combine(root, Constants.PackagesFolderName, name)).FullName
let targetFile = FileInfo(Path.Combine(targetFolder, "license.html"))
if not force && targetFile.Exists then
verbosefn "License %s %A already copied" name version
else
File.Copy(cacheFile.FullName, targetFile.FullName, true)
with
| exn -> traceWarnfn "Could not copy license for %s %A from %s.%s %s" name version cacheFileName Environment.NewLine exn.Message
}

/// Extracts the given package to the ./packages folder
let CopyFromCache(root, cacheFileName, name, version:SemVerInfo, force) =
let CopyFromCache(root, cacheFileName, licenseCacheFile, name, version:SemVerInfo, force) =
async {
let targetFolder = DirectoryInfo(Path.Combine(root, Constants.PackagesFolderName, name)).FullName
let fi = FileInfo(cacheFileName)
Expand All @@ -370,20 +394,58 @@ let CopyFromCache(root, cacheFileName, name, version:SemVerInfo, force) =
else
CleanDir targetFolder
File.Copy(cacheFileName, targetFile.FullName)
try
return! ExtractPackage(targetFile.FullName,targetFolder,name,version)
try
let! extracted = ExtractPackage(targetFile.FullName,targetFolder,name,version)
do! CopyLicenseFromCache(root, licenseCacheFile, name, version, force)
return extracted
with
| exn ->
File.Delete targetFile.FullName
Directory.Delete(targetFolder,true)
return! raise exn
}

let DownloadLicense(root,force,name,version:SemVerInfo,licenseUrl,targetFileName) =
async {
if String.IsNullOrWhiteSpace licenseUrl then return () else

let targetFile = FileInfo targetFileName
if not force && targetFile.Exists && targetFile.Length > 0L then
verbosefn "License for %s %A already downloaded" name version
else
try
verbosefn "Downloading license for %s %A to %s" name version targetFileName

let request = HttpWebRequest.Create(Uri licenseUrl) :?> HttpWebRequest
request.AutomaticDecompression <- DecompressionMethods.GZip ||| DecompressionMethods.Deflate
request.UserAgent <- "Paket"
request.UseDefaultCredentials <- true
request.Proxy <- Utils.getDefaultProxyFor licenseUrl
use! httpResponse = request.AsyncGetResponse()

use httpResponseStream = httpResponse.GetResponseStream()

let bufferSize = 4096
let buffer : byte [] = Array.zeroCreate bufferSize
let bytesRead = ref -1

use fileStream = File.Create(targetFileName)

while !bytesRead <> 0 do
let! bytes = httpResponseStream.AsyncRead(buffer, 0, bufferSize)
bytesRead := bytes
do! fileStream.AsyncWrite(buffer, 0, !bytesRead)

with
| exn -> traceWarnfn "Could not download license for %s %A from %s.%s %s" name version licenseUrl Environment.NewLine exn.Message
}

/// Downloads the given package to the NuGet Cache folder
let DownloadPackage(root, auth, url, name, version:SemVerInfo, force) =
async {
let targetFileName = Path.Combine(CacheFolder, name + "." + version.Normalize() + ".nupkg")
let targetFile = FileInfo targetFileName
let licenseFileName = Path.Combine(CacheFolder, name + "." + version.Normalize() + ".license.html")
if not force && targetFile.Exists && targetFile.Length > 0L then
verbosefn "%s %A already downloaded" name version
else
Expand Down Expand Up @@ -424,10 +486,12 @@ let DownloadPackage(root, auth, url, name, version:SemVerInfo, force) =
let! bytes = httpResponseStream.AsyncRead(buffer, 0, bufferSize)
bytesRead := bytes
do! fileStream.AsyncWrite(buffer, 0, !bytesRead)


do! DownloadLicense(root,force,name,version,nugetPackage.LicenseUrl,licenseFileName)
with
| exn -> failwithf "Could not download %s %A.%s %s" name version Environment.NewLine exn.Message
return! CopyFromCache(root, targetFile.FullName, name, version, force)

return! CopyFromCache(root, targetFile.FullName, licenseFileName, name, version, force)
}

/// Finds all libraries in a nuget package.
Expand Down Expand Up @@ -472,7 +536,7 @@ let GetTargetsFiles(targetFolder) =

targetsFiles

let GetPackageDetails force sources (PackageName package) (version:SemVerInfo) : PackageResolver.PackageDetails=
let GetPackageDetails force sources (PackageName package) (version:SemVerInfo) : PackageResolver.PackageDetails =
let rec tryNext xs =
match xs with
| source :: rest ->
Expand Down Expand Up @@ -501,6 +565,7 @@ let GetPackageDetails force sources (PackageName package) (version:SemVerInfo) :
Source = source
DownloadLink = nugetObject.DownloadUrl
Unlisted = nugetObject.Unlisted
LicenseUrl = nugetObject.LicenseUrl
DirectDependencies =
nugetObject.Dependencies
|> Requirements.optimizeRestrictions
Expand Down
11 changes: 9 additions & 2 deletions src/Paket.Core/Nuspec.fs
Expand Up @@ -22,10 +22,11 @@ type Nuspec =
{ References : NuspecReferences
Dependencies : (PackageName * VersionRequirement * FrameworkRestrictions) list
OfficialName : string
LicenseUrl : string
FrameworkAssemblyReferences : FrameworkAssemblyReference list }

static member All = { References = NuspecReferences.All; Dependencies = []; FrameworkAssemblyReferences = []; OfficialName = "" }
static member Explicit references = { References = NuspecReferences.Explicit references; Dependencies = []; FrameworkAssemblyReferences = []; OfficialName = "" }
static member All = { References = NuspecReferences.All; Dependencies = []; FrameworkAssemblyReferences = []; OfficialName = ""; LicenseUrl = "" }
static member Explicit references = { References = NuspecReferences.Explicit references; Dependencies = []; FrameworkAssemblyReferences = []; OfficialName = ""; LicenseUrl = "" }
static member Load(fileName : string) =
let fi = FileInfo(fileName)
if not fi.Exists then Nuspec.All
Expand Down Expand Up @@ -76,6 +77,11 @@ type Nuspec =
|> List.map dependency
|> List.append frameworks
|> Requirements.optimizeRestrictions

let licenseUrl =
match doc |> getNode "package" |> optGetNode "metadata" |> optGetNode "licenseUrl" with
| Some link -> link.InnerText
| None -> ""

let references =
doc
Expand Down Expand Up @@ -114,4 +120,5 @@ type Nuspec =
{ References = if references = [] then NuspecReferences.All else NuspecReferences.Explicit references
Dependencies = dependencies
OfficialName = officialName
LicenseUrl = licenseUrl
FrameworkAssemblyReferences = frameworkAssemblyReferences }
3 changes: 2 additions & 1 deletion src/Paket.Core/PackageResolver.fs
Expand Up @@ -45,6 +45,7 @@ type PackageDetails =
{ Name : PackageName
Source : PackageSource
DownloadLink : string
LicenseUrl : string
Unlisted : bool
DirectDependencies : DependencySet }

Expand All @@ -53,7 +54,7 @@ type ResolvedPackage =
{ Name : PackageName
Version : SemVerInfo
Dependencies : DependencySet
Unlisted : bool
Unlisted : bool
Settings : InstallSettings
Source : PackageSource }

Expand Down
2 changes: 1 addition & 1 deletion src/Paket.Core/RestoreProcess.fs
Expand Up @@ -31,7 +31,7 @@ let ExtractPackage(root, sources, force, package : ResolvedPackage) =
| LocalNuget path ->
let path = Utils.normalizeLocalPath path
let packageFile = Path.Combine(root, path, sprintf "%s.%A.nupkg" name v)
let! folder = NuGetV2.CopyFromCache(root, packageFile, name, v, force)
let! folder = NuGetV2.CopyFromCache(root, packageFile, "", name, v, force) // TODO: Restore license
return package, NuGetV2.GetLibFiles folder, NuGetV2.GetTargetsFiles folder
}

Expand Down
2 changes: 1 addition & 1 deletion src/Paket/Paket.fsproj
Expand Up @@ -27,7 +27,7 @@
<WarningLevel>3</WarningLevel>
<DocumentationFile>
</DocumentationFile>
<StartArguments>update</StartArguments>
<StartArguments>restore -f</StartArguments>
<StartAction>Project</StartAction>
<StartProgram>paket.exe</StartProgram>
<StartWorkingDirectory>D:\code\Paketkopie</StartWorkingDirectory>
Expand Down
1 change: 1 addition & 0 deletions tests/Paket.Tests/InstallModel/Xml/RxXaml.fs
Expand Up @@ -101,6 +101,7 @@ let ``should generate Xml for Rx-XAML 2.2.4 with correct framework assembly refe
{ References = NuspecReferences.All
OfficialName = "Reactive Extensions - XAML Support Library"
Dependencies = []
LicenseUrl = ""
FrameworkAssemblyReferences =
[{ AssemblyName = "WindowsBase"; FrameworkRestrictions = [FrameworkRestriction.Exactly(DotNetFramework FrameworkVersion.V4_5)] }
{ AssemblyName = "WindowsBase"; FrameworkRestrictions = [FrameworkRestriction.Exactly(DotNetFramework FrameworkVersion.V4)] }
Expand Down
Expand Up @@ -62,6 +62,7 @@ let ``should generate Xml for System.Net.Http 2.2.8``() =
{ References = NuspecReferences.All
OfficialName = "Microsoft.Net.Http"
Dependencies = []
LicenseUrl = ""
FrameworkAssemblyReferences =
[{ AssemblyName = "System.Net.Http"; FrameworkRestrictions = [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] }
{ AssemblyName = "System.Net.Http.WebRequest"; FrameworkRestrictions = [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] }]})
Expand Down
Expand Up @@ -70,6 +70,7 @@ let ``should generate Xml for System.Net.Http 2.2.8``() =
{ References = NuspecReferences.All
OfficialName = "Microsoft.Net.Http"
Dependencies = []
LicenseUrl = ""
FrameworkAssemblyReferences =
[{ AssemblyName = "System.Net.Http"; FrameworkRestrictions = [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))] }
{ AssemblyName = "System.Net.Http.WebRequest"; FrameworkRestrictions = [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] }]})
Expand Down
6 changes: 6 additions & 0 deletions tests/Paket.Tests/NuGetOData/ODataSpecs.fs
Expand Up @@ -23,6 +23,7 @@ let ``can detect explicit dependencies for Fantomas``() =
DownloadUrl = "http://www.nuget.org/api/v2/package/Fantomas/1.6.0"
Dependencies = [PackageName "FSharp.Compiler.Service",DependenciesFileParser.parseVersionRequirement(">= 0.0.73"), []]
Unlisted = false
LicenseUrl = "http://github.com/dungpa/fantomas/blob/master/LICENSE.md"
CacheVersion = NugetPackageCache.CurrentCacheVersion
SourceUrl = fakeUrl }

Expand All @@ -36,6 +37,7 @@ let ``can detect explicit dependencies for Rx-PlaformServices``() =
[PackageName "Rx-Interfaces",DependenciesFileParser.parseVersionRequirement(">= 2.2"), []
PackageName "Rx-Core",DependenciesFileParser.parseVersionRequirement(">= 2.2"), []]
Unlisted = true
LicenseUrl = "http://go.microsoft.com/fwlink/?LinkID=261272"
CacheVersion = NugetPackageCache.CurrentCacheVersion
SourceUrl = fakeUrl }

Expand All @@ -48,6 +50,7 @@ let ``can detect explicit dependencies for EasyNetQ``() =
Dependencies =
[PackageName "RabbitMQ.Client",DependenciesFileParser.parseVersionRequirement(">= 3.4.3"), []]
Unlisted = false
LicenseUrl = "https://github.com/mikehadlow/EasyNetQ/blob/master/licence.txt"
CacheVersion = NugetPackageCache.CurrentCacheVersion
SourceUrl = fakeUrl }

Expand All @@ -59,6 +62,7 @@ let ``can detect explicit dependencies for Fleece``() =
DownloadUrl = "http://www.nuget.org/api/v2/package/Fleece/0.4.0"
Unlisted = false
CacheVersion = NugetPackageCache.CurrentCacheVersion
LicenseUrl = "https://raw.github.com/mausch/Fleece/master/LICENSE"
Dependencies =
[PackageName "FSharpPlus",DependenciesFileParser.parseVersionRequirement(">= 0.0.4"), []
PackageName "ReadOnlyCollectionInterfaces",DependenciesFileParser.parseVersionRequirement("1.0.0"), []
Expand All @@ -74,6 +78,7 @@ let ``can detect explicit dependencies for ReadOnlyCollectionExtensions``() =
DownloadUrl = "http://www.nuget.org/api/v2/package/ReadOnlyCollectionExtensions/1.2.0"
Unlisted = false
CacheVersion = NugetPackageCache.CurrentCacheVersion
LicenseUrl = "https://github.com/mausch/ReadOnlyCollections/blob/master/license.txt"
Dependencies =
[PackageName "LinqBridge",DependenciesFileParser.parseVersionRequirement(">= 1.3.0"),
[FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V2),DotNetFramework(FrameworkVersion.V3_5))]
Expand All @@ -90,6 +95,7 @@ let ``can detect explicit dependencies for Math.Numerics``() =
{ PackageName = "MathNet.Numerics"
DownloadUrl = "http://www.nuget.org/api/v2/package/MathNet.Numerics/3.3.0"
Unlisted = false
LicenseUrl = "http://numerics.mathdotnet.com/docs/License.html"
CacheVersion = NugetPackageCache.CurrentCacheVersion
Dependencies =
[PackageName "TaskParallelLibrary",DependenciesFileParser.parseVersionRequirement(">= 1.0.2856"),
Expand Down
5 changes: 5 additions & 0 deletions tests/Paket.Tests/Nuspec/NuspecSpecs.fs
Expand Up @@ -83,6 +83,11 @@ let ``can detect framework assemblies for SqlCLient``() =
[{ AssemblyName = "System.Data"; FrameworkRestrictions = [] }
{ AssemblyName = "System.Xml"; FrameworkRestrictions = [] } ]

[<Test>]
let ``can detect license for SqlCLient``() =
Nuspec.Load("Nuspec/FSharp.Data.SqlClient.nuspec").LicenseUrl
|> shouldEqual "http://github.com/fsprojects/FSharp.Data.SqlClient/blob/master/LICENSE.md"

[<Test>]
let ``can detect dependencies for SqlCLient``() =
Nuspec.Load("Nuspec/FSharp.Data.SqlClient.nuspec").Dependencies
Expand Down
1 change: 1 addition & 0 deletions tests/Paket.Tests/TestHelpers.fs
Expand Up @@ -19,6 +19,7 @@ let PackageDetailsFromGraph (graph : seq<string * string * (string * VersionRequ
{ Name = name
Source = Seq.head sources
DownloadLink = ""
LicenseUrl = ""
Unlisted = false
DirectDependencies = Set.ofList dependencies }

Expand Down