Skip to content

Commit 0f06e4c

Browse files
committed
Merge branch 'dev' (#74)
2 parents fe2231b + 3b9e7de commit 0f06e4c

27 files changed

Lines changed: 607 additions & 46 deletions

.nuget/packages.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
33
<package id="xunit.runner.console" version="2.1.0" />
4+
<package id="MicroBuild.Core" version="0.3.0" />
45
</packages>

build.ps1

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ param (
99
[string]$SemanticVersion = '1.0.0-zlocal',
1010
[string]$Branch,
1111
[string]$CommitSHA,
12-
[string]$BuildBranch = '802a2329581ab88326bf1fd442595bac6dbaa848'
12+
[string]$BuildBranch = '1c8734ee61e209f159972ab974784ba55ee2bd6d'
1313
)
1414

15+
$msBuildVersion = 15;
16+
1517
# For TeamCity - If any issue occurs, this script fail the build. - By default, TeamCity returns an exit code of 0 for all powershell scripts, even if they fail
1618
trap {
1719
Write-Host "BUILD FAILED: $_" -ForegroundColor Red
@@ -28,7 +30,7 @@ if (-not (Test-Path "$PSScriptRoot/build")) {
2830
# Enable TLS 1.2 since GitHub requires it.
2931
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
3032

31-
wget -UseBasicParsing -Uri "https://raw.githubusercontent.com/NuGet/ServerCommon/$BuildBranch/build/init.ps1" -OutFile "$PSScriptRoot/build/init.ps1"
33+
Invoke-WebRequest -UseBasicParsing -Uri "https://raw.githubusercontent.com/NuGet/ServerCommon/$BuildBranch/build/init.ps1" -OutFile "$PSScriptRoot/build/init.ps1"
3234
. "$PSScriptRoot/build/init.ps1" -BuildBranch "$BuildBranch"
3335

3436
Write-Host ("`r`n" * 3)
@@ -73,14 +75,25 @@ Invoke-BuildStep 'Set version metadata in AssemblyInfo.cs' {
7375

7476
Invoke-BuildStep 'Building solution' {
7577
$SolutionPath = Join-Path $PSScriptRoot "NuGet.Server.sln"
76-
Build-Solution $Configuration $BuildNumber -MSBuildVersion "15" $SolutionPath -SkipRestore:$SkipRestore `
78+
Build-Solution $Configuration $BuildNumber -MSBuildVersion "$msBuildVersion" $SolutionPath -SkipRestore:$SkipRestore `
7779
} `
7880
-ev +BuildErrors
7981

8082
Invoke-BuildStep 'Creating artifacts' {
81-
New-Package (Join-Path $PSScriptRoot "src\NuGet.Server.Core\NuGet.Server.Core.csproj") -Configuration $Configuration -Symbols -BuildNumber $BuildNumber -Version $SemanticVersion -Branch $Branch
82-
New-Package (Join-Path $PSScriptRoot "src\NuGet.Server.V2\NuGet.Server.V2.csproj") -Configuration $Configuration -Symbols -BuildNumber $BuildNumber -Version $SemanticVersion -Branch $Branch
83-
New-Package (Join-Path $PSScriptRoot "src\NuGet.Server\NuGet.Server.nuspec") -Configuration $Configuration -Symbols -BuildNumber $BuildNumber -Version $SemanticVersion -Branch $Branch
83+
$projects = `
84+
"src\NuGet.Server.Core\NuGet.Server.Core.csproj", `
85+
"src\NuGet.Server.V2\NuGet.Server.V2.csproj", `
86+
"src\NuGet.Server\NuGet.Server.nuspec"
87+
88+
Foreach ($project in $projects) {
89+
New-Package (Join-Path $PSScriptRoot $project) -Configuration $Configuration -Symbols -BuildNumber $BuildNumber -MSBuildVersion "$msBuildVersion" -Version $SemanticVersion -Branch $Branch
90+
}
91+
} `
92+
-ev +BuildErrors
93+
94+
Invoke-BuildStep 'Signing the packages' {
95+
$ProjectPath = Join-Path $PSScriptRoot "build\sign.proj"
96+
Build-Solution $Configuration $BuildNumber -MSBuildVersion "$msBuildVersion" $ProjectPath `
8497
} `
8598
-ev +BuildErrors
8699

build/sign.proj

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="15.0" DefaultTargets="AfterBuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.props" Condition="Exists('..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.props')" />
4+
5+
<PropertyGroup>
6+
<RepositoryRootDirectory>$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'README.md'))\</RepositoryRootDirectory>
7+
<IntermediateOutputPath>$(RepositoryRootDirectory)artifacts\sign\obj\</IntermediateOutputPath>
8+
<OutDir>$(RepositoryRootDirectory)</OutDir>
9+
<SignTargetsDependOn>GetOutputNupkgs</SignTargetsDependOn>
10+
</PropertyGroup>
11+
12+
<Target Name="GetOutputNupkgs">
13+
<ItemGroup>
14+
<FilesToSign Include="$(RepositoryRootDirectory)artifacts\*.nupkg">
15+
<Authenticode>NuGet</Authenticode>
16+
</FilesToSign>
17+
</ItemGroup>
18+
<Message Text="Files to sign:%0A@(FilesToSign, '%0A')" Importance="High" />
19+
</Target>
20+
21+
<Target Name="AfterBuild" DependsOnTargets="$(SignTargetsDependOn)"/>
22+
23+
<Import Project="..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.targets" Condition="Exists('..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.targets')" />
24+
</Project>

samples/NuGet.Server.V2.Samples.OwinHost/DictionarySettingsProvider.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,21 @@ namespace NuGet.Server.V2.Samples.OwinHost
88
{
99
public class DictionarySettingsProvider : ISettingsProvider
1010
{
11-
readonly Dictionary<string, object> _settings;
11+
private readonly Dictionary<string, object> _settings;
1212

1313
public DictionarySettingsProvider(Dictionary<string, object> settings)
1414
{
1515
_settings = settings;
1616
}
1717

18-
1918
public bool GetBoolSetting(string key, bool defaultValue)
2019
{
21-
System.Diagnostics.Debug.WriteLine("getSetting: " + key);
2220
return _settings.ContainsKey(key) ? Convert.ToBoolean(_settings[key]) : defaultValue;
21+
}
2322

23+
public int GetIntSetting(string key, int defaultValue)
24+
{
25+
return _settings.ContainsKey(key) ? Convert.ToInt32(_settings[key]) : defaultValue;
2426
}
2527

2628
public string GetStringSetting(string key, string defaultValue)

samples/NuGet.Server.V2.Samples.OwinHost/NuGet.Server.V2.Samples.OwinHost.csproj

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="..\..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.props" Condition="Exists('..\..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.props')" />
34
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
45
<PropertyGroup>
56
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -12,6 +13,8 @@
1213
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
1314
<FileAlignment>512</FileAlignment>
1415
<TargetFrameworkProfile />
16+
<NuGetPackageImportStamp>
17+
</NuGetPackageImportStamp>
1518
</PropertyGroup>
1619
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
1720
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -136,5 +139,20 @@
136139
</ProjectReference>
137140
</ItemGroup>
138141
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
139-
<Import Project="..\..\build\sign.targets" Condition="Exists('..\..\build\sign.targets')" />
142+
<PropertyGroup>
143+
<SignPath>..\..\build</SignPath>
144+
<SignPath Condition="'$(BUILD_SOURCESDIRECTORY)' != ''">$(BUILD_SOURCESDIRECTORY)\build</SignPath>
145+
<SignPath Condition="'$(NuGetBuildPath)' != ''">$(NuGetBuildPath)</SignPath>
146+
<SignType Condition="'$(SignType)' == ''">none</SignType>
147+
</PropertyGroup>
148+
<Import Project="$(SignPath)\sign.targets" Condition="Exists('$(SignPath)\sign.targets')" />
149+
<Import Project="$(SignPath)\sign.microbuild.targets" Condition="Exists('$(SignPath)\sign.microbuild.targets')" />
150+
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
151+
<PropertyGroup>
152+
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
153+
</PropertyGroup>
154+
<Error Condition="!Exists('..\..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.props'))" />
155+
<Error Condition="!Exists('..\..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.targets'))" />
156+
</Target>
157+
<Import Project="..\..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.targets" Condition="Exists('..\..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.targets')" />
140158
</Project>

samples/NuGet.Server.V2.Samples.OwinHost/packages.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
3+
<package id="MicroBuild.Core" version="0.3.0" targetFramework="net46" developmentDependency="true" />
34
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net461" />
45
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net45" />
56
<package id="Microsoft.AspNet.WebApi.OData" version="5.7.0" targetFramework="net45" />

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ public bool GetBoolSetting(string key, bool defaultValue)
99
return defaultValue;
1010
}
1111

12+
public int GetIntSetting(string key, int defaultValue)
13+
{
14+
return defaultValue;
15+
}
16+
1217
public string GetStringSetting(string key, string defaultValue)
1318
{
1419
return defaultValue;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ public interface ISettingsProvider
66
{
77
bool GetBoolSetting(string key, bool defaultValue);
88
string GetStringSetting(string key, string defaultValue);
9+
int GetIntSetting(string key, int defaultValue);
910
}
1011
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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.IO;
5+
6+
namespace NuGet.Server.Core.Infrastructure
7+
{
8+
public static class KnownPathUtility
9+
{
10+
/// <summary>
11+
/// Determines if a relative file path could have been generated by <see cref="ExpandedPackageRepository"/>.
12+
/// The path is assumed to be relative to the base of the package directory.
13+
/// </summary>
14+
/// <param name="path">The file path to parse.</param>
15+
/// <param name="id">The package ID found.</param>
16+
/// <param name="version">The package version found.</param>
17+
/// <returns>True if the file name is known.</returns>
18+
public static bool TryParseFileName(string path, out string id, out SemanticVersion version)
19+
{
20+
id = null;
21+
version = null;
22+
23+
if (path == null || Path.IsPathRooted(path))
24+
{
25+
return false;
26+
}
27+
28+
var pathPieces = path.Split(Path.DirectorySeparatorChar);
29+
if (pathPieces.Length != 3) // {id}\{version}\{file name}
30+
{
31+
return false;
32+
}
33+
34+
id = pathPieces[pathPieces.Length - 3];
35+
var unparsedVersion = pathPieces[pathPieces.Length - 2];
36+
var fileName = pathPieces[pathPieces.Length - 1];
37+
38+
if (!SemanticVersion.TryParse(unparsedVersion, out version)
39+
|| version.ToNormalizedString() != unparsedVersion)
40+
{
41+
return false;
42+
}
43+
44+
string expectedFileName;
45+
if (fileName.EndsWith(NuGet.Constants.PackageExtension))
46+
{
47+
expectedFileName = $"{id}.{version}{NuGet.Constants.PackageExtension}";
48+
}
49+
else if (fileName.EndsWith(NuGet.Constants.HashFileExtension))
50+
{
51+
expectedFileName = $"{id}.{version}{NuGet.Constants.HashFileExtension}";
52+
}
53+
else if (fileName.EndsWith(NuGet.Constants.ManifestExtension))
54+
{
55+
expectedFileName = $"{id}{NuGet.Constants.ManifestExtension}";
56+
}
57+
else
58+
{
59+
return false;
60+
}
61+
62+
return expectedFileName == fileName;
63+
}
64+
}
65+
}

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

Lines changed: 95 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,35 @@ internal ServerPackageRepository(
108108

109109
private string CacheFileName => _settingsProvider.GetStringSetting("cacheFileName", null);
110110

111+
private TimeSpan InitialCacheRebuildAfter
112+
{
113+
get
114+
{
115+
var value = GetPositiveIntSetting("initialCacheRebuildAfterSeconds", 15);
116+
return TimeSpan.FromSeconds(value);
117+
}
118+
}
119+
120+
private TimeSpan CacheRebuildFrequency
121+
{
122+
get
123+
{
124+
int value = GetPositiveIntSetting("cacheRebuildFrequencyInMinutes", 60);
125+
return TimeSpan.FromMinutes(value);
126+
}
127+
}
128+
129+
private int GetPositiveIntSetting(string name, int defaultValue)
130+
{
131+
var value = _settingsProvider.GetIntSetting(name, defaultValue);
132+
if (value <= 0)
133+
{
134+
value = defaultValue;
135+
}
136+
137+
return value;
138+
}
139+
111140
private ServerPackageCache InitializeServerPackageCache()
112141
{
113142
return new ServerPackageCache(_fileSystem, ResolveCacheFileName());
@@ -529,18 +558,21 @@ private void SetupBackgroundJobs()
529558
_logger.Log(LogLevel.Info, "Registering background jobs...");
530559

531560
// Persist to package store at given interval (when dirty)
561+
_logger.Log(LogLevel.Info, "Persisting the cache file every 1 minute.");
532562
_persistenceTimer = new Timer(
533563
callback: state => _serverPackageCache.PersistIfDirty(),
534564
state: null,
535565
dueTime: TimeSpan.FromMinutes(1),
536566
period: TimeSpan.FromMinutes(1));
537567

538-
// Rebuild the package store in the background (every hour)
568+
// Rebuild the package store in the background
569+
_logger.Log(LogLevel.Info, "Rebuilding the cache file for the first time after {0} second(s).", InitialCacheRebuildAfter.TotalSeconds);
570+
_logger.Log(LogLevel.Info, "Rebuilding the cache file every {0} hour(s).", CacheRebuildFrequency.TotalHours);
539571
_rebuildTimer = new Timer(
540572
callback: state => RebuildPackageStoreAsync(CancellationToken.None),
541573
state: null,
542-
dueTime: TimeSpan.FromSeconds(15),
543-
period: TimeSpan.FromHours(1));
574+
dueTime: InitialCacheRebuildAfter,
575+
period: CacheRebuildFrequency);
544576

545577
_logger.Log(LogLevel.Info, "Finished registering background jobs.");
546578
}
@@ -595,7 +627,6 @@ private void UnregisterFileSystemWatcher()
595627
_watchDirectory = null;
596628
}
597629

598-
599630
/// <summary>
600631
/// This is an event handler for background work. Therefore, it should never throw exceptions.
601632
/// </summary>
@@ -608,6 +639,12 @@ private async void FileSystemChangedAsync(object sender, FileSystemEventArgs e)
608639
return;
609640
}
610641

642+
if (ShouldIgnoreFileSystemEvent(e))
643+
{
644+
_logger.Log(LogLevel.Verbose, "File system event ignored. File: {0} - Change: {1}", e.Name, e.ChangeType);
645+
return;
646+
}
647+
611648
_logger.Log(LogLevel.Verbose, "File system changed. File: {0} - Change: {1}", e.Name, e.ChangeType);
612649

613650
var changedDirectory = Path.GetDirectoryName(e.FullPath);
@@ -642,6 +679,59 @@ private async void FileSystemChangedAsync(object sender, FileSystemEventArgs e)
642679
}
643680
}
644681

682+
private bool ShouldIgnoreFileSystemEvent(FileSystemEventArgs e)
683+
{
684+
// We can only ignore Created or Changed events. All other types are always processed. Eventually we could
685+
// try to ignore some Deleted events in the case of API package delete, but this is harder.
686+
if (e.ChangeType != WatcherChangeTypes.Created
687+
&& e.ChangeType != WatcherChangeTypes.Changed)
688+
{
689+
_logger.Log(LogLevel.Verbose, "The file system event change type is not ignorable.");
690+
return false;
691+
}
692+
693+
/// We can only ignore events related to file paths changed by the
694+
/// <see cref="ExpandedPackageRepository"/>. If the file system event is representing a known file path
695+
/// extracted during package push, we can ignore the event. File system events are supressed during package
696+
/// push but this is still necessary since file system events can come some time after the suppression
697+
/// window has ended.
698+
if (!KnownPathUtility.TryParseFileName(e.Name, out var id, out var version))
699+
{
700+
_logger.Log(LogLevel.Verbose, "The file system event is not related to a known package path.");
701+
return false;
702+
}
703+
704+
/// The file path could have been generated by <see cref="ExpandedPackageRepository"/>. Now
705+
/// determine if the package is in the cache.
706+
var matchingPackage = _serverPackageCache
707+
.GetAll()
708+
.Where(p => StringComparer.OrdinalIgnoreCase.Equals(p.Id, id))
709+
.Where(p => version.Equals(p.Version))
710+
.FirstOrDefault();
711+
712+
if (matchingPackage == null)
713+
{
714+
_logger.Log(LogLevel.Verbose, "The file system event is not related to a known package.");
715+
return false;
716+
}
717+
718+
var fileInfo = new FileInfo(e.FullPath);
719+
if (!fileInfo.Exists)
720+
{
721+
_logger.Log(LogLevel.Verbose, "The package file is missing.");
722+
return false;
723+
}
724+
725+
var minimumCreationTime = DateTimeOffset.UtcNow.AddMinutes(-1);
726+
if (fileInfo.CreationTimeUtc < minimumCreationTime)
727+
{
728+
_logger.Log(LogLevel.Verbose, "The package file was not created recently.");
729+
return false;
730+
}
731+
732+
return true;
733+
}
734+
645735
private async Task<Lock> LockAsync(CancellationToken token)
646736
{
647737
var handle = new Lock(_syncLock);
@@ -710,8 +800,8 @@ public void Dispose()
710800
{
711801
if (_lockHandle != null && _lockHandle.LockTaken)
712802
{
713-
_lockHandle.Dispose();
714803
_repository._isFileSystemWatcherSuppressed = false;
804+
_lockHandle.Dispose();
715805
}
716806
}
717807
}

0 commit comments

Comments
 (0)