- Add a dotnet {deb|rpm|zip|tarball} install command

- Do an implicit restore before running dotnet {deb|rpm|zip|tarball}
- After restoring, check whether Packaging.Targets is present in the lock file.
This commit is contained in:
Frederik Carlier
2019-11-21 15:29:37 +01:00
parent 022765151f
commit 1e328bdfb9
9 changed files with 161 additions and 49 deletions

View File

@@ -6,7 +6,7 @@ namespace Dotnet.Packaging
{
static int Main(string[] args)
{
PackagingRunner runner = new PackagingRunner("Debian/Ubuntu installer package", "CreateDeb");
PackagingRunner runner = new PackagingRunner("Debian/Ubuntu installer package", "CreateDeb", "deb");
return runner.Run(args);
}
}

View File

@@ -14,6 +14,9 @@ See https://github.com/qmfrederik/dotnet-packaging/ for more information on how
<ItemGroup>
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="2.3.4" />
<PackageReference Include="Microsoft.Build" Version="15.9.20" ExcludeAssets="runtime" />
<PackageReference Include="Microsoft.Build.Locator" Version="1.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,7 +1,16 @@
using McMaster.Extensions.CommandLineUtils;
using Microsoft.Build.Locator;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using ConsoleLogger = Microsoft.Build.Logging.ConsoleLogger;
using IMSBuildLogger = Microsoft.Build.Framework.ILogger;
using LoggerVerbosity = Microsoft.Build.Framework.LoggerVerbosity;
using MSBuild = Microsoft.Build.Evaluation;
namespace Dotnet.Packaging
{
@@ -9,11 +18,15 @@ namespace Dotnet.Packaging
{
private readonly string outputName;
private readonly string msbuildTarget;
private readonly string commandName;
public PackagingRunner(string outputName, string msbuildTarget)
public PackagingRunner(string outputName, string msbuildTarget, string commandName)
{
MSBuildLocator.RegisterDefaults();
this.outputName = outputName;
this.msbuildTarget = msbuildTarget;
this.commandName = commandName;
}
public int Run(string[] args)
@@ -36,40 +49,84 @@ namespace Dotnet.Packaging
CommandOptionType.SingleValue);
CommandOption versionSuffix = commandLineApplication.Option(
"---version-suffix <version-suffix>",
"--version-suffix <version-suffix>",
"Defines the value for the $(VersionSuffix) property in the project.",
CommandOptionType.SingleValue);
CommandOption noRestore = commandLineApplication.Option(
"--no-restore",
"Do not restore the project before building.",
CommandOptionType.NoValue);
commandLineApplication.HelpOption("-? | -h | --help");
commandLineApplication.FullName = $"dotnet {this.outputName}";
commandLineApplication.FullName = $"dotnet {this.commandName}";
commandLineApplication.LongVersionGetter = () => ThisAssembly.AssemblyInformationalVersion;
commandLineApplication.ExtendedHelpText = $"{Environment.NewLine}See https://github.com/qmfrederik/dotnet-packaging for more information";
var installCommand = commandLineApplication.Command(
"install",
command => command.OnExecute(() =>
{
Console.WriteLine($"dotnet {this.commandName} ({ThisAssembly.AssemblyInformationalVersion})");
// Create/update the Directory.Build.props file in the directory of the version.json file to add the Packaging.Targets package.
string directoryBuildPropsPath = Path.Combine(Environment.CurrentDirectory, "Directory.Build.props");
MSBuild.Project propsFile;
if (File.Exists(directoryBuildPropsPath))
{
propsFile = new MSBuild.Project(directoryBuildPropsPath);
}
else
{
propsFile = new MSBuild.Project();
}
const string PackageReferenceItemType = "PackageReference";
const string PackageId = "Packaging.Targets";
if (!propsFile.GetItemsByEvaluatedInclude(PackageId).Any(i => i.ItemType == PackageReferenceItemType && i.EvaluatedInclude == PackageId))
{
string packageVersion = ThisAssembly.AssemblyInformationalVersion.Replace("+", "-g");
propsFile.AddItem(
PackageReferenceItemType,
PackageId,
new Dictionary<string, string>
{
{ "Version", packageVersion },
{ "PrivateAssets", "all" },
});
propsFile.Save(directoryBuildPropsPath);
}
Console.WriteLine($"Successfully installed dotnet {this.commandName}. Now run 'dotnet {this.commandName}' to package your");
Console.WriteLine($"application as a {this.outputName}");
}));
commandLineApplication.OnExecute(() =>
{
Console.WriteLine($"dotnet {this.outputName} ({ThisAssembly.AssemblyInformationalVersion})");
Console.WriteLine($"dotnet {this.commandName} ({ThisAssembly.AssemblyInformationalVersion})");
if (!framework.HasValue())
if (!noRestore.HasValue())
{
Console.WriteLine("You must specify a target framework.");
commandLineApplication.ShowHint();
return -1;
}
if (!runtime.HasValue())
{
Console.WriteLine("You must specify a target runtime.");
commandLineApplication.ShowHint();
return -1;
if (!this.IsPackagingTargetsInstalled())
{
return -1;
}
}
StringBuilder msbuildArguments = new StringBuilder();
msbuildArguments.Append($"msbuild /t:{msbuildTarget} ");
msbuildArguments.Append($"/p:RuntimeIdentifier={runtime.Value()} ");
msbuildArguments.Append($"/p:TargetFramework={framework.Value()} ");
if (runtime.HasValue())
{
msbuildArguments.Append($"/p:RuntimeIdentifier={runtime.Value()} ");
}
if (framework.HasValue())
{
msbuildArguments.Append($"/p:TargetFramework={framework.Value()} ");
}
if (configuration.HasValue())
{
@@ -81,25 +138,77 @@ namespace Dotnet.Packaging
msbuildArguments.Append($"/p:VersionSuffix={versionSuffix.Value()} ");
}
var psi = new ProcessStartInfo
{
FileName = "dotnet",
Arguments = msbuildArguments.ToString()
};
var process = new Process
{
StartInfo = psi,
};
process.Start();
process.WaitForExit();
return process.ExitCode;
return RunDotnet(msbuildArguments);
});
return commandLineApplication.Execute(args);
}
public int RunDotnet(StringBuilder msbuildArguments)
{
var psi = new ProcessStartInfo
{
FileName = "dotnet",
Arguments = msbuildArguments.ToString()
};
var process = new Process
{
StartInfo = psi,
};
process.Start();
process.WaitForExit();
return process.ExitCode;
}
public bool IsPackagingTargetsInstalled()
{
var projectFilePath = Directory.GetFiles(Environment.CurrentDirectory, "*.csproj").SingleOrDefault();
if (projectFilePath == null)
{
Console.Error.WriteLine($"Failed to find a .csproj file in '{Environment.CurrentDirectory}'. dotnet {this.commandName} only works if");
Console.Error.WriteLine($"you have exactly one .csproj file in your directory. For advanced scenarios, please use 'dotnet msbuild /t:{this.msbuildTarget}'");
return false;
}
var loggers = new IMSBuildLogger[] { new ConsoleLogger(LoggerVerbosity.Quiet) };
var project = new MSBuild.Project(projectFilePath);
if (!project.Build("Restore", loggers))
{
Console.Error.WriteLine($"Failed to restore '{Path.GetFileName(projectFilePath)}'. Please run dotnet restore, and try again.");
return false;
}
var projectAssetsPath = project.GetPropertyValue("ProjectAssetsFile");
// NuGet has a LockFileUtilities.GetLockFile API which provides direct access to this file format,
// but loading NuGet in the same process as MSBuild creates dependency conflicts.
LockFile lockFile = null;
using (StreamReader reader = File.OpenText(projectAssetsPath))
using (JsonReader jsonReader = new JsonTextReader(reader))
{
JsonSerializer serializer = new JsonSerializer();
lockFile = serializer.Deserialize<LockFile>(jsonReader);
}
if (!lockFile.Libraries.Any(l => l.Key.StartsWith("Packaging.Targets/")))
{
Console.Error.WriteLine($"The project '{Path.GetFileName(projectFilePath)}' doesn't have a PackageReference to Packaging.Targets.");
Console.Error.WriteLine($"Please run 'dotnet {this.commandName} install', and try again.");
return false;
}
return true;
}
class LockFile
{
public Dictionary<string, object> Libraries;
}
}
}

