Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Replace ZipPackage with OptimizedZipPackage to reduce overall memory …

…usage and avoid OutOfMemory exception when dealing with large packages. Work items: 2777
  • Loading branch information...
commit c2da08da1f666417ebe88a40fb722084d8d7e25d 1 parent 024e8c0
dotnetjunky authored dotnetjunky committed
Showing with 882 additions and 250 deletions.
  1. +1 −0  NuGet.sln
  2. +2 −1  changelog.txt
  3. +2 −2 src/CommandLine/Commands/PackCommand.cs
  4. +1 −1  src/CommandLine/Commands/PushCommand.cs
  5. +31 −0 src/Core/Authoring/PhysicalPackageAssemblyReference.cs
  6. +18 −4 src/Core/Authoring/PhysicalPackageFile.cs
  7. +3 −0  src/Core/Core.csproj
  8. +6 −11 src/Core/Http/HttpClient.cs
  9. +2 −1  src/Core/Http/IHttpClient.cs
  10. +12 −12 src/Core/Packages/DataServicePackage.cs
  11. +6 −6 src/Core/Packages/LocalPackage.cs
  12. +244 −0 src/Core/Packages/OptimizedZipPackage.cs
  13. +5 −6 src/Core/Packages/UnzippedPackage.cs
  14. +2 −2 src/Core/Packages/ZipPackage.cs
  15. +1 −0  src/Core/ProjectSystem/IFileSystem.cs
  16. +5 −0 src/Core/ProjectSystem/NullFileSystem.cs
  17. +16 −0 src/Core/ProjectSystem/PhysicalFileSystem.cs
  18. +9 −10 src/Core/Repositories/DataServiceContextWrapper.cs
  19. +1 −2  src/Core/Repositories/DataServicePackageRepository.cs
  20. +9 −0 src/Core/Repositories/IPackageCacheRepository.cs
  21. +1 −1  src/Core/Repositories/IPackageRepository.cs
  22. +2 −10 src/Core/Repositories/LocalPackageRepository.cs
  23. +12 −5 src/Core/Repositories/MachineCache.cs
  24. +21 −70 src/Core/Repositories/SharedPackageRepository.cs
  25. +10 −1 src/Core/Resources/NuGetResources.Designer.cs
  26. +3 −0  src/Core/Resources/NuGetResources.resx
  27. +7 −13 src/Core/Utility/PackageDownloader.cs
  28. +9 −0 src/Core/Utility/PathUtility.cs
  29. +34 −0 src/TeamFoundationServer/TfsFileSystem.cs
  30. +11 −8 src/VisualStudio/PackageRestore/PackageRestoreManager.cs
  31. +6 −0 src/VisualStudio/ProjectSystems/VsProjectSystem.cs
  32. +10 −8 src/VsConsole/PowerShellCmdlets/JsonApiCommandBase.cs
  33. +2 −0  src/VsConsole/PowerShellHost/Scripts/NuGet.Format.ps1xml
  34. +1 −0  test/Core.Test/Core.Test.csproj
  35. +5 −5 test/Core.Test/DataServicePackageRepositoryTest.cs
  36. +24 −17 test/Core.Test/DataServicePackageTest.cs
  37. +256 −0 test/Core.Test/OptimizedZipPackageTest.cs
  38. +27 −51 test/Core.Test/SharedPackageRepositoryTest.cs
  39. +3 −1 test/EndToEnd/NuGet.Tests.psm1
  40. +10 −0 test/Test.Integration/Core/LocalPackageRepositoryTest.cs
  41. +23 −0 test/Test.Utility/Mocks/EventMemoryStream.cs
  42. +15 −2 test/Test.Utility/Mocks/MockFileSystem.cs
  43. +12 −0 test/Test.Utility/Mocks/MockPackageCacheRepository.cs
  44. +2 −0  test/Test.Utility/Test.Utility.csproj
View
1  NuGet.sln
@@ -14,6 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
ProjectSection(SolutionItems) = preProject
Build\Build.proj = Build\Build.proj
Build\Build.tasks = Build\Build.tasks
+ changelog.txt = changelog.txt
CodeAnalysisDictionary.xml = CodeAnalysisDictionary.xml
Build\ilmerge.internalize.ignore.txt = Build\ilmerge.internalize.ignore.txt
Build\NuGet.Restore.targets = Build\NuGet.Restore.targets
View
3  changelog.txt
@@ -6,7 +6,8 @@ Release notes
- Add to all commands new option -ConfigFile, which enables user to use his/her own config file instead of the default one %AppData%\nuget\nuget.config.
- Add support for UNC and directory path as source for push and delete commands.
- Add support for Azure project.
-- Added a parameter to View.PackageManagerConsole. Using this parameter, PSCmdlets of Package Manager Console can be invoked from outside of VS Process.
+- Added a parameter to View.PackageManagerConsole. Using this parameter, PSCmdlets of Package Manager Console can be invoked from anywhere inside VS.
+- Reduce overall memory consumption significantly, avoiding OutOfMemory exception in certain circumstances.
*** v2.2 ***
View
4 src/CommandLine/Commands/PackCommand.cs
@@ -150,13 +150,13 @@ private IPackage BuildPackage(PackageBuilder builder, string outputPath = null)
Console.WriteLine(NuGetResources.PackageCommandSuccess, outputPath);
- return new ZipPackage(outputPath);
+ return new OptimizedZipPackage(outputPath);
}
private void PrintVerbose(string outputPath)
{
Console.WriteLine();
- var package = new ZipPackage(outputPath);
+ var package = new OptimizedZipPackage(outputPath);
Console.WriteLine("Id: {0}", package.Id);
Console.WriteLine("Version: {0}", package.Version);
View
2  src/CommandLine/Commands/PushCommand.cs
@@ -123,7 +123,7 @@ private void PushPackage(string packagePath, string source, string apiKey, TimeS
private void PushPackageCore(string source, string apiKey, PackageServer packageServer, string packageToPush, TimeSpan timeout)
{
// Push the package to the server
- var package = new ZipPackage(packageToPush);
+ var package = new OptimizedZipPackage(packageToPush);
string sourceName = CommandLineUtility.GetSourceDisplayName(source);
Console.WriteLine(NuGetResources.PushCommandPushingPackage, package.GetFullName(), sourceName);
View
31 src/Core/Authoring/PhysicalPackageAssemblyReference.cs
@@ -0,0 +1,31 @@
+using System;
+using System.IO;
+
+namespace NuGet
+{
+ public class PhysicalPackageAssemblyReference : PhysicalPackageFile, IPackageAssemblyReference
+ {
+ public PhysicalPackageAssemblyReference()
+ {
+ }
+
+ public PhysicalPackageAssemblyReference(PhysicalPackageFile file)
+ : base(file)
+ {
+
+ }
+
+ public PhysicalPackageAssemblyReference(Func<Stream> streamFactory)
+ : base(streamFactory)
+ {
+ }
+
+ public string Name
+ {
+ get
+ {
+ return String.IsNullOrEmpty(Path) ? String.Empty : System.IO.Path.GetFileName(Path);
+ }
+ }
+ }
+}
View
22 src/Core/Authoring/PhysicalPackageFile.cs
@@ -15,6 +15,12 @@ public PhysicalPackageFile()
{
}
+ public PhysicalPackageFile(PhysicalPackageFile file)
+ {
+ SourcePath = file.SourcePath;
+ TargetPath = file.TargetPath;
+ }
+
internal PhysicalPackageFile(Func<Stream> streamFactory)
{
_streamFactory = streamFactory;
@@ -101,10 +107,18 @@ public override bool Equals(object obj)
public override int GetHashCode()
{
- HashCodeCombiner combiner = new HashCodeCombiner();
- combiner.AddObject(SourcePath);
- combiner.AddObject(TargetPath);
- return combiner.CombinedHash;
+ int hash = 0;
+ if (SourcePath != null)
+ {
+ hash = SourcePath.GetHashCode();
+ }
+
+ if (TargetPath != null)
+ {
+ hash = hash * 4567 + TargetPath.GetHashCode();
+ }
+
+ return hash;
}
}
}
View
3  src/Core/Core.csproj
@@ -66,6 +66,7 @@
<Compile Include="Authoring\ManifestVersionUtility.cs" />
<Compile Include="Authoring\NullPropertyProvider.cs" />
<Compile Include="Authoring\PackageDependencySet.cs" />
+ <Compile Include="Authoring\PhysicalPackageAssemblyReference.cs" />
<Compile Include="Configuration\SettingsCredentialProvider.cs" />
<Compile Include="Configuration\ISettings.cs" />
<Compile Include="Configuration\NullSettings.cs" />
@@ -97,11 +98,13 @@
<Compile Include="NETPortable\NetPortableProfileTable.cs" />
<Compile Include="PackageRestoreConsent.cs" />
<Compile Include="Packages\LocalPackage.cs" />
+ <Compile Include="Packages\OptimizedZipPackage.cs" />
<Compile Include="Packages\UnzippedPackage.cs" />
<Compile Include="Repositories\ILatestPackageLookup.cs" />
<Compile Include="ProjectSystem\IBatchProcessor.cs" />
<Compile Include="Repositories\ICloneableRepository.cs" />
<Compile Include="Repositories\ICultureAwareRepository.cs" />
+ <Compile Include="Repositories\IPackageCacheRepository.cs" />
<Compile Include="Repositories\IPackageReferenceRepository.cs" />
<Compile Include="Repositories\IOperationAwareRepository.cs" />
<Compile Include="Repositories\IServiceBasedRepository.cs" />
View
17 src/Core/Http/HttpClient.cs
@@ -131,11 +131,10 @@ private void InitializeRequestProperties(WebRequest request)
}
}
- public byte[] DownloadData()
+ public void DownloadData(Stream targetStream)
{
const int ChunkSize = 1024 * 4; // 4KB
- byte[] buffer;
using (var response = GetResponse())
{
// Total response length
@@ -146,11 +145,7 @@ public byte[] DownloadData()
// the ContentLength = -1. In which case, we copy the whole stream and do not report progress.
if (length < 0)
{
- using (var memoryStream = new MemoryStream())
- {
- stream.CopyTo(memoryStream, ChunkSize);
- buffer = memoryStream.ToArray();
- }
+ stream.CopyTo(targetStream);
// reporting fake progress as 100%
OnProgressAvailable(100);
@@ -160,16 +155,18 @@ public byte[] DownloadData()
// We read the response stream chunk by chunk (each chunk is 4KB).
// After reading each chunk, we report the progress based on the total number bytes read so far.
int totalReadSoFar = 0;
- buffer = new byte[length];
+ byte[] buffer = new byte[ChunkSize];
while (totalReadSoFar < length)
{
- int bytesRead = stream.Read(buffer, totalReadSoFar, Math.Min(length - totalReadSoFar, ChunkSize));
+ int bytesRead = stream.Read(buffer, 0, Math.Min(length - totalReadSoFar, ChunkSize));
if (bytesRead == 0)
{
break;
}
else
{
+ targetStream.Write(buffer, 0, bytesRead);
+
totalReadSoFar += bytesRead;
OnProgressAvailable((totalReadSoFar * 100) / length);
}
@@ -177,8 +174,6 @@ public byte[] DownloadData()
}
}
}
-
- return buffer;
}
private void OnProgressAvailable(int percentage)
View
3  src/Core/Http/IHttpClient.cs
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
+using System.IO;
using System.Net;
namespace NuGet
@@ -26,6 +27,6 @@ bool AcceptCompression
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "This is expensive")]
WebResponse GetResponse();
void InitializeRequest(WebRequest request);
- byte[] DownloadData();
+ void DownloadData(Stream targetStream);
}
}
View
24 src/Core/Packages/DataServicePackage.cs
@@ -302,7 +302,7 @@ public override string ToString()
return this.GetFullName();
}
- internal void EnsurePackage(IPackageRepository cacheRepository)
+ internal void EnsurePackage(IPackageCacheRepository cacheRepository)
{
// OData caches instances of DataServicePackage while updating their property values. As a result,
// the ZipPackage that we downloaded may no longer be valid (as indicated by a newer hash).
@@ -310,11 +310,12 @@ internal void EnsurePackage(IPackageRepository cacheRepository)
// we'll simply verify the file exists between successive calls.
IPackageMetadata packageMetadata = this;
bool refreshPackage = _package == null ||
+ (_package is OptimizedZipPackage && !((OptimizedZipPackage)_package).IsValid) ||
!String.Equals(OldHash, PackageHash, StringComparison.OrdinalIgnoreCase) ||
(_usingMachineCache && !cacheRepository.Exists(Id, packageMetadata.Version));
- if (refreshPackage
- && TryGetPackage(cacheRepository, packageMetadata, out _package)
- && _package.GetHash(HashProvider).Equals(PackageHash, StringComparison.OrdinalIgnoreCase))
+ if (refreshPackage &&
+ TryGetPackage(cacheRepository, packageMetadata, out _package) &&
+ _package.GetHash(HashProvider).Equals(PackageHash, StringComparison.OrdinalIgnoreCase))
{
OldHash = PackageHash;
@@ -327,19 +328,18 @@ internal void EnsurePackage(IPackageRepository cacheRepository)
if (refreshPackage)
{
- // We either do not have a package available locally or they are invalid. Download the package from the server.
- _package = Downloader.DownloadPackage(DownloadUrl, this);
+ using (Stream targetStream = cacheRepository.CreatePackageStream(packageMetadata.Id, packageMetadata.Version))
+ {
+ // We either do not have a package available locally or they are invalid. Download the package from the server.
+ Downloader.DownloadPackage(DownloadUrl, this, targetStream);
+ }
+
+ _package = cacheRepository.FindPackage(packageMetadata.Id, packageMetadata.Version);
// Make a note that we are using an in-memory instance of the package.
_usingMachineCache = false;
- // Add the package to the cache
- cacheRepository.AddPackage(_package);
-
OldHash = PackageHash;
-
- // Clear any cached items for this package
- ZipPackage.ClearCache(_package);
}
}
View
12 src/Core/Packages/LocalPackage.cs
@@ -262,13 +262,13 @@ internal static bool IsAssemblyReference(string filePath, IEnumerable<string> re
var fileName = Path.GetFileName(filePath);
return filePath.StartsWith(Constants.LibDirectory, StringComparison.OrdinalIgnoreCase) &&
- // empty file
+ // empty file
(fileName == Constants.PackageEmptyFileName ||
- // Exclude resource assemblies
- !filePath.EndsWith(ResourceAssemblyExtension, StringComparison.OrdinalIgnoreCase) &&
- Constants.AssemblyReferencesExtensions.Contains(Path.GetExtension(filePath), StringComparer.OrdinalIgnoreCase) &&
- // If references are listed, ensure that the file is listed in it.
- (references.IsEmpty() || references.Contains(fileName)));
+ // Exclude resource assemblies
+ !filePath.EndsWith(ResourceAssemblyExtension, StringComparison.OrdinalIgnoreCase) &&
+ Constants.AssemblyReferencesExtensions.Contains(Path.GetExtension(filePath), StringComparer.OrdinalIgnoreCase) &&
+ // If references are listed, ensure that the file is listed in it.
+ (references.IsEmpty() || references.Contains(fileName)));
}
public override string ToString()
View
244 src/Core/Packages/OptimizedZipPackage.cs
@@ -0,0 +1,244 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Globalization;
+using System.IO;
+using System.IO.Packaging;
+using System.Linq;
+using System.Runtime.Versioning;
+using NuGet.Resources;
+
+namespace NuGet
+{
+ /// <summary>
+ /// Represents a NuGet package backed by a .nupkg file on disk.
+ /// </summary>
+ /// <remarks>
+ /// Unlike <see cref="ZipPackage"/>, OptimizedZipPackage doesn't store content files in memory.
+ /// Instead, it unzips the .nupkg file to a temp folder on disk, which helps reduce overall memory usage.
+ /// </remarks>
+ public class OptimizedZipPackage : LocalPackage
+ {
+ private Dictionary<string, PhysicalPackageFile> _files;
+ private ICollection<IPackageAssemblyReference> _assemblyReferences;
+ private ICollection<FrameworkName> _supportedFrameworks;
+ private readonly IFileSystem _fileSystem;
+ private readonly IFileSystem _expandedFileSystem;
+ private readonly string _packagePath;
+ private string _expandedFolderPath;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OptimizedZipPackage" /> class.
+ /// </summary>
+ /// <param name="fullPackagePath">The full package path on disk.</param>
+ /// <exception cref="System.ArgumentException">fullPackagePath</exception>
+ public OptimizedZipPackage(string fullPackagePath)
+ {
+ if (String.IsNullOrEmpty(fullPackagePath))
+ {
+ throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "fullPackagePath");
+ }
+
+ if (!File.Exists(fullPackagePath))
+ {
+ throw new ArgumentException(
+ String.Format(CultureInfo.CurrentCulture, NuGetResources.FileDoesNotExit, fullPackagePath),
+ "fullPackagePath");
+ }
+
+ string directory = Path.GetDirectoryName(fullPackagePath);
+ _fileSystem = new PhysicalFileSystem(directory);
+ _packagePath = Path.GetFileName(fullPackagePath);
+ _expandedFileSystem = new PhysicalFileSystem(Path.GetTempPath());
+
+ EnsureManifest();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OptimizedZipPackage" /> class.
+ /// </summary>
+ /// <param name="fileSystem">The file system which contains the .nupkg file.</param>
+ /// <param name="packagePath">The relative package path within the file system.</param>
+ public OptimizedZipPackage(IFileSystem fileSystem, string packagePath)
+ : this(fileSystem, packagePath, new PhysicalFileSystem(Path.GetTempPath()))
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OptimizedZipPackage" /> class.
+ /// </summary>
+ /// <param name="fileSystem">The file system which contains the .nupkg file.</param>
+ /// <param name="packagePath">The relative package path within the file system.</param>
+ /// <param name="expandedFileSystem">The file system which should be used to store unzipped content files.</param>
+ /// <exception cref="System.ArgumentNullException">fileSystem</exception>
+ /// <exception cref="System.ArgumentException">packagePath</exception>
+ public OptimizedZipPackage(IFileSystem fileSystem, string packagePath, IFileSystem expandedFileSystem)
+ {
+ if (fileSystem == null)
+ {
+ throw new ArgumentNullException("fileSystem");
+ }
+
+ if (expandedFileSystem == null)
+ {
+ throw new ArgumentNullException("expandedFileSystem");
+ }
+
+ if (String.IsNullOrEmpty(packagePath))
+ {
+ throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "packagePath");
+ }
+
+ _fileSystem = fileSystem;
+ _packagePath = packagePath;
+ _expandedFileSystem = expandedFileSystem;
+
+ EnsureManifest();
+ }
+
+ public bool IsValid
+ {
+ get
+ {
+ return _fileSystem.FileExists(_packagePath);
+ }
+ }
+
+ protected IFileSystem FileSystem
+ {
+ get
+ {
+ return _fileSystem;
+ }
+ }
+
+ public override Stream GetStream()
+ {
+ return _fileSystem.OpenFile(_packagePath);
+ }
+
+ protected override IEnumerable<IPackageFile> GetFilesBase()
+ {
+ EnsurePackageFiles();
+ return _files.Values;
+ }
+
+ protected override IEnumerable<IPackageAssemblyReference> GetAssemblyReferencesBase()
+ {
+ EnsurePackageFiles();
+
+ if (_assemblyReferences == null)
+ {
+ var references = from file in _files.Values
+ where IsAssemblyReference(file)
+ select (IPackageAssemblyReference)new PhysicalPackageAssemblyReference(file);
+
+ _assemblyReferences = new ReadOnlyCollection<IPackageAssemblyReference>(references.ToList());
+ }
+
+ return _assemblyReferences;
+ }
+
+ public override IEnumerable<FrameworkName> GetSupportedFrameworks()
+ {
+ EnsurePackageFiles();
+
+ if (_supportedFrameworks == null)
+ {
+ var fileFrameworks = _files.Values.Select(c => c.TargetFramework);
+ var combinedFrameworks = base.GetSupportedFrameworks()
+ .Concat(fileFrameworks)
+ .Where(f => f != null)
+ .Distinct();
+
+ _supportedFrameworks = new ReadOnlyCollection<FrameworkName>(combinedFrameworks.ToList());
+ }
+
+ return _supportedFrameworks;
+ }
+
+ private void EnsureManifest()
+ {
+ using (Stream stream = _fileSystem.OpenFile(_packagePath))
+ {
+ Package package = Package.Open(stream);
+ PackageRelationship relationshipType = package.GetRelationshipsByType(Constants.PackageRelationshipNamespace + PackageBuilder.ManifestRelationType).SingleOrDefault();
+
+ if (relationshipType == null)
+ {
+ throw new InvalidOperationException(NuGetResources.PackageDoesNotContainManifest);
+ }
+
+ PackagePart manifestPart = package.GetPart(relationshipType.TargetUri);
+
+ if (manifestPart == null)
+ {
+ throw new InvalidOperationException(NuGetResources.PackageDoesNotContainManifest);
+ }
+
+ using (Stream manifestStream = manifestPart.GetStream())
+ {
+ ReadManifest(manifestStream);
+ }
+ }
+ }
+
+ private void EnsurePackageFiles()
+ {
+ if (_files != null && _expandedFileSystem.DirectoryExists(_expandedFolderPath))
+ {
+ return;
+ }
+
+ _files = new Dictionary<string, PhysicalPackageFile>();
+ _assemblyReferences = null;
+ _supportedFrameworks = null;
+
+ using (Stream stream = GetStream())
+ {
+ Package package = Package.Open(stream);
+
+ _expandedFolderPath = GetExpandedFolderPath();
+
+ // unzip files inside package
+ var files = from part in package.GetParts()
+ where ZipPackage.IsPackageFile(part)
+ select part;
+
+ // now copy all package's files to disk
+ foreach (PackagePart file in files)
+ {
+ string path = UriUtility.GetPath(file.Uri);
+ string filePath = Path.Combine(_expandedFolderPath, path);
+
+ using (Stream partStream = file.GetStream())
+ {
+ // only copy the package part to disk if there doesn't exist
+ // a file with the same name.
+ if (!_expandedFileSystem.FileExists(filePath))
+ {
+ using (Stream targetStream = _expandedFileSystem.CreateFile(filePath))
+ {
+ partStream.CopyTo(targetStream);
+ }
+ }
+ }
+
+ var packageFile = new PhysicalPackageFile
+ {
+ SourcePath = _expandedFileSystem.GetFullPath(filePath),
+ TargetPath = path
+ };
+
+ _files[path] = packageFile;
+ }
+ }
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
+ protected virtual string GetExpandedFolderPath()
+ {
+ return Path.Combine("nuget", Path.GetRandomFileName());
+ }
+ }
+}
View
11 src/Core/Packages/UnzippedPackage.cs
@@ -95,12 +95,11 @@ protected override IEnumerable<IPackageAssemblyReference> GetAssemblyReferencesB
return from p in _repositoryFileSystem.GetFiles(libDirectory, "*.*", recursive: true)
let targetPath = GetPackageRelativePath(p)
where IsAssemblyReference(targetPath)
- let file = new PhysicalPackageFile(() => _repositoryFileSystem.OpenFile(p))
- {
- SourcePath = _repositoryFileSystem.GetFullPath(p),
- TargetPath = targetPath
- }
- select new ZipPackageAssemblyReference(file);
+ select new PhysicalPackageAssemblyReference
+ {
+ SourcePath = _repositoryFileSystem.GetFullPath(p),
+ TargetPath = targetPath
+ };
}
private IEnumerable<string> GetPackageFilePaths()
View
4 src/Core/Packages/ZipPackage.cs
@@ -42,7 +42,7 @@ public ZipPackage(Stream stream)
EnsureManifest();
}
- internal ZipPackage(string filePath, bool enableCaching)
+ private ZipPackage(string filePath, bool enableCaching)
{
if (String.IsNullOrEmpty(filePath))
{
@@ -171,7 +171,7 @@ private string GetAssembliesCacheKey()
return String.Format(CultureInfo.InvariantCulture, CacheKeyFormat, AssembliesCacheKey, Id, Version);
}
- private static bool IsPackageFile(PackagePart part)
+ internal static bool IsPackageFile(PackagePart part)
{
string path = UriUtility.GetPath(part.Uri);
// We exclude any opc files and the manifest file (.nuspec)
View
1  src/Core/ProjectSystem/IFileSystem.cs
@@ -17,6 +17,7 @@ public interface IFileSystem
bool DirectoryExists(string path);
void AddFile(string path, Stream stream);
void AddFile(string path, Action<Stream> writeToStream);
+ Stream CreateFile(string path);
Stream OpenFile(string path);
DateTimeOffset GetLastModified(string path);
DateTimeOffset GetCreated(string path);
View
5 src/Core/ProjectSystem/NullFileSystem.cs
@@ -75,6 +75,11 @@ public void AddFile(string path, Action<Stream> writeToStream)
// Do nothing
}
+ public Stream CreateFile(string path)
+ {
+ return Stream.Null;
+ }
+
public Stream OpenFile(string path)
{
return Stream.Null;
View
16 src/Core/ProjectSystem/PhysicalFileSystem.cs
@@ -260,6 +260,22 @@ public virtual Stream OpenFile(string path)
return File.OpenRead(path);
}
+ public virtual Stream CreateFile(string path)
+ {
+ string fullPath = GetFullPath(path);
+
+ // before creating the file, ensure the parent directory exists first.
+ string directory = Path.GetDirectoryName(fullPath);
+ if (!Directory.Exists(directory))
+ {
+ Directory.CreateDirectory(directory);
+ }
+
+ WriteAddedFileAndDirectory(path);
+
+ return File.Create(fullPath);
+ }
+
protected string MakeRelativePath(string fullPath)
{
return fullPath.Substring(Root.Length).TrimStart(Path.DirectorySeparatorChar);
View
19 src/Core/Repositories/DataServiceContextWrapper.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Data.Services.Client;
using System.Diagnostics.CodeAnalysis;
+using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
@@ -150,22 +151,20 @@ private static DataServiceMetadata GetDataServiceMetadata(Uri metadataUri)
// Make a request to the metadata uri and get the schema
var client = new HttpClient(metadataUri);
- byte[] data = client.DownloadData();
- if (data == null)
+ using (MemoryStream stream = new MemoryStream())
{
- return null;
- }
+ client.DownloadData(stream);
- string schema = Encoding.UTF8.GetString(data);
-
- return ExtractMetadataFromSchema(schema);
+ stream.Seek(0, SeekOrigin.Begin);
+ return ExtractMetadataFromSchema(stream);
+ }
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "If the docuument is in fails to parse in any way, we want to not fail.")]
- internal static DataServiceMetadata ExtractMetadataFromSchema(string schema)
+ internal static DataServiceMetadata ExtractMetadataFromSchema(Stream schemaStream)
{
- if (String.IsNullOrEmpty(schema))
+ if (schemaStream == null)
{
return null;
}
@@ -174,7 +173,7 @@ internal static DataServiceMetadata ExtractMetadataFromSchema(string schema)
try
{
- schemaDocument = XDocument.Parse(schema);
+ schemaDocument = XDocument.Load(schemaStream);
}
catch
{
View
3  src/Core/Repositories/DataServicePackageRepository.cs
@@ -230,8 +230,7 @@ public IEnumerable<IPackage> GetUpdates(IEnumerable<IPackage> packages, bool inc
{ "versions", "'" + versions + "'" },
{ "includePrerelease", ToString(includePrerelease) },
{ "includeAllVersions", ToString(includeAllVersions) },
- { "targetFrameworks", "'" + UrlEncodeOdataParameter(targetFrameworksValue) + "'" },
-
+ { "targetFrameworks", "'" + UrlEncodeOdataParameter(targetFrameworksValue) + "'" }
};
var query = Context.CreateQuery<DataServicePackage>(GetUpdatesSvcMethod, serviceParameters);
View
9 src/Core/Repositories/IPackageCacheRepository.cs
@@ -0,0 +1,9 @@
+using System.IO;
+
+namespace NuGet
+{
+ public interface IPackageCacheRepository : IPackageRepository
+ {
+ Stream CreatePackageStream(string packageId, SemanticVersion version);
+ }
+}
View
2  src/Core/Repositories/IPackageRepository.cs
@@ -12,4 +12,4 @@ public interface IPackageRepository
void AddPackage(IPackage package);
void RemovePackage(IPackage package);
}
-}
+}
View
12 src/Core/Repositories/LocalPackageRepository.cs
@@ -253,16 +253,10 @@ internal IEnumerable<string> GetPackageFiles(string filter = null)
protected virtual IPackage OpenPackage(string path)
{
- var nuspecPath = Path.ChangeExtension(path, Constants.ManifestExtension);
- if (FileSystem.FileExists(nuspecPath))
- {
- return new UnzippedPackage(FileSystem, Path.GetFileNameWithoutExtension(nuspecPath));
- }
-
- ZipPackage package;
+ OptimizedZipPackage package;
try
{
- package = new ZipPackage(() => FileSystem.OpenFile(path), _enableCaching);
+ package = new OptimizedZipPackage(FileSystem, path);
}
catch (FileFormatException ex)
{
@@ -271,8 +265,6 @@ protected virtual IPackage OpenPackage(string path)
// Set the last modified date on the package
package.Published = FileSystem.GetLastModified(path);
- // Clear the cache whenever we open a new package file
- ZipPackage.ClearCache(package);
return package;
}
View
17 src/Core/Repositories/MachineCache.cs
@@ -9,13 +9,13 @@ namespace NuGet
/// <summary>
/// The machine cache represents a location on the machine where packages are cached. It is a specific implementation of a local repository and can be used as such.
/// </summary>
- public class MachineCache : LocalPackageRepository
+ public class MachineCache : LocalPackageRepository, IPackageCacheRepository
{
/// <summary>
/// Maximum number of packages that can live in this cache.
/// </summary>
private const int MaxPackages = 100;
-
+
private const string NuGetCachePathEnvironmentVariable = "NuGetCachePath";
private static readonly Lazy<MachineCache> _instance = new Lazy<MachineCache>(() => CreateDefault(GetCachePath));
@@ -85,6 +85,12 @@ public override bool Exists(string packageId, SemanticVersion version)
return FileSystem.FileExists(packagePath);
}
+ public Stream CreatePackageStream(string packageId, SemanticVersion version)
+ {
+ string packagePath = GetPackageFilePath(packageId, version);
+ return FileSystem.CreateFile(packagePath);
+ }
+
public void Clear()
{
TryClear(GetPackageFiles().ToList());
@@ -94,7 +100,7 @@ private void TryClear(IEnumerable<string> files)
{
foreach (var packageFile in files)
{
- TryAct(() => FileSystem.DeleteFileSafe(packageFile));
+ TryAct(() => FileSystem.DeleteFileSafe(packageFile));
}
}
@@ -112,7 +118,8 @@ protected override string GetPackageFilePath(string id, SemanticVersion version)
/// Determines the cache path to use for NuGet.exe. By default, NuGet caches files under %LocalAppData%\NuGet\Cache.
/// This path can be overridden by specifying a value in the NuGetCachePath environment variable.
/// </summary>
- internal static string GetCachePath() {
+ internal static string GetCachePath()
+ {
return GetCachePath(Environment.GetEnvironmentVariable, Environment.GetFolderPath);
}
@@ -145,7 +152,7 @@ private static void TryAct(Action action)
action();
}
catch (IOException)
- {
+ {
}
catch (UnauthorizedAccessException)
{
View
91 src/Core/Repositories/SharedPackageRepository.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
@@ -69,12 +68,10 @@ public override bool Exists(string packageId, SemanticVersion version)
{
if (version != null)
{
- // optimization: if we find the .nuspec file at "id.version"\"id.version".nuspec or
- // the .nupkg file at "id.version"\"id.version".nupkg, consider it exists
+ // optimization: if we find the .nupkg file at "id.version"\"id.version.nupkg", consider it exist
bool hasPackageDirectory = version.GetComparableVersionStrings()
.Select(v => packageId + "." + v)
- .Any(path => FileSystem.FileExists(Path.Combine(path, path + Constants.PackageExtension)) ||
- FileSystem.FileExists(Path.Combine(path, path + Constants.ManifestExtension)));
+ .Any(path => FileSystem.FileExists(Path.Combine(path, path + Constants.PackageExtension)));
if (hasPackageDirectory)
{
@@ -85,22 +82,6 @@ public override bool Exists(string packageId, SemanticVersion version)
return FindPackage(packageId, version) != null;
}
- public override IPackage FindPackage(string packageId, SemanticVersion version)
- {
- if (version != null)
- {
- string packagePath = GetManifestFilePath(packageId, version);
- if (FileSystem.FileExists(packagePath))
- {
- string packageDirectory = PathResolver.GetPackageDirectory(packageId, version);
- return new UnzippedPackage(FileSystem, packageDirectory);
- }
- }
-
- // if we didn't find the .nuspec file, search for .nupkg file
- return base.FindPackage(packageId, version);
- }
-
public void AddPackageReferenceEntry(string packageId, SemanticVersion version)
{
if (_packageReferenceFile != null)
@@ -124,47 +105,17 @@ protected IEnumerable<IPackage> SearchPackages()
{
string partialPath = Path.Combine(directory, directory);
- // always search for .nuspec-based packages first
- if (FileSystem.FileExists(partialPath + Constants.ManifestExtension))
- {
- yield return new UnzippedPackage(FileSystem, directory);
- continue;
- }
-
string nupkgPath = partialPath + Constants.PackageExtension;
if (FileSystem.FileExists(nupkgPath))
{
- yield return new ZipPackage(FileSystem.GetFullPath(nupkgPath));
+ yield return new SharedOptimizedZipPackage(FileSystem, nupkgPath);
}
}
}
- public override void AddPackage(IPackage package)
- {
- // Starting from 2.1, we save the nuspec file into the subdirectory with the name as <packageId>.<version>
- // for example, for jQuery version 1.0, it will be "jQuery.1.0\\jQuery.1.0.nuspec"
- string packageFilePath = GetManifestFilePath(package);
- Manifest manifest = Manifest.Create(package);
-
- // The IPackage object doesn't carry the References information.
- // Thus we set the References for the manifest to the set of all valid assembly references
-
- manifest.Metadata.References = package.AssemblyReferences
- .Select(p => new ManifestReference() { File = p.Name })
- .Distinct()
- .ToList();
-
- FileSystem.AddFileWithCheck(packageFilePath, manifest.Save);
-
- // But in order to maintain backwards compatibility with older versions of NuGet,
- // we will save the .nupkg file too. This way, 2.1 will read the .nuspec file, and
- // pre 2.1 will read the .nupkg
- base.AddPackage(package);
- }
-
public override void RemovePackage(IPackage package)
{
- string packageFilePath = GetManifestFilePath(package);
+ string packageFilePath = GetManifestFilePath(package.Id, package.Version);
if (FileSystem.FileExists(packageFilePath))
{
// delete .nuspec file
@@ -190,18 +141,7 @@ protected virtual IPackageRepository CreateRepository(string path)
protected override IPackage OpenPackage(string path)
{
- // We could either be passed in manifest path or the path to the nupkg. The manifest path ensures that the calling code has already verified the existence of the
- // manifest and we can return an UnzippedPackageRepository. If the caller passed in a nupkg, we'll quickly verify if a manifest exists alongside.
- string extension = Path.GetExtension(path);
- if (extension.Equals(Constants.ManifestExtension, StringComparison.OrdinalIgnoreCase) ||
- FileSystem.FileExists(Path.ChangeExtension(path, Constants.ManifestExtension)))
- {
- return new UnzippedPackage(FileSystem, Path.GetDirectoryName(path));
- }
-
- // if the package path doesn't end with .nuspec, it means this repository was created before 2.1.
- // in that case, let the base class read the .nupkg file
- return base.OpenPackage(path);
+ return new SharedOptimizedZipPackage(FileSystem, path);
}
private IEnumerable<IPackageRepository> GetRepositories()
@@ -390,11 +330,6 @@ private string NormalizePath(string path)
return path;
}
- private string GetManifestFilePath(IPackage package)
- {
- return GetManifestFilePath(package.Id, package.Version);
- }
-
private string GetManifestFilePath(string packageId, SemanticVersion version)
{
string packageDirectory = PathResolver.GetPackageDirectory(packageId, version);
@@ -402,5 +337,21 @@ private string GetManifestFilePath(string packageId, SemanticVersion version)
return Path.Combine(packageDirectory, manifestFileName);
}
+
+ private class SharedOptimizedZipPackage : OptimizedZipPackage
+ {
+ private readonly string _folderPath;
+
+ public SharedOptimizedZipPackage(IFileSystem fileSystem, string packagePath)
+ : base(fileSystem, packagePath, fileSystem)
+ {
+ _folderPath = Path.GetDirectoryName(packagePath);
+ }
+
+ protected override string GetExpandedFolderPath()
+ {
+ return _folderPath;
+ }
+ }
}
}
View
11 src/Core/Resources/NuGetResources.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
-// Runtime Version:4.0.30319.17929
+// Runtime Version:4.0.30319.18010
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -232,6 +232,15 @@ internal class NuGetResources {
}
/// <summary>
+ /// Looks up a localized string similar to File &apos;{0}&apos; does not exist..
+ /// </summary>
+ internal static string FileDoesNotExit {
+ get {
+ return ResourceManager.GetString("FileDoesNotExit", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to The schema version of &apos;{0}&apos; is incompatible with version {1} of NuGet. Please upgrade NuGet to the latest version from http://go.microsoft.com/fwlink/?LinkId=213942..
/// </summary>
internal static string IncompatibleSchema {
View
3  src/Core/Resources/NuGetResources.resx
@@ -373,4 +373,7 @@
<data name="ErrorReadingPackage" xml:space="preserve">
<value>Unable to read package from path '{0}'.</value>
</data>
+ <data name="FileDoesNotExit" xml:space="preserve">
+ <value>File '{0}' does not exist.</value>
+ </data>
</root>
View
20 src/Core/Utility/PackageDownloader.cs
@@ -13,33 +13,30 @@ public class PackageDownloader : IHttpClientEvents
public event EventHandler<ProgressEventArgs> ProgressAvailable = delegate { };
public event EventHandler<WebRequestEventArgs> SendingRequest = delegate { };
- public virtual IPackage DownloadPackage(Uri uri, IPackageMetadata package)
+ public virtual void DownloadPackage(Uri uri, IPackageMetadata package, Stream targetStream)
{
if (uri == null)
{
throw new ArgumentNullException("uri");
}
- if (package == null)
- {
- throw new ArgumentNullException("package");
- }
var downloadClient = new HttpClient(uri)
{
UserAgent = HttpUtility.CreateUserAgentString(DefaultUserAgentClient)
};
- return DownloadPackage(downloadClient, package);
+ DownloadPackage(downloadClient, package, targetStream);
}
- public IPackage DownloadPackage(IHttpClient downloadClient, IPackageMetadata package)
+ public void DownloadPackage(IHttpClient downloadClient, IPackageMetadata package, Stream targetStream)
{
if (downloadClient == null)
{
throw new ArgumentNullException("downloadClient");
}
- if (package == null)
+
+ if (targetStream == null)
{
- throw new ArgumentNullException("package");
+ throw new ArgumentNullException("targetStream");
}
// Get the operation display text
@@ -60,10 +57,7 @@ public IPackage DownloadPackage(IHttpClient downloadClient, IPackageMetadata pac
downloadClient.ProgressAvailable += progressAvailableHandler;
downloadClient.SendingRequest += beforeSendingRequesthandler;
- // TODO: This gets held onto in memory which we want to get rid of eventually
- byte[] buffer = downloadClient.DownloadData();
- Func<Stream> streamFactory = () => new MemoryStream(buffer, writable: false);
- return new ZipPackage(streamFactory, enableCaching: true);
+ downloadClient.DownloadData(targetStream);
}
finally
{
View
9 src/Core/Utility/PathUtility.cs
@@ -45,6 +45,15 @@ private static string EnsureTrailingCharacter(string path, char trailingCharacte
return path + trailingCharacter;
}
+ public static void EnsureParentDirectory(string filePath)
+ {
+ string directory = Path.GetDirectoryName(filePath);
+ if (!Directory.Exists(directory))
+ {
+ Directory.CreateDirectory(directory);
+ }
+ }
+
/// <summary>
/// Returns path2 relative to path1
/// </summary>
View
34 src/TeamFoundationServer/TfsFileSystem.cs
@@ -79,6 +79,40 @@ private void AddFileCore(string path, Action addFile)
}
}
+ public override Stream CreateFile(string path)
+ {
+ string fullPath = GetFullPath(path);
+
+ if (!base.FileExists(path))
+ {
+ // if this file doesn't exist, it's a new file
+ Stream stream = base.CreateFile(path);
+ Workspace.PendAdd(fullPath);
+ return stream;
+ }
+ else
+ {
+ // otherwise it's an edit.
+
+ bool requiresEdit = false;
+
+ bool sourceControlBound = IsSourceControlBound(path);
+ if (sourceControlBound)
+ {
+ // only pend edit if the file is not already in edit state
+ var pendingChanges = Workspace.GetPendingChanges(fullPath, RecursionType.None);
+ requiresEdit = !pendingChanges.Any(c => c.IsEdit || c.IsAdd);
+ }
+
+ if (requiresEdit)
+ {
+ Workspace.PendEdit(fullPath);
+ }
+
+ return base.CreateFile(path);
+ }
+ }
+
public override void DeleteFile(string path)
{
string fullPath = GetFullPath(path);
View
19 src/VisualStudio/PackageRestore/PackageRestoreManager.cs
@@ -1,19 +1,19 @@
-using EnvDTE;
-using Microsoft.VisualStudio.Project;
-using Microsoft.VisualStudio.Project.Designers;
-using Microsoft.VisualStudio.Shell.Interop;
-using NuGet.VisualStudio.Resources;
-using System;
+using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
+using EnvDTE;
+using Microsoft.VisualStudio.Project;
+using Microsoft.VisualStudio.Project.Designers;
+using Microsoft.VisualStudio.Shell.Interop;
+using NuGet.VisualStudio.Resources;
using MsBuildProject = Microsoft.Build.Evaluation.Project;
-using System.Diagnostics.CodeAnalysis;
namespace NuGet.VisualStudio
{
@@ -479,7 +479,10 @@ private IPackage GetPackage(IPackageRepository repository, string packageId, boo
if (!fromCache)
{
- _localCacheRepository.AddPackage(package);
+ if (!_localCacheRepository.Exists(package))
+ {
+ _localCacheRepository.AddPackage(package);
+ }
// swap to the Zip package to avoid potential downloading package twice
package = _localCacheRepository.FindPackage(package.Id, package.Version);
View
6 src/VisualStudio/ProjectSystems/VsProjectSystem.cs
@@ -114,6 +114,12 @@ private void AddFileCore(string path, Action addFile)
}
}
+ public override Stream CreateFile(string path)
+ {
+ EnsureCheckedOutIfExists(path);
+ return base.CreateFile(path);
+ }
+
public override void DeleteDirectory(string path, bool recursive = false)
{
// Only delete this folder if it is empty and we didn't specify that we want to recurse
View
18 src/VsConsole/PowerShellCmdlets/JsonApiCommandBase.cs
@@ -19,20 +19,20 @@ public abstract class JsonApiCommandBase<T> : NuGetBaseCommand where T : class
protected JsonApiCommandBase()
: this(
- ServiceLocator.GetInstance<ISolutionManager>(),
- ServiceLocator.GetInstance<IVsPackageManagerFactory>(),
- ServiceLocator.GetInstance<IHttpClientEvents>(),
+ ServiceLocator.GetInstance<ISolutionManager>(),
+ ServiceLocator.GetInstance<IVsPackageManagerFactory>(),
+ ServiceLocator.GetInstance<IHttpClientEvents>(),
ServiceLocator.GetInstance<IPackageRepositoryFactory>(),
- ServiceLocator.GetInstance<IVsPackageSourceProvider>())
+ ServiceLocator.GetInstance<IVsPackageSourceProvider>())
{
}
protected JsonApiCommandBase(
- ISolutionManager solutionManager,
- IVsPackageManagerFactory packageManagerFactory,
+ ISolutionManager solutionManager,
+ IVsPackageManagerFactory packageManagerFactory,
IHttpClientEvents httpClientEvents,
IPackageRepositoryFactory repositoryFactory,
- IVsPackageSourceProvider packageSourceProvider)
+ IVsPackageSourceProvider packageSourceProvider)
: base(solutionManager, packageManagerFactory, httpClientEvents)
{
_repositoryFactory = repositoryFactory;
@@ -73,8 +73,10 @@ protected virtual IEnumerable<T> GetResults(Uri apiEndpointUri)
{
var jsonSerializer = new DataContractJsonSerializer(typeof(T[]));
var httpClient = new HttpClient(apiEndpointUri);
- using (var stream = new MemoryStream(httpClient.DownloadData()))
+ using (var stream = new MemoryStream())
{
+ httpClient.DownloadData(stream);
+ stream.Seek(0, SeekOrigin.Begin);
return jsonSerializer.ReadObject(stream) as T[];
}
}
View
2  src/VsConsole/PowerShellHost/Scripts/NuGet.Format.ps1xml
@@ -7,6 +7,7 @@
<TypeName>NuGet.ZipPackage</TypeName>
<TypeName>NuGet.DataServicePackage</TypeName>
<TypeName>NuGet.UnzippedPackage</TypeName>
+ <TypeName>NuGet.OptimizedZipPackage</TypeName>
</ViewSelectedBy>
<TableControl>
@@ -54,6 +55,7 @@
<Name>NuGet.IPackage.List</Name>
<ViewSelectedBy>
<TypeName>NuGet.ZipPackage</TypeName>
+ <TypeName>NuGet.OptimizedZipPackage</TypeName>
<TypeName>NuGet.UnzippedPackage</TypeName>
</ViewSelectedBy>
View
1  test/Core.Test/Core.Test.csproj
@@ -74,6 +74,7 @@
<Compile Include="NetPortableProfileTest.cs" />
<Compile Include="NullFileSystemTest.cs" />
<Compile Include="NullSettingsTest.cs" />
+ <Compile Include="OptimizedZipPackageTest.cs" />
<Compile Include="PackageDependencyTest.cs" />
<Compile Include="PackageExtensionsTest.cs" />
<Compile Include="PackageHelperTest.cs" />
View
10 test/Core.Test/DataServicePackageRepositoryTest.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using Moq;
using Xunit;
@@ -6,7 +7,6 @@
namespace NuGet.Test
{
-
public class DataServicePackageRepositoryTest
{
[Fact]
@@ -199,7 +199,7 @@ public void UpdatesMethodWithPortableFrameworkEncodesTheValueCorrectly()
IEnumerable<string> sampleProperties, IEnumerable<string> expectedMethods)
{
// Act
- var schemaMetadata = DataServiceContextWrapper.ExtractMetadataFromSchema(schema);
+ var schemaMetadata = DataServiceContextWrapper.ExtractMetadataFromSchema(schema.AsStream());
// Assert
Assert.NotNull(schemaMetadata);
@@ -217,13 +217,13 @@ public void UpdatesMethodWithPortableFrameworkEncodesTheValueCorrectly()
public void ExtractMetadataReturnsNullForBadSchema(string schema)
{
// Act
- var schemaMetadata = DataServiceContextWrapper.ExtractMetadataFromSchema(schema);
+ var stream = schema == null ? (Stream)null : schema.AsStream();
+ var schemaMetadata = DataServiceContextWrapper.ExtractMetadataFromSchema(stream);
// Assert
Assert.Null(schemaMetadata);
}
-
private class NuGetFeedSchema
{
public const string SchemaWithMethod = @"<?xml version=""1.0"" encoding=""utf-8"" standalone=""yes""?>
@@ -348,4 +348,4 @@ private class NuGetFeedSchema
</edmx:Edmx>";
}
}
-}
+}
View
41 test/Core.Test/DataServicePackageTest.cs
@@ -102,12 +102,13 @@ public void EnsurePackageDownloadsThePackageIfItIsNotCachedInMemoryOnInMachineCa
// Arrange
var zipPackage = PackageUtility.CreatePackage("A", "1.2");
var uri = new Uri("http://nuget.org");
+ var mockRepository = new MockPackageCacheRepository();
var packageDownloader = new Mock<PackageDownloader>();
- packageDownloader.Setup(d => d.DownloadPackage(uri, It.IsAny<IPackageMetadata>()))
- .Returns(zipPackage)
+ packageDownloader.Setup(d => d.DownloadPackage(uri, It.IsAny<IPackageMetadata>(), It.IsAny<Stream>()))
+ .Callback(() => mockRepository.AddPackage(zipPackage))
.Verifiable();
var hashProvider = new Mock<IHashProvider>(MockBehavior.Strict);
- var mockRepository = new MockPackageRepository();
+
var context = new Mock<IDataServiceContext>();
context.Setup(c => c.GetReadStreamUri(It.IsAny<object>())).Returns(uri).Verifiable();
@@ -136,12 +137,13 @@ public void EnsurePackageDownloadsUsesInMemoryCachedInstanceOnceDownloaded()
// Arrange
var zipPackage = PackageUtility.CreatePackage("A", "1.2");
var uri = new Uri("http://nuget.org");
+ var mockRepository = new MockPackageCacheRepository();
var packageDownloader = new Mock<PackageDownloader>();
- packageDownloader.Setup(d => d.DownloadPackage(uri, It.IsAny<IPackageMetadata>()))
- .Returns(zipPackage)
+ packageDownloader.Setup(d => d.DownloadPackage(uri, It.IsAny<IPackageMetadata>(), It.IsAny<Stream>()))
+ .Callback(() => mockRepository.AddPackage(zipPackage))
.Verifiable();
var hashProvider = new Mock<IHashProvider>(MockBehavior.Strict);
- var mockRepository = new MockPackageRepository();
+
var context = new Mock<IDataServiceContext>();
context.Setup(c => c.GetReadStreamUri(It.IsAny<object>())).Returns(uri).Verifiable();
@@ -163,7 +165,7 @@ public void EnsurePackageDownloadsUsesInMemoryCachedInstanceOnceDownloaded()
// Assert
Assert.Equal(zipPackage, servicePackage._package);
context.Verify(s => s.GetReadStreamUri(It.IsAny<object>()), Times.Once());
- packageDownloader.Verify(d => d.DownloadPackage(uri, It.IsAny<IPackageMetadata>()), Times.Once());
+ packageDownloader.Verify(d => d.DownloadPackage(uri, It.IsAny<IPackageMetadata>(), It.IsAny<Stream>()), Times.Once());
Assert.True(mockRepository.Exists(zipPackage));
}
@@ -178,7 +180,7 @@ public void EnsurePackageDownloadsUsesMachineCacheIfAvailable()
var hashProvider = new Mock<IHashProvider>(MockBehavior.Strict);
hashProvider.Setup(h => h.CalculateHash(It.IsAny<Stream>())).Returns(hashBytes);
- var mockRepository = new MockPackageRepository();
+ var mockRepository = new MockPackageCacheRepository();
mockRepository.Add(zipPackage);
var servicePackage = new DataServicePackage
@@ -200,26 +202,33 @@ public void EnsurePackageDownloadsUsesMachineCacheIfAvailable()
public void EnsurePackageDownloadsPackageIfCacheIsInvalid()
{
// Arrange
- byte[] hashBytes1 = new byte[] { 1, 2, 3, 4 }, hashBytes2 = new byte[] { 3, 4, 5, 6 };
- string hash1 = Convert.ToBase64String(hashBytes1), hash2 = Convert.ToBase64String(hashBytes2);
+ byte[] hashBytes1 = new byte[] { 1, 2, 3, 4 };
+ byte[] hashBytes2 = new byte[] { 3, 4, 5, 6 };
+ string hash1 = Convert.ToBase64String(hashBytes1);
+ string hash2 = Convert.ToBase64String(hashBytes2);
var zipPackage1 = PackageUtility.CreatePackage("A", "1.2");
- var zipPackage2 = PackageUtility.CreatePackage("A", "1.2");
+ var zipPackage2 = PackageUtility.CreatePackage("B", "1.2");
var hashProvider = new Mock<IHashProvider>(MockBehavior.Strict);
hashProvider.Setup(h => h.CalculateHash(It.IsAny<Stream>())).Returns(hashBytes1);
- var mockRepository = new Mock<IPackageRepository>(MockBehavior.Strict);
+ var mockRepository = new Mock<IPackageCacheRepository>(MockBehavior.Strict);
var lookup = mockRepository.As<IPackageLookup>();
lookup.Setup(s => s.FindPackage("A", new SemanticVersion("1.2")))
.Returns(zipPackage1);
lookup.Setup(s => s.Exists("A", new SemanticVersion("1.2")))
.Returns(true);
- mockRepository.Setup(s => s.AddPackage(zipPackage2)).Verifiable();
+ mockRepository.Setup(s => s.CreatePackageStream("A", new SemanticVersion("1.2")))
+ .Returns(new MemoryStream());
var uri = new Uri("http://nuget.org");
var packageDownloader = new Mock<PackageDownloader>();
- packageDownloader.Setup(d => d.DownloadPackage(uri, It.IsAny<IPackageMetadata>()))
- .Returns(zipPackage2)
+ packageDownloader.Setup(d => d.DownloadPackage(uri, It.IsAny<IPackageMetadata>(), It.IsAny<Stream>()))
+ .Callback(() =>
+ {
+ lookup.Setup(s => s.FindPackage("A", new SemanticVersion("1.2")))
+ .Returns(zipPackage2);
+ })
.Verifiable();
var context = new Mock<IDataServiceContext>();
@@ -249,10 +258,8 @@ public void EnsurePackageDownloadsPackageIfCacheIsInvalid()
// Assert 2
Assert.Equal(zipPackage2, servicePackage._package);
- mockRepository.Verify();
context.Verify();
packageDownloader.Verify();
-
}
}
}
View
256 test/Core.Test/OptimizedZipPackageTest.cs
@@ -0,0 +1,256 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Runtime.Versioning;
+using NuGet.Test.Mocks;
+using NuGet.Test.Utility;
+using Xunit;
+
+namespace NuGet.Test
+{
+ public class OptimizedZipPackageTest
+ {
+ [Fact]
+ public void TestingCtorWithFileSystemAndPackagePath()
+ {
+ // Arrange
+ var ms = GetPackageStream();
+
+ var fileSystem = new MockFileSystem("x:\\");
+ fileSystem.AddFile("pam.nupkg", ms);
+
+ // Act
+ var ozp = new OptimizedZipPackage(fileSystem, "pam.nupkg", new MockFileSystem("y:\\"));
+
+ // Assert
+ Assert.Equal("Package", ozp.Id);
+ Assert.Equal(new SemanticVersion("1.0"), ozp.Version);
+ Assert.Equal("This is a test package", ozp.Description);
+ Assert.Equal("This is a release note.", ozp.ReleaseNotes);
+ Assert.Equal("Copyright", ozp.Copyright);
+ Assert.Equal("dotnetjunky", ozp.Authors.First());
+
+ // Order is not gauranteed (or required) from GetFiles(),
+ // but we rely on the order for a few of the asserts,
+ // and it appears to not behave the same way on Mono,
+ // so we call "order by" here to force a specific order.
+ var files = ozp.GetFiles().OrderBy(k => k.Path).ToList();
+
+ Assert.Equal(2, files.Count);
+ Assert.Equal(PathFixUtility.FixPath(@"content\foo"), files[0].Path);
+ Assert.Equal(PathFixUtility.FixPath(@"lib\40\A.dll"), files[1].Path);
+
+ var assemblyReferences = ozp.AssemblyReferences.ToList();
+ Assert.Equal(1, assemblyReferences.Count);
+ Assert.Equal("A.dll", assemblyReferences[0].Name);
+ Assert.Equal(new FrameworkName(".NETFramework", new Version("4.0")), assemblyReferences[0].TargetFramework);
+
+ var supportedReferences = ozp.GetSupportedFrameworks().OrderBy(p => p.FullName).ToList();
+ Assert.Equal(3, supportedReferences.Count);
+ Assert.Equal(new FrameworkName(".NETFramework", new Version("4.0")), supportedReferences[0]);
+ Assert.Equal(new FrameworkName("Silverlight", new Version("5.0")), supportedReferences[1]);
+ Assert.Equal(new FrameworkName("Windows", new Version("8.0")), supportedReferences[2]);
+ }
+
+ [Fact]
+ public void CallingCtorDoesNotExpandFiles()
+ {
+ // Arrange
+ var ms = GetPackageStream();
+
+ var fileSystem = new MockFileSystem("x:\\");
+ fileSystem.AddFile("pam.nupkg", ms);
+
+ var expandedFileSystem = new MockFileSystem();
+
+ // Act
+ var ozp = new TestableOptimizedZipPackage(fileSystem, "pam.nupkg", expandedFileSystem);
+
+ // Assert
+ Assert.False(ozp.HasCalledExpandedFolderPath);
+ Assert.Equal(0, expandedFileSystem.Paths.Count);
+ }
+
+ [Fact]
+ public void CallingGetFilesExpandFilesIntoSpecifiedFileSystem()
+ {
+ // Arrange
+ var ms = GetPackageStream();
+
+ var fileSystem = new MockFileSystem("x:\\");
+ fileSystem.AddFile("pam.nupkg", ms);
+
+ var expandedFileSystem = new MockFileSystem("y:\\");
+
+ var ozp = new TestableOptimizedZipPackage(fileSystem, "pam.nupkg", expandedFileSystem);
+
+ // Act
+ var files = ozp.GetFiles().ToList();
+
+ // Assert
+ Assert.Equal(2, files.Count);
+ Assert.True(expandedFileSystem.FileExists("random\\content\\foo"));
+ Assert.True(expandedFileSystem.FileExists("random\\lib\\40\\A.dll"));
+ }
+
+ [Fact]
+ public void CallingGetFilesTwiceDoesNotExpandFilesIntoSpecifiedFileSystemAgain()
+ {
+ // Arrange
+ var ms = GetPackageStream();
+
+ var fileSystem = new MockFileSystem("x:\\");
+ fileSystem.AddFile("pam.nupkg", ms);
+
+ var expandedFileSystem = new MockFileSystem("y:\\");
+
+ var ozp = new TestableOptimizedZipPackage(fileSystem, "pam.nupkg", expandedFileSystem);
+ var files = ozp.GetFiles().ToList();
+
+ Assert.True(expandedFileSystem.FileExists("random\\content\\foo"));
+ Assert.True(expandedFileSystem.FileExists("random\\lib\\40\\A.dll"));
+
+ ozp.Reset();
+
+ // Act
+ files = ozp.GetFiles().ToList();
+
+ // Assert
+ Assert.False(ozp.HasCalledExpandedFolderPath);
+ }
+
+ [Fact]
+ public void CallingAssemblyReferencesExpandFilesIntoSpecifiedFileSystem()
+ {
+ // Arrange
+ var ms = GetPackageStream();
+
+ var fileSystem = new MockFileSystem("x:\\");
+ fileSystem.AddFile("pam.nupkg", ms);
+
+ var expandedFileSystem = new MockFileSystem("y:\\");
+
+ var ozp = new TestableOptimizedZipPackage(fileSystem, "pam.nupkg", expandedFileSystem);
+
+ // Act
+ var files = ozp.AssemblyReferences.ToList();
+
+ // Assert
+ Assert.Equal(1, files.Count);
+ Assert.True(expandedFileSystem.FileExists("random\\content\\foo"));
+ Assert.True(expandedFileSystem.FileExists("random\\lib\\40\\A.dll"));
+ }
+
+ [Fact]
+ public void CallingGetSupportedFrameworksExpandFilesIntoSpecifiedFileSystem()
+ {
+ // Arrange
+ var ms = GetPackageStream();
+
+ var fileSystem = new MockFileSystem("x:\\");
+ fileSystem.AddFile("pam.nupkg", ms);
+
+ var expandedFileSystem = new MockFileSystem("y:\\");
+
+ var ozp = new TestableOptimizedZipPackage(fileSystem, "pam.nupkg", expandedFileSystem);
+
+ // Act
+ var files = ozp.GetSupportedFrameworks().ToList();
+
+ // Assert
+ Assert.Equal(3, files.Count);
+ Assert.True(expandedFileSystem.FileExists("random\\content\\foo"));
+ Assert.True(expandedFileSystem.FileExists("random\\lib\\40\\A.dll"));
+ }
+
+ [Fact]
+ public void IsValidIsTrueWhenNupkgFileIsDeleted()
+ {
+ // Arrange
+ var ms = GetPackageStream();
+
+ var fileSystem = new MockFileSystem("x:\\");
+ fileSystem.AddFile("pam.nupkg", ms);
+
+ var expandedFileSystem = new MockFileSystem("y:\\");
+
+ var ozp = new TestableOptimizedZipPackage(fileSystem, "pam.nupkg", expandedFileSystem);
+ Assert.True(ozp.IsValid);
+
+ // Act
+ fileSystem.DeleteFile("pam.nupkg");
+
+ // Assert
+ Assert.False(ozp.IsValid);
+ }
+
+ [Fact]
+ public void SkipExistingFilesWhileExpandingFiles()
+ {
+ // Arrange
+ var ms = GetPackageStream();
+
+ var fileSystem = new MockFileSystem("x:\\");
+ fileSystem.AddFile("pam.nupkg", ms);
+
+ var expandedFileSystem = new MockFileSystem("y:\\");
+ expandedFileSystem.AddFile("random\\content\\foo", "happy new year");
+
+ var ozp = new TestableOptimizedZipPackage(fileSystem, "pam.nupkg", expandedFileSystem);
+
+ // Act
+ var files = ozp.GetFiles().ToList();
+
+ // Assert
+ Assert.True(expandedFileSystem.FileExists("random\\content\\foo"));
+ Assert.True(expandedFileSystem.FileExists("random\\lib\\40\\A.dll"));
+ Assert.Equal("happy new year", expandedFileSystem.ReadAllText("random\\content\\foo"));
+ }
+
+ private static MemoryStream GetPackageStream()
+ {
+ var builder = new PackageBuilder();
+ builder.Id = "Package";
+ builder.Version = new SemanticVersion("1.0");
+ builder.Authors.Add("dotnetjunky");
+ builder.Description = "This is a test package";
+ builder.ReleaseNotes = "This is a release note.";
+ builder.Copyright = "Copyright";
+ builder.Files.AddRange(
+ PackageUtility.CreateFiles(
+ new[] { PathFixUtility.FixPath(@"lib\40\A.dll"), PathFixUtility.FixPath(@"content\foo") }
+ ));
+
+ builder.FrameworkReferences.AddRange(
+ new[] { new FrameworkAssemblyReference("A", new[] { VersionUtility.ParseFrameworkName("sl50") }),
+ new FrameworkAssemblyReference("B", new[] { VersionUtility.ParseFrameworkName("windows8") })
+ });
+
+ var ms = new MemoryStream();
+ builder.Save(ms);
+ ms.Seek(0, SeekOrigin.Begin);
+ return ms;
+ }
+
+ private class TestableOptimizedZipPackage : OptimizedZipPackage
+ {
+ public TestableOptimizedZipPackage(IFileSystem fileSystem, string packagePath, IFileSystem expandedFileSystem)
+ : base(fileSystem, packagePath, expandedFileSystem)
+ {
+ }
+
+ public bool HasCalledExpandedFolderPath { get; private set; }
+
+ public void Reset()
+ {
+ HasCalledExpandedFolderPath = false;
+ }
+
+ protected override string GetExpandedFolderPath()
+ {
+ HasCalledExpandedFolderPath = true;
+ return "random";
+ }
+ }
+ }
+}
View
78 test/Core.Test/SharedPackageRepositoryTest.cs
@@ -14,10 +14,10 @@ public class SharedPackageRepositoryTest
[InlineData("A", "2.0", "A.2.0\\A.2.0.nuspec", "A.2.0\\A.2.0.nupkg")]
[InlineData("B", "1.0.0-alpha", "B.1.0.0-alpha\\B.1.0.0-alpha.nuspec", "B.1.0.0-alpha\\B.1.0.0-alpha.nupkg")]
[InlineData("C", "3.1.2.4-rtm", "C.3.1.2.4-rtm\\C.3.1.2.4-rtm.nuspec", "C.3.1.2.4-rtm\\C.3.1.2.4-rtm.nupkg")]
- public void CallAddPackageWillAddBothNuspecFileAndNupkgFile(string id, string version, string nuspecPath, string nupkgPath)
+ public void CallAddPackageWillOnlyAddNupkgFile(string id, string version, string nuspecPath, string nupkgPath)
{
// Arrange
- var fileSystem = new MockFileSystem("x:\root");
+ var fileSystem = new MockFileSystem("x:\\root");
var configFileSystem = new MockFileSystem();
var repository = new SharedPackageRepository(new DefaultPackagePathResolver(fileSystem), fileSystem, configFileSystem);
@@ -25,12 +25,12 @@ public void CallAddPackageWillAddBothNuspecFileAndNupkgFile(string id, string ve
repository.AddPackage(PackageUtility.CreatePackage(id, version));
// Assert
- Assert.True(fileSystem.FileExists(nuspecPath));
+ Assert.False(fileSystem.FileExists(nuspecPath));
Assert.True(fileSystem.FileExists(nupkgPath));
}
[Fact]
- public void CallAddPackageWillAddNuspecWhichHasReferencesData()
+ public void CallAddPackageWillNotAddNuspec()
{
// Arrange
var fileSystem = new MockFileSystem("x:\root");
@@ -43,15 +43,8 @@ public void CallAddPackageWillAddNuspecWhichHasReferencesData()
assemblyReferences: new [] { "net40\\A.dll", "sl45\\B.dll", "A.dll", "win8\\C.dll" }));
// Assert
- Assert.True(fileSystem.FileExists("A.1.0\\A.1.0.nuspec"));
-
- Stream manifestContentStream = fileSystem.OpenFile("A.1.0\\A.1.0.nuspec");
- Manifest manifest = Manifest.ReadFrom(manifestContentStream);
-
- Assert.Equal(3, manifest.Metadata.References.Count);
- Assert.Equal("A.dll", manifest.Metadata.References[0].File);
- Assert.Equal("B.dll", manifest.Metadata.References[1].File);
- Assert.Equal("C.dll", manifest.Metadata.References[2].File);
+ Assert.False(fileSystem.FileExists("A.1.0\\A.1.0.nuspec"));
+ Assert.True(fileSystem.FileExists("A.1.0\\A.1.0.nupkg"));
}
[Theory]
@@ -61,7 +54,7 @@ public void CallAddPackageWillAddNuspecWhichHasReferencesData()
public void CallRemovePackageWillRemoveNuspecFile(string id, string version, string unexpectedPath)
{
// Arrange
- var fileSystem = new MockFileSystem("x:\root");
+ var fileSystem = new MockFileSystem("x:\\root");
fileSystem.AddFile(unexpectedPath);
var configFileSystem = new MockFileSystem();
var repository = new SharedPackageRepository(new DefaultPackagePathResolver(fileSystem), fileSystem, configFileSystem);
@@ -80,7 +73,7 @@ public void CallRemovePackageWillRemoveNuspecFile(string id, string version, str
public void CallRemovePackageWillRemoveNupkgFile(string id, string version, string unexpectedPath)
{
// Arrange
- var fileSystem = new MockFileSystem("x:\root");
+ var fileSystem = new MockFileSystem("x:\\root");
fileSystem.AddFile(unexpectedPath);
var configFileSystem = new MockFileSystem();
var repository = new SharedPackageRepository(new DefaultPackagePathResolver(fileSystem), fileSystem, configFileSystem);
@@ -99,7 +92,7 @@ public void CallRemovePackageWillRemoveNupkgFile(string id, string version, stri
public void CallRemovePackageWillRemoveBothNupkgFileAndNuSpecFile(string id, string version, string nuspecPath, string nupkgPath)
{
// Arrange
- var fileSystem = new MockFileSystem("x:\root");
+ var fileSystem = new MockFileSystem("x:\\root");
fileSystem.AddFile(nuspecPath);
fileSystem.AddFile(nupkgPath);
var configFileSystem = new MockFileSystem();
@@ -122,7 +115,7 @@ public void CallRemovePackageWillRemoveBothNupkgFileAndNuSpecFile(string id, str
public void ExistChecksForPresenceOfPackageFileUnderDirectory(string id, string version, string path)
{
// Arrange
- var fileSystem = new MockFileSystem("x:\root");
+ var fileSystem = new MockFileSystem("x:\\root");
fileSystem.CreateDirectory(path);
fileSystem.AddFile(path + "\\" + path + ".nupkg");
@@ -142,10 +135,10 @@ public void ExistChecksForPresenceOfPackageFileUnderDirectory(string id, string
[InlineData("C", "3.1.2.4-rtm", "C.3.1.2.4-rtm")]
[InlineData("D", "4.0", "D.4.0.0.0")]
[InlineData("E", "5.1.4", "E.5.1.4.0")]
- public void ExistChecksForPresenceOfManifestFileUnderDirectory(string id, string version, string path)
+ public void ExistDoesNotCheckForPresenceOfManifestFileUnderDirectory(string id, string version, string path)
{
// Arrange
- var fileSystem = new MockFileSystem("x:\root");
+ var fileSystem = new MockFileSystem("x:\\root");
fileSystem.CreateDirectory(path);
fileSystem.AddFile(path + "\\" + path + ".nuspec");
@@ -156,29 +149,18 @@ public void ExistChecksForPresenceOfManifestFileUnderDirectory(string id, string
bool exists = repository.Exists(id, new SemanticVersion(version));
// Assert
- Assert.True(exists);
+ Assert.False(exists);
}
[Fact]
- public void FindPackageReturnUnzippedPackageObject()
+ public void FindPackageReturnOptimizedZipPackageObject()
{
// Arrange
- string manifestContent = @"<?xml version=""1.0""?>
-<package xmlns=""http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"">
- <metadata>
- <version>1.0-alpha</version>
- <authors>dotnetjunky</authors>
- <owners />
- <id>One</id>
- <title />
- <requireLicenseAcceptance>false</requireLicenseAcceptance>
- <description>My package description.</description>
- </metadata>
- <files />
-</package>";
+ var packageStream = GetPackageStream("one", "1.0.0-alpha");
- var fileSystem = new MockFileSystem("x:\root");
- fileSystem.AddFile("one.1.0.0-alpha\\one.1.0.0-alpha.nuspec", manifestContent.AsStream());
+ var fileSystem = new MockFileSystem("x:\\root");
+ fileSystem.AddFile("one.1.0.0-alpha\\one.1.0.0-alpha.nupkg", packageStream);
+
var configFileSystem = new MockFileSystem();
var repository = new SharedPackageRepository(new DefaultPackagePathResolver(fileSystem), fileSystem, configFileSystem);
@@ -186,14 +168,14 @@ public void FindPackageReturnUnzippedPackageObject()
IPackage package = repository.FindPackage("one", new SemanticVersion("1.0.0-alpha"));
// Assert
- Assert.IsType<UnzippedPackage>(package);
- Assert.Equal("One", package.Id);
+ Assert.True(package is OptimizedZipPackage);
+ Assert.Equal("one", package.Id);
Assert.Equal(new SemanticVersion("1.0.0-alpha"), package.Version);
- Assert.Equal(new string[] { "dotnetjunky" }, package.Authors);
+ Assert.Equal("Test description", package.Description);
}
[Fact]
- public void FindPackagesByIdReturnsAnUnzippedInstanceIfANuspecIsAvailableAndAZipPackageOtherwise()
+ public void FindPackagesByIdAlwaysReturnsOptimizedZipPackageEvenIfNuspecIfPresent()
{
// Arrange
string manifestContent = @"<?xml version=""1.0""?>
@@ -207,12 +189,11 @@ public void FindPackagesByIdReturnsAnUnzippedInstanceIfANuspecIsAvailableAndAZip
<files />
</package>";
- var fileSystem = new MockFileSystem("x:\root");
+ var fileSystem = new MockFileSystem("x:\\root");
fileSystem.AddFile("one.1.0.0-alpha\\one.1.0.0-alpha.nuspec", manifestContent.AsStream());
- fileSystem.AddFile("one.1.0.0-alpha\\one.1.0.0-alpha.nupkg", Stream.Null);
- var packageStream = GetPackageStream("One", "1.0.0");
- fileSystem.AddFile("one.1.0\\one.1.0.nupkg", packageStream);
+ var packageStream = GetPackageStream("One", "1.0.0-alpha");
+ fileSystem.AddFile("one.1.0.0-alpha\\one.1.0.0-alpha.nupkg", packageStream);
var configFileSystem = new MockFileSystem();
var repository = new SharedPackageRepository(new DefaultPackagePathResolver(fileSystem), fileSystem, configFileSystem);
@@ -221,16 +202,11 @@ public void FindPackagesByIdReturnsAnUnzippedInstanceIfANuspecIsAvailableAndAZip
var packages = repository.FindPackagesById("one").ToList();
// Assert
- Assert.Equal(2, packages.Count);
+ Assert.Equal(1, packages.Count);
var package = packages[0];
- Assert.IsType<UnzippedPackage>(package);
+ Assert.True(package is OptimizedZipPackage);
Assert.Equal("One", package.Id);
Assert.Equal(new SemanticVersion("1.0.0-alpha"), package.Version);
-
- package = packages[1];
- Assert.IsType<ZipPackage>(package);
- Assert.Equal("One", package.Id);
- Assert.Equal(new SemanticVersion("1.0.0"), package.Version);
}
[Fact]
View
4 test/EndToEnd/NuGet.Tests.psm1
@@ -222,7 +222,9 @@ function global:Run-Test {
$failedTests = @($results.GetEnumerator() | ? { $_.Value.Error -and !$_.Value.Skipped } | % { $_.Name })
if ($failedTests -gt 0)
{
- Write-Warning "There are $($failedTests.Count) failed tests. Re-running them one more time..."
+ Write-Warning "There are $($failedTests.Count) failed test(s). Re-running them one more time..."
+
+ $dte.Solution.Close()
$tests = @($failedTests | % { Get-ChildItem "function:\Test-$_" })
}
else
View
10 test/Test.Integration/Core/LocalPackageRepositoryTest.cs
@@ -33,6 +33,7 @@ public void FindPackageReturnsPackageWithVersionedFileNameAtRoot(string id, stri
var findPackage = repository.FindPackage(id, new SemanticVersion(version));
// Assert
+ Assert.True(findPackage is OptimizedZipPackage);
AssertPackage(id, version, findPackage);
}
@@ -51,6 +52,7 @@ public void FindPackageReturnsPackageWithUnVersionedFileNameWhenUsingVersionless
var findPackage = repository.FindPackage(id, new SemanticVersion(version));
// Assert
+ Assert.True(findPackage is OptimizedZipPackage);
AssertPackage(id, version, findPackage);
}
@@ -99,6 +101,7 @@ public void FindPackageReturnsPackagesFromNestedDirectories()
var findPackage = repository.FindPackage(id, new SemanticVersion(version));
// Assert
+ Assert.True(findPackage is OptimizedZipPackage);
AssertPackage(id, version, findPackage);
}
@@ -118,6 +121,8 @@ public void FindPackageReturnsPackagesWithDotInId()
var result2 = repository.FindPackage("test.extensions", new SemanticVersion("1.3-alpha"));
// Assert
+ Assert.True(result1 is OptimizedZipPackage);
+ Assert.True(result2 is OptimizedZipPackage);
AssertPackage("test.extensions", "1.0", result1);
AssertPackage("test.extensions", "1.3.0-alpha", result2);
}
@@ -161,6 +166,11 @@ public void FindPackagesByIdFindPackagesMatchingExactId()
var packages = repository.FindPackagesById(id).ToList();
// Assert
+ foreach (var p in packages)
+ {
+ Assert.True(p is OptimizedZipPackage);
+ }
+
Assert.Equal(3, packages.Count);
Assert.Equal("1.2", packages[0].Version.ToString());
Assert.Equal("1.3", packages[1].Version.ToString());
View
23 test/Test.Utility/Mocks/EventMemoryStream.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace NuGet.Test.Mocks
+{
+ internal class EventMemoryStream : MemoryStream
+ {
+ private static Action<Stream> _closeAction;
+
+ public EventMemoryStream(Action<Stream> closeAction)
+ {
+ Debug.Assert(closeAction != null);
+ _closeAction = closeAction;
+ }
+
+ public override void Close()
+ {
+ _closeAction(this);
+ base.Close();
+ }
+ }
+}
View
17 test/Test.Utility/Mocks/MockFileSystem.cs
@@ -143,6 +143,18 @@ public virtual Stream OpenFile(string path)
return factory();
}
+ public virtual Stream CreateFile(string path)
+ {
+ Paths[path] = () => Stream.Null;
+
+ Action<Stream> streamClose = (stream) => {
+ stream.Seek(0, SeekOrigin.Begin);
+ AddFile(path, stream);
+ };
+ var memoryStream = new EventMemoryStream(streamClose);
+ return memoryStream;
+ }
+
public string ReadAllText(string path)
{
return OpenFile(path).ReadToEnd();
@@ -150,9 +162,10 @@ public string ReadAllText(string path)
public virtual bool DirectoryExists(string path)
{
- return Paths.Select(file => file.Key)
+ string pathPrefix = PathUtility.EnsureTrailingSlash(path);
+ return Paths.Keys
.Any(file => file.Equals(path, StringComparison.OrdinalIgnoreCase) ||
- Path.GetDirectoryName(file).Equals(path, StringComparison.OrdinalIgnoreCase));
+ file.StartsWith(pathPrefix, StringComparison.OrdinalIgnoreCase));
}
public virtual IEnumerable<string> GetDirectories(string path)
View
12 test/Test.Utility/Mocks/MockPackageCacheRepository.cs
@@ -0,0 +1,12 @@
+using System.IO;
+
+namespace NuGet.Test.Mocks
+{
+ public class MockPackageCacheRepository : MockPackageRepository, IPackageCacheRepository
+ {
+ public Stream CreatePackageStream(string packageId, SemanticVersion version)
+ {
+ return new MemoryStream();
+ }
+ }
+}
View
2  test/Test.Utility/Test.Utility.csproj
@@ -35,6 +35,8 @@
</Reference>
</ItemGroup>
<ItemGroup>
+ <Compile Include="Mocks\EventMemoryStream.cs" />
+ <Compile Include="Mocks\MockPackageCacheRepository.cs" />
<Compile Include="Mocks\MockSharedPackageRepository.cs" />
<Compile Include="Mocks\MockFileSystem.cs" />
<Compile Include="Mocks\MockPackageRepository.cs" />
Please sign in to comment.
Something went wrong with that request. Please try again.