Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
jherby2k committed Jul 8, 2020
2 parents f9c2f77 + 0490be1 commit b0fd4ff
Show file tree
Hide file tree
Showing 109 changed files with 1,427 additions and 1,340 deletions.
6 changes: 6 additions & 0 deletions AudioWorks/AudioWorks.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,20 @@
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeLocalFunctionBody/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeMethodOrOperatorBody/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AssignNullToNotNullAttribute/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AutoPropertyCanBeMadeGetOnly_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassCanBeSealed_002EGlobal/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassCanBeSealed_002ELocal/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToUsingDeclaration/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InconsistentNaming/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MemberCanBePrivate_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ObjectCreationAsStatement/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=PossibleNullReferenceException/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RemoveRedundantBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnnecessaryWhitespace/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedAutoPropertyAccessor_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedMemberInSuper_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedMember_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedType_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_DOWHILE/@EntryValue">NotRequired</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FIXED/@EntryValue">NotRequired</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_LOCK/@EntryValue">NotRequired</s:String>
Expand Down
23 changes: 7 additions & 16 deletions AudioWorks/src/AudioWorks.Api/AudioWorks.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>
<VersionPrefix>1.0.0</VersionPrefix>
<VersionSuffix>beta8</VersionSuffix>
<VersionSuffix>beta9</VersionSuffix>
<Revision>$(BUILD_BUILDID)</Revision>
<Revision Condition="'$(Revision)'==''">0</Revision>
<FileVersion>1.0.0.$(Revision)</FileVersion>
Expand All @@ -25,6 +25,8 @@
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<NeutralLanguage>en-US</NeutralLanguage>
<CodeAnalysisRuleSet>CodeAnalysis.ruleset</CodeAnalysisRuleSet>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>StrongName.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)'=='Release'">
Expand All @@ -42,22 +44,11 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="AudioWorks.Extensibility" Version="1.0.0-beta8" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="all" />
<PackageReference Include="AudioWorks.Extensibility" Version="1.0.0-beta9" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.0.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="all" />
<PackageReference Include="NuGet.Resolver" Version="5.4.0" />
</ItemGroup>

<!-- ReSharper disable once UnknownProperty -->
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.1'">
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="3.1.2" />
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="4.11.0" />
</ItemGroup>

<!-- ReSharper disable once UnknownProperty -->
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="2.1.0" />
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="4.9.0" />
<PackageReference Include="NuGet.Resolver" Version="5.5.0" />
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="4.8.0" />
</ItemGroup>

<ItemGroup>
Expand Down
189 changes: 114 additions & 75 deletions AudioWorks/src/AudioWorks.Api/ExtensionInstaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ This file is part of AudioWorks.
using AudioWorks.Common;
using AudioWorks.Extensibility;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.Logging;
using NuGet.Common;
using NuGet.Configuration;
Expand Down Expand Up @@ -69,9 +68,9 @@ static class ExtensionInstaller
".so"
});

static readonly string[] _rootAssemblyNames = GetRootAssemblyNames();
static readonly string[] _rootAssemblyNames = GetRootAssemblyNames().ToArray();

internal static async Task DownloadAsync()
internal static async Task TryDownloadAsync()
{
var logger = LoggerManager.LoggerFactory.CreateLogger(typeof(ExtensionInstaller).FullName);

Expand All @@ -81,8 +80,27 @@ internal static async Task DownloadAsync()
{
logger.LogInformation("Beginning automatic extension updates.");

Directory.CreateDirectory(_extensionRoot);
try
{
await DownloadAsync(logger).ConfigureAwait(false);
}
catch (AggregateException e)
{
// Log any connection errors and otherwise fail silently
if (e.InnerException is FatalProtocolException)
logger.LogError(e.InnerException.Message);
else
throw;
}
}
}

static async Task DownloadAsync(ILogger logger)
{
Directory.CreateDirectory(_extensionRoot);

try
{
using (var tokenSource = new CancellationTokenSource(
ConfigurationManager.Configuration.GetValue("AutomaticExtensionDownloadTimeout", 30) * 1000))
{
Expand All @@ -98,22 +116,32 @@ internal static async Task DownloadAsync()

// Remove any extensions that aren't published
if (Directory.Exists(_extensionRoot))
foreach (var obsoleteExtension in new DirectoryInfo(_extensionRoot).GetDirectories()
foreach (var installedExtension in new DirectoryInfo(_extensionRoot).GetDirectories()
.Select(dir => dir.Name)
.Except(publishedPackages.Select(package => package.Identity.ToString()),
StringComparer.OrdinalIgnoreCase))
{
Directory.Delete(Path.Combine(_extensionRoot, obsoleteExtension), true);
Directory.Delete(Path.Combine(_extensionRoot, installedExtension), true);

logger.LogDebug("Deleted unlisted or obsolete extension in '{0}'.",
obsoleteExtension);
logger.LogDebug("Deleted unlisted or obsolete extension in '{0}'.", installedExtension);
}

logger.LogInformation(!packagesInstalled
? "Extensions are already up to date."
: "Extensions successfully updated.");
}
}
catch (FatalProtocolException e)
{
if (e.InnerException is OperationCanceledException)
logger.LogWarning("Timed out enumerating the published extensions.");
else
throw;
}
catch (OperationCanceledException e)
{
logger.LogWarning(e.Message);
}
}

static async Task<IPackageSearchMetadata[]> GetPublishedPackagesAsync(
Expand Down Expand Up @@ -161,64 +189,86 @@ static async Task<bool> InstallPackageAsync(
logger.LogInformation("Installing '{0}' version {1}.",
packageMetadata.Identity.Id, packageMetadata.Identity.Version.ToString());

using (var cacheContext = new SourceCacheContext())
try
{
var packagesToInstall =
await ResolvePackagesAsync(packageMetadata.Identity, cacheContext, cancellationToken)
.ConfigureAwait(false);

var settings = Settings.LoadDefaultSettings(null);
var frameworkReducer = new FrameworkReducer();

// Download and install the package and its dependencies
foreach (var packageToInstall in packagesToInstall)
using (var cacheContext = new SourceCacheContext())
{
var downloadResource = await packageToInstall.Source
.GetResourceAsync<DownloadResource>(cancellationToken)
.ConfigureAwait(false);
var downloadResult = await downloadResource.GetDownloadResourceResultAsync(
packageToInstall,
new PackageDownloadContext(cacheContext),
SettingsUtility.GetGlobalPackagesFolder(settings),
NullLogger.Instance,
cancellationToken)
.ConfigureAwait(false);

var libGroups = downloadResult.PackageReader.GetLibItems().ToArray();
var nearestLibFramework =
frameworkReducer.GetNearest(_framework, libGroups.Select(l => l.TargetFramework));

// Copy the relevant libraries directly from the NuGet cache
foreach (var item in libGroups
.First(l => l.TargetFramework.Equals(nearestLibFramework)).Items)
CopyLibFiles(
Path.Combine(Path.GetDirectoryName(((FileStream) downloadResult.PackageStream).Name), item),
Path.Combine(extensionDir.FullName, Path.GetFileName(item)),
logger);

if (!packageToInstall.Id.StartsWith("AudioWorks.Extensions", StringComparison.OrdinalIgnoreCase))
continue;
var packagesToInstall =
await ResolvePackagesAsync(packageMetadata.Identity, cacheContext, cancellationToken)
.ConfigureAwait(false);

// For AudioWorks extension packages only, copy the native library content files as well
var contentGroups = downloadResult.PackageReader.GetItems("contentFiles").ToArray();
if (contentGroups.Length <= 0) continue;
var settings = Settings.LoadDefaultSettings(null);
var frameworkReducer = new FrameworkReducer();

var nearestContentFramework =
frameworkReducer.GetNearest(_framework, contentGroups.Select(c => c.TargetFramework));

foreach (var item in contentGroups
.First(c => c.TargetFramework.Equals(nearestContentFramework)).Items)
// Download and install the package and its dependencies
foreach (var packageToInstall in packagesToInstall)
{
var sourceFileName = Path.Combine(
Path.GetDirectoryName(((FileStream) downloadResult.PackageStream).Name), item);

CopyContentFiles(
sourceFileName,
Path.Combine(extensionDir.FullName, new DirectoryInfo(sourceFileName).Parent?.Name,
Path.GetFileName(item)),
logger);
var downloadResource = await packageToInstall.Source
.GetResourceAsync<DownloadResource>(cancellationToken)
.ConfigureAwait(false);
var downloadResult = await downloadResource.GetDownloadResourceResultAsync(
packageToInstall,
new PackageDownloadContext(cacheContext),
SettingsUtility.GetGlobalPackagesFolder(settings),
NullLogger.Instance,
cancellationToken)
.ConfigureAwait(false);

if (downloadResult.Status != DownloadResourceResultStatus.Available) continue;

var libGroups = (await downloadResult.PackageReader.GetLibItemsAsync(cancellationToken)
.ConfigureAwait(false)).ToArray();
var nearestLibFramework =
frameworkReducer.GetNearest(_framework, libGroups.Select(l => l.TargetFramework));

// Copy the relevant libraries directly from the NuGet cache
foreach (var item in libGroups
.First(l => l.TargetFramework.Equals(nearestLibFramework)).Items)
CopyLibFiles(
Path.Combine(Path.GetDirectoryName(((FileStream) downloadResult.PackageStream).Name),
item),
Path.Combine(extensionDir.FullName, Path.GetFileName(item)),
logger);

if (!packageToInstall.Id.StartsWith("AudioWorks.Extensions",
StringComparison.OrdinalIgnoreCase))
continue;

// For AudioWorks extension packages only, copy the native library content files as well
var contentGroups = (await downloadResult.PackageReader
.GetItemsAsync("contentFiles", cancellationToken).ConfigureAwait(false)).ToArray();
if (contentGroups.Length <= 0) continue;

var nearestContentFramework =
frameworkReducer.GetNearest(_framework, contentGroups.Select(c => c.TargetFramework));

foreach (var item in contentGroups
.First(c => c.TargetFramework.Equals(nearestContentFramework)).Items)
{
var sourceFileName = Path.Combine(
Path.GetDirectoryName(((FileStream) downloadResult.PackageStream).Name), item);

CopyContentFiles(
sourceFileName,
Path.Combine(extensionDir.FullName, new DirectoryInfo(sourceFileName).Parent?.Name,
Path.GetFileName(item)),
logger);
}
}
}

cancellationToken.ThrowIfCancellationRequested();
}
catch (Exception)
{
// Clean up a partial installation
if (Directory.Exists(extensionDir.FullName))
{
logger.LogDebug("Deleting partially-installed extension '{0}'.", extensionDir.Name);
extensionDir.Delete(true);
}

throw;
}

return true;
Expand Down Expand Up @@ -264,7 +314,7 @@ static async Task CollectDependenciesAsync(
.ConfigureAwait(false);
var dependencyInfo = await dependencyInfoResource.ResolvePackage(
packageIdentity,
NuGetFramework.AnyFramework,
_framework,
cacheContext,
NullLogger.Instance,
cancellationToken)
Expand Down Expand Up @@ -328,12 +378,10 @@ static void CopyContentFiles(string source, string destination, ILogger logger)
File.Copy(source, destination);
}

static string[] GetRootAssemblyNames()
{
var rootDirectory = new DirectoryInfo(
Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath));

var result = rootDirectory.GetFiles("*.dll")
static IEnumerable<string> GetRootAssemblyNames() =>
new DirectoryInfo(
Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath))
.EnumerateFiles("*.dll")
.Select(file =>
{
try
Expand All @@ -346,14 +394,5 @@ static string[] GetRootAssemblyNames()
return Path.GetFileNameWithoutExtension(file.Name);
}
});

// .NET Core applications may be loading via a runtime configuration file
foreach (var dependenciesFile in rootDirectory.GetFiles("*.deps.json"))
using (var stream = dependenciesFile.OpenRead())
using (var reader = new DependencyContextJsonReader())
result = result.Union(reader.Read(stream).RuntimeLibraries.Select(library => library.Name));

return result.ToArray();
}
}
}
2 changes: 1 addition & 1 deletion AudioWorks/src/AudioWorks.Api/ExtensionProviderWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace AudioWorks.Api
{
static class ExtensionProviderWrapper
{
static ExtensionProviderWrapper() => ExtensionInstaller.DownloadAsync().Wait();
static ExtensionProviderWrapper() => ExtensionInstaller.TryDownloadAsync().Wait();

internal static IEnumerable<ExportFactory<T, IDictionary<string, object>>> GetFactories<T>()
where T : class =>
Expand Down
Binary file added AudioWorks/src/AudioWorks.Api/StrongName.snk
Binary file not shown.
6 changes: 2 additions & 4 deletions AudioWorks/src/AudioWorks.Api/TaggedAudioFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ public TaggedAudioFile(string path)
/// <inheritdoc/>
public void SaveMetadata(SettingDictionary? settings = null)
{
if (settings == null)
settings = new SettingDictionary();
settings ??= new SettingDictionary();
var extension = IO.Path.GetExtension(Path);

// Make sure the provided settings are clean
Expand All @@ -61,8 +60,7 @@ public void SaveMetadata(SettingDictionary? settings = null)
"Extension", extension))
using (var export = factory.CreateExport())
{
if (_metadata == null)
_metadata = LoadMetadata(fileStream);
_metadata ??= LoadMetadata(fileStream);

export.Value.WriteMetadata(fileStream, _metadata, settings);
return;
Expand Down
Loading

0 comments on commit b0fd4ff

Please sign in to comment.