This repository was archived by the owner on Jul 14, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
Add aggregatePackage module #80
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
0be07e8
Add aggregatePackage module
9b32d99
Refactor aggregate package options
6a0e8b5
Refactor and change hash function for folder name to avoid collisions…
b1059a4
Merge branch 'master' into iss60
kingerja bcfcaa4
Merge branch 'master' into iss60
1bd3381
Merge branch 'iss60' of https://github.com/kingerja/CBT.Modules into …
3eca220
Merge branch 'master' into iss60
663f955
Merge branch 'master' into iss60
f8f4426
wire up CBTParseError
e9eea63
Do not date hash known immutable roots.
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
20 changes: 20 additions & 0 deletions
20
src/CBT.NuGet.AggregatePackage/CBT.NuGet.AggregatePackage.nuproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| <PropertyGroup Label="Configuration"> | ||
| <Description>Provides ability to aggregate nuget packages.</Description> | ||
| <NoPackageAnalysis>true</NoPackageAnalysis> | ||
| <ProjectGuid>525e50eb-c6d9-497d-bc54-c625ab62b7d0</ProjectGuid> | ||
| <Tags>CBT Module NuGet Aggregate Packages</Tags> | ||
| <Title>CBT NuGet Aggregate Package Restore</Title> | ||
| </PropertyGroup> | ||
| <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory).., build.props))\build.props" /> | ||
| <Import Project="$(NuProjPath)\NuProj.props" Condition="Exists('$(NuProjPath)\NuProj.props')" /> | ||
| <ItemGroup> | ||
| <Dependency Include="CBT.Nuget"> | ||
| <Version>[1.0,)</Version> | ||
| </Dependency> | ||
| <Content Include="CBT\*\**" /> | ||
| <None Include="version.json" /> | ||
| </ItemGroup> | ||
| <Import Project="$(NuProjPath)\NuProj.targets" Condition="Exists('$(NuProjPath)\NuProj.targets')" /> | ||
| </Project> |
5 changes: 5 additions & 0 deletions
5
src/CBT.NuGet.AggregatePackage/CBT/Module/After.CBT.NuGet.props
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
|
|
||
| <Import Project="$(MSBuildThisFileDirectory)\CBT.Nuget.AggregatePackage.props"/> | ||
| </Project> |
23 changes: 23 additions & 0 deletions
23
src/CBT.NuGet.AggregatePackage/CBT/Module/After.Microsoft.Common.targets
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" InitialTargets="NuGetRestoreGlobalPackages"> | ||
|
|
||
| <PropertyGroup> | ||
| <RestoreNuGetPackagesDependsOn>$(RestoreNuGetPackagesDependsOn);AggregateNugetPackages</RestoreNuGetPackagesDependsOn> | ||
| </PropertyGroup> | ||
| <UsingTask AssemblyFile="$(CBTNuGetTasksAssemblyPath)" TaskName="CBT.NuGet.Tasks.AggregatePackages" /> | ||
|
|
||
| <Target Name="AggregateNugetPackages" | ||
| Condition=" '$(CBTAggregatePackage)' != '' And '$(CBTEnableAggregatePackageRestore)' == 'true'" | ||
| Inputs="$(MSBuildAllProjects)" | ||
| Outputs="$(CBTNuGetAggregatePackagePropertyFile)"> | ||
|
|
||
| <AggregatePackages | ||
| AggregateDestinationRoot="$(CBTAggregateDestPackageRoot)" | ||
| PackagesToAggregate="$(CBTAggregatePackage)" | ||
| PropsFile="$(CBTNuGetAggregatePackagePropertyFile)" | ||
| ImmutableRoots="$(CBTNugetAggregatePackageImmutableRoots)" | ||
| /> | ||
|
|
||
| </Target> | ||
|
|
||
| </Project> |
36 changes: 36 additions & 0 deletions
36
src/CBT.NuGet.AggregatePackage/CBT/Module/CBT.Nuget.AggregatePackage.props
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
|
|
||
| <PropertyGroup> | ||
| <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects> | ||
| </PropertyGroup> | ||
|
|
||
| <Import Project="$(CBTLocalBuildExtensionsPath)\Before.$(MSBuildThisFile)" Condition=" '$(CBTLocalBuildExtensionsPath)' != '' And Exists('$(CBTLocalBuildExtensionsPath)\Before.$(MSBuildThisFile)') " /> | ||
| <Import Project="$(CBTModuleExtensionsPath)\Before.$(MSBuildThisFile)" Condition=" '$(CBTModuleExtensionsPath)' != '' And Exists('$(CBTModuleExtensionsPath)\Before.$(MSBuildThisFile)') " /> | ||
|
|
||
| <PropertyGroup> | ||
| <CBTEnableAggregatePackageRestore Condition=" '$(CBTEnableAggregatePackageRestore)' == '' ">true</CBTEnableAggregatePackageRestore> | ||
| <CBTAggregatePackageImport Condition=" '$(CBTAggregatePackageImport)'=='' and Exists('$(MSBuildProjectDirectory)\CBT.AggregatePackages.props')">$(MSBuildProjectDirectory)\CBT.AggregatePackages.props</CBTAggregatePackageImport> | ||
| <CBTAggregateDestPackageRoot Condition=" '$(CBTAggregateDestPackageRoot)'=='' ">$(NuGetPackagesPath)\.agg</CBTAggregateDestPackageRoot> | ||
| <CBTNugetAggregatePackageImmutableRoots Condition=" '$(CBTNugetAggregatePackageImmutableRoots)'=='' ">$(NuGetPackagesPath)</CBTNugetAggregatePackageImmutableRoots> | ||
| </PropertyGroup> | ||
|
|
||
| <Import Project="$(CBTAggregatePackageImport)" Condition=" '$(CBTAggregatePackageImport)'!='' and '$(CBTEnableAggregatePackageRestore)'=='true' "/> | ||
|
|
||
| <PropertyGroup Condition=" '$(CBTEnableAggregatePackageRestore)' == 'true' "> | ||
| <CBTNuGetAggregatePackagePropertyFile Condition=" '$(CBTNuGetAggregatePackagePropertyFile)' == '' ">$(IntermediateOutputPath)\AggregatePackages.props</CBTNuGetAggregatePackagePropertyFile> | ||
| <CBTNuGetAggregatePackageGenerated>$(CBTNuGetTasksAssemblyPath.GetType().Assembly.GetType('System.AppDomain').GetProperty('CurrentDomain').GetValue(null).CreateInstanceFromAndUnwrap($(CBTNuGetTasksAssemblyPath), 'CBT.NuGet.Tasks.AggregatePackages').Execute('$(CBTAggregateDestPackageRoot)', '$(CBTAggregatePackage)', '$(CBTNuGetAggregatePackagePropertyFile)', '$(CBTNugetAggregatePackageImmutableRoots)'))</CBTNuGetAggregatePackageGenerated> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <CBTParseError Condition=" '$(CBTNuGetAggregatePackageGenerated)' == 'false' " Include="Aggregate packages were not generated and the build cannot continue. Refer to other errors for more information."> | ||
| <Code>CBT.Nuget.AggregatePackage.1000</Code> | ||
| </CBTParseError> | ||
| </ItemGroup> | ||
|
|
||
| <Import Project="$(CBTNuGetAggregatePackagePropertyFile)" Condition=" '$(CBTNuGetAggregatePackageGenerated)' == 'true' And Exists('$(CBTNuGetAggregatePackagePropertyFile)') "/> | ||
|
|
||
| <Import Project="$(CBTLocalBuildExtensionsPath)\After.$(MSBuildThisFile)" Condition=" '$(CBTLocalBuildExtensionsPath)' != '' And Exists('$(CBTLocalBuildExtensionsPath)\After.$(MSBuildThisFile)') " /> | ||
| <Import Project="$(CBTModuleExtensionsPath)\After.$(MSBuildThisFile)" Condition=" '$(CBTModuleExtensionsPath)' != '' And Exists('$(CBTModuleExtensionsPath)\After.$(MSBuildThisFile)') " /> | ||
|
|
||
| </Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| <?xml version="1.0"?> | ||
| <configuration> | ||
| <extensionImports> | ||
| <add name="Before.CBT.NuGet.AggregatePackage.props" /> | ||
| <add name="After.CBT.NuGet.AggregatePackage.props" /> | ||
| </extensionImports> | ||
| </configuration> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| { | ||
| "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", | ||
| "version": "1.0-dev", | ||
| "buildNumberOffset": 0, | ||
| "publicReleaseRefSpec": [ | ||
| "^refs/tags/CBT\\.NuGet\\.AggregatePackage.*" | ||
| ], | ||
| "cloudBuild": { | ||
| "setVersionVariables": false | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.IO; | ||
| using System.Linq; | ||
| using System.Security.Cryptography; | ||
| using System.Text; | ||
| using System.Text.RegularExpressions; | ||
|
|
||
| namespace CBT.NuGet.Internal | ||
| { | ||
| internal sealed class AggregatePackage | ||
| { | ||
| public enum AggregateOperation | ||
| { | ||
| Add = '*', | ||
| Remove = '!', | ||
| } | ||
|
|
||
| internal class PackageOperation | ||
| { | ||
| private string folder = string.Empty; | ||
| internal AggregateOperation Operation { get; set; } | ||
|
|
||
| internal string Folder | ||
| { | ||
| get | ||
| { | ||
| return folder; | ||
| } | ||
| set | ||
| { | ||
| folder = Path.GetFullPath(value); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private string[] immutableRootPaths = null; | ||
|
|
||
| public AggregatePackage(string outPropertyId, ICollection<PackageOperation> packagesToAggregate, string destinationRoot, string immutableRoots) | ||
| { | ||
| OutPropertyId = outPropertyId; | ||
| PackagesToAggregate = packagesToAggregate; | ||
| immutableRootPaths = immutableRoots.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(i => Path.GetFullPath(i.Trim())).Where(j => !string.IsNullOrWhiteSpace(j)).ToArray(); | ||
| OutPropertyValue = Path.Combine(destinationRoot, $"{outPropertyId}.{GetOutputPropertyHash()}"); | ||
| } | ||
|
|
||
| public string OutPropertyId { get; private set; } | ||
|
|
||
| public string OutPropertyValue { get; private set; } | ||
|
|
||
| public ICollection<PackageOperation> PackagesToAggregate { get; private set; } | ||
|
|
||
| private string GetOutputPropertyHash() | ||
| { | ||
| StringBuilder valueToHash = new StringBuilder(); | ||
| foreach (var pkg in PackagesToAggregate) | ||
| { | ||
| valueToHash.Append(pkg.Folder.ToLower()); | ||
| // Include last write time on all files to ensure that if the source folder was updated a new aggregate package will be created. | ||
| // if a file was removed then it will not be in the value to hash so the hash will still change to trigger a new aggregation as desired. | ||
| // We don't care about directories in aggregation since removing directories is not possible given current implementation. | ||
| // This is in the scenario where the user aggregates against a nuget package and a checked in folder under source control that contains a config file or whatever. | ||
| // Since this is a string contains match an immutable root match could be problematic in corner cases. d:\tmp\src and d:\tmp\src2 will both match d:\tmp\sr as an immutable root. | ||
| valueToHash.Append(Directory.GetLastWriteTime(pkg.Folder).ToString()); | ||
| if ( !immutableRootPaths.Any() || !immutableRootPaths.Where(i => pkg.Folder.IndexOf(i, StringComparison.OrdinalIgnoreCase) >= 0).Any()) | ||
| { | ||
| foreach (var f in Directory.EnumerateFiles(pkg.Folder, "*.*", SearchOption.AllDirectories)) | ||
| { | ||
| valueToHash.Append(File.GetLastWriteTime(f).ToString()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| string hashValue = Convert.ToBase64String((new SHA1CryptoServiceProvider()).ComputeHash(Encoding.UTF8.GetBytes(valueToHash.ToString()))); | ||
| Regex pattern = new Regex("[/=+]"); | ||
| hashValue = pattern.Replace(hashValue, "x"); | ||
| return string.Format("{0:X}", hashValue); | ||
| } | ||
|
|
||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Diagnostics; | ||
| using System.IO; | ||
| using System.Linq; | ||
| using System.Security.Cryptography; | ||
| using System.Text; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
|
|
||
| namespace CBT.NuGet.Internal | ||
| { | ||
| class FileUtilities | ||
| { | ||
| // Need to find a proper directory copy routine. | ||
| public static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs, bool overWriteFiles) | ||
| { | ||
| if (!Directory.Exists(sourceDirName)) | ||
| { | ||
| throw new DirectoryNotFoundException("Source Directory does not exist or could not be found: " + sourceDirName); | ||
| } | ||
| DirectoryInfo dir = new DirectoryInfo(sourceDirName); | ||
| DirectoryInfo[] dirs = dir.GetDirectories(); | ||
| if (!Directory.Exists(destDirName)) | ||
| { | ||
| Directory.CreateDirectory(destDirName); | ||
| } | ||
| FileInfo[] files = dir.GetFiles(); | ||
| foreach (FileInfo file in files) | ||
| { | ||
| string tempPath = Path.Combine(destDirName, file.Name); | ||
| file.CopyTo(tempPath, overWriteFiles); | ||
| } | ||
| if (copySubDirs) | ||
| { | ||
| foreach (DirectoryInfo subdir in dirs) | ||
| { | ||
| string temppath = Path.Combine(destDirName, subdir.Name); | ||
| DirectoryCopy(subdir.FullName, temppath, copySubDirs, overWriteFiles); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public static void DirectoryRemove(string sourceDirName, string destDirName, bool recurseSubDirs) | ||
| { | ||
| DirectoryInfo dir = new DirectoryInfo(sourceDirName); | ||
| if (!dir.Exists) | ||
| { | ||
| throw new DirectoryNotFoundException("Source Directory does not exist or could not be found: " + sourceDirName); | ||
| } | ||
| DirectoryInfo[] dirs = dir.GetDirectories(); | ||
|
|
||
| FileInfo[] files = dir.GetFiles(); | ||
| foreach (FileInfo file in files) | ||
| { | ||
| string tempPath = Path.Combine(destDirName, file.Name); | ||
| if (File.Exists(tempPath)) | ||
| { | ||
| File.SetAttributes(tempPath, File.GetAttributes(tempPath) & ~FileAttributes.ReadOnly); | ||
| File.Delete(tempPath); | ||
| } | ||
| } | ||
| if (recurseSubDirs) | ||
| { | ||
| foreach (DirectoryInfo subdir in dirs) | ||
| { | ||
| string temppath = Path.Combine(destDirName, subdir.Name); | ||
| DirectoryRemove(subdir.FullName, temppath, recurseSubDirs); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Mutex isn't platform agnostic need to consider options. | ||
| public static string ComputeMutexName(string sessionString) | ||
| { | ||
| // get a hash of the file path; reason: there's a limit on name length for named mutexes | ||
| using (var algo = SHA256.Create()) | ||
| { | ||
| // Global: make it work across TS sessions; not that we should need this, but just to be super-extra safe | ||
| return "Global\\" + Convert.ToBase64String(algo.ComputeHash(Encoding.UTF8.GetBytes(sessionString.ToUpperInvariant()))); | ||
| } | ||
| } | ||
|
|
||
| public static void AcquireMutex(Mutex mutex) | ||
| { | ||
| try | ||
| { | ||
| bool owner = mutex.WaitOne(); // Perhaps specify a timeout value so builds don't hang. | ||
| if (!owner) | ||
| throw new TimeoutException("Timeout waiting for mutex"); | ||
| } | ||
| catch (AbandonedMutexException) | ||
| { | ||
| // Unlikely we care. | ||
| Trace.TraceWarning("mutex for Aggregate package was abandoned."); | ||
| } | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use
EnumerateDirectoriesinstead andEnumerateFilesinstead ofGetFilesbelow. We should probably revisit this method and see if Async copies or parallelism would help here.