Remove build-time service reference download feature (#8981)
- #7500 - skip dotnet-watch `RenameCompiledFile()` test - #8987
This commit is contained in:
parent
6a6a870f08
commit
91dcbd44c1
|
|
@ -1,229 +0,0 @@
|
||||||
// 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;
|
|
||||||
using System.IO;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Build.Framework;
|
|
||||||
using Microsoft.Build.Utilities;
|
|
||||||
using Task = System.Threading.Tasks.Task;
|
|
||||||
using Utilities = Microsoft.Build.Utilities;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.ApiDescription.Tasks
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Downloads a file.
|
|
||||||
/// </summary>
|
|
||||||
public class DownloadFile : Utilities.Task, ICancelableTask
|
|
||||||
{
|
|
||||||
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The URI to download.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public string Uri { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Destination for the downloaded file. If the file already exists, it is not re-downloaded unless
|
|
||||||
/// <see cref="Overwrite"/> is true.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public string DestinationPath { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Should <see cref="DestinationPath"/> be overwritten. When <c>true</c>, the file is downloaded and its hash
|
|
||||||
/// compared to the existing file. If those hashes do not match (or <see cref="DestinationPath"/> does not
|
|
||||||
/// exist), <see cref="DestinationPath"/> is overwritten.
|
|
||||||
/// </summary>
|
|
||||||
public bool Overwrite { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The maximum amount of time in seconds to allow for downloading the file. Defaults to 2 minutes.
|
|
||||||
/// </summary>
|
|
||||||
public int TimeoutSeconds { get; set; } = 60 * 2;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void Cancel() => _cts.Cancel();
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public override bool Execute() => ExecuteAsync().Result;
|
|
||||||
|
|
||||||
public async Task<bool> ExecuteAsync()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(Uri))
|
|
||||||
{
|
|
||||||
Log.LogError("Uri parameter must not be null or empty.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(Uri))
|
|
||||||
{
|
|
||||||
Log.LogError("DestinationPath parameter must not be null or empty.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var builder = new UriBuilder(Uri);
|
|
||||||
if (!string.Equals(System.Uri.UriSchemeHttp, builder.Scheme, StringComparison.OrdinalIgnoreCase) &&
|
|
||||||
!string.Equals(System.Uri.UriSchemeHttps, builder.Scheme, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Log.LogError($"{nameof(Uri)} parameter does not have scheme {System.Uri.UriSchemeHttp} or " +
|
|
||||||
$"{System.Uri.UriSchemeHttps}.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
await DownloadFileAsync(Uri, DestinationPath, Overwrite, _cts.Token, TimeoutSeconds, Log);
|
|
||||||
|
|
||||||
return !Log.HasLoggedErrors;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task DownloadFileAsync(
|
|
||||||
string uri,
|
|
||||||
string destinationPath,
|
|
||||||
bool overwrite,
|
|
||||||
CancellationToken cancellationToken,
|
|
||||||
int timeoutSeconds,
|
|
||||||
TaskLoggingHelper log)
|
|
||||||
{
|
|
||||||
var destinationExists = File.Exists(destinationPath);
|
|
||||||
if (destinationExists && !overwrite)
|
|
||||||
{
|
|
||||||
log.LogMessage($"Not downloading '{uri}' to overwrite existing file '{destinationPath}'.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
log.LogMessage(MessageImportance.High, $"Downloading '{uri}' to '{destinationPath}'.");
|
|
||||||
|
|
||||||
using (var httpClient = new HttpClient())
|
|
||||||
{
|
|
||||||
await DownloadAsync(uri, destinationPath, httpClient, cancellationToken, log, timeoutSeconds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task DownloadAsync(
|
|
||||||
string uri,
|
|
||||||
string destinationPath,
|
|
||||||
HttpClient httpClient,
|
|
||||||
CancellationToken cancellationToken,
|
|
||||||
TaskLoggingHelper log,
|
|
||||||
int timeoutSeconds)
|
|
||||||
{
|
|
||||||
// Timeout if the response has not begun within 1 minute
|
|
||||||
httpClient.Timeout = TimeSpan.FromMinutes(1);
|
|
||||||
|
|
||||||
var destinationExists = File.Exists(destinationPath);
|
|
||||||
var reachedCopy = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var response = await httpClient.GetAsync(uri, cancellationToken))
|
|
||||||
{
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
using (var responseStreamTask = response.Content.ReadAsStreamAsync())
|
|
||||||
{
|
|
||||||
var finished = await Task.WhenAny(
|
|
||||||
responseStreamTask,
|
|
||||||
Task.Delay(TimeSpan.FromSeconds(timeoutSeconds)));
|
|
||||||
|
|
||||||
if (!ReferenceEquals(responseStreamTask, finished))
|
|
||||||
{
|
|
||||||
throw new TimeoutException($"Download failed to complete in {timeoutSeconds} seconds.");
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var responseStream = await responseStreamTask)
|
|
||||||
{
|
|
||||||
if (destinationExists)
|
|
||||||
{
|
|
||||||
// Check hashes before using the downloaded information.
|
|
||||||
var downloadHash = GetHash(responseStream);
|
|
||||||
responseStream.Position = 0L;
|
|
||||||
|
|
||||||
byte[] destinationHash;
|
|
||||||
using (var destinationStream = File.OpenRead(destinationPath))
|
|
||||||
{
|
|
||||||
destinationHash = GetHash(destinationStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
var sameHashes = downloadHash.Length == destinationHash.Length;
|
|
||||||
for (var i = 0; sameHashes && i < downloadHash.Length; i++)
|
|
||||||
{
|
|
||||||
sameHashes = downloadHash[i] == destinationHash[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sameHashes)
|
|
||||||
{
|
|
||||||
log.LogMessage($"Not overwriting existing and matching file '{destinationPath}'.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// May need to create directory to hold the file.
|
|
||||||
var destinationDirectory = Path.GetDirectoryName(destinationPath);
|
|
||||||
if (!string.IsNullOrEmpty(destinationDirectory))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(destinationDirectory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create or overwrite the destination file.
|
|
||||||
reachedCopy = true;
|
|
||||||
using (var outStream = File.Create(destinationPath))
|
|
||||||
{
|
|
||||||
await responseStream.CopyToAsync(outStream);
|
|
||||||
|
|
||||||
await outStream.FlushAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (HttpRequestException ex) when (destinationExists)
|
|
||||||
{
|
|
||||||
if (ex.InnerException is SocketException socketException)
|
|
||||||
{
|
|
||||||
log.LogWarning($"Unable to download {uri}, socket error code '{socketException.SocketErrorCode}'.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log.LogWarning($"Unable to download {uri}: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
log.LogError($"Downloading '{uri}' failed.");
|
|
||||||
log.LogErrorFromException(ex, showStackTrace: true);
|
|
||||||
if (reachedCopy)
|
|
||||||
{
|
|
||||||
File.Delete(destinationPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] GetHash(Stream stream)
|
|
||||||
{
|
|
||||||
SHA256 algorithm;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
algorithm = SHA256.Create();
|
|
||||||
}
|
|
||||||
catch (TargetInvocationException)
|
|
||||||
{
|
|
||||||
// SHA256.Create is documented to throw this exception on FIPS-compliant machines. See
|
|
||||||
// https://msdn.microsoft.com/en-us/library/z08hz7ad Fall back to a FIPS-compliant SHA256 algorithm.
|
|
||||||
algorithm = new SHA256CryptoServiceProvider();
|
|
||||||
}
|
|
||||||
|
|
||||||
using (algorithm)
|
|
||||||
{
|
|
||||||
return algorithm.ComputeHash(stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -66,10 +66,6 @@ namespace Microsoft.Extensions.ApiDescription.Tasks
|
||||||
{
|
{
|
||||||
type = "ServiceProjectReference";
|
type = "ServiceProjectReference";
|
||||||
}
|
}
|
||||||
else if (!string.IsNullOrEmpty(item.GetMetadata("SourceUri")))
|
|
||||||
{
|
|
||||||
type = "ServiceUriReference";
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type = "ServiceFileReference";
|
type = "ServiceFileReference";
|
||||||
|
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
// 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;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
using Microsoft.Build.Framework;
|
|
||||||
using Microsoft.Build.Utilities;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.ApiDescription.Tasks
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Adds or corrects DocumentPath metadata in ServiceUriReference items.
|
|
||||||
/// </summary>
|
|
||||||
public class GetUriReferenceMetadata : Task
|
|
||||||
{
|
|
||||||
private static readonly char[] InvalidFilenameCharacters = Path.GetInvalidFileNameChars();
|
|
||||||
private static readonly string[] InvalidFilenameStrings = new[] { ".." };
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default directory for DocumentPath metadata values.
|
|
||||||
/// </summary>
|
|
||||||
public string DocumentDirectory { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The ServiceUriReference items to update.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public ITaskItem[] Inputs { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The updated ServiceUriReference items. Will include DocumentPath metadata with full paths.
|
|
||||||
/// </summary>
|
|
||||||
[Output]
|
|
||||||
public ITaskItem[] Outputs{ get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool Execute()
|
|
||||||
{
|
|
||||||
var outputs = new List<ITaskItem>(Inputs.Length);
|
|
||||||
var destinations = new HashSet<string>();
|
|
||||||
foreach (var item in Inputs)
|
|
||||||
{
|
|
||||||
var newItem = new TaskItem(item);
|
|
||||||
outputs.Add(newItem);
|
|
||||||
|
|
||||||
var uri = item.ItemSpec;
|
|
||||||
var builder = new UriBuilder(uri);
|
|
||||||
if (!builder.Uri.IsAbsoluteUri)
|
|
||||||
{
|
|
||||||
Log.LogError($"{nameof(Inputs)} item '{uri}' is not an absolute URI.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.Equals(Uri.UriSchemeHttp, builder.Scheme, StringComparison.OrdinalIgnoreCase) &&
|
|
||||||
!string.Equals(Uri.UriSchemeHttps, builder.Scheme, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Log.LogError($"{nameof(Inputs)} item '{uri}' does not have scheme {Uri.UriSchemeHttp} or " +
|
|
||||||
$"{Uri.UriSchemeHttps}.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not specified, base filename on the URI.
|
|
||||||
var documentPath = item.GetMetadata("DocumentPath");
|
|
||||||
if (string.IsNullOrEmpty(documentPath))
|
|
||||||
{
|
|
||||||
// Default to a fairly long but identifiable and fairly unique filename.
|
|
||||||
var documentPathBuilder = new StringBuilder(builder.Host);
|
|
||||||
if (!string.IsNullOrEmpty(builder.Path) &&
|
|
||||||
!string.Equals("/", builder.Path, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
documentPathBuilder.Append(builder.Path);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(builder.Query) &&
|
|
||||||
!string.Equals("?", builder.Query, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
documentPathBuilder.Append(builder.Query);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sanitize the string because it likely contains illegal filename characters such as '/' and '?'.
|
|
||||||
// (Do not treat slashes as folder separators.)
|
|
||||||
documentPath = documentPathBuilder.ToString();
|
|
||||||
documentPath = string.Join("_", documentPath.Split(InvalidFilenameCharacters));
|
|
||||||
while (documentPath.Contains(InvalidFilenameStrings[0]))
|
|
||||||
{
|
|
||||||
documentPath = string.Join(
|
|
||||||
".",
|
|
||||||
documentPath.Split(InvalidFilenameStrings, StringSplitOptions.None));
|
|
||||||
}
|
|
||||||
|
|
||||||
// URI might end with ".json". Don't duplicate that or a final period.
|
|
||||||
if (!documentPath.EndsWith(".json", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
if (documentPath.EndsWith(".", StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
documentPath += "json";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
documentPath += ".json";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
documentPath = GetFullPath(documentPath);
|
|
||||||
if (!destinations.Add(documentPath))
|
|
||||||
{
|
|
||||||
// This case may occur when user is experimenting e.g. with multiple code generators or options.
|
|
||||||
// May also occur when user accidentally duplicates DocumentPath metadata.
|
|
||||||
Log.LogError(Resources.FormatDuplicateUriDocumentPaths(documentPath));
|
|
||||||
}
|
|
||||||
|
|
||||||
MetadataSerializer.SetMetadata(newItem, "DocumentPath", documentPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
Outputs = outputs.ToArray();
|
|
||||||
|
|
||||||
return !Log.HasLoggedErrors;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetFullPath(string path)
|
|
||||||
{
|
|
||||||
if (!Path.IsPathRooted(path))
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(DocumentDirectory))
|
|
||||||
{
|
|
||||||
path = Path.Combine(DocumentDirectory, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
path = Path.GetFullPath(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -11,7 +11,7 @@ namespace Microsoft.Extensions.ApiDescription.Tasks
|
||||||
= new ResourceManager("Microsoft.Extensions.ApiDescription.Tasks.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
= new ResourceManager("Microsoft.Extensions.ApiDescription.Tasks.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Multiple items have OutputPath='{0}'. All ServiceFileReference, ServiceProjectReference and ServiceUriReference items must have unique OutputPath metadata.
|
/// Multiple items have OutputPath='{0}'. All ServiceFileReference and ServiceProjectReference items must have unique OutputPath metadata.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string DuplicateFileOutputPaths
|
internal static string DuplicateFileOutputPaths
|
||||||
{
|
{
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.Extensions.ApiDescription.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Multiple items have OutputPath='{0}'. All ServiceFileReference, ServiceProjectReference and ServiceUriReference items must have unique OutputPath metadata.
|
/// Multiple items have OutputPath='{0}'. All ServiceFileReference and ServiceProjectReference items must have unique OutputPath metadata.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string FormatDuplicateFileOutputPaths(object p0)
|
internal static string FormatDuplicateFileOutputPaths(object p0)
|
||||||
=> string.Format(CultureInfo.CurrentCulture, GetString("DuplicateFileOutputPaths"), p0);
|
=> string.Format(CultureInfo.CurrentCulture, GetString("DuplicateFileOutputPaths"), p0);
|
||||||
|
|
@ -38,20 +38,6 @@ namespace Microsoft.Extensions.ApiDescription.Tasks
|
||||||
internal static string FormatDuplicateProjectDocumentPaths(object p0)
|
internal static string FormatDuplicateProjectDocumentPaths(object p0)
|
||||||
=> string.Format(CultureInfo.CurrentCulture, GetString("DuplicateProjectDocumentPaths"), p0);
|
=> string.Format(CultureInfo.CurrentCulture, GetString("DuplicateProjectDocumentPaths"), p0);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Mutliple ServiceUriReference items have DocumentPath='{0}'. ServiceUriReference items must have unique DocumentPath metadata.
|
|
||||||
/// </summary>
|
|
||||||
internal static string DuplicateUriDocumentPaths
|
|
||||||
{
|
|
||||||
get => GetString("DuplicateUriDocumentPaths");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Mutliple ServiceUriReference items have DocumentPath='{0}'. ServiceUriReference items must have unique DocumentPath metadata.
|
|
||||||
/// </summary>
|
|
||||||
internal static string FormatDuplicateUriDocumentPaths(object p0)
|
|
||||||
=> string.Format(CultureInfo.CurrentCulture, GetString("DuplicateUriDocumentPaths"), p0);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invalid {0} metadata value for {1} item '{2}'. {0} metadata must not be set to the empty string.
|
/// Invalid {0} metadata value for {1} item '{2}'. {0} metadata must not be set to the empty string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -118,16 +118,12 @@
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<data name="DuplicateFileOutputPaths" xml:space="preserve">
|
<data name="DuplicateFileOutputPaths" xml:space="preserve">
|
||||||
<value>Multiple items have OutputPath='{0}'. All ServiceFileReference, ServiceProjectReference and ServiceUriReference items must have unique OutputPath metadata.</value>
|
<value>Multiple items have OutputPath='{0}'. All ServiceFileReference and ServiceProjectReference items must have unique OutputPath metadata.</value>
|
||||||
<comment>ServiceProjectReference and ServiceUriReference items become ServiceFileReference items and all ServiceFileReference items must have unique OutputPath metadata.</comment>
|
<comment>ServiceProjectReference items become ServiceFileReference items and all ServiceFileReference items must have unique OutputPath metadata.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="DuplicateProjectDocumentPaths" xml:space="preserve">
|
<data name="DuplicateProjectDocumentPaths" xml:space="preserve">
|
||||||
<value>Mutliple ServiceProjectReference items have DocumentPath='{0}'. ServiceProjectReference items must have unique DocumentPath metadata.</value>
|
<value>Mutliple ServiceProjectReference items have DocumentPath='{0}'. ServiceProjectReference items must have unique DocumentPath metadata.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DuplicateUriDocumentPaths" xml:space="preserve">
|
|
||||||
<value>Mutliple ServiceUriReference items have DocumentPath='{0}'. ServiceUriReference items must have unique DocumentPath metadata.</value>
|
|
||||||
<comment>Ignore corner case of ServiceProjectReference and ServiceUriReference items having the same DocumentPath.</comment>
|
|
||||||
</data>
|
|
||||||
<data name="InvalidEmptyMetadataValue" xml:space="preserve">
|
<data name="InvalidEmptyMetadataValue" xml:space="preserve">
|
||||||
<value>Invalid {0} metadata value for {1} item '{2}'. {0} metadata must not be set to the empty string.</value>
|
<value>Invalid {0} metadata value for {1} item '{2}'. {0} metadata must not be set to the empty string.</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,6 @@
|
||||||
<UsingTask TaskName="GetCurrentItems" AssemblyFile="$(_ApiDescriptionTasksAssemblyPath)" />
|
<UsingTask TaskName="GetCurrentItems" AssemblyFile="$(_ApiDescriptionTasksAssemblyPath)" />
|
||||||
<UsingTask TaskName="GetFileReferenceMetadata" AssemblyFile="$(_ApiDescriptionTasksAssemblyPath)" />
|
<UsingTask TaskName="GetFileReferenceMetadata" AssemblyFile="$(_ApiDescriptionTasksAssemblyPath)" />
|
||||||
<UsingTask TaskName="GetProjectReferenceMetadata" AssemblyFile="$(_ApiDescriptionTasksAssemblyPath)" />
|
<UsingTask TaskName="GetProjectReferenceMetadata" AssemblyFile="$(_ApiDescriptionTasksAssemblyPath)" />
|
||||||
<UsingTask TaskName="GetUriReferenceMetadata" AssemblyFile="$(_ApiDescriptionTasksAssemblyPath)" />
|
|
||||||
<UsingTask TaskName="Microsoft.Extensions.ApiDescription.Tasks.DownloadFile"
|
|
||||||
AssemblyFile="$(_ApiDescriptionTasksAssemblyPath)" />
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Settings users may update as they see fit. All $(...Directory) values are interpreted relative to the client
|
Settings users may update as they see fit. All $(...Directory) values are interpreted relative to the client
|
||||||
|
|
@ -25,11 +22,6 @@
|
||||||
<ServiceProjectReferenceDirectory
|
<ServiceProjectReferenceDirectory
|
||||||
Condition="'$(ServiceProjectReferenceDirectory)' != ''">$([MSBuild]::EnsureTrailingSlash('$(ServiceProjectReferenceDirectory)'))</ServiceProjectReferenceDirectory>
|
Condition="'$(ServiceProjectReferenceDirectory)' != ''">$([MSBuild]::EnsureTrailingSlash('$(ServiceProjectReferenceDirectory)'))</ServiceProjectReferenceDirectory>
|
||||||
|
|
||||||
<ServiceUriReferenceCheckIfNewer
|
|
||||||
Condition="'$(ServiceUriReferenceCheckIfNewer)' == ''">true</ServiceUriReferenceCheckIfNewer>
|
|
||||||
<ServiceUriReferenceDirectory
|
|
||||||
Condition="'$(ServiceUriReferenceDirectory)' != ''">$([MSBuild]::EnsureTrailingSlash('$(ServiceUriReferenceDirectory)'))</ServiceUriReferenceDirectory>
|
|
||||||
|
|
||||||
<ServiceFileReferenceCheckIfNewer
|
<ServiceFileReferenceCheckIfNewer
|
||||||
Condition="'$(ServiceFileReferenceCheckIfNewer)' == ''">true</ServiceFileReferenceCheckIfNewer>
|
Condition="'$(ServiceFileReferenceCheckIfNewer)' == ''">true</ServiceFileReferenceCheckIfNewer>
|
||||||
<ServiceFileReferenceDirectory
|
<ServiceFileReferenceDirectory
|
||||||
|
|
@ -39,8 +31,8 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Well-known metadata of the code and document generator item groups. ServiceProjectReference and ServiceUriReference
|
Well-known metadata of the code and document generator item groups. ServiceProjectReference items may also include
|
||||||
items may also include ServiceFileReference metadata.
|
ServiceFileReference metadata.
|
||||||
-->
|
-->
|
||||||
<ItemDefinitionGroup>
|
<ItemDefinitionGroup>
|
||||||
<ServiceProjectReference>
|
<ServiceProjectReference>
|
||||||
|
|
@ -107,14 +99,6 @@
|
||||||
<Service />
|
<Service />
|
||||||
</ServiceProjectReference>
|
</ServiceProjectReference>
|
||||||
|
|
||||||
<ServiceUriReference>
|
|
||||||
<!--
|
|
||||||
Full path where the API description document is placed. Default filename is based on %(Identity).
|
|
||||||
Filenames and relative paths (if explicitly set) are combined with $(ServiceUriReferenceDirectory).
|
|
||||||
-->
|
|
||||||
<DocumentPath />
|
|
||||||
</ServiceUriReference>
|
|
||||||
|
|
||||||
<ServiceFileReference>
|
<ServiceFileReference>
|
||||||
<!-- Name of the class to generate. Defaults to match final segment of %(OutputPath). -->
|
<!-- Name of the class to generate. Defaults to match final segment of %(OutputPath). -->
|
||||||
<ClassName />
|
<ClassName />
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,8 @@
|
||||||
_GenerateServiceProjectReferenceDocuments;
|
_GenerateServiceProjectReferenceDocuments;
|
||||||
_CreateFileItemsForServiceProjectReferences
|
_CreateFileItemsForServiceProjectReferences
|
||||||
</GenerateServiceProjectReferenceDocumentsDependsOn>
|
</GenerateServiceProjectReferenceDocumentsDependsOn>
|
||||||
<GenerateServiceUriReferenceDocumentsDependsOn>
|
|
||||||
_GetMetadataForServiceUriReferences;
|
|
||||||
_GenerateServiceUriReferenceDocuments
|
|
||||||
</GenerateServiceUriReferenceDocumentsDependsOn>
|
|
||||||
<GenerateServiceFileReferenceCodesDependsOn>
|
<GenerateServiceFileReferenceCodesDependsOn>
|
||||||
GenerateServiceProjectReferenceDocuments;
|
GenerateServiceProjectReferenceDocuments;
|
||||||
GenerateServiceUriReferenceDocuments;
|
|
||||||
_GetMetadataForServiceFileReferences;
|
_GetMetadataForServiceFileReferences;
|
||||||
_GenerateServiceFileReferenceCodes;
|
_GenerateServiceFileReferenceCodes;
|
||||||
_CreateCompileItemsForServiceFileReferences
|
_CreateCompileItemsForServiceFileReferences
|
||||||
|
|
@ -210,41 +205,6 @@
|
||||||
IgnoreExitCode="$([System.IO.File]::Exists('%(DocumentPath)'))" />
|
IgnoreExitCode="$([System.IO.File]::Exists('%(DocumentPath)'))" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<!-- ServiceUriReference support -->
|
|
||||||
|
|
||||||
<Target Name="_GetMetadataForServiceUriReferences" Condition="'@(ServiceUriReference)' != ''">
|
|
||||||
<ItemGroup>
|
|
||||||
<_Temporary Remove="@(_Temporary)" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<GetUriReferenceMetadata Inputs="@(ServiceUriReference)" DocumentDirectory="$(ServiceUriReferenceDirectory)">
|
|
||||||
<Output TaskParameter="Outputs" ItemName="_Temporary" />
|
|
||||||
</GetUriReferenceMetadata>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ServiceUriReference Remove="@(ServiceUriReference)" />
|
|
||||||
<ServiceUriReference Include="@(_Temporary)" />
|
|
||||||
<_Temporary Remove="@(_Temporary)" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<Target Name="_GenerateServiceUriReferenceDocuments" Condition="'@(ServiceUriReference)' != ''">
|
|
||||||
<Microsoft.Extensions.ApiDescription.Tasks.DownloadFile Uri="%(ServiceUriReference.Identity)"
|
|
||||||
DestinationPath="%(DocumentPath)"
|
|
||||||
Overwrite="$(ServiceUriReferenceCheckIfNewer)" />
|
|
||||||
|
|
||||||
<!-- GetUriReferenceMetadata task guarantees %(DocumentPath) values are unique. -->
|
|
||||||
<ItemGroup>
|
|
||||||
<ServiceFileReference Remove="@(ServiceUriReference -> '%(DocumentPath)')" />
|
|
||||||
<ServiceFileReference Include="@(ServiceUriReference -> '%(DocumentPath)')">
|
|
||||||
<SourceUri>%(ServiceUriReference.Identity)</SourceUri>
|
|
||||||
</ServiceFileReference>
|
|
||||||
</ItemGroup>
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<Target Name="GenerateServiceUriReferenceDocuments"
|
|
||||||
DependsOnTargets="$(GenerateServiceUriReferenceDocumentsDependsOn)" />
|
|
||||||
|
|
||||||
<!-- ServiceFileReference support -->
|
<!-- ServiceFileReference support -->
|
||||||
|
|
||||||
<Target Name="_GetMetadataForServiceFileReferences" Condition="'@(ServiceFileReference)' != ''">
|
<Target Name="_GetMetadataForServiceFileReferences" Condition="'@(ServiceFileReference)' != ''">
|
||||||
|
|
@ -285,8 +245,8 @@
|
||||||
|
|
||||||
<Target Name="_CreateCompileItemsForServiceFileReferences" Condition="'@(ServiceFileReference)' != ''">
|
<Target Name="_CreateCompileItemsForServiceFileReferences" Condition="'@(ServiceFileReference)' != ''">
|
||||||
<!--
|
<!--
|
||||||
While %(DocumentPath) metadata may include duplicates (due to overlaps between ServiceUriReference and
|
While %(DocumentPath) metadata may include duplicates, GetFileReferenceMetadata task guarantees %(OutputPath)
|
||||||
ServiceProjectReference items), GetFileReferenceMetadata task guarantees %(OutputPath) values are unique.
|
values are unique.
|
||||||
-->
|
-->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<_Files Remove="@(_Files)" />
|
<_Files Remove="@(_Files)" />
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
||||||
Assert.Equal(1, types);
|
Assert.Equal(1, types);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/8987")]
|
||||||
public async Task RenameCompiledFile()
|
public async Task RenameCompiledFile()
|
||||||
{
|
{
|
||||||
await _app.StartWatcherAsync();
|
await _app.StartWatcherAsync();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue