/// <summary>
/// Ensures the appropriate version of the specified packages are installed. If an existing version of the package
/// already exists the following will happen:
/// If a semantically compatible version already exists, no change is made to the package.
/// If an older major version exists, a warning is logged and the package is upgraded.
/// If an older minor/build version exists, an information message is logged and the package is upgraded.
/// If a newer major version exists, a warning is logged and no change is made to the package.
/// </summary>
public static async Task InstallPackagesAsync(
Project targetProject,
Dictionary <string, string> packages,
Func <string, string, Task> installPackage,
ConnectedServiceLogger logger,
IVsPackageInstallerServices packageInstallerServices)
{
IEnumerable <IVsPackageMetadata> installedPackages;
try
{
installedPackages = packageInstallerServices.GetInstalledPackages(targetProject);
}
catch (ArgumentException)
{
// This happens for C++ projects
installedPackages = new List <IVsPackageMetadata>();
}
foreach (KeyValuePair <string, string> requiredPackage in packages)
{
IVsPackageMetadata installedPackage = installedPackages.FirstOrDefault(p => p.Id == requiredPackage.Key);
if (installedPackage == null)
{
// The package does not exist - notify and install the package.
await logger.WriteMessageAsync(
LoggerMessageCategory.Information,
Resource.LogMessage_AddingNuGetPackage,
requiredPackage.Key,
requiredPackage.Value);
}
else
{
Version installedVersion = NuGetUtilities.GetVersion(installedPackage.VersionString);
Version requiredVersion = NuGetUtilities.GetVersion(requiredPackage.Value);
if (installedVersion == null || requiredVersion == null)
{
// Unable to parse the version - continue.
continue;
}
else if (installedVersion.Major < requiredVersion.Major)
{
// An older potentially non-compatible version of the package already exists - warn and upgrade the package.
await logger.WriteMessageAsync(
LoggerMessageCategory.Warning,
Resource.LogMessage_OlderMajorVersionNuGetPackageExists,
requiredPackage.Key,
installedPackage.VersionString,
requiredPackage.Value);
}
else if (installedVersion.Major > requiredVersion.Major)
{
// A newer potentially non-compatible version of the package already exists - warn and continue.
await logger.WriteMessageAsync(
LoggerMessageCategory.Warning,
Resource.LogMessage_NewerMajorVersionNuGetPackageExists,
requiredPackage.Key,
requiredPackage.Value,
installedPackage.VersionString);
continue;
}
else if (installedVersion >= requiredVersion)
{
// A semantically compatible version of the package already exists - continue.
continue;
}
else
{
// An older semantically compatible version of the package exists - notify and upgrade the package.
await logger.WriteMessageAsync(
LoggerMessageCategory.Information,
Resource.LogMessage_UpgradingNuGetPackage,
requiredPackage.Key,
installedPackage.VersionString,
requiredPackage.Value);
}
}
await installPackage(requiredPackage.Key, requiredPackage.Value);
}
}