First pass at dotnet-pack
- Ported nuget package building code over from dnu. Moved that code to use NuGet v3 primitives. - Simplified the package builder API - Left out resources and schema detection for now - This folder should remain self contained as the code will be copied into NuGet v3. - Missing features include symbols packages
This commit is contained in:
parent
ba3f0745e3
commit
df3a5fba7a
23 changed files with 1870 additions and 18 deletions
|
@ -220,7 +220,7 @@ namespace Microsoft.Extensions.ProjectModel.Compilation
|
|||
{
|
||||
foreach (var assemblyPath in section)
|
||||
{
|
||||
if (PathUtility.IsPlaceholderFile(assemblyPath))
|
||||
if (IsPlaceholderFile(assemblyPath))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -232,6 +232,11 @@ namespace Microsoft.Extensions.ProjectModel.Compilation
|
|||
}
|
||||
}
|
||||
|
||||
private static bool IsPlaceholderFile(string path)
|
||||
{
|
||||
return string.Equals(Path.GetFileName(path), "_._", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static bool LibraryIsOfType(LibraryType type, LibraryDescription library)
|
||||
{
|
||||
return type.Equals(LibraryType.Unspecified) || // No type filter was requested
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace Microsoft.Extensions.ProjectModel.Graph
|
|||
{
|
||||
private readonly LibraryDependencyTypeFlag _flags;
|
||||
|
||||
public static LibraryDependencyType Default = new LibraryDependencyType();
|
||||
public static LibraryDependencyType Default = LibraryDependencyType.Parse("default");
|
||||
|
||||
private LibraryDependencyType(LibraryDependencyTypeFlag flags)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Linq;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
namespace NuGet.Frameworks
|
||||
{
|
||||
|
@ -8,13 +9,45 @@ namespace NuGet.Frameworks
|
|||
public static string GetTwoDigitShortFolderName(this NuGetFramework self)
|
||||
{
|
||||
var original = self.GetShortFolderName();
|
||||
|
||||
var digits = original.SkipWhile(c => !char.IsDigit(c)).ToArray();
|
||||
if(digits.Length == 1)
|
||||
var index = 0;
|
||||
for (; index < original.Length; index++)
|
||||
{
|
||||
return original + "0";
|
||||
if (char.IsDigit(original[index]))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return original;
|
||||
|
||||
var versionPart = original.Substring(index);
|
||||
|
||||
// Assume if the version part was preserved then leave it alone
|
||||
if (versionPart.IndexOf('.') != -1)
|
||||
{
|
||||
return original;
|
||||
}
|
||||
|
||||
var name = original.Substring(0, index);
|
||||
var version = self.Version.ToString(2);
|
||||
|
||||
if (self.Framework.Equals(FrameworkConstants.FrameworkIdentifiers.NetPlatform))
|
||||
{
|
||||
return name + version;
|
||||
}
|
||||
|
||||
return name + version.Replace(".", string.Empty);
|
||||
}
|
||||
|
||||
// NuGet.Frameworks doesn't have the equivalent of the old VersionUtility.GetFrameworkString
|
||||
// which is relevant for building packages
|
||||
public static string GetFrameworkString(this NuGetFramework self)
|
||||
{
|
||||
var frameworkName = new FrameworkName(self.DotNetFrameworkName);
|
||||
string name = frameworkName.Identifier + frameworkName.Version;
|
||||
if (string.IsNullOrEmpty(frameworkName.Profile))
|
||||
{
|
||||
return name;
|
||||
}
|
||||
return name + "-" + frameworkName.Profile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,6 @@ namespace Microsoft.Extensions.ProjectModel.Utilities
|
|||
{
|
||||
internal static class PathUtility
|
||||
{
|
||||
public static bool IsPlaceholderFile(string path)
|
||||
{
|
||||
return string.Equals(Path.GetFileName(path), "_._", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public static bool IsChildOfDirectory(string dir, string candidate)
|
||||
{
|
||||
if (dir == null)
|
||||
|
|
|
@ -5,9 +5,9 @@ using NuGet.Versioning;
|
|||
|
||||
namespace Microsoft.Extensions.ProjectModel.Utilities
|
||||
{
|
||||
internal static class VersionUtility
|
||||
public static class VersionUtility
|
||||
{
|
||||
public static NuGetVersion GetAssemblyVersion(string path)
|
||||
internal static NuGetVersion GetAssemblyVersion(string path)
|
||||
{
|
||||
return new NuGetVersion(AssemblyLoadContext.GetAssemblyName(path).Version);
|
||||
}
|
||||
|
|
|
@ -268,9 +268,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
runtimeContext.CreateExporter(configuration));
|
||||
}
|
||||
|
||||
PrintSummary(diagnostics, sw, success);
|
||||
|
||||
return success;
|
||||
return PrintSummary(diagnostics, sw, success);
|
||||
}
|
||||
|
||||
private static string GetProjectOutput(Project project, NuGetFramework framework, string configuration, string outputPath)
|
||||
|
@ -433,7 +431,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
return "\"" + input.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
|
||||
}
|
||||
|
||||
private static void PrintSummary(List<DiagnosticMessage> diagnostics, Stopwatch sw, bool success = true)
|
||||
private static bool PrintSummary(List<DiagnosticMessage> diagnostics, Stopwatch sw, bool success = true)
|
||||
{
|
||||
PrintDiagnostics(diagnostics);
|
||||
|
||||
|
@ -445,6 +443,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
if (errorCount > 0 || !success)
|
||||
{
|
||||
Reporter.Output.WriteLine("Compilation failed.".Red());
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -458,6 +457,8 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
|
||||
Reporter.Output.WriteLine($"Time elapsed {sw.Elapsed}");
|
||||
Reporter.Output.WriteLine();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private static bool AddResources(Project project, List<string> compilerArgs, string intermediateOutputPath)
|
||||
|
|
64
src/Microsoft.DotNet.Tools.Pack/NuGet/Constants.cs
Normal file
64
src/Microsoft.DotNet.Tools.Pack/NuGet/Constants.cs
Normal file
|
@ -0,0 +1,64 @@
|
|||
// 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;
|
||||
|
||||
namespace NuGet
|
||||
{
|
||||
public static class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the ".nupkg" extension.
|
||||
/// </summary>
|
||||
public static readonly string PackageExtension = ".nupkg";
|
||||
|
||||
/// <summary>
|
||||
/// Represents the ".nuspec" extension.
|
||||
/// </summary>
|
||||
public static readonly string ManifestExtension = ".nuspec";
|
||||
|
||||
/// <summary>
|
||||
/// Represents the ".nupkg.sha512" extension.
|
||||
/// </summary>
|
||||
public static readonly string HashFileExtension = ".nupkg.sha512";
|
||||
|
||||
/// <summary>
|
||||
/// Represents the content directory in the package.
|
||||
/// </summary>
|
||||
public static readonly string ContentDirectory = "content";
|
||||
|
||||
/// <summary>
|
||||
/// Represents the lib directory in the package.
|
||||
/// </summary>
|
||||
public static readonly string LibDirectory = "lib";
|
||||
|
||||
/// <summary>
|
||||
/// Represents the tools directory in the package.
|
||||
/// </summary>
|
||||
public static readonly string ToolsDirectory = "tools";
|
||||
|
||||
/// <summary>
|
||||
/// Represents the build directory in the package.
|
||||
/// </summary>
|
||||
public static readonly string BuildDirectory = "build";
|
||||
|
||||
public static readonly string BinDirectory = "bin";
|
||||
public static readonly string PackageReferenceFile = "packages.config";
|
||||
|
||||
public static readonly string BeginIgnoreMarker = "NUGET: BEGIN LICENSE TEXT";
|
||||
public static readonly string EndIgnoreMarker = "NUGET: END LICENSE TEXT";
|
||||
|
||||
internal const string PackageRelationshipNamespace = "http://schemas.microsoft.com/packaging/2010/07/";
|
||||
|
||||
// Starting from nuget 2.0, we use a file with the special name '_._' to represent an empty folder.
|
||||
public const string PackageEmptyFileName = "_._";
|
||||
|
||||
// This is temporary until we fix the gallery to have proper first class support for this.
|
||||
// The magic unpublished date is 1900-01-01T00:00:00
|
||||
public static readonly DateTimeOffset Unpublished = new DateTimeOffset(1900, 1, 1, 0, 0, 0, TimeSpan.FromHours(-8));
|
||||
|
||||
public static readonly IReadOnlyList<string> AssemblyReferencesExtensions
|
||||
= new string[] { ".dll", ".exe", ".winmd" };
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NuGet.Frameworks;
|
||||
|
||||
namespace NuGet
|
||||
{
|
||||
public class FrameworkAssemblyReference
|
||||
{
|
||||
public FrameworkAssemblyReference(string assemblyName, IEnumerable<NuGetFramework> supportedFrameworks)
|
||||
{
|
||||
if (string.IsNullOrEmpty(assemblyName))
|
||||
{
|
||||
throw new ArgumentException(nameof(assemblyName));
|
||||
}
|
||||
|
||||
if (supportedFrameworks == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(supportedFrameworks));
|
||||
}
|
||||
|
||||
AssemblyName = assemblyName;
|
||||
SupportedFrameworks = supportedFrameworks;
|
||||
}
|
||||
|
||||
public string AssemblyName { get; private set; }
|
||||
|
||||
public IEnumerable<NuGetFramework> SupportedFrameworks { get; private set; }
|
||||
}
|
||||
}
|
20
src/Microsoft.DotNet.Tools.Pack/NuGet/IPackageFile.cs
Normal file
20
src/Microsoft.DotNet.Tools.Pack/NuGet/IPackageFile.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
// 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
|
||||
{
|
||||
public interface IPackageFile
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the full path of the file inside the package.
|
||||
/// </summary>
|
||||
string Path
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
Stream GetStream();
|
||||
}
|
||||
}
|
87
src/Microsoft.DotNet.Tools.Pack/NuGet/Manifest.cs
Normal file
87
src/Microsoft.DotNet.Tools.Pack/NuGet/Manifest.cs
Normal file
|
@ -0,0 +1,87 @@
|
|||
// 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.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace NuGet
|
||||
{
|
||||
public class Manifest
|
||||
{
|
||||
private const string SchemaVersionAttributeName = "schemaVersion";
|
||||
|
||||
public Manifest(ManifestMetadata metadata)
|
||||
{
|
||||
if (metadata == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(metadata));
|
||||
}
|
||||
|
||||
Metadata = metadata;
|
||||
}
|
||||
|
||||
public ManifestMetadata Metadata { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Saves the current manifest to the specified stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">The target stream.</param>
|
||||
public void Save(Stream stream)
|
||||
{
|
||||
Save(stream, validate: true, minimumManifestVersion: 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the current manifest to the specified stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">The target stream.</param>
|
||||
/// <param name="minimumManifestVersion">The minimum manifest version that this class must use when saving.</param>
|
||||
public void Save(Stream stream, int minimumManifestVersion)
|
||||
{
|
||||
Save(stream, validate: true, minimumManifestVersion: minimumManifestVersion);
|
||||
}
|
||||
|
||||
public void Save(Stream stream, bool validate)
|
||||
{
|
||||
Save(stream, validate, minimumManifestVersion: 1);
|
||||
}
|
||||
|
||||
public void Save(Stream stream, bool validate, int minimumManifestVersion)
|
||||
{
|
||||
int version = Math.Max(minimumManifestVersion, ManifestVersionUtility.GetManifestVersion(Metadata));
|
||||
var schemaNamespace = (XNamespace)ManifestSchemaUtility.GetSchemaNamespace(version);
|
||||
|
||||
new XDocument(
|
||||
new XElement(schemaNamespace + "package",
|
||||
Metadata.ToXElement(schemaNamespace))).Save(stream);
|
||||
}
|
||||
|
||||
public static Manifest Create(PackageBuilder copy)
|
||||
{
|
||||
var metadata = new ManifestMetadata();
|
||||
metadata.Id = copy.Id?.Trim();
|
||||
metadata.Version = copy.Version;
|
||||
metadata.Title = copy.Title?.Trim();
|
||||
metadata.Authors = copy.Authors.Distinct();
|
||||
metadata.Owners = copy.Owners.Distinct();
|
||||
metadata.Tags = string.Join(",", copy.Tags).Trim();
|
||||
metadata.LicenseUrl = copy.LicenseUrl;
|
||||
metadata.ProjectUrl = copy.ProjectUrl;
|
||||
metadata.IconUrl = copy.IconUrl;
|
||||
metadata.RequireLicenseAcceptance = copy.RequireLicenseAcceptance;
|
||||
metadata.Description = copy.Description?.Trim();
|
||||
metadata.Copyright = copy.Copyright?.Trim();
|
||||
metadata.Summary = copy.Summary?.Trim();
|
||||
metadata.ReleaseNotes = copy.ReleaseNotes?.Trim();
|
||||
metadata.Language = copy.Language?.Trim();
|
||||
metadata.DependencySets = copy.DependencySets;
|
||||
metadata.FrameworkAssemblies = copy.FrameworkAssemblies;
|
||||
metadata.PackageAssemblyReferences = copy.PackageAssemblyReferences;
|
||||
metadata.MinClientVersionString = copy.MinClientVersion?.ToString();
|
||||
|
||||
return new Manifest(metadata);
|
||||
}
|
||||
}
|
||||
}
|
84
src/Microsoft.DotNet.Tools.Pack/NuGet/ManifestMetadata.cs
Normal file
84
src/Microsoft.DotNet.Tools.Pack/NuGet/ManifestMetadata.cs
Normal file
|
@ -0,0 +1,84 @@
|
|||
// 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.Linq;
|
||||
using NuGet.Versioning;
|
||||
|
||||
namespace NuGet
|
||||
{
|
||||
public class ManifestMetadata
|
||||
{
|
||||
private string _minClientVersionString;
|
||||
private IEnumerable<string> _authors = Enumerable.Empty<string>();
|
||||
private IEnumerable<string> _owners = Enumerable.Empty<string>();
|
||||
|
||||
[ManifestVersion(5)]
|
||||
public string MinClientVersionString
|
||||
{
|
||||
get { return _minClientVersionString; }
|
||||
set
|
||||
{
|
||||
Version version = null;
|
||||
if (!string.IsNullOrEmpty(value) && !System.Version.TryParse(value, out version))
|
||||
{
|
||||
// TODO: Resources
|
||||
throw new InvalidDataException("NuGetResources.Manifest_InvalidMinClientVersion");
|
||||
}
|
||||
|
||||
_minClientVersionString = value;
|
||||
MinClientVersion = version;
|
||||
}
|
||||
}
|
||||
|
||||
public Version MinClientVersion { get; private set; }
|
||||
|
||||
public string Id { get; set; }
|
||||
|
||||
public NuGetVersion Version { get; set; }
|
||||
|
||||
public string Title { get; set; }
|
||||
|
||||
public IEnumerable<string> Authors
|
||||
{
|
||||
get { return _authors; }
|
||||
set { _authors = value ?? Enumerable.Empty<string>(); }
|
||||
}
|
||||
|
||||
public IEnumerable<string> Owners
|
||||
{
|
||||
get { return (_owners == null || !_owners.Any()) ? _authors : _owners; }
|
||||
set { _owners = value ?? Enumerable.Empty<string>(); }
|
||||
}
|
||||
|
||||
public Uri IconUrl { get; set; }
|
||||
|
||||
public Uri LicenseUrl { get; set; }
|
||||
|
||||
public Uri ProjectUrl { get; set; }
|
||||
|
||||
public bool RequireLicenseAcceptance { get; set; }
|
||||
|
||||
public string Description { get; set; }
|
||||
|
||||
public string Summary { get; set; }
|
||||
|
||||
[ManifestVersion(2)]
|
||||
public string ReleaseNotes { get; set; }
|
||||
|
||||
[ManifestVersion(2)]
|
||||
public string Copyright { get; set; }
|
||||
|
||||
public string Language { get; set; }
|
||||
|
||||
public string Tags { get; set; }
|
||||
|
||||
public IEnumerable<PackageDependencySet> DependencySets { get; set; } = new List<PackageDependencySet>();
|
||||
|
||||
public ICollection<PackageReferenceSet> PackageAssemblyReferences { get; set; } = new List<PackageReferenceSet>();
|
||||
|
||||
public IEnumerable<FrameworkAssemblyReference> FrameworkAssemblies { get; set; } = new List<FrameworkAssemblyReference>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
// 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.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace NuGet
|
||||
{
|
||||
internal static class ManifestSchemaUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// Baseline schema
|
||||
/// </summary>
|
||||
internal const string SchemaVersionV1 = "http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd";
|
||||
|
||||
/// <summary>
|
||||
/// Added copyrights, references and release notes
|
||||
/// </summary>
|
||||
internal const string SchemaVersionV2 = "http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd";
|
||||
|
||||
/// <summary>
|
||||
/// Used if the version is a semantic version.
|
||||
/// </summary>
|
||||
internal const string SchemaVersionV3 = "http://schemas.microsoft.com/packaging/2011/10/nuspec.xsd";
|
||||
|
||||
/// <summary>
|
||||
/// Added 'targetFramework' attribute for 'dependency' elements.
|
||||
/// Allow framework folders under 'content' and 'tools' folders.
|
||||
/// </summary>
|
||||
internal const string SchemaVersionV4 = "http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd";
|
||||
|
||||
/// <summary>
|
||||
/// Added 'targetFramework' attribute for 'references' elements.
|
||||
/// Added 'minClientVersion' attribute
|
||||
/// </summary>
|
||||
internal const string SchemaVersionV5 = "http://schemas.microsoft.com/packaging/2013/01/nuspec.xsd";
|
||||
|
||||
/// <summary>
|
||||
/// Allows XDT transformation
|
||||
/// </summary>
|
||||
internal const string SchemaVersionV6 = "http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd";
|
||||
|
||||
private static readonly string[] VersionToSchemaMappings = new[] {
|
||||
SchemaVersionV1,
|
||||
SchemaVersionV2,
|
||||
SchemaVersionV3,
|
||||
SchemaVersionV4,
|
||||
SchemaVersionV5,
|
||||
SchemaVersionV6
|
||||
};
|
||||
|
||||
public static int GetVersionFromNamespace(string @namespace)
|
||||
{
|
||||
int index = Math.Max(0, Array.IndexOf(VersionToSchemaMappings, @namespace));
|
||||
|
||||
// we count version from 1 instead of 0
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
public static string GetSchemaNamespace(int version)
|
||||
{
|
||||
// Versions are internally 0-indexed but stored with a 1 index so decrement it by 1
|
||||
if (version <= 0 || version > VersionToSchemaMappings.Length)
|
||||
{
|
||||
// TODO: Resources
|
||||
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, "NuGetResources.UnknownSchemaVersion", version));
|
||||
}
|
||||
return VersionToSchemaMappings[version - 1];
|
||||
}
|
||||
|
||||
public static bool IsKnownSchema(string schemaNamespace)
|
||||
{
|
||||
return VersionToSchemaMappings.Contains(schemaNamespace, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
// 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;
|
||||
|
||||
namespace NuGet
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
|
||||
internal sealed class ManifestVersionAttribute : Attribute
|
||||
{
|
||||
public ManifestVersionAttribute(int version)
|
||||
{
|
||||
Version = version;
|
||||
}
|
||||
|
||||
public int Version { get; private set; }
|
||||
}
|
||||
}
|
111
src/Microsoft.DotNet.Tools.Pack/NuGet/ManifestVersionUtility.cs
Normal file
111
src/Microsoft.DotNet.Tools.Pack/NuGet/ManifestVersionUtility.cs
Normal file
|
@ -0,0 +1,111 @@
|
|||
// 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;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace NuGet
|
||||
{
|
||||
internal static class ManifestVersionUtility
|
||||
{
|
||||
public const int DefaultVersion = 1;
|
||||
public const int SemverVersion = 3;
|
||||
public const int TargetFrameworkSupportForDependencyContentsAndToolsVersion = 4;
|
||||
public const int TargetFrameworkSupportForReferencesVersion = 5;
|
||||
public const int XdtTransformationVersion = 6;
|
||||
|
||||
public static int GetManifestVersion(ManifestMetadata metadata)
|
||||
{
|
||||
return Math.Max(GetVersionFromObject(metadata), GetMaxVersionFromMetadata(metadata));
|
||||
}
|
||||
|
||||
private static int GetMaxVersionFromMetadata(ManifestMetadata metadata)
|
||||
{
|
||||
// Important: check for version 5 before version 4
|
||||
bool referencesHasTargetFramework =
|
||||
metadata.PackageAssemblyReferences != null &&
|
||||
metadata.PackageAssemblyReferences.Any(r => r.TargetFramework != null);
|
||||
|
||||
if (referencesHasTargetFramework)
|
||||
{
|
||||
return TargetFrameworkSupportForReferencesVersion;
|
||||
}
|
||||
|
||||
bool dependencyHasTargetFramework =
|
||||
metadata.DependencySets != null &&
|
||||
metadata.DependencySets.Any(d => d.TargetFramework != null);
|
||||
|
||||
if (dependencyHasTargetFramework)
|
||||
{
|
||||
return TargetFrameworkSupportForDependencyContentsAndToolsVersion;
|
||||
}
|
||||
|
||||
if (metadata.Version.IsPrerelease)
|
||||
{
|
||||
return SemverVersion;
|
||||
}
|
||||
|
||||
return DefaultVersion;
|
||||
}
|
||||
|
||||
private static int GetVersionFromObject(object obj)
|
||||
{
|
||||
// all public, gettable, non-static properties
|
||||
return obj?.GetType()
|
||||
.GetRuntimeProperties()
|
||||
.Where(prop => prop.GetMethod != null && prop.GetMethod.IsPublic && !prop.GetMethod.IsStatic)
|
||||
.Select(prop => GetVersionFromPropertyInfo(obj, prop))
|
||||
.Max()
|
||||
?? DefaultVersion;
|
||||
}
|
||||
|
||||
private static int GetVersionFromPropertyInfo(object obj, PropertyInfo property)
|
||||
{
|
||||
var value = property.GetValue(obj, index: null);
|
||||
if (value == null)
|
||||
{
|
||||
return DefaultVersion;
|
||||
}
|
||||
|
||||
int? version = GetPropertyVersion(property);
|
||||
if (!version.HasValue)
|
||||
{
|
||||
return DefaultVersion;
|
||||
}
|
||||
|
||||
var stringValue = value as string;
|
||||
if (stringValue != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(stringValue))
|
||||
{
|
||||
return version.Value;
|
||||
}
|
||||
|
||||
return DefaultVersion;
|
||||
}
|
||||
|
||||
// For all other object types a null check would suffice.
|
||||
return version.Value;
|
||||
}
|
||||
|
||||
private static int VisitList(IEnumerable list)
|
||||
{
|
||||
int version = DefaultVersion;
|
||||
|
||||
foreach (var item in list)
|
||||
{
|
||||
version = Math.Max(version, GetVersionFromObject(item));
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
private static int? GetPropertyVersion(PropertyInfo property)
|
||||
{
|
||||
var attribute = property.GetCustomAttribute<ManifestVersionAttribute>();
|
||||
return attribute?.Version;
|
||||
}
|
||||
}
|
||||
}
|
382
src/Microsoft.DotNet.Tools.Pack/NuGet/PackageBuilder.cs
Normal file
382
src/Microsoft.DotNet.Tools.Pack/NuGet/PackageBuilder.cs
Normal file
|
@ -0,0 +1,382 @@
|
|||
// 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.Globalization;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using NuGet.Packaging;
|
||||
using NuGet.Packaging.Core;
|
||||
using NuGet.Versioning;
|
||||
|
||||
namespace NuGet
|
||||
{
|
||||
public class PackageBuilder
|
||||
{
|
||||
private const string DefaultContentType = "application/octet";
|
||||
internal const string ManifestRelationType = "manifest";
|
||||
|
||||
public PackageBuilder()
|
||||
{
|
||||
Files = new List<IPackageFile>();
|
||||
DependencySets = new List<PackageDependencySet>();
|
||||
FrameworkAssemblies = new List<FrameworkAssemblyReference>();
|
||||
PackageAssemblyReferences = new List<PackageReferenceSet>();
|
||||
Authors = new List<string>();
|
||||
Owners = new List<string>();
|
||||
Tags = new List<string>();
|
||||
}
|
||||
|
||||
public string Id
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public NuGetVersion Version
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string Title
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public List<string> Authors
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public List<string> Owners
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Uri IconUrl
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Uri LicenseUrl
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Uri ProjectUrl
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool RequireLicenseAcceptance
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool DevelopmentDependency
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string Summary
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string ReleaseNotes
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string Language
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public List<string> Tags
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string Copyright
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public List<PackageDependencySet> DependencySets
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public List<IPackageFile> Files
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public List<FrameworkAssemblyReference> FrameworkAssemblies
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public List<PackageReferenceSet> PackageAssemblyReferences
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Version MinClientVersion
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public void Save(Stream stream)
|
||||
{
|
||||
// Make sure we're saving a valid package id
|
||||
PackageIdValidator.ValidatePackageId(Id);
|
||||
|
||||
// Throw if the package doesn't contain any dependencies nor content
|
||||
if (!Files.Any() && !DependencySets.SelectMany(d => d.Dependencies).Any() && !FrameworkAssemblies.Any())
|
||||
{
|
||||
// TODO: Resources
|
||||
throw new InvalidOperationException("NuGetResources.CannotCreateEmptyPackage");
|
||||
}
|
||||
|
||||
if (!ValidateSpecialVersionLength(Version))
|
||||
{
|
||||
// TODO: Resources
|
||||
throw new InvalidOperationException("NuGetResources.SemVerSpecialVersionTooLong");
|
||||
}
|
||||
|
||||
ValidateDependencySets(Version, DependencySets);
|
||||
ValidateReferenceAssemblies(Files, PackageAssemblyReferences);
|
||||
|
||||
using (var package = new ZipArchive(stream, ZipArchiveMode.Create))
|
||||
{
|
||||
// Validate and write the manifest
|
||||
WriteManifest(package, ManifestVersionUtility.DefaultVersion);
|
||||
|
||||
// Write the files to the package
|
||||
var extensions = WriteFiles(package);
|
||||
|
||||
extensions.Add("nuspec");
|
||||
|
||||
WriteOpcContentTypes(package, extensions);
|
||||
}
|
||||
}
|
||||
|
||||
private static string CreatorInfo()
|
||||
{
|
||||
var creatorInfo = new List<string>();
|
||||
var assembly = typeof(PackageBuilder).GetTypeInfo().Assembly;
|
||||
creatorInfo.Add(assembly.FullName);
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
creatorInfo.Add("Linux");
|
||||
}
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
{
|
||||
creatorInfo.Add("OSX");
|
||||
}
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
creatorInfo.Add("Windows");
|
||||
}
|
||||
|
||||
var attribute = assembly.GetCustomAttributes<System.Runtime.Versioning.TargetFrameworkAttribute>().FirstOrDefault();
|
||||
if (attribute != null)
|
||||
{
|
||||
creatorInfo.Add(attribute.FrameworkDisplayName);
|
||||
}
|
||||
|
||||
return String.Join(";", creatorInfo);
|
||||
}
|
||||
|
||||
internal static void ValidateDependencySets(SemanticVersion version, IEnumerable<PackageDependencySet> dependencies)
|
||||
{
|
||||
if (version == null)
|
||||
{
|
||||
// We have independent validation for null-versions.
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var dep in dependencies.SelectMany(s => s.Dependencies))
|
||||
{
|
||||
PackageIdValidator.ValidatePackageId(dep.Id);
|
||||
}
|
||||
|
||||
// REVIEW: Do we want to keep enfocing this?
|
||||
/*if (version.IsPrerelease)
|
||||
{
|
||||
// If we are creating a production package, do not allow any of the dependencies to be a prerelease version.
|
||||
var prereleaseDependency = dependencies.SelectMany(set => set.Dependencies).FirstOrDefault(IsPrereleaseDependency);
|
||||
if (prereleaseDependency != null)
|
||||
{
|
||||
throw new InvalidDataException(String.Format(CultureInfo.CurrentCulture, "NuGetResources.Manifest_InvalidPrereleaseDependency", prereleaseDependency.ToString()));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
internal static void ValidateReferenceAssemblies(IEnumerable<IPackageFile> files, IEnumerable<PackageReferenceSet> packageAssemblyReferences)
|
||||
{
|
||||
var libFiles = new HashSet<string>(from file in files
|
||||
where !string.IsNullOrEmpty(file.Path) && file.Path.StartsWith("lib", StringComparison.OrdinalIgnoreCase)
|
||||
select Path.GetFileName(file.Path), StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var reference in packageAssemblyReferences.SelectMany(p => p.References))
|
||||
{
|
||||
if (!libFiles.Contains(reference) &&
|
||||
!libFiles.Contains(reference + ".dll") &&
|
||||
!libFiles.Contains(reference + ".exe") &&
|
||||
!libFiles.Contains(reference + ".winmd"))
|
||||
{
|
||||
// TODO: Resources
|
||||
throw new InvalidDataException(String.Format(CultureInfo.CurrentCulture, "NuGetResources.Manifest_InvalidReference", reference));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteManifest(ZipArchive package, int minimumManifestVersion)
|
||||
{
|
||||
string path = Id + Constants.ManifestExtension;
|
||||
|
||||
WriteOpcManifestRelationship(package, path);
|
||||
|
||||
ZipArchiveEntry entry = package.CreateEntry(path, CompressionLevel.Optimal);
|
||||
|
||||
using (Stream stream = entry.Open())
|
||||
{
|
||||
Manifest manifest = Manifest.Create(this);
|
||||
manifest.Save(stream, minimumManifestVersion);
|
||||
}
|
||||
}
|
||||
|
||||
private HashSet<string> WriteFiles(ZipArchive package)
|
||||
{
|
||||
var extensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
// Add files that might not come from expanding files on disk
|
||||
foreach (var file in Files.Distinct())
|
||||
{
|
||||
using (Stream stream = file.GetStream())
|
||||
{
|
||||
try
|
||||
{
|
||||
CreatePart(package, file.Path, stream);
|
||||
|
||||
var fileExtension = Path.GetExtension(file.Path);
|
||||
|
||||
// We have files without extension (e.g. the executables for Nix)
|
||||
if (!string.IsNullOrEmpty(fileExtension))
|
||||
{
|
||||
extensions.Add(fileExtension.Substring(1));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return extensions;
|
||||
}
|
||||
|
||||
private static void CreatePart(ZipArchive package, string path, Stream sourceStream)
|
||||
{
|
||||
if (PackageHelper.IsManifest(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var entry = package.CreateEntry(PathUtility.GetPathWithForwardSlashes(path), CompressionLevel.Optimal);
|
||||
using (var stream = entry.Open())
|
||||
{
|
||||
sourceStream.CopyTo(stream);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsPrereleaseDependency(PackageDependency dependency)
|
||||
{
|
||||
return dependency.VersionRange.MinVersion?.IsPrerelease == true ||
|
||||
dependency.VersionRange.MaxVersion?.IsPrerelease == true;
|
||||
}
|
||||
|
||||
private static bool ValidateSpecialVersionLength(SemanticVersion version)
|
||||
{
|
||||
if (!version.IsPrerelease)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return version == null || version.Release.Length <= 20;
|
||||
}
|
||||
|
||||
private void WriteOpcManifestRelationship(ZipArchive package, string path)
|
||||
{
|
||||
ZipArchiveEntry relsEntry = package.CreateEntry("_rels/.rels", CompressionLevel.Optimal);
|
||||
|
||||
using (var writer = new StreamWriter(relsEntry.Open()))
|
||||
{
|
||||
writer.Write(String.Format(@"<?xml version=""1.0"" encoding=""utf-8""?>
|
||||
<Relationships xmlns=""http://schemas.openxmlformats.org/package/2006/relationships"">
|
||||
<Relationship Type=""http://schemas.microsoft.com/packaging/2010/07/manifest"" Target=""/{0}"" Id=""{1}"" />
|
||||
</Relationships>", path, GenerateRelationshipId()));
|
||||
writer.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteOpcContentTypes(ZipArchive package, HashSet<string> extensions)
|
||||
{
|
||||
// OPC backwards compatibility
|
||||
ZipArchiveEntry relsEntry = package.CreateEntry("[Content_Types].xml", CompressionLevel.Optimal);
|
||||
|
||||
using (var writer = new StreamWriter(relsEntry.Open()))
|
||||
{
|
||||
writer.Write(@"<?xml version=""1.0"" encoding=""utf-8""?>
|
||||
<Types xmlns=""http://schemas.openxmlformats.org/package/2006/content-types"">
|
||||
<Default Extension=""rels"" ContentType=""application/vnd.openxmlformats-package.relationships+xml"" />");
|
||||
foreach (var extension in extensions)
|
||||
{
|
||||
writer.Write(@"<Default Extension=""" + extension + @""" ContentType=""application/octet"" />");
|
||||
}
|
||||
writer.Write("</Types>");
|
||||
writer.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a relationship id for compatibility
|
||||
private string GenerateRelationshipId()
|
||||
{
|
||||
return "R" + Guid.NewGuid().ToString("N").Substring(0, 16);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// 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.Linq;
|
||||
using NuGet.Frameworks;
|
||||
using NuGet.Packaging.Core;
|
||||
|
||||
namespace NuGet
|
||||
{
|
||||
public class PackageDependencySet
|
||||
{
|
||||
public PackageDependencySet(IEnumerable<PackageDependency> dependencies)
|
||||
: this((NuGetFramework)null, dependencies)
|
||||
{
|
||||
}
|
||||
|
||||
public PackageDependencySet(string targetFramework, IEnumerable<PackageDependency> dependencies)
|
||||
: this(targetFramework != null ? NuGetFramework.Parse(targetFramework) : null, dependencies)
|
||||
{
|
||||
}
|
||||
|
||||
public PackageDependencySet(NuGetFramework targetFramework, IEnumerable<PackageDependency> dependencies)
|
||||
{
|
||||
if (dependencies == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dependencies));
|
||||
}
|
||||
|
||||
TargetFramework = targetFramework;
|
||||
Dependencies = dependencies.ToArray();
|
||||
}
|
||||
|
||||
public NuGetFramework TargetFramework { get; }
|
||||
|
||||
public IReadOnlyList<PackageDependency> Dependencies { get; }
|
||||
}
|
||||
}
|
72
src/Microsoft.DotNet.Tools.Pack/NuGet/PackageIdValidator.cs
Normal file
72
src/Microsoft.DotNet.Tools.Pack/NuGet/PackageIdValidator.cs
Normal file
|
@ -0,0 +1,72 @@
|
|||
// 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.Globalization;
|
||||
|
||||
namespace NuGet
|
||||
{
|
||||
public static class PackageIdValidator
|
||||
{
|
||||
internal const int MaxPackageIdLength = 100;
|
||||
|
||||
public static bool IsValidPackageId(string packageId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(packageId))
|
||||
{
|
||||
throw new ArgumentException(nameof(packageId));
|
||||
}
|
||||
|
||||
// Rules:
|
||||
// Should start with a character
|
||||
// Can be followed by '.' or '-'. Cannot have 2 of these special characters consecutively.
|
||||
// Cannot end with '-' or '.'
|
||||
|
||||
var firstChar = packageId[0];
|
||||
if (!char.IsLetterOrDigit(firstChar) && firstChar != '_')
|
||||
{
|
||||
// Should start with a char/digit/_.
|
||||
return false;
|
||||
}
|
||||
|
||||
var lastChar = packageId[packageId.Length - 1];
|
||||
if (lastChar == '-' || lastChar == '.')
|
||||
{
|
||||
// Should not end with a '-' or '.'.
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int index = 1; index < packageId.Length - 1; index++)
|
||||
{
|
||||
var ch = packageId[index];
|
||||
if (!char.IsLetterOrDigit(ch) && ch != '-' && ch != '.')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ch == '-' || ch == '.') && ch == packageId[index - 1])
|
||||
{
|
||||
// Cannot have two successive '-' or '.' in the name.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void ValidatePackageId(string packageId)
|
||||
{
|
||||
if (packageId.Length > MaxPackageIdLength)
|
||||
{
|
||||
// TODO: Resources
|
||||
throw new ArgumentException("NuGetResources.Manifest_IdMaxLengthExceeded");
|
||||
}
|
||||
|
||||
if (!IsValidPackageId(packageId))
|
||||
{
|
||||
// TODO: Resources
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "NuGetResources.InvalidPackageId", packageId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
// 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.Linq;
|
||||
using System.Xml.Linq;
|
||||
using NuGet.Frameworks;
|
||||
using NuGet.Packaging.Core;
|
||||
|
||||
namespace NuGet
|
||||
{
|
||||
internal static class PackageMetadataXmlExtensions
|
||||
{
|
||||
private const string References = "references";
|
||||
private const string Reference = "reference";
|
||||
private const string Group = "group";
|
||||
private const string File = "file";
|
||||
private const string TargetFramework = "targetFramework";
|
||||
private const string FrameworkAssemblies = "frameworkAssemblies";
|
||||
private const string FrameworkAssembly = "frameworkAssembly";
|
||||
private const string AssemblyName = "assemblyName";
|
||||
private const string Dependencies = "dependencies";
|
||||
|
||||
public static XElement ToXElement(this ManifestMetadata metadata, XNamespace ns)
|
||||
{
|
||||
var elem = new XElement(ns + "metadata");
|
||||
if (metadata.MinClientVersionString != null)
|
||||
{
|
||||
elem.SetAttributeValue("minClientVersion", metadata.MinClientVersionString);
|
||||
}
|
||||
|
||||
elem.Add(new XElement(ns + "id", metadata.Id));
|
||||
elem.Add(new XElement(ns + "version", metadata.Version.ToString()));
|
||||
AddElementIfNotNull(elem, ns, "title", metadata.Title);
|
||||
elem.Add(new XElement(ns + "requireLicenseAcceptance", metadata.RequireLicenseAcceptance));
|
||||
AddElementIfNotNull(elem, ns, "authors", metadata.Authors, authors => string.Join(",", authors));
|
||||
AddElementIfNotNull(elem, ns, "owners", metadata.Owners, owners => string.Join(",", owners));
|
||||
AddElementIfNotNull(elem, ns, "licenseUrl", metadata.LicenseUrl);
|
||||
AddElementIfNotNull(elem, ns, "projectUrl", metadata.ProjectUrl);
|
||||
AddElementIfNotNull(elem, ns, "iconUrl", metadata.IconUrl);
|
||||
AddElementIfNotNull(elem, ns, "description", metadata.Description);
|
||||
AddElementIfNotNull(elem, ns, "summary", metadata.Summary);
|
||||
AddElementIfNotNull(elem, ns, "releaseNotes", metadata.ReleaseNotes);
|
||||
AddElementIfNotNull(elem, ns, "copyright", metadata.Copyright);
|
||||
AddElementIfNotNull(elem, ns, "language", metadata.Language);
|
||||
AddElementIfNotNull(elem, ns, "tags", metadata.Tags);
|
||||
|
||||
elem.Add(GetXElementFromGroupableItemSets(
|
||||
ns,
|
||||
metadata.DependencySets,
|
||||
set => set.TargetFramework != null,
|
||||
set => set.TargetFramework.GetFrameworkString(),
|
||||
set => set.Dependencies,
|
||||
GetXElementFromPackageDependency,
|
||||
Dependencies,
|
||||
TargetFramework));
|
||||
|
||||
elem.Add(GetXElementFromGroupableItemSets(
|
||||
ns,
|
||||
metadata.PackageAssemblyReferences,
|
||||
set => set.TargetFramework != null,
|
||||
set => set.TargetFramework.GetFrameworkString(),
|
||||
set => set.References,
|
||||
GetXElementFromPackageReference,
|
||||
References,
|
||||
TargetFramework));
|
||||
|
||||
elem.Add(GetXElementFromFrameworkAssemblies(ns, metadata.FrameworkAssemblies));
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
private static XElement GetXElementFromGroupableItemSets<TSet, TItem>(
|
||||
XNamespace ns,
|
||||
IEnumerable<TSet> objectSets,
|
||||
Func<TSet, bool> isGroupable,
|
||||
Func<TSet, string> getGroupIdentifer,
|
||||
Func<TSet, IEnumerable<TItem>> getItems,
|
||||
Func<XNamespace, TItem, XElement> getXElementFromItem,
|
||||
string parentName,
|
||||
string identiferAttributeName)
|
||||
{
|
||||
if (objectSets == null || !objectSets.Any())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var groupableSets = new List<TSet>();
|
||||
var ungroupableSets = new List<TSet>();
|
||||
|
||||
foreach (var set in objectSets)
|
||||
{
|
||||
if (isGroupable(set))
|
||||
{
|
||||
groupableSets.Add(set);
|
||||
}
|
||||
else
|
||||
{
|
||||
ungroupableSets.Add(set);
|
||||
}
|
||||
}
|
||||
|
||||
var childElements = new List<XElement>();
|
||||
if (!groupableSets.Any())
|
||||
{
|
||||
// none of the item sets are groupable, then flatten the items
|
||||
childElements.AddRange(objectSets.SelectMany(getItems).Select(item => getXElementFromItem(ns, item)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// move the group with null target framework (if any) to the front just for nicer display in UI
|
||||
foreach (var set in ungroupableSets.Concat(groupableSets))
|
||||
{
|
||||
var groupElem = new XElement(
|
||||
ns + Group,
|
||||
getItems(set).Select(item => getXElementFromItem(ns, item)).ToArray());
|
||||
|
||||
if (isGroupable(set))
|
||||
{
|
||||
groupElem.SetAttributeValue(identiferAttributeName, getGroupIdentifer(set));
|
||||
}
|
||||
|
||||
childElements.Add(groupElem);
|
||||
}
|
||||
}
|
||||
|
||||
return new XElement(ns + parentName, childElements.ToArray());
|
||||
}
|
||||
|
||||
private static XElement GetXElementFromPackageReference(XNamespace ns, string reference)
|
||||
{
|
||||
return new XElement(ns + Reference, new XAttribute(File, reference));
|
||||
}
|
||||
|
||||
private static XElement GetXElementFromPackageDependency(XNamespace ns, PackageDependency dependency)
|
||||
{
|
||||
return new XElement(ns + "dependency",
|
||||
new XAttribute("id", dependency.Id),
|
||||
dependency.VersionRange != null ? new XAttribute("version", dependency.VersionRange.ToString()) : null);
|
||||
}
|
||||
|
||||
private static XElement GetXElementFromFrameworkAssemblies(XNamespace ns, IEnumerable<FrameworkAssemblyReference> references)
|
||||
{
|
||||
if (references == null || !references.Any())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new XElement(
|
||||
ns + FrameworkAssemblies,
|
||||
references.Select(reference =>
|
||||
new XElement(ns + FrameworkAssembly,
|
||||
new XAttribute(AssemblyName, reference.AssemblyName),
|
||||
reference.SupportedFrameworks != null && reference.SupportedFrameworks.Any() ?
|
||||
new XAttribute("targetFramework", string.Join(", ", reference.SupportedFrameworks.Select(f => f.GetFrameworkString()))) :
|
||||
null)));
|
||||
}
|
||||
|
||||
private static void AddElementIfNotNull<T>(XElement parent, XNamespace ns, string name, T value)
|
||||
where T : class
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
parent.Add(new XElement(ns + name, value));
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddElementIfNotNull<T>(XElement parent, XNamespace ns, string name, T value, Func<T, object> process)
|
||||
where T : class
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
var processed = process(value);
|
||||
if (processed != null)
|
||||
{
|
||||
parent.Add(new XElement(ns + name, processed));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
34
src/Microsoft.DotNet.Tools.Pack/NuGet/PackageReferenceSet.cs
Normal file
34
src/Microsoft.DotNet.Tools.Pack/NuGet/PackageReferenceSet.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
// 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.Linq;
|
||||
using NuGet.Frameworks;
|
||||
|
||||
namespace NuGet
|
||||
{
|
||||
public class PackageReferenceSet
|
||||
{
|
||||
public PackageReferenceSet(IEnumerable<string> references)
|
||||
: this(null, references)
|
||||
{
|
||||
}
|
||||
|
||||
public PackageReferenceSet(NuGetFramework targetFramework, IEnumerable<string> references)
|
||||
{
|
||||
if (references == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(references));
|
||||
}
|
||||
|
||||
TargetFramework = targetFramework;
|
||||
References = references.ToArray();
|
||||
}
|
||||
|
||||
public IReadOnlyCollection<string> References { get; }
|
||||
|
||||
public NuGetFramework TargetFramework { get; }
|
||||
|
||||
}
|
||||
}
|
33
src/Microsoft.DotNet.Tools.Pack/NuGet/PathUtility.cs
Normal file
33
src/Microsoft.DotNet.Tools.Pack/NuGet/PathUtility.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
// 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;
|
||||
|
||||
namespace NuGet
|
||||
{
|
||||
internal static class PathUtility
|
||||
{
|
||||
public static string GetPathWithForwardSlashes(string path)
|
||||
{
|
||||
return path.Replace('\\', '/');
|
||||
}
|
||||
|
||||
public static string GetPathWithBackSlashes(string path)
|
||||
{
|
||||
return path.Replace('/', '\\');
|
||||
}
|
||||
|
||||
public static string GetPathWithDirectorySeparator(string path)
|
||||
{
|
||||
if (Path.DirectorySeparatorChar == '/')
|
||||
{
|
||||
return GetPathWithForwardSlashes(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetPathWithBackSlashes(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
80
src/Microsoft.DotNet.Tools.Pack/NuGet/PhysicalPackageFile.cs
Normal file
80
src/Microsoft.DotNet.Tools.Pack/NuGet/PhysicalPackageFile.cs
Normal file
|
@ -0,0 +1,80 @@
|
|||
// 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;
|
||||
|
||||
namespace NuGet
|
||||
{
|
||||
public class PhysicalPackageFile : IPackageFile
|
||||
{
|
||||
private readonly Func<Stream> _streamFactory;
|
||||
|
||||
public PhysicalPackageFile()
|
||||
{
|
||||
}
|
||||
|
||||
public PhysicalPackageFile(PhysicalPackageFile file)
|
||||
{
|
||||
SourcePath = file.SourcePath;
|
||||
TargetPath = file.TargetPath;
|
||||
}
|
||||
|
||||
internal PhysicalPackageFile(Func<Stream> streamFactory)
|
||||
{
|
||||
_streamFactory = streamFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Path on disk
|
||||
/// </summary>
|
||||
public string SourcePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Path in package
|
||||
/// </summary>
|
||||
public string TargetPath { get; set; }
|
||||
|
||||
public string Path
|
||||
{
|
||||
get
|
||||
{
|
||||
return TargetPath;
|
||||
}
|
||||
}
|
||||
|
||||
public Stream GetStream()
|
||||
{
|
||||
return _streamFactory != null ? _streamFactory() : File.OpenRead(SourcePath);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return TargetPath;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var file = obj as PhysicalPackageFile;
|
||||
|
||||
return file != null && string.Equals(SourcePath, file.SourcePath, StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(TargetPath, file.TargetPath, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int hash = 0;
|
||||
if (SourcePath != null)
|
||||
{
|
||||
hash = SourcePath.GetHashCode();
|
||||
}
|
||||
|
||||
if (TargetPath != null)
|
||||
{
|
||||
hash = hash * 4567 + TargetPath.GetHashCode();
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
475
src/Microsoft.DotNet.Tools.Pack/Program.cs
Normal file
475
src/Microsoft.DotNet.Tools.Pack/Program.cs
Normal file
|
@ -0,0 +1,475 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.ProjectModel;
|
||||
using NuGet;
|
||||
using Microsoft.Dnx.Runtime.Common.CommandLine;
|
||||
using Microsoft.DotNet.Cli.Utils;
|
||||
using NuGet.Packaging.Core;
|
||||
using Microsoft.Extensions.ProjectModel.Graph;
|
||||
using NuGet.Versioning;
|
||||
using NuGet.Frameworks;
|
||||
using Microsoft.Extensions.ProjectModel.Files;
|
||||
using Microsoft.Extensions.FileSystemGlobbing;
|
||||
using Microsoft.Extensions.FileSystemGlobbing.Abstractions;
|
||||
using Microsoft.Extensions.ProjectModel.Utilities;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Compiler
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
DebugHelper.HandleDebugSwitch(ref args);
|
||||
|
||||
var app = new CommandLineApplication();
|
||||
app.Name = "dotnet compile";
|
||||
app.FullName = ".NET Compiler";
|
||||
app.Description = "Compiler for the .NET Platform";
|
||||
app.HelpOption("-h|--help");
|
||||
|
||||
var output = app.Option("-o|--output <OUTPUT_DIR>", "Directory in which to place outputs", CommandOptionType.SingleValue);
|
||||
var intermediateOutput = app.Option("-t|--temp-output <OUTPUT_DIR>", "Directory in which to place temporary outputs", CommandOptionType.SingleValue);
|
||||
var configuration = app.Option("-c|--configuration <CONFIGURATION>", "Configuration under which to build", CommandOptionType.SingleValue);
|
||||
var project = app.Argument("<PROJECT>", "The project to compile, defaults to the current directory. Can be a path to a project.json or a project directory");
|
||||
|
||||
app.OnExecute(() =>
|
||||
{
|
||||
// Locate the project and get the name and full path
|
||||
var path = project.Value;
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
path = Directory.GetCurrentDirectory();
|
||||
}
|
||||
|
||||
var configValue = configuration.Value() ?? Cli.Utils.Constants.DefaultConfiguration;
|
||||
var outputValue = output.Value();
|
||||
|
||||
return BuildPackage(path, configValue, outputValue, intermediateOutput.Value()) ? 1 : 0;
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
return app.Execute(args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
#if DEBUG
|
||||
Console.Error.WriteLine(ex);
|
||||
#else
|
||||
Console.Error.WriteLine(ex.Message);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool BuildPackage(string path, string configuration, string outputValue, string intermediateOutputValue)
|
||||
{
|
||||
var contexts = ProjectContext.CreateContextForEachFramework(path);
|
||||
var project = contexts.First().ProjectFile;
|
||||
|
||||
if (project.Files.SourceFiles.Any())
|
||||
{
|
||||
var argsBuilder = new StringBuilder();
|
||||
argsBuilder.Append($"--configuration {configuration}");
|
||||
|
||||
if (!string.IsNullOrEmpty(outputValue))
|
||||
{
|
||||
argsBuilder.Append($" --output \"{outputValue}\"");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(intermediateOutputValue))
|
||||
{
|
||||
argsBuilder.Append($" --temp-output \"{intermediateOutputValue}\"");
|
||||
}
|
||||
|
||||
argsBuilder.Append($" \"{path}\"");
|
||||
|
||||
var result = Command.Create("dotnet-compile", argsBuilder.ToString())
|
||||
.ForwardStdOut()
|
||||
.ForwardStdErr()
|
||||
.Execute();
|
||||
|
||||
if (result.ExitCode != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reporter.Output.WriteLine($"Producing nuget package for {project.Name}");
|
||||
|
||||
var packDiagnostics = new List<DiagnosticMessage>();
|
||||
|
||||
// Things compiled now build the package
|
||||
var packageBuilder = CreatePackageBuilder(project);
|
||||
|
||||
// TODO: Report errors for required fields
|
||||
// id
|
||||
// author
|
||||
// description
|
||||
foreach (var context in contexts)
|
||||
{
|
||||
Reporter.Verbose.WriteLine($"Processing {context.TargetFramework.ToString().Yellow()}");
|
||||
PopulateDependencies(context, packageBuilder);
|
||||
|
||||
var outputPath = GetOutputPath(context, configuration, outputValue);
|
||||
var outputName = GetProjectOutputName(context.ProjectFile, context.TargetFramework, configuration);
|
||||
|
||||
TryAddOutputFile(packageBuilder, context, outputPath, outputName);
|
||||
|
||||
// REVIEW: Do we keep making symbols packages?
|
||||
TryAddOutputFile(packageBuilder, context, outputPath, $"{project.Name}.pdb");
|
||||
TryAddOutputFile(packageBuilder, context, outputPath, $"{project.Name}.mdb");
|
||||
|
||||
TryAddOutputFile(packageBuilder, context, outputPath, $"{project.Name}.xml");
|
||||
|
||||
Reporter.Verbose.WriteLine("");
|
||||
}
|
||||
|
||||
var rootOutputPath = GetOutputPath(project, configuration, outputValue);
|
||||
var packageOutputPath = GetPackagePath(project, rootOutputPath);
|
||||
|
||||
if (GeneratePackage(project, packageBuilder, packageOutputPath, packDiagnostics))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool GeneratePackage(Project project, PackageBuilder packageBuilder, string nupkg, List<DiagnosticMessage> packDiagnostics)
|
||||
{
|
||||
foreach (var sharedFile in project.Files.SharedFiles)
|
||||
{
|
||||
var file = new PhysicalPackageFile();
|
||||
file.SourcePath = sharedFile;
|
||||
file.TargetPath = Path.Combine("shared", Path.GetFileName(sharedFile));
|
||||
packageBuilder.Files.Add(file);
|
||||
}
|
||||
|
||||
var root = project.ProjectDirectory;
|
||||
|
||||
if (project.Files.PackInclude != null && project.Files.PackInclude.Any())
|
||||
{
|
||||
AddPackageFiles(project, project.Files.PackInclude, packageBuilder, packDiagnostics);
|
||||
}
|
||||
|
||||
// Write the packages as long as we're still in a success state.
|
||||
if (!packDiagnostics.Any(d => d.Severity == DiagnosticMessageSeverity.Error))
|
||||
{
|
||||
Reporter.Verbose.WriteLine($"Adding package files");
|
||||
foreach (var file in packageBuilder.Files.OfType<PhysicalPackageFile>())
|
||||
{
|
||||
if (file.SourcePath != null && File.Exists(file.SourcePath))
|
||||
{
|
||||
Reporter.Verbose.WriteLine($"Adding {file.Path.Yellow()}");
|
||||
}
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(nupkg));
|
||||
|
||||
using (var fs = File.Create(nupkg))
|
||||
{
|
||||
packageBuilder.Save(fs);
|
||||
Reporter.Output.WriteLine($"{project.Name} -> {Path.GetFullPath(nupkg)}");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void AddPackageFiles(Project project, IEnumerable<PackIncludeEntry> packageFiles, PackageBuilder packageBuilder, IList<DiagnosticMessage> diagnostics)
|
||||
{
|
||||
var rootDirectory = new DirectoryInfoWrapper(new DirectoryInfo(project.ProjectDirectory));
|
||||
|
||||
foreach (var match in CollectAdditionalFiles(rootDirectory, packageFiles, project.ProjectFilePath, diagnostics))
|
||||
{
|
||||
packageBuilder.Files.Add(match);
|
||||
}
|
||||
}
|
||||
|
||||
internal static IEnumerable<PhysicalPackageFile> CollectAdditionalFiles(DirectoryInfoBase rootDirectory, IEnumerable<PackIncludeEntry> projectFileGlobs, string projectFilePath, IList<DiagnosticMessage> diagnostics)
|
||||
{
|
||||
foreach (var entry in projectFileGlobs)
|
||||
{
|
||||
// Evaluate the globs on the right
|
||||
var matcher = new Matcher();
|
||||
matcher.AddIncludePatterns(entry.SourceGlobs);
|
||||
var results = matcher.Execute(rootDirectory);
|
||||
var files = results.Files.ToList();
|
||||
|
||||
// Check for illegal characters
|
||||
if (string.IsNullOrEmpty(entry.Target))
|
||||
{
|
||||
diagnostics.Add(new DiagnosticMessage(
|
||||
ErrorCodes.NU1003,
|
||||
$"Invalid '{ProjectFilesCollection.PackIncludePropertyName}' section. The target '{entry.Target}' is invalid, " +
|
||||
"targets must either be a file name or a directory suffixed with '/'. " +
|
||||
"The root directory of the package can be specified by using a single '/' character.",
|
||||
projectFilePath,
|
||||
DiagnosticMessageSeverity.Error,
|
||||
entry.Line,
|
||||
entry.Column));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.Target.Split('/').Any(s => s.Equals(".") || s.Equals("..")))
|
||||
{
|
||||
diagnostics.Add(new DiagnosticMessage(
|
||||
ErrorCodes.NU1004,
|
||||
$"Invalid '{ProjectFilesCollection.PackIncludePropertyName}' section. " +
|
||||
$"The target '{entry.Target}' contains path-traversal characters ('.' or '..'). " +
|
||||
"These characters are not permitted in target paths.",
|
||||
projectFilePath,
|
||||
DiagnosticMessageSeverity.Error,
|
||||
entry.Line,
|
||||
entry.Column));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check the arity of the left
|
||||
if (entry.Target.EndsWith("/"))
|
||||
{
|
||||
var dir = entry.Target.Substring(0, entry.Target.Length - 1).Replace('/', Path.DirectorySeparatorChar);
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
yield return new PhysicalPackageFile()
|
||||
{
|
||||
SourcePath = Path.Combine(rootDirectory.FullName, PathUtility.GetPathWithDirectorySeparator(file.Path)),
|
||||
TargetPath = Path.Combine(dir, PathUtility.GetPathWithDirectorySeparator(file.Stem))
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's a file. If the glob matched multiple things, we're sad :(
|
||||
if (files.Count > 1)
|
||||
{
|
||||
// Arity mismatch!
|
||||
string sourceValue = entry.SourceGlobs.Length == 1 ?
|
||||
$"\"{entry.SourceGlobs[0]}\"" :
|
||||
("[" + string.Join(",", entry.SourceGlobs.Select(v => $"\"{v}\"")) + "]");
|
||||
diagnostics.Add(new DiagnosticMessage(
|
||||
ErrorCodes.NU1005,
|
||||
$"Invalid '{ProjectFilesCollection.PackIncludePropertyName}' section. " +
|
||||
$"The target '{entry.Target}' refers to a single file, but the pattern {sourceValue} " +
|
||||
"produces multiple files. To mark the target as a directory, suffix it with '/'.",
|
||||
projectFilePath,
|
||||
DiagnosticMessageSeverity.Error,
|
||||
entry.Line,
|
||||
entry.Column));
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new PhysicalPackageFile()
|
||||
{
|
||||
SourcePath = Path.Combine(rootDirectory.FullName, files[0].Path),
|
||||
TargetPath = PathUtility.GetPathWithDirectorySeparator(entry.Target)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void TryAddOutputFile(PackageBuilder packageBuilder,
|
||||
ProjectContext context,
|
||||
string outputPath,
|
||||
string filePath)
|
||||
{
|
||||
var targetPath = Path.Combine("lib", context.TargetFramework.GetTwoDigitShortFolderName(), Path.GetFileName(filePath));
|
||||
var sourcePath = Path.Combine(outputPath, filePath);
|
||||
|
||||
if (!File.Exists(sourcePath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
packageBuilder.Files.Add(new PhysicalPackageFile
|
||||
{
|
||||
SourcePath = sourcePath,
|
||||
TargetPath = targetPath
|
||||
});
|
||||
}
|
||||
|
||||
public static void PopulateDependencies(ProjectContext context, PackageBuilder packageBuilder)
|
||||
{
|
||||
var dependencies = new List<PackageDependency>();
|
||||
var project = context.RootProject;
|
||||
|
||||
foreach (var dependency in project.Dependencies)
|
||||
{
|
||||
if (!dependency.HasFlag(LibraryDependencyTypeFlag.BecomesNupkgDependency))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: Efficiency
|
||||
var dependencyDescription = context.LibraryManager.GetLibraries().First(l => l.RequestedRanges.Contains(dependency));
|
||||
|
||||
// REVIEW: Can we get this far with unresolved dependencies
|
||||
if (dependencyDescription == null || !dependencyDescription.Resolved)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dependencyDescription.Identity.Type == LibraryType.Project &&
|
||||
((ProjectDescription)dependencyDescription).Project.EmbedInteropTypes)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dependency.Target == LibraryType.ReferenceAssembly)
|
||||
{
|
||||
packageBuilder.FrameworkAssemblies.Add(new FrameworkAssemblyReference(dependency.Name, new[] { context.TargetFramework }));
|
||||
|
||||
Reporter.Verbose.WriteLine($"Adding framework assembly {dependency.Name.Yellow()}");
|
||||
}
|
||||
else
|
||||
{
|
||||
VersionRange dependencyVersion = null;
|
||||
|
||||
if (dependency.VersionRange == null ||
|
||||
dependency.VersionRange.IsFloating)
|
||||
{
|
||||
dependencyVersion = new VersionRange(dependencyDescription.Identity.Version);
|
||||
}
|
||||
else
|
||||
{
|
||||
dependencyVersion = dependency.VersionRange;
|
||||
}
|
||||
|
||||
Reporter.Verbose.WriteLine($"Adding dependency {dependency.Name.Yellow()} {VersionUtility.RenderVersion(dependencyVersion).Yellow()}");
|
||||
|
||||
dependencies.Add(new PackageDependency(dependency.Name, dependencyVersion));
|
||||
}
|
||||
}
|
||||
|
||||
packageBuilder.DependencySets.Add(new PackageDependencySet(context.TargetFramework, dependencies));
|
||||
}
|
||||
|
||||
private static string GetPackagePath(Project project, string outputPath, bool symbols = false)
|
||||
{
|
||||
string fileName = $"{project.Name}.{project.Version}{(symbols ? ".symbols" : string.Empty)}{NuGet.Constants.PackageExtension}";
|
||||
return Path.Combine(outputPath, fileName);
|
||||
}
|
||||
|
||||
private static PackageBuilder CreatePackageBuilder(Project project)
|
||||
{
|
||||
var builder = new PackageBuilder();
|
||||
builder.Authors.AddRange(project.Authors);
|
||||
builder.Owners.AddRange(project.Owners);
|
||||
|
||||
if (builder.Authors.Count == 0)
|
||||
{
|
||||
var defaultAuthor = Environment.GetEnvironmentVariable("NUGET_AUTHOR");
|
||||
if (string.IsNullOrEmpty(defaultAuthor))
|
||||
{
|
||||
builder.Authors.Add(project.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Authors.Add(defaultAuthor);
|
||||
}
|
||||
}
|
||||
|
||||
builder.Description = project.Description ?? project.Name;
|
||||
builder.Id = project.Name;
|
||||
builder.Version = project.Version;
|
||||
builder.Title = project.Title;
|
||||
builder.Summary = project.Summary;
|
||||
builder.Copyright = project.Copyright;
|
||||
builder.RequireLicenseAcceptance = project.RequireLicenseAcceptance;
|
||||
builder.ReleaseNotes = project.ReleaseNotes;
|
||||
builder.Language = project.Language;
|
||||
builder.Tags.AddRange(project.Tags);
|
||||
|
||||
if (!string.IsNullOrEmpty(project.IconUrl))
|
||||
{
|
||||
builder.IconUrl = new Uri(project.IconUrl);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(project.ProjectUrl))
|
||||
{
|
||||
builder.ProjectUrl = new Uri(project.ProjectUrl);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(project.LicenseUrl))
|
||||
{
|
||||
builder.LicenseUrl = new Uri(project.LicenseUrl);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
// REVIEW: This code copying kinda sucks
|
||||
private static string GetProjectOutputName(Project project, NuGetFramework framework, string configuration)
|
||||
{
|
||||
var compilationOptions = project.GetCompilerOptions(framework, configuration);
|
||||
var outputExtension = ".dll";
|
||||
|
||||
if (framework.IsDesktop() && compilationOptions.EmitEntryPoint.GetValueOrDefault())
|
||||
{
|
||||
outputExtension = ".exe";
|
||||
}
|
||||
|
||||
return project.Name + outputExtension;
|
||||
}
|
||||
|
||||
private static string GetOutputPath(Project project, string configuration, string outputOptionValue)
|
||||
{
|
||||
var outputPath = string.Empty;
|
||||
|
||||
if (string.IsNullOrEmpty(outputOptionValue))
|
||||
{
|
||||
outputPath = Path.Combine(
|
||||
GetDefaultRootOutputPath(project, outputOptionValue),
|
||||
Cli.Utils.Constants.BinDirectoryName,
|
||||
configuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputPath = outputOptionValue;
|
||||
}
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
private static string GetOutputPath(ProjectContext context, string configuration, string outputOptionValue)
|
||||
{
|
||||
var outputPath = string.Empty;
|
||||
|
||||
if (string.IsNullOrEmpty(outputOptionValue))
|
||||
{
|
||||
outputPath = Path.Combine(
|
||||
GetDefaultRootOutputPath(context.ProjectFile, outputOptionValue),
|
||||
Cli.Utils.Constants.BinDirectoryName,
|
||||
configuration,
|
||||
context.TargetFramework.GetTwoDigitShortFolderName());
|
||||
}
|
||||
else
|
||||
{
|
||||
outputPath = outputOptionValue;
|
||||
}
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
private static string GetDefaultRootOutputPath(Project project, string outputOptionValue)
|
||||
{
|
||||
string rootOutputPath = string.Empty;
|
||||
|
||||
if (string.IsNullOrEmpty(outputOptionValue))
|
||||
{
|
||||
rootOutputPath = project.ProjectDirectory;
|
||||
}
|
||||
|
||||
return rootOutputPath;
|
||||
}
|
||||
}
|
||||
}
|
31
src/Microsoft.DotNet.Tools.Pack/project.json
Normal file
31
src/Microsoft.DotNet.Tools.Pack/project.json
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"name": "dotnet-pack",
|
||||
"version": "1.0.0-*",
|
||||
"compilationOptions": {
|
||||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Runtime": "1.0.1-beta-23504",
|
||||
"System.IO.Compression.ZipFile": "4.0.1-beta-23504",
|
||||
"Microsoft.NETCore.Targets.DNXCore": "5.0.0-beta-23511",
|
||||
|
||||
"System.Console": "4.0.0-beta-23504",
|
||||
"System.Collections": "4.0.11-beta-23504",
|
||||
"System.Linq": "4.0.1-beta-23504",
|
||||
"System.Diagnostics.Process": "4.1.0-beta-23504",
|
||||
"System.IO.FileSystem": "4.0.1-beta-23504",
|
||||
|
||||
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
|
||||
"Microsoft.DotNet.Cli.Utils": {
|
||||
"type": "build",
|
||||
"version": "1.0.0-*"
|
||||
},
|
||||
"Microsoft.Extensions.CommandLineUtils.Sources": {
|
||||
"type": "build",
|
||||
"version": "1.0.0-*"
|
||||
}
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": { }
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue