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

Lowercase package names in package cache (resolves #2676) #2826

Merged
merged 13 commits into from
Oct 7, 2017
66 changes: 65 additions & 1 deletion integrationtests/Paket.IntegrationTests/RestoreSpecs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ open System.IO
open Fake
open NUnit.Framework
open FsUnit
open Paket
open Paket.Utils

[<Test>]
let ``#2496 Paket fails on projects that target multiple frameworks``() =
Expand All @@ -14,4 +16,66 @@ let ``#2496 Paket fails on projects that target multiple frameworks``() =

let wd = (scenarioTempPath scenario) @@ project
directDotnet true (sprintf "restore %s.csproj" project) wd
|> ignore
|> ignore

[<Test>]
let ``#2812 Lowercase package names in package cache: old csproj, packages folder enabled``() =
let scenario = "i002812-old-csproj-storage-default"
let projectName = "project"
let packageName = "AutoMapper"
let packageNameLowercase = packageName.ToLower()
let workingDir = scenarioTempPath scenario
let csprojFile = workingDir @@ projectName @@ sprintf "%s.csproj" projectName
let packagesDir = workingDir @@ "packages"

[ packageName; packageNameLowercase ] |> Seq.iter clearPackage

prepareSdk scenario
directPaket "restore" scenario |> ignore
isPackageCachedWithOnlyLowercaseNames packageName |> shouldEqual true
packagesDir
|> Directory.GetDirectories
|> Array.map Path.GetFileName
|> shouldEqual [| packageName |]
MSBuildRelease "" "Build" [ csprojFile ] |> ignore

[<Test>]
let ``#2812 Lowercase package names in package cache: new csproj, packages folder enabled``() =
let scenario = "i002812-new-csproj-storage-default"
let projectName = "project"
let packageName = "AutoMapper"
let packageNameLowercase = packageName.ToLower()
let workingDir = scenarioTempPath scenario
let projectDir = workingDir @@ projectName
let emptyFeedPath = workingDir @@ "emptyFeed"
let packagesDir = workingDir @@ "packages"

[ packageName; packageNameLowercase ] |> Seq.iter clearPackage

prepareSdk scenario
directPaket "restore" scenario |> ignore
isPackageCachedWithOnlyLowercaseNames packageName |> shouldEqual true
packagesDir
|> Directory.GetDirectories
|> Array.map Path.GetFileName
|> shouldEqual [| packageName |]
directDotnet false (sprintf "restore --source \"%s\"" emptyFeedPath) projectDir |> ignore
directDotnet false "build --no-restore" projectDir |> ignore

[<Test>]
let ``#2812 Lowercase package names in package cache: new csproj, packages folder disabled``() =
let scenario = "i002812-new-csproj-storage-default"
let projectName = "project"
let packageName = "AutoMapper"
let packageNameLowercase = packageName.ToLower()
let workingDir = scenarioTempPath scenario
let projectDir = workingDir @@ projectName
let emptyFeedPath = workingDir @@ "emptyFeed"

[ packageName; packageNameLowercase ] |> Seq.iter clearPackage

prepareSdk scenario
directPaket "restore" scenario |> ignore
isPackageCachedWithOnlyLowercaseNames packageName |> shouldEqual true
directDotnet false (sprintf "restore --source \"%s\"" emptyFeedPath) projectDir |> ignore
directDotnet false "build --no-restore" projectDir |> ignore
35 changes: 35 additions & 0 deletions integrationtests/Paket.IntegrationTests/TestHelper.fs
Original file line number Diff line number Diff line change
Expand Up @@ -273,3 +273,38 @@ let isPackageCached name =
Seq.append dirs files
|> Seq.toList
else [])

// Checks if a given package is present in cache ONLY with lowercase naming (see issue #2812)
let isPackageCachedWithOnlyLowercaseNames (name: string) =
// // ~/.nuget/packages
let userPackageFolder = Paket.Constants.UserNuGetPackagesFolder

// // %APPDATA%/NuGet/Cache
let nugetCache = Paket.Constants.NuGetCacheFolder

let lowercaseName = name.ToLowerInvariant()

let packageFolders =
[ nugetCache; userPackageFolder ]
|> List.collect (Directory.GetDirectories >> List.ofArray)
|> List.filter (fun x -> Path.GetFileName x |> String.equalsIgnoreCase name)

let packageFolderNames = packageFolders |> List.map Path.GetFileName |> List.distinct

// ensure that names of package directories are lowercase only
match packageFolderNames with
| [ x ] when x = lowercaseName ->
// ensure thet names o package files that start with package name are lowercase only
let packageFiles =
packageFolders
|> Seq.collect Directory.GetDirectories
|> Seq.collect Directory.GetFiles
let packageFileNames = packageFiles |> Seq.map Path.GetFileName
let packageNameSegments =
packageFileNames
|> Seq.filter (String.startsWithIgnoreCase <| sprintf "%s." name)
|> Seq.map (fun x -> x.Substring(0, name.Length))
|> Seq.distinct
|> List.ofSeq
packageNameSegments = [ lowercaseName ]
| _ -> false
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source https://api.nuget.org/v3/index.json
framework: net45
references: strict
nuget AutoMapper == 6.1.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
REFERENCES: STRICT
RESTRICTION: == net45
NUGET
remote: https://api.nuget.org/v3/index.json
AutoMapper (6.1.1)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
AutoMapper
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net45</TargetFramework>
</PropertyGroup>
<Import Project="..\.paket\Paket.Restore.targets" />
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
source https://api.nuget.org/v3/index.json
framework: net45
references: strict
storage: none
nuget AutoMapper == 6.1.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
REFERENCES: STRICT
STORAGE: NONE
RESTRICTION: == net45
NUGET
remote: https://api.nuget.org/v3/index.json
AutoMapper (6.1.1)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
AutoMapper
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net45</TargetFramework>
</PropertyGroup>
<Import Project="..\.paket\Paket.Restore.targets" />
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source https://api.nuget.org/v3/index.json
framework: net45
references: strict
nuget AutoMapper == 6.1.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
REFERENCES: STRICT
RESTRICTION: == net45
NUGET
remote: https://api.nuget.org/v3/index.json
AutoMapper (6.1.1)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
AutoMapper
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{1782EFD0-F1D8-4640-A11D-1F3A8A39CBF7}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>project</RootNamespace>
<AssemblyName>project</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v4.5'">
<ItemGroup>
<Reference Include="AutoMapper">
<HintPath>..\packages\AutoMapper\lib\net45\AutoMapper.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
</ItemGroup>
</When>
</Choose>
</Project>
18 changes: 10 additions & 8 deletions src/Paket.Core/Dependencies/NuGetCache.fs
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,8 @@ let fixArchive fileName =
if isMonoRuntime then
fixDatesInArchive fileName

let GetLicenseFileName (packageName:PackageName) (version:SemVerInfo) = packageName.ToString() + "." + version.Normalize() + ".license.html"
let GetPackageFileName (packageName:PackageName) (version:SemVerInfo) = packageName.ToString() + "." + version.Normalize() + ".nupkg"
let GetLicenseFileName (packageName:PackageName) (version:SemVerInfo) = packageName.ToString().ToLower() + "." + version.Normalize() + ".license.html"
let GetPackageFileName (packageName:PackageName) (version:SemVerInfo) = packageName.ToString().ToLower() + "." + version.Normalize() + ".nupkg"

let inline isExtracted (directory:DirectoryInfo) (packageName:PackageName) (version:SemVerInfo) =
let inDir f = Path.Combine(directory.FullName, f)
Expand Down Expand Up @@ -294,16 +294,16 @@ let rec private cleanup (dir : DirectoryInfo) =
File.Move(file.FullName, newFullName)


let GetTargetUserFolder packageName (version:SemVerInfo) =
DirectoryInfo(Path.Combine(Constants.UserNuGetPackagesFolder,packageName.ToString(),version.Normalize())).FullName
let GetTargetUserFolder (packageName:PackageName) (version:SemVerInfo) =
DirectoryInfo(Path.Combine(Constants.UserNuGetPackagesFolder,packageName.CompareString,version.Normalize())).FullName

let GetTargetUserNupkg packageName (version:SemVerInfo) =
let GetTargetUserNupkg (packageName:PackageName) (version:SemVerInfo) =
let normalizedNupkgName = GetPackageFileName packageName version
let path = GetTargetUserFolder packageName version
Path.Combine(path, normalizedNupkgName)

let GetTargetUserToolsFolder packageName (version:SemVerInfo) =
DirectoryInfo(Path.Combine(Constants.UserNuGetPackagesFolder,".tools",packageName.ToString(),version.Normalize())).FullName
let GetTargetUserToolsFolder (packageName:PackageName) (version:SemVerInfo) =
DirectoryInfo(Path.Combine(Constants.UserNuGetPackagesFolder,".tools",packageName.CompareString,version.Normalize())).FullName

/// Extracts the given package to the user folder
let rec ExtractPackageToUserFolder(fileName:string, packageName:PackageName, version:SemVerInfo, isCliTool) =
Expand All @@ -327,7 +327,9 @@ let rec ExtractPackageToUserFolder(fileName:string, packageName:PackageName, ver
File.Copy(fileName,targetPackageFileName,true)

ZipFile.ExtractToDirectory(fileName, targetFolder.FullName)

// lowercase the .nuspec file to mimic NuGet behavior
let nuspecFileName = sprintf "%s.nuspec" (packageName.ToString())
File.Move(Path.Combine(targetFolder.FullName, nuspecFileName), Path.Combine(targetFolder.FullName, nuspecFileName.ToLowerInvariant()))
let cachedHashFile = Path.Combine(Constants.NuGetCacheFolder,fi.Name + ".sha512")
if not <| File.Exists cachedHashFile then
let packageHash = getSha512File fileName
Expand Down