Skip to content

Commit

Permalink
Enable Visual Studio project mutation event batching per package for …
Browse files Browse the repository at this point in the history
…MSBuild projects (#895)
  • Loading branch information
dtivel committed Sep 27, 2016
1 parent 46a8ddf commit 964fe41
Show file tree
Hide file tree
Showing 6 changed files with 425 additions and 239 deletions.
5 changes: 0 additions & 5 deletions src/NuGet.Core/NuGet.PackageManagement/NuGetPackageManager.cs
Expand Up @@ -1732,11 +1732,6 @@ await PreviewBuildIntegratedProjectActionsAsync(buildIntegratedProject, actions,

if (msbuildProject != null)
{
// Leaving it as comment for future reference
// Don't use batch API for whole install or uninstall which also includes adding/ removing references
// from project, since it could then create problems while adding binding redirects.
// msbuildProject.MSBuildNuGetProjectSystem.BeginProcessing();

// raise Nuget batch start event
var batchId = Guid.NewGuid().ToString();
string name;
Expand Down
184 changes: 101 additions & 83 deletions src/NuGet.Core/NuGet.ProjectManagement/Projects/MSBuildNuGetProject.cs
Expand Up @@ -275,64 +275,73 @@ private static bool IsSkipAssemblyReferences(INuGetProjectContext nuGetProjectCo
}
PackageEventsProvider.Instance.NotifyInstalled(packageEventArgs);

// Step-8: MSBuildNuGetProjectSystem operations
// Step-8.1: Add references to project
if (!IsSkipAssemblyReferences(nuGetProjectContext) &&
MSBuildNuGetProjectSystemUtility.IsValid(compatibleReferenceItemsGroup))
try
{
foreach (var referenceItem in compatibleReferenceItemsGroup.Items)
MSBuildNuGetProjectSystem.BeginProcessing();

// Step-8: MSBuildNuGetProjectSystem operations
// Step-8.1: Add references to project
if (!IsSkipAssemblyReferences(nuGetProjectContext) &&
MSBuildNuGetProjectSystemUtility.IsValid(compatibleReferenceItemsGroup))
{
if (IsAssemblyReference(referenceItem))
foreach (var referenceItem in compatibleReferenceItemsGroup.Items)
{
var referenceItemFullPath = Path.Combine(packageInstallPath, referenceItem);
var referenceName = Path.GetFileName(referenceItem);

if (MSBuildNuGetProjectSystem.ReferenceExists(referenceName))
if (IsAssemblyReference(referenceItem))
{
MSBuildNuGetProjectSystem.RemoveReference(referenceName);
}
var referenceItemFullPath = Path.Combine(packageInstallPath, referenceItem);
var referenceName = Path.GetFileName(referenceItem);

if (MSBuildNuGetProjectSystem.ReferenceExists(referenceName))
{
MSBuildNuGetProjectSystem.RemoveReference(referenceName);
}

MSBuildNuGetProjectSystem.AddReference(referenceItemFullPath);
MSBuildNuGetProjectSystem.AddReference(referenceItemFullPath);
}
}
}
}

// Step-8.2: Add Frameworkreferences to project
if (!IsSkipAssemblyReferences(nuGetProjectContext) &&
MSBuildNuGetProjectSystemUtility.IsValid(compatibleFrameworkReferencesGroup))
{
foreach (var frameworkReference in compatibleFrameworkReferencesGroup.Items)
// Step-8.2: Add Frameworkreferences to project
if (!IsSkipAssemblyReferences(nuGetProjectContext) &&
MSBuildNuGetProjectSystemUtility.IsValid(compatibleFrameworkReferencesGroup))
{
if (!MSBuildNuGetProjectSystem.ReferenceExists(frameworkReference))
foreach (var frameworkReference in compatibleFrameworkReferencesGroup.Items)
{
MSBuildNuGetProjectSystem.AddFrameworkReference(frameworkReference, packageIdentity.Id);
if (!MSBuildNuGetProjectSystem.ReferenceExists(frameworkReference))
{
MSBuildNuGetProjectSystem.AddFrameworkReference(frameworkReference, packageIdentity.Id);
}
}
}
}

// Step-8.3: Add Content Files
if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleContentFilesGroup))
{
MSBuildNuGetProjectSystemUtility.AddFiles(MSBuildNuGetProjectSystem,
packageReader, compatibleContentFilesGroup, FileTransformers);
}
// Step-8.3: Add Content Files
if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleContentFilesGroup))
{
MSBuildNuGetProjectSystemUtility.AddFiles(MSBuildNuGetProjectSystem,
packageReader, compatibleContentFilesGroup, FileTransformers);
}

// Step-8.4: Add Build imports
if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleBuildFilesGroup))
{
foreach (var buildImportFile in compatibleBuildFilesGroup.Items)
// Step-8.4: Add Build imports
if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleBuildFilesGroup))
{
var fullImportFilePath = Path.Combine(packageInstallPath, buildImportFile);
MSBuildNuGetProjectSystem.AddImport(fullImportFilePath,
fullImportFilePath.EndsWith(".props", StringComparison.OrdinalIgnoreCase) ? ImportLocation.Top : ImportLocation.Bottom);
foreach (var buildImportFile in compatibleBuildFilesGroup.Items)
{
var fullImportFilePath = Path.Combine(packageInstallPath, buildImportFile);
MSBuildNuGetProjectSystem.AddImport(fullImportFilePath,
fullImportFilePath.EndsWith(".props", StringComparison.OrdinalIgnoreCase) ? ImportLocation.Top : ImportLocation.Bottom);
}
}
}

// Step-9: Install package to PackagesConfigNuGetProject
await PackagesConfigNuGetProject.InstallPackageAsync(packageIdentity, downloadResourceResult, nuGetProjectContext, token);
// Step-9: Install package to PackagesConfigNuGetProject
await PackagesConfigNuGetProject.InstallPackageAsync(packageIdentity, downloadResourceResult, nuGetProjectContext, token);

// Step-10: Add packages.config to MSBuildNuGetProject
MSBuildNuGetProjectSystem.AddExistingFile(Path.GetFileName(PackagesConfigNuGetProject.FullPath));
// Step-10: Add packages.config to MSBuildNuGetProject
MSBuildNuGetProjectSystem.AddExistingFile(Path.GetFileName(PackagesConfigNuGetProject.FullPath));
}
finally
{
MSBuildNuGetProjectSystem.EndProcessing();
}

// Step 11: Raise PackageReferenceAdded event
PackageReferenceAdded?.Invoke(this, packageEventArgs);
Expand Down Expand Up @@ -446,61 +455,70 @@ public override async Task<bool> UninstallPackageAsync(PackageIdentity packageId
compatibleBuildFilesGroup
= MSBuildNuGetProjectSystemUtility.Normalize(compatibleBuildFilesGroup);

// Step-5: Remove package reference from packages.config
await PackagesConfigNuGetProject.UninstallPackageAsync(packageIdentity, nuGetProjectContext, token);

// Step-6: Remove packages.config from MSBuildNuGetProject if there are no packages
// OR Add it again (to ensure that Source Control works), when there are some packages
if (!(await PackagesConfigNuGetProject.GetInstalledPackagesAsync(token)).Any())
try
{
MSBuildNuGetProjectSystem.RemoveFile(Path.GetFileName(PackagesConfigNuGetProject.FullPath));
}
else
{
MSBuildNuGetProjectSystem.AddExistingFile(Path.GetFileName(PackagesConfigNuGetProject.FullPath));
}
MSBuildNuGetProjectSystem.BeginProcessing();

// Step-7: Uninstall package from the msbuild project
// Step-7.1: Remove references
if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleReferenceItemsGroup))
{
foreach (var item in compatibleReferenceItemsGroup.Items)
// Step-5: Remove package reference from packages.config
await PackagesConfigNuGetProject.UninstallPackageAsync(packageIdentity, nuGetProjectContext, token);

// Step-6: Remove packages.config from MSBuildNuGetProject if there are no packages
// OR Add it again (to ensure that Source Control works), when there are some packages
if (!(await PackagesConfigNuGetProject.GetInstalledPackagesAsync(token)).Any())
{
MSBuildNuGetProjectSystem.RemoveFile(Path.GetFileName(PackagesConfigNuGetProject.FullPath));
}
else
{
if (IsAssemblyReference(item))
MSBuildNuGetProjectSystem.AddExistingFile(Path.GetFileName(PackagesConfigNuGetProject.FullPath));
}

// Step-7: Uninstall package from the msbuild project
// Step-7.1: Remove references
if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleReferenceItemsGroup))
{
foreach (var item in compatibleReferenceItemsGroup.Items)
{
MSBuildNuGetProjectSystem.RemoveReference(Path.GetFileName(item));
if (IsAssemblyReference(item))
{
MSBuildNuGetProjectSystem.RemoveReference(Path.GetFileName(item));
}
}
}
}

// Step-7.2: Framework references are never removed. This is a no-op
// Step-7.2: Framework references are never removed. This is a no-op

// Step-7.3: Remove content files
if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleContentFilesGroup))
{
var packagesPaths = (await GetInstalledPackagesAsync(token))
.Select(pr => FolderNuGetProject.GetInstalledPackageFilePath(pr.PackageIdentity));

MSBuildNuGetProjectSystemUtility.DeleteFiles(MSBuildNuGetProjectSystem,
zipArchive,
packagesPaths,
compatibleContentFilesGroup,
FileTransformers);
}
// Step-7.3: Remove content files
if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleContentFilesGroup))
{
var packagesPaths = (await GetInstalledPackagesAsync(token))
.Select(pr => FolderNuGetProject.GetInstalledPackageFilePath(pr.PackageIdentity));

MSBuildNuGetProjectSystemUtility.DeleteFiles(MSBuildNuGetProjectSystem,
zipArchive,
packagesPaths,
compatibleContentFilesGroup,
FileTransformers);
}

// Step-7.4: Remove build imports
if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleBuildFilesGroup))
{
foreach (var buildImportFile in compatibleBuildFilesGroup.Items)
// Step-7.4: Remove build imports
if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleBuildFilesGroup))
{
var fullImportFilePath = Path.Combine(FolderNuGetProject.GetInstalledPath(packageIdentity), buildImportFile);
MSBuildNuGetProjectSystem.RemoveImport(fullImportFilePath);
foreach (var buildImportFile in compatibleBuildFilesGroup.Items)
{
var fullImportFilePath = Path.Combine(FolderNuGetProject.GetInstalledPath(packageIdentity), buildImportFile);
MSBuildNuGetProjectSystem.RemoveImport(fullImportFilePath);
}
}
}

// Step-7.5: Remove binding redirects. This is a no-op
// Binding redirects will be removed when all packages have finished
// uninstalling for performance reasons
// Step-7.5: Remove binding redirects. This is a no-op
// Binding redirects will be removed when all packages have finished
// uninstalling for performance reasons
}
finally
{
MSBuildNuGetProjectSystem.EndProcessing();
}

// Step-8: Raise PackageReferenceRemoved event
if (PackageReferenceRemoved != null)
Expand Down

0 comments on commit 964fe41

Please sign in to comment.