Skip to content

Commit 135a920

Browse files
committed
Use a null file system for the OptimizedZipPackage's expanded file system (#48)
Address NuGet/NuGetGallery#5230
1 parent f5aa2ba commit 135a920

8 files changed

Lines changed: 300 additions & 7 deletions

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.IO;
7+
8+
namespace NuGet.Server.Core
9+
{
10+
/// <summary>
11+
/// A file system implementation that persists nothing. This is intended to be used with
12+
/// <see cref="OptimizedZipPackage"/> so that package files are never actually extracted anywhere on disk.
13+
/// </summary>
14+
public class NullFileSystem : IFileSystem
15+
{
16+
public static NullFileSystem Instance { get; } = new NullFileSystem();
17+
18+
public Stream CreateFile(string path) => Stream.Null;
19+
public bool DirectoryExists(string path) => true;
20+
public bool FileExists(string path) => false;
21+
public string GetFullPath(string path) => null;
22+
public Stream OpenFile(string path) => Stream.Null;
23+
24+
public ILogger Logger { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
25+
public string Root => throw new NotSupportedException();
26+
public void AddFile(string path, Stream stream) => throw new NotSupportedException();
27+
public void AddFile(string path, Action<Stream> writeToStream) => throw new NotSupportedException();
28+
public void AddFiles(IEnumerable<IPackageFile> files, string rootDir) => throw new NotSupportedException();
29+
public void DeleteDirectory(string path, bool recursive) => throw new NotSupportedException();
30+
public void DeleteFile(string path) => throw new NotSupportedException();
31+
public void DeleteFiles(IEnumerable<IPackageFile> files, string rootDir) => throw new NotSupportedException();
32+
public DateTimeOffset GetCreated(string path) => throw new NotSupportedException();
33+
public IEnumerable<string> GetDirectories(string path) => throw new NotSupportedException();
34+
public IEnumerable<string> GetFiles(string path, string filter, bool recursive) => throw new NotSupportedException();
35+
public DateTimeOffset GetLastAccessed(string path) => throw new NotSupportedException();
36+
public DateTimeOffset GetLastModified(string path) => throw new NotSupportedException();
37+
public void MakeFileWritable(string path) => throw new NotSupportedException();
38+
public void MoveFile(string source, string destination) => throw new NotSupportedException();
39+
}
40+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.IO;
6+
7+
namespace NuGet.Server.Core
8+
{
9+
public static class PackageFactory
10+
{
11+
public static IPackage Open(string fullPackagePath)
12+
{
13+
if (string.IsNullOrEmpty(fullPackagePath))
14+
{
15+
throw new ArgumentNullException(nameof(fullPackagePath));
16+
}
17+
18+
var directoryName = Path.GetDirectoryName(fullPackagePath);
19+
var fileName = Path.GetFileName(fullPackagePath);
20+
21+
var fileSystem = new PhysicalFileSystem(directoryName);
22+
23+
return new OptimizedZipPackage(
24+
fileSystem,
25+
fileName,
26+
NullFileSystem.Instance);
27+
}
28+
}
29+
}

src/NuGet.Server.Core/Infrastructure/ServerPackageRepository.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ private void AddPackagesFromDropFolderWithoutLocking()
236236
try
237237
{
238238
// Create package
239-
var package = new OptimizedZipPackage(_fileSystem, packageFile);
239+
var package = PackageFactory.Open(_fileSystem.GetFullPath(packageFile));
240240

241241
if (!CanPackageBeAddedWithoutLocking(package, shouldThrow: false))
242242
{

src/NuGet.Server.Core/NuGet.Server.Core.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@
5858
</Compile>
5959
<Compile Include="Core\Constants.cs" />
6060
<Compile Include="Core\FrameworkNameExtensions.cs" />
61+
<Compile Include="Core\NullFileSystem.cs" />
6162
<Compile Include="Core\PackageExtensions.cs" />
63+
<Compile Include="Core\PackageFactory.cs" />
6264
<Compile Include="DataServices\IgnoreCaseForPackageIdInterceptor.cs" />
6365
<Compile Include="DataServices\NormalizeVersionInterceptor.cs" />
6466
<Compile Include="DataServices\ODataPackage.cs" />

src/NuGet.Server.V2/Controllers/NuGetODataController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using System.Web.Http;
1515
using System.Web.Http.OData;
1616
using System.Web.Http.OData.Query;
17+
using NuGet.Server.Core;
1718
using NuGet.Server.Core.DataServices;
1819
using NuGet.Server.Core.Infrastructure;
1920
using NuGet.Server.V2.Model;
@@ -396,8 +397,7 @@ public virtual async Task<HttpResponseMessage> UploadPackage(CancellationToken t
396397
}
397398
}
398399

399-
var package = new OptimizedZipPackage(temporaryFile);
400-
400+
var package = PackageFactory.Open(temporaryFile);
401401

402402
HttpResponseMessage retValue;
403403
if (_authenticationService.IsAuthenticated(User, apiKey, package.Id))
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.IO;
6+
using NuGet.Server.Core.Tests.Infrastructure;
7+
using Xunit;
8+
9+
namespace NuGet.Server.Core.Tests.Core
10+
{
11+
public class PackageFactoryTest
12+
{
13+
public class Open : IDisposable
14+
{
15+
private readonly TemporaryDirectory _directory;
16+
17+
public Open()
18+
{
19+
_directory = new TemporaryDirectory();
20+
}
21+
22+
[Theory]
23+
[InlineData(null)]
24+
[InlineData("")]
25+
public void RejectsInvalidPaths(string path)
26+
{
27+
var ex = Assert.Throws<ArgumentNullException>(
28+
() => PackageFactory.Open(path));
29+
Assert.Equal("fullPackagePath", ex.ParamName);
30+
}
31+
32+
[Fact]
33+
public void InitializesPackageWithMetadata()
34+
{
35+
// Arrange
36+
var path = Path.Combine(_directory, "package.nupkg");
37+
TestData.CopyResourceToPath(TestData.PackageResource, path);
38+
39+
// Act
40+
var package = PackageFactory.Open(path);
41+
42+
// Assert
43+
Assert.Equal(TestData.PackageId, package.Id);
44+
Assert.Equal(TestData.PackageVersion, package.Version);
45+
}
46+
47+
[Fact]
48+
public void InitializesPackageWithSupportedFrameworks()
49+
{
50+
// Arrange
51+
var path = Path.Combine(_directory, "package.nupkg");
52+
TestData.CopyResourceToPath(TestData.PackageResource, path);
53+
54+
// Act
55+
var package = PackageFactory.Open(path);
56+
57+
// Assert
58+
var frameworks = package.GetSupportedFrameworks();
59+
var framework = Assert.Single(frameworks);
60+
Assert.Equal(VersionUtility.ParseFrameworkName("net40-client"), framework);
61+
}
62+
63+
[Fact]
64+
public void InitializesPackageWhichCanBeCheckedForSymbols()
65+
{
66+
// Arrange
67+
var path = Path.Combine(_directory, "package.nupkg");
68+
TestData.CopyResourceToPath(TestData.PackageResource, path);
69+
70+
// Act
71+
var package = PackageFactory.Open(path);
72+
73+
// Assert
74+
Assert.False(package.IsSymbolsPackage(), "The provided package is not a symbols package.");
75+
}
76+
77+
public void Dispose()
78+
{
79+
_directory?.Dispose();
80+
}
81+
}
82+
}
83+
}

test/NuGet.Server.Core.Tests/NuGet.Server.Core.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
<ItemGroup>
8282
<Compile Include="ApiKeyPackageAuthenticationServiceTest.cs" />
8383
<Compile Include="ClientCompatibilityFactoryTests.cs" />
84+
<Compile Include="Core\PackageFactoryTest.cs" />
8485
<Compile Include="IdAndVersionEqualityComparerTest.cs" />
8586
<Compile Include="IgnoreCaseForPackageIdInterceptorTest.cs" />
8687
<Compile Include="Infrastructure\FuncSettingsProvider.cs" />

0 commit comments

Comments
 (0)