View File

@@ -1,15 +1,10 @@
using McMaster.Extensions.CommandLineUtils;
using System;
using System.Diagnostics;
using System.Text;
namespace Dotnet.Packaging
namespace Dotnet.Packaging
{
public class Program
{
public static int Main(string[] args)
{
PackagingRunner runner = new PackagingRunner("RPM package", "CreateRpm");
PackagingRunner runner = new PackagingRunner("RPM package", "CreateRpm", "rpm");
return runner.Run(args);
}
}

View File

@@ -14,5 +14,8 @@ See https://github.com/qmfrederik/dotnet-packaging/ for more information on how
<ItemGroup>
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="2.3.4" />
<PackageReference Include="Microsoft.Build" Version="15.9.20" ExcludeAssets="runtime" />
<PackageReference Include="Microsoft.Build.Locator" Version="1.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
</Project>

View File

@@ -1,12 +1,10 @@
using System.Diagnostics;
namespace Dotnet.Packaging
{
class Program
{
static int Main(string[] args)
{
PackagingRunner runner = new PackagingRunner("tarball", "CreateTarball");
PackagingRunner runner = new PackagingRunner("tarball", "CreateTarball", "tarball");
return runner.Run(args);
}
}

View File

@@ -14,6 +14,9 @@ See https://github.com/qmfrederik/dotnet-packaging/ for more information on how
<ItemGroup>
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="2.3.4" />
<PackageReference Include="Microsoft.Build" Version="15.9.20" ExcludeAssets="runtime" />
<PackageReference Include="Microsoft.Build.Locator" Version="1.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,12 +1,10 @@
using System.Diagnostics;
namespace Dotnet.Packaging
{
class Program
{
static int Main(string[] args)
{
PackagingRunner runner = new PackagingRunner("zip archive", "CreateZip");
PackagingRunner runner = new PackagingRunner("zip archive", "CreateZip", "zip");
return runner.Run(args);
}
}

View File

@@ -14,6 +14,9 @@ See https://github.com/qmfrederik/dotnet-packaging/ for more information on how
<ItemGroup>
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="2.3.4" />
<PackageReference Include="Microsoft.Build" Version="15.9.20" ExcludeAssets="runtime" />
<PackageReference Include="Microsoft.Build.Locator" Version="1.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
<ItemGroup>