Skip to content

Commit

Permalink
Merge branch 'dev' (#74)
Browse files Browse the repository at this point in the history
  • Loading branch information
joelverhagen committed Mar 11, 2019
2 parents fe2231b + 3b9e7de commit 0f06e4c
Show file tree
Hide file tree
Showing 27 changed files with 607 additions and 46 deletions.
1 change: 1 addition & 0 deletions .nuget/packages.config
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="xunit.runner.console" version="2.1.0" />
<package id="MicroBuild.Core" version="0.3.0" />
</packages>
25 changes: 19 additions & 6 deletions build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ param (
[string]$SemanticVersion = '1.0.0-zlocal',
[string]$Branch,
[string]$CommitSHA,
[string]$BuildBranch = '802a2329581ab88326bf1fd442595bac6dbaa848'
[string]$BuildBranch = '1c8734ee61e209f159972ab974784ba55ee2bd6d'
)

$msBuildVersion = 15;

# 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
trap {
Write-Host "BUILD FAILED: $_" -ForegroundColor Red
Expand All @@ -28,7 +30,7 @@ if (-not (Test-Path "$PSScriptRoot/build")) {
# Enable TLS 1.2 since GitHub requires it.
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12

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

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

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

Invoke-BuildStep 'Creating artifacts' {
New-Package (Join-Path $PSScriptRoot "src\NuGet.Server.Core\NuGet.Server.Core.csproj") -Configuration $Configuration -Symbols -BuildNumber $BuildNumber -Version $SemanticVersion -Branch $Branch
New-Package (Join-Path $PSScriptRoot "src\NuGet.Server.V2\NuGet.Server.V2.csproj") -Configuration $Configuration -Symbols -BuildNumber $BuildNumber -Version $SemanticVersion -Branch $Branch
New-Package (Join-Path $PSScriptRoot "src\NuGet.Server\NuGet.Server.nuspec") -Configuration $Configuration -Symbols -BuildNumber $BuildNumber -Version $SemanticVersion -Branch $Branch
$projects = `
"src\NuGet.Server.Core\NuGet.Server.Core.csproj", `
"src\NuGet.Server.V2\NuGet.Server.V2.csproj", `
"src\NuGet.Server\NuGet.Server.nuspec"

Foreach ($project in $projects) {
New-Package (Join-Path $PSScriptRoot $project) -Configuration $Configuration -Symbols -BuildNumber $BuildNumber -MSBuildVersion "$msBuildVersion" -Version $SemanticVersion -Branch $Branch
}
} `
-ev +BuildErrors

Invoke-BuildStep 'Signing the packages' {
$ProjectPath = Join-Path $PSScriptRoot "build\sign.proj"
Build-Solution $Configuration $BuildNumber -MSBuildVersion "$msBuildVersion" $ProjectPath `
} `
-ev +BuildErrors

Expand Down
24 changes: 24 additions & 0 deletions build/sign.proj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="AfterBuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.props" Condition="Exists('..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.props')" />

<PropertyGroup>
<RepositoryRootDirectory>$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'README.md'))\</RepositoryRootDirectory>
<IntermediateOutputPath>$(RepositoryRootDirectory)artifacts\sign\obj\</IntermediateOutputPath>
<OutDir>$(RepositoryRootDirectory)</OutDir>
<SignTargetsDependOn>GetOutputNupkgs</SignTargetsDependOn>
</PropertyGroup>

<Target Name="GetOutputNupkgs">
<ItemGroup>
<FilesToSign Include="$(RepositoryRootDirectory)artifacts\*.nupkg">
<Authenticode>NuGet</Authenticode>
</FilesToSign>
</ItemGroup>
<Message Text="Files to sign:%0A@(FilesToSign, '%0A')" Importance="High" />
</Target>

<Target Name="AfterBuild" DependsOnTargets="$(SignTargetsDependOn)"/>

<Import Project="..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.targets" Condition="Exists('..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.targets')" />
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,21 @@ namespace NuGet.Server.V2.Samples.OwinHost
{
public class DictionarySettingsProvider : ISettingsProvider
{
readonly Dictionary<string, object> _settings;
private readonly Dictionary<string, object> _settings;

public DictionarySettingsProvider(Dictionary<string, object> settings)
{
_settings = settings;
}


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

public int GetIntSetting(string key, int defaultValue)
{
return _settings.ContainsKey(key) ? Convert.ToInt32(_settings[key]) : defaultValue;
}

public string GetStringSetting(string key, string defaultValue)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.props" Condition="Exists('..\..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
Expand All @@ -12,6 +13,8 @@
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
Expand Down Expand Up @@ -136,5 +139,20 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\build\sign.targets" Condition="Exists('..\..\build\sign.targets')" />
<PropertyGroup>
<SignPath>..\..\build</SignPath>
<SignPath Condition="'$(BUILD_SOURCESDIRECTORY)' != ''">$(BUILD_SOURCESDIRECTORY)\build</SignPath>
<SignPath Condition="'$(NuGetBuildPath)' != ''">$(NuGetBuildPath)</SignPath>
<SignType Condition="'$(SignType)' == ''">none</SignType>
</PropertyGroup>
<Import Project="$(SignPath)\sign.targets" Condition="Exists('$(SignPath)\sign.targets')" />
<Import Project="$(SignPath)\sign.microbuild.targets" Condition="Exists('$(SignPath)\sign.microbuild.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<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>
</PropertyGroup>
<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'))" />
<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'))" />
</Target>
<Import Project="..\..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.targets" Condition="Exists('..\..\packages\MicroBuild.Core.0.3.0\build\MicroBuild.Core.targets')" />
</Project>
1 change: 1 addition & 0 deletions samples/NuGet.Server.V2.Samples.OwinHost/packages.config
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MicroBuild.Core" version="0.3.0" targetFramework="net46" developmentDependency="true" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.OData" version="5.7.0" targetFramework="net45" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ public bool GetBoolSetting(string key, bool defaultValue)
return defaultValue;
}

public int GetIntSetting(string key, int defaultValue)
{
return defaultValue;
}

public string GetStringSetting(string key, string defaultValue)
{
return defaultValue;
Expand Down
1 change: 1 addition & 0 deletions src/NuGet.Server.Core/Infrastructure/ISettingsProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ public interface ISettingsProvider
{
bool GetBoolSetting(string key, bool defaultValue);
string GetStringSetting(string key, string defaultValue);
int GetIntSetting(string key, int defaultValue);
}
}
65 changes: 65 additions & 0 deletions src/NuGet.Server.Core/Infrastructure/KnownPathUtility.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.IO;

namespace NuGet.Server.Core.Infrastructure
{
public static class KnownPathUtility
{
/// <summary>
/// Determines if a relative file path could have been generated by <see cref="ExpandedPackageRepository"/>.
/// The path is assumed to be relative to the base of the package directory.
/// </summary>
/// <param name="path">The file path to parse.</param>
/// <param name="id">The package ID found.</param>
/// <param name="version">The package version found.</param>
/// <returns>True if the file name is known.</returns>
public static bool TryParseFileName(string path, out string id, out SemanticVersion version)
{
id = null;
version = null;

if (path == null || Path.IsPathRooted(path))
{
return false;
}

var pathPieces = path.Split(Path.DirectorySeparatorChar);
if (pathPieces.Length != 3) // {id}\{version}\{file name}
{
return false;
}

id = pathPieces[pathPieces.Length - 3];
var unparsedVersion = pathPieces[pathPieces.Length - 2];
var fileName = pathPieces[pathPieces.Length - 1];

if (!SemanticVersion.TryParse(unparsedVersion, out version)
|| version.ToNormalizedString() != unparsedVersion)
{
return false;
}

string expectedFileName;
if (fileName.EndsWith(NuGet.Constants.PackageExtension))
{
expectedFileName = $"{id}.{version}{NuGet.Constants.PackageExtension}";
}
else if (fileName.EndsWith(NuGet.Constants.HashFileExtension))
{
expectedFileName = $"{id}.{version}{NuGet.Constants.HashFileExtension}";
}
else if (fileName.EndsWith(NuGet.Constants.ManifestExtension))
{
expectedFileName = $"{id}{NuGet.Constants.ManifestExtension}";
}
else
{
return false;
}

return expectedFileName == fileName;
}
}
}
100 changes: 95 additions & 5 deletions src/NuGet.Server.Core/Infrastructure/ServerPackageRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,35 @@ internal ServerPackageRepository(

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

private TimeSpan InitialCacheRebuildAfter
{
get
{
var value = GetPositiveIntSetting("initialCacheRebuildAfterSeconds", 15);
return TimeSpan.FromSeconds(value);
}
}

private TimeSpan CacheRebuildFrequency
{
get
{
int value = GetPositiveIntSetting("cacheRebuildFrequencyInMinutes", 60);
return TimeSpan.FromMinutes(value);
}
}

private int GetPositiveIntSetting(string name, int defaultValue)
{
var value = _settingsProvider.GetIntSetting(name, defaultValue);
if (value <= 0)
{
value = defaultValue;
}

return value;
}

private ServerPackageCache InitializeServerPackageCache()
{
return new ServerPackageCache(_fileSystem, ResolveCacheFileName());
Expand Down Expand Up @@ -529,18 +558,21 @@ private void SetupBackgroundJobs()
_logger.Log(LogLevel.Info, "Registering background jobs...");

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

// Rebuild the package store in the background (every hour)
// Rebuild the package store in the background
_logger.Log(LogLevel.Info, "Rebuilding the cache file for the first time after {0} second(s).", InitialCacheRebuildAfter.TotalSeconds);
_logger.Log(LogLevel.Info, "Rebuilding the cache file every {0} hour(s).", CacheRebuildFrequency.TotalHours);
_rebuildTimer = new Timer(
callback: state => RebuildPackageStoreAsync(CancellationToken.None),
state: null,
dueTime: TimeSpan.FromSeconds(15),
period: TimeSpan.FromHours(1));
dueTime: InitialCacheRebuildAfter,
period: CacheRebuildFrequency);

_logger.Log(LogLevel.Info, "Finished registering background jobs.");
}
Expand Down Expand Up @@ -595,7 +627,6 @@ private void UnregisterFileSystemWatcher()
_watchDirectory = null;
}


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

if (ShouldIgnoreFileSystemEvent(e))
{
_logger.Log(LogLevel.Verbose, "File system event ignored. File: {0} - Change: {1}", e.Name, e.ChangeType);
return;
}

_logger.Log(LogLevel.Verbose, "File system changed. File: {0} - Change: {1}", e.Name, e.ChangeType);

var changedDirectory = Path.GetDirectoryName(e.FullPath);
Expand Down Expand Up @@ -642,6 +679,59 @@ private async void FileSystemChangedAsync(object sender, FileSystemEventArgs e)
}
}

private bool ShouldIgnoreFileSystemEvent(FileSystemEventArgs e)
{
// We can only ignore Created or Changed events. All other types are always processed. Eventually we could
// try to ignore some Deleted events in the case of API package delete, but this is harder.
if (e.ChangeType != WatcherChangeTypes.Created
&& e.ChangeType != WatcherChangeTypes.Changed)
{
_logger.Log(LogLevel.Verbose, "The file system event change type is not ignorable.");
return false;
}

/// We can only ignore events related to file paths changed by the
/// <see cref="ExpandedPackageRepository"/>. If the file system event is representing a known file path
/// extracted during package push, we can ignore the event. File system events are supressed during package
/// push but this is still necessary since file system events can come some time after the suppression
/// window has ended.
if (!KnownPathUtility.TryParseFileName(e.Name, out var id, out var version))
{
_logger.Log(LogLevel.Verbose, "The file system event is not related to a known package path.");
return false;
}

/// The file path could have been generated by <see cref="ExpandedPackageRepository"/>. Now
/// determine if the package is in the cache.
var matchingPackage = _serverPackageCache
.GetAll()
.Where(p => StringComparer.OrdinalIgnoreCase.Equals(p.Id, id))
.Where(p => version.Equals(p.Version))
.FirstOrDefault();

if (matchingPackage == null)
{
_logger.Log(LogLevel.Verbose, "The file system event is not related to a known package.");
return false;
}

var fileInfo = new FileInfo(e.FullPath);
if (!fileInfo.Exists)
{
_logger.Log(LogLevel.Verbose, "The package file is missing.");
return false;
}

var minimumCreationTime = DateTimeOffset.UtcNow.AddMinutes(-1);
if (fileInfo.CreationTimeUtc < minimumCreationTime)
{
_logger.Log(LogLevel.Verbose, "The package file was not created recently.");
return false;
}

return true;
}

private async Task<Lock> LockAsync(CancellationToken token)
{
var handle = new Lock(_syncLock);
Expand Down Expand Up @@ -710,8 +800,8 @@ public void Dispose()
{
if (_lockHandle != null && _lockHandle.LockTaken)
{
_lockHandle.Dispose();
_repository._isFileSystemWatcherSuppressed = false;
_lockHandle.Dispose();
}
}
}
Expand Down
Loading

0 comments on commit 0f06e4c

Please sign in to comment.