diff options
Diffstat (limited to 'src/DotNetOpenAuth.BuildTasks')
8 files changed, 280 insertions, 30 deletions
diff --git a/src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs b/src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs index e17d8f2..38f3b50 100644 --- a/src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs +++ b/src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs @@ -58,36 +58,47 @@ namespace DotNetOpenAuth.BuildTasks { string destPath = this.DestinationFiles[i].ItemSpec; bool skipUnchangedFiles = bool.Parse(this.SourceFiles[i].GetMetadata("SkipUnchangedFiles")); - // We deliberably consider newer destination files to be up-to-date rather than - // requiring equality because this task modifies the destination file while copying. - if (skipUnchangedFiles && File.GetLastWriteTimeUtc(sourcePath) < File.GetLastWriteTimeUtc(destPath)) { - Log.LogMessage(MessageImportance.Low, "Skipping \"{0}\" -> \"{1}\" because the destination is up to date.", sourcePath, destPath); - continue; - } + if (string.IsNullOrEmpty(this.SourceFiles[i].GetMetadata("BeforeTokens"))) { + // this is just a standard copy without token substitution + if (skipUnchangedFiles && File.GetLastWriteTimeUtc(sourcePath) == File.GetLastWriteTimeUtc(destPath)) { + Log.LogMessage(MessageImportance.Low, "Skipping \"{0}\" -> \"{1}\" because the destination is up to date.", sourcePath, destPath); + continue; + } - Log.LogMessage(MessageImportance.Normal, "Transforming \"{0}\" -> \"{1}\"", sourcePath, destPath); + Log.LogMessage(MessageImportance.Normal, "Copying \"{0}\" -> \"{1}\"", sourcePath, destPath); + File.Copy(sourcePath, destPath, true); + } else { + // We deliberably consider newer destination files to be up-to-date rather than + // requiring equality because this task modifies the destination file while copying. + if (skipUnchangedFiles && File.GetLastWriteTimeUtc(sourcePath) < File.GetLastWriteTimeUtc(destPath)) { + Log.LogMessage(MessageImportance.Low, "Skipping \"{0}\" -> \"{1}\" because the destination is up to date.", sourcePath, destPath); + continue; + } - string[] beforeTokens = this.SourceFiles[i].GetMetadata("BeforeTokens").Split(';'); - string[] afterTokens = this.SourceFiles[i].GetMetadata("AfterTokens").Split(';'); - if (beforeTokens.Length != afterTokens.Length) { - Log.LogError("Unequal number of before and after tokens. Before: \"{0}\". After \"{1}\".", beforeTokens, afterTokens); - return false; - } + Log.LogMessage(MessageImportance.Normal, "Transforming \"{0}\" -> \"{1}\"", sourcePath, destPath); - using (StreamReader sr = File.OpenText(sourcePath)) { - if (!Directory.Exists(Path.GetDirectoryName(destPath))) { - Directory.CreateDirectory(Path.GetDirectoryName(destPath)); + string[] beforeTokens = this.SourceFiles[i].GetMetadata("BeforeTokens").Split(';'); + string[] afterTokens = this.SourceFiles[i].GetMetadata("AfterTokens").Split(';'); + if (beforeTokens.Length != afterTokens.Length) { + Log.LogError("Unequal number of before and after tokens. Before: \"{0}\". After \"{1}\".", beforeTokens, afterTokens); + return false; } - using (StreamWriter sw = File.CreateText(destPath)) { - StringBuilder line = new StringBuilder(); - while (!sr.EndOfStream) { - line.Length = 0; - line.Append(sr.ReadLine()); - for (int j = 0; j < beforeTokens.Length; j++) { - line.Replace(beforeTokens[j], afterTokens[j]); - } - sw.WriteLine(line); + using (StreamReader sr = File.OpenText(sourcePath)) { + if (!Directory.Exists(Path.GetDirectoryName(destPath))) { + Directory.CreateDirectory(Path.GetDirectoryName(destPath)); + } + using (StreamWriter sw = File.CreateText(destPath)) { + StringBuilder line = new StringBuilder(); + while (!sr.EndOfStream) { + line.Length = 0; + line.Append(sr.ReadLine()); + for (int j = 0; j < beforeTokens.Length; j++) { + line.Replace(beforeTokens[j], afterTokens[j]); + } + + sw.WriteLine(line); + } } } } diff --git a/src/DotNetOpenAuth.BuildTasks/DiscoverProjectTemplates.cs b/src/DotNetOpenAuth.BuildTasks/DiscoverProjectTemplates.cs index 0162c16..f49c9b1 100644 --- a/src/DotNetOpenAuth.BuildTasks/DiscoverProjectTemplates.cs +++ b/src/DotNetOpenAuth.BuildTasks/DiscoverProjectTemplates.cs @@ -15,6 +15,7 @@ namespace DotNetOpenAuth.BuildTasks { using Microsoft.Build.Utilities; public class DiscoverProjectTemplates : Task { + [Required] public ITaskItem[] TopLevelTemplates { get; set; } [Output] diff --git a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj index b8cff51..3f76f78 100644 --- a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj +++ b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> @@ -12,6 +12,21 @@ <AssemblyName>DotNetOpenAuth.BuildTasks</AssemblyName> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> <FileAlignment>512</FileAlignment> + <PublishUrl>publish\</PublishUrl> + <Install>true</Install> + <InstallFrom>Disk</InstallFrom> + <UpdateEnabled>false</UpdateEnabled> + <UpdateMode>Foreground</UpdateMode> + <UpdateInterval>7</UpdateInterval> + <UpdateIntervalUnits>Days</UpdateIntervalUnits> + <UpdatePeriodically>false</UpdatePeriodically> + <UpdateRequired>false</UpdateRequired> + <MapFileExtensions>true</MapFileExtensions> + <ApplicationRevision>0</ApplicationRevision> + <ApplicationVersion>1.0.0.%2a</ApplicationVersion> + <IsWebBootstrapper>false</IsWebBootstrapper> + <UseApplicationTrust>false</UseApplicationTrust> + <BootstrapperEnabled>true</BootstrapperEnabled> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> @@ -48,6 +63,7 @@ </CodeContractsBaseLineFile> <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel> <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugType>pdbonly</DebugType> @@ -56,6 +72,7 @@ <DefineConstants>TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> <Reference Include="Microsoft.Build.Engine" /> @@ -89,14 +106,17 @@ <Compile Include="CreateWebApplication.cs" /> <Compile Include="DeleteWebApplication.cs" /> <Compile Include="DiscoverProjectTemplates.cs" /> + <Compile Include="DowngradeProjects.cs" /> <Compile Include="ECMAScriptPacker.cs" /> <Compile Include="FilterItems.cs" /> <Compile Include="FixupReferenceHintPaths.cs" /> <Compile Include="FixupShippingToolSamples.cs" /> + <Compile Include="HardLinkCopy.cs" /> <Compile Include="MergeProjectWithVSTemplate.cs" /> <Compile Include="GetBuildVersion.cs" /> <Compile Include="CheckAdminRights.cs" /> <Compile Include="JsPack.cs" /> + <Compile Include="NativeMethods.cs" /> <Compile Include="ParseMaster.cs" /> <Compile Include="Publicize.cs" /> <Compile Include="Purge.cs" /> @@ -118,6 +138,23 @@ <LastGenOutput>TaskStrings.Designer.cs</LastGenOutput> </EmbeddedResource> </ItemGroup> + <ItemGroup> + <BootstrapperPackage Include="Microsoft.Net.Client.3.5"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1</ProductName> + <Install>true</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1"> + <Visible>False</Visible> + <ProductName>Windows Installer 3.1</ProductName> + <Install>true</Install> + </BootstrapperPackage> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. diff --git a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln index 0d0900b..34a8e46 100644 --- a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln +++ b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln @@ -1,8 +1,6 @@ -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.BuildTasks", "DotNetOpenAuth.BuildTasks.csproj", "{AC231A51-EF60-437C-A33F-AF8ADEB8EB74}" -EndProject +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{ABBE14A3-0404-4123-9093-E598C3DD3E9B}" ProjectSection(SolutionItems) = preProject ..\..\build.proj = ..\..\build.proj @@ -13,6 +11,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ..\..\tools\DotNetOpenAuth.Versioning.targets = ..\..\tools\DotNetOpenAuth.Versioning.targets EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.BuildTasks", "DotNetOpenAuth.BuildTasks.csproj", "{AC231A51-EF60-437C-A33F-AF8ADEB8EB74}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/src/DotNetOpenAuth.BuildTasks/DowngradeProjects.cs b/src/DotNetOpenAuth.BuildTasks/DowngradeProjects.cs new file mode 100644 index 0000000..645522d --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/DowngradeProjects.cs @@ -0,0 +1,110 @@ +//----------------------------------------------------------------------- +// <copyright file="DowngradeProjects.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.BuildTasks { + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Text; + using Microsoft.Build.BuildEngine; + using Microsoft.Build.Framework; + using Microsoft.Build.Utilities; + + /// <summary> + /// Downgrades Visual Studio 2010 solutions and projects so that they load in Visual Studio 2008. + /// </summary> + public class DowngradeProjects : Task { + /// <summary> + /// Gets or sets the projects and solutions to downgrade. + /// </summary> + [Required] + public ITaskItem[] Projects { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether ASP.NET MVC 2 projects are downgraded to MVC 1.0. + /// </summary> + public bool DowngradeMvc2ToMvc1 { get; set; } + + /// <summary> + /// Executes this instance. + /// </summary> + public override bool Execute() { + foreach (ITaskItem taskItem in this.Projects) { + switch (GetClassification(taskItem)) { + case ProjectClassification.VS2010Project: + this.Log.LogMessage(MessageImportance.Low, "Downgrading project \"{0}\".", taskItem.ItemSpec); + Project project = new Project(); + project.Load(taskItem.ItemSpec); + project.DefaultToolsVersion = "3.5"; + + if (this.DowngradeMvc2ToMvc1) { + string projectTypeGuids = project.GetEvaluatedProperty("ProjectTypeGuids"); + if (!string.IsNullOrEmpty(projectTypeGuids)) { + projectTypeGuids = projectTypeGuids.Replace("{F85E285D-A4E0-4152-9332-AB1D724D3325}", "{603c0e0b-db56-11dc-be95-000d561079b0}"); + project.SetProperty("ProjectTypeGuids", projectTypeGuids); + } + } + + // Web projects usually have an import that includes these substrings + foreach (Import import in project.Imports) { + import.ProjectPath = import.ProjectPath + .Replace("$(MSBuildExtensionsPath32)", "$(MSBuildExtensionsPath)") + .Replace("VisualStudio\\v10.0", "VisualStudio\\v9.0"); + } + + // VS2010 won't let you have a System.Core reference, but VS2008 requires it. + BuildItemGroup references = project.GetEvaluatedItemsByName("Reference"); + if (!references.Cast<BuildItem>().Any(item => item.FinalItemSpec.StartsWith("System.Core", StringComparison.OrdinalIgnoreCase))) { + project.AddNewItem("Reference", "System.Core"); + } + + project.Save(taskItem.ItemSpec); + break; + case ProjectClassification.VS2010Solution: + this.Log.LogMessage(MessageImportance.Low, "Downgrading solution \"{0}\".", taskItem.ItemSpec); + string[] contents = File.ReadAllLines(taskItem.ItemSpec); + if (contents[1] != "Microsoft Visual Studio Solution File, Format Version 11.00" || + contents[2] != "# Visual Studio 2010") { + this.Log.LogError("Unrecognized solution file header in \"{0}\".", taskItem.ItemSpec); + break; + } + + contents[1] = "Microsoft Visual Studio Solution File, Format Version 10.00"; + contents[2] = "# Visual Studio 2008"; + + for (int i = 3; i < contents.Length; i++) { + contents[i] = contents[i].Replace("TargetFrameworkMoniker = \".NETFramework,Version%3Dv", "TargetFramework = \""); + } + + File.WriteAllLines(taskItem.ItemSpec, contents); + break; + default: + this.Log.LogWarning("Unrecognized project type for \"{0}\".", taskItem.ItemSpec); + break; + } + } + + return !this.Log.HasLoggedErrors; + } + + private static ProjectClassification GetClassification(ITaskItem taskItem) { + if (Path.GetExtension(taskItem.ItemSpec).EndsWith("proj", StringComparison.OrdinalIgnoreCase)) { + return ProjectClassification.VS2010Project; + } else if (Path.GetExtension(taskItem.ItemSpec).Equals(".sln", StringComparison.OrdinalIgnoreCase)) { + return ProjectClassification.VS2010Solution; + } else { + return ProjectClassification.Unrecognized; + } + } + + private enum ProjectClassification { + VS2010Project, + VS2010Solution, + Unrecognized, + } + } +} diff --git a/src/DotNetOpenAuth.BuildTasks/FixupShippingToolSamples.cs b/src/DotNetOpenAuth.BuildTasks/FixupShippingToolSamples.cs index a6088c9..6c71740 100644 --- a/src/DotNetOpenAuth.BuildTasks/FixupShippingToolSamples.cs +++ b/src/DotNetOpenAuth.BuildTasks/FixupShippingToolSamples.cs @@ -6,6 +6,7 @@ namespace DotNetOpenAuth.BuildTasks { using System; + using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; @@ -24,6 +25,8 @@ namespace DotNetOpenAuth.BuildTasks { public string[] RemoveImportsStartingWith { get; set; } + public ITaskItem[] AddReferences { get; set; } + /// <summary> /// Executes this instance. /// </summary> @@ -43,6 +46,15 @@ namespace DotNetOpenAuth.BuildTasks { .ForEach(import => project.Imports.RemoveImport(import)); } + if (this.AddReferences != null) { + foreach (var reference in this.AddReferences) { + BuildItem item = project.AddNewItem("Reference", reference.ItemSpec); + foreach (DictionaryEntry metadata in reference.CloneCustomMetadata()) { + item.SetMetadata((string)metadata.Key, (string)metadata.Value); + } + } + } + project.Save(projectTaskItem.ItemSpec); } diff --git a/src/DotNetOpenAuth.BuildTasks/HardLinkCopy.cs b/src/DotNetOpenAuth.BuildTasks/HardLinkCopy.cs new file mode 100644 index 0000000..af2d1d0 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/HardLinkCopy.cs @@ -0,0 +1,61 @@ +//----------------------------------------------------------------------- +// <copyright file="HardLinkCopy.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.BuildTasks { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using Microsoft.Build.Framework; + using Microsoft.Build.Utilities; + using System.IO; + + public class HardLinkCopy : Task { + [Required] + public ITaskItem[] SourceFiles { get; set; } + + [Required] + public ITaskItem[] DestinationFiles { get; set; } + + /// <summary> + /// Executes this instance. + /// </summary> + public override bool Execute() { + if (this.SourceFiles.Length != this.DestinationFiles.Length) { + this.Log.LogError("SourceFiles has {0} elements and DestinationFiles has {1} elements.", this.SourceFiles.Length, this.DestinationFiles.Length); + return false; + } + + for (int i = 0; i < this.SourceFiles.Length; i++) { + bool hardLink; + bool.TryParse(this.DestinationFiles[i].GetMetadata("HardLink"), out hardLink); + string sourceFile = this.SourceFiles[i].ItemSpec; + string destinationFile = this.DestinationFiles[i].ItemSpec; + this.Log.LogMessage( + MessageImportance.Low, + "Copying {0} -> {1}{2}.", + sourceFile, + destinationFile, + hardLink ? " as hard link" : string.Empty); + + if (!Directory.Exists(Path.GetDirectoryName(destinationFile))) { + Directory.CreateDirectory(Path.GetDirectoryName(destinationFile)); + } + + if (hardLink) { + if (File.Exists(destinationFile)) { + File.Delete(destinationFile); + } + NativeMethods.CreateHardLink(sourceFile, destinationFile); + } else { + File.Copy(sourceFile, destinationFile, true); + } + } + + return !this.Log.HasLoggedErrors; + } + } +} diff --git a/src/DotNetOpenAuth.BuildTasks/NativeMethods.cs b/src/DotNetOpenAuth.BuildTasks/NativeMethods.cs new file mode 100644 index 0000000..26de3a4 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/NativeMethods.cs @@ -0,0 +1,18 @@ +namespace DotNetOpenAuth.BuildTasks { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Runtime.InteropServices; + + internal static class NativeMethods { + [DllImport("kernel32", SetLastError = true)] + private static extern bool CreateHardLink(string newFileName, string existingFileName, IntPtr securityAttributes); + + internal static void CreateHardLink(string existingFileName, string newFileName) { + if (!CreateHardLink(newFileName, existingFileName, IntPtr.Zero)) { + Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); + } + } + } +} |