diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2010-02-20 13:43:17 -0800 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2010-02-20 13:43:17 -0800 |
commit | f1718afbd134c9b4a5db2dfe3c3ec1f804312123 (patch) | |
tree | fc4e04018874e30bf93e1cbb4f0c4874fbcbc193 | |
parent | 1cc3bef4af253d5e82a5561049b5bdf412013cb5 (diff) | |
parent | 79b38d534537eec6b3e49bd428e768f600a3d370 (diff) | |
download | DotNetOpenAuth-f1718afbd134c9b4a5db2dfe3c3ec1f804312123.zip DotNetOpenAuth-f1718afbd134c9b4a5db2dfe3c3ec1f804312123.tar.gz DotNetOpenAuth-f1718afbd134c9b4a5db2dfe3c3ec1f804312123.tar.bz2 |
Merge branch 'v3.4'
-rw-r--r-- | lib/DotNetOpenAuth.BuildTasks.dll | bin | 76800 -> 91648 bytes | |||
-rw-r--r-- | lib/DotNetOpenAuth.BuildTasks.pdb | bin | 163328 -> 196096 bytes | |||
-rw-r--r-- | projecttemplates/projecttemplates.proj | 51 | ||||
-rw-r--r-- | samples/tools.proj | 25 | ||||
-rw-r--r-- | src/DotNetOpenAuth.BuildTasks/AddProjectItems.cs | 7 | ||||
-rw-r--r-- | src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj | 1 | ||||
-rw-r--r-- | src/DotNetOpenAuth.BuildTasks/MergeProjectWithVSTemplate.cs | 111 | ||||
-rw-r--r-- | src/DotNetOpenAuth.BuildTasks/PathSegment.cs | 321 | ||||
-rw-r--r-- | src/DotNetOpenAuth/DotNetOpenAuth.csproj | 4 | ||||
-rw-r--r-- | src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs | 14 | ||||
-rw-r--r-- | tools/DotNetOpenAuth.props | 1 | ||||
-rw-r--r-- | tools/DotNetOpenAuth.targets | 49 | ||||
-rw-r--r-- | tools/drop.proj | 13 | ||||
-rw-r--r-- | vsi/vsi.proj | 9 | ||||
-rw-r--r-- | vsix/vsix.proj | 3 |
15 files changed, 467 insertions, 142 deletions
diff --git a/lib/DotNetOpenAuth.BuildTasks.dll b/lib/DotNetOpenAuth.BuildTasks.dll Binary files differindex d26f276..b3c6244 100644 --- a/lib/DotNetOpenAuth.BuildTasks.dll +++ b/lib/DotNetOpenAuth.BuildTasks.dll diff --git a/lib/DotNetOpenAuth.BuildTasks.pdb b/lib/DotNetOpenAuth.BuildTasks.pdb Binary files differindex 0169338..676ff46 100644 --- a/lib/DotNetOpenAuth.BuildTasks.pdb +++ b/lib/DotNetOpenAuth.BuildTasks.pdb diff --git a/projecttemplates/projecttemplates.proj b/projecttemplates/projecttemplates.proj index d4d3a56..9df3fa8 100644 --- a/projecttemplates/projecttemplates.proj +++ b/projecttemplates/projecttemplates.proj @@ -3,7 +3,7 @@ <Import Project="ProjectTemplates.props"/> <PropertyGroup> - <ProjectTemplateMaxPath Condition=" '$(ProjectTemplateMaxPath)' == '' ">50</ProjectTemplateMaxPath> + <ProjectTemplateMaxPath Condition=" '$(ProjectTemplateMaxPath)' == '' ">6</ProjectTemplateMaxPath> <LayoutDependsOn> BuildUnifiedProduct; @@ -34,6 +34,9 @@ </Target> <Target Name="LayoutProjects"> + <MSBuild Projects="..\src\$(ProductName)\$(ProductName).csproj" Targets="Sign" BuildInParallel="$(BuildInParallel)"> + <Output TaskParameter="TargetOutputs" ItemName="SignedProductAssemblies" /> + </MSBuild> <ItemGroup> <TemplateProjects Include="**\*.csproj" Exclude="$(MSBuildThisFile)"> <AfterTokens>$safeprojectname$</AfterTokens> @@ -45,19 +48,29 @@ </TemplateProjects> <TemplateProjectsLayout Include="@(TemplateProjects->'$(ProjectTemplatesLayoutPath)%(RecursiveDir)%(FileName)%(Extension)')"/> - <!-- Add external libraries --> - <!-- Include the unified, signed version of the library --> - <ProjectTemplateLibraries Include="$(ILMergeOutputAssembly)" /> - <ProjectTemplateLibraries Include="$(ILMergeOutputAssemblyDirectory)$(ProductName).pdb" /> + <!-- Add external libraries and their symbols --> + <ProjectTemplateLibraries Include="@(SignedProductAssemblies)" /> + <ProjectTemplateLibraries Include="@(SignedProductAssemblies->'%(SymbolPath)')" /> <ProjectTemplateLibraries Include="$(OutputPath)$(ProductName).xml" /> - <ProjectTemplateLibraries Include="$(OutputPath)$(ProductName).Contracts.dll" /> <!-- ... and log4net --> <ProjectTemplateLibraries Include="$(ProjectRoot)lib\log4net.dll" /> <ProjectTemplateLibraries Include="$(ProjectRoot)lib\log4net.xml" /> - <ProjectTemplateLibrariesTargets Include="@(ProjectTemplateLibraries->'$(ProjectTemplatesLayoutPath)RelyingPartyLogic\lib\%(FileName)%(Extension)')" /> + <ProjectTemplateLibrariesTargets Include="@(ProjectTemplateLibraries->'$(ProjectTemplatesLayoutPath)RelyingPartyLogic\lib\%(CultureDir)%(FileName)%(Extension)')"> + <ApparentSource>RelyingPartyLogic\lib\%(ProjectTemplateLibraries.CultureDir)%(FileName)%(Extension)</ApparentSource> + <ActualSource>%(Identity)</ActualSource> + </ProjectTemplateLibrariesTargets> + <ProjectTemplateLibrariesSourceExceptions Include="@(ProjectTemplateLibrariesTargets->'%(ApparentSource)')"/> <FixupReferenceAssemblies Include="@(ProjectTemplateLibrariesTargets)" Condition="'%(Extension)' == '.dll'" /> - <InjectedLibraryItems Include="@(ProjectTemplateLibrariesTargets->'lib\%(FileName)%(Extension)')" /> + <InjectedLibraryItems Include="@(ProjectTemplateLibraries->'lib\%(CultureDir)%(FileName)%(Extension)')"> + <Visible/> + <UnsignedAssemblyPath/> + <SymbolPath/> + <OriginalItemSpec/> + <MSBuildSourceProjectFile/> + <MSBuildSourceTargetName/> + <CultureDir/> + </InjectedLibraryItems> <VSProjectTemplates Include="**\*.vstemplate" Exclude="*.vstemplate" /> <VSProjectTemplatesLayout Include="@(VSProjectTemplates->'$(ProjectTemplatesLayoutPath)%(RecursiveDir)%(FileName)%(Extension)')" /> @@ -89,6 +102,7 @@ SourceTemplates="@(VSProjectTemplates)" SourceProjects="@(TemplateProjectsLayout)" DestinationTemplates="@(VSProjectTemplatesLayout)" + SourcePathExceptions="@(ProjectTemplateLibrariesSourceExceptions)" MaximumRelativePathLength="$(ProjectTemplateMaxPath)" > <Output TaskParameter="ProjectItems" ItemName="TemplateProjectItems"/> @@ -97,34 +111,19 @@ <Target Name="Layout" DependsOnTargets="$(LayoutDependsOn)"> <ItemGroup> - <TemplateProjectItems Condition=" - '%(Extension)' == '.cs' - or '%(Extension)' == '.csproj' - or '%(Extension)' == '.sql' - or '%(Extension)' == '.config' - or '%(Extension)' == '.Master' - or '%(Extension)' == '.aspx' - or '%(Extension)' == '.ascx' - or '%(Extension)' == '.asax' - or '%(Extension)' == '.ashx' - "> + <TemplateProjectItems Condition=" '%(Transform)' == 'true' "> <BeforeTokens>%(RecursiveDir)</BeforeTokens> <AfterTokens>$safeprojectname$</AfterTokens> </TemplateProjectItems> <TemplateProjectItems> <SkipUnchangedFiles>true</SkipUnchangedFiles> </TemplateProjectItems> - <TemplateProjectItemsForTransformSource Include="@(TemplateProjectItems->'%(SourceFullPath)')" - Condition=" '%(TemplateProjectItems.RelativeDir)' != 'RelyingPartyLogic\lib\' "/> - <TemplateProjectItemsForTransformLayout Include="@(TemplateProjectItems->'%(DestinationFullPath)')" - Condition=" '%(TemplateProjectItems.RelativeDir)' != 'RelyingPartyLogic\lib\' "/> + <TemplateProjectItemsForTransformSource Include="@(TemplateProjectItems->'%(SourceFullPath)')" /> + <TemplateProjectItemsForTransformLayout Include="@(TemplateProjectItems->'%(DestinationFullPath)')" /> <RootVsTemplateSource Include="*.vstemplate" /> <ProjectTemplatesSource Include="@(RootVsTemplateSource)" /> <ProjectTemplatesLayout Include="@(RootVsTemplateSource->'$(ProjectTemplatesLayoutPath)%(FileName)%(Extension)')" /> - <ProjectTemplatesSource Include="@(ProjectTemplateLibraries)" /> - <ProjectTemplatesLayout Include="@(ProjectTemplateLibrariesTargets)" /> - <!-- Include the template icon --> <ProjectTemplatesSource Include="$(ProjectRoot)doc\logo\favicon.ico" /> <ProjectTemplatesLayout Include="$(ProjectTemplatesLayoutPath)__TemplateIcon.ico" /> diff --git a/samples/tools.proj b/samples/tools.proj index 7d5396b..74f6457 100644 --- a/samples/tools.proj +++ b/samples/tools.proj @@ -2,30 +2,29 @@ <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$(MSBuildProjectDirectory)\..\tools\DotNetOpenAuth.automated.props"/> - <Target Name="Layout" DependsOnTargets="BuildUnifiedProduct;ResignDelaySignedAssemblies"> + <Target Name="Layout"> <PropertyGroup> <ToolsDirectoryNoSlash>$(DropsRoot)$(ProductName)-Tools-$(BuildVersion)</ToolsDirectoryNoSlash> <ToolsDirectory>$(ToolsDirectoryNoSlash)\</ToolsDirectory> </PropertyGroup> <ItemGroup> - <ToolProjects Include="$(ProjectRoot)Samples\OpenIdOfflineProvider\OpenIdOfflineProvider.csproj" /> + <ToolProjects Include="$(ProjectRoot)Samples\OpenIdOfflineProvider\OpenIdOfflineProvider.csproj"> + <Targets>Sign</Targets> + </ToolProjects> </ItemGroup> - <MSBuild Projects="@(ToolProjects)" BuildInParallel="$(BuildInParallel)" /> + <MSBuild Projects="@(ToolProjects)" Targets="%(ToolProjects.Targets)" BuildInParallel="$(BuildInParallel)"> + <Output TaskParameter="TargetOutputs" ItemName="OfflineProvider"/> + </MSBuild> <ItemGroup> - <OfflineProvider Include=" - $(OutputPath)**\*.dll; - $(OutputPath)OpenIdOfflineProvider.exe" - Exclude=" - $(OutputPath)$(ProductName).*; - $(ILMergeOutputAssembly); - "/> + <!-- Remove the un-unified assembly. --> + <OfflineProvider Remove="$(OutputPath)$(SignedSubPath)$(ProductName).dll" /> + <!-- add the PDBs --> + <OfflineProvider Include="@(OfflineProvider->'%(SymbolPath)')" /> <OfflineProviderTargets Include=" - @(OfflineProvider->'$(ToolsDirectory)%(RecursiveDir)%(FileName)%(Extension)')"/> - <OfflineProvider Include="$(ILMergeOutputAssembly)" /> - <OfflineProviderTargets Include="$(ToolsDirectory)$(ProductName).dll" /> + @(OfflineProvider->'$(ToolsDirectory)%(CultureDir)%(FileName)%(Extension)')"/> <AllToolSources Include="@(OfflineProvider)" /> <AllToolTargets Include="@(OfflineProviderTargets)" /> diff --git a/src/DotNetOpenAuth.BuildTasks/AddProjectItems.cs b/src/DotNetOpenAuth.BuildTasks/AddProjectItems.cs index 30fa284..0b84398 100644 --- a/src/DotNetOpenAuth.BuildTasks/AddProjectItems.cs +++ b/src/DotNetOpenAuth.BuildTasks/AddProjectItems.cs @@ -6,13 +6,13 @@ namespace DotNetOpenAuth.BuildTasks { using System; + using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Build.BuildEngine; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; - using System.Collections; public class AddProjectItems : Task { /// <summary> @@ -49,7 +49,10 @@ namespace DotNetOpenAuth.BuildTasks { BuildItem newItem = project.AddNewItem(itemType, projectItem.ItemSpec, false); var customMetadata = projectItem.CloneCustomMetadata(); foreach (DictionaryEntry entry in customMetadata) { - newItem.SetMetadata((string)entry.Key, (string)entry.Value); + string value = (string)entry.Value; + if (value.Length > 0) { + newItem.SetMetadata((string)entry.Key, value); + } } } diff --git a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj index f107e81..365bec5 100644 --- a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj +++ b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj @@ -118,6 +118,7 @@ <Compile Include="JsPack.cs" /> <Compile Include="NativeMethods.cs" /> <Compile Include="ParseMaster.cs" /> + <Compile Include="PathSegment.cs" /> <Compile Include="Publicize.cs" /> <Compile Include="Purge.cs" /> <Compile Include="ReSignDelaySignedAssemblies.cs" /> diff --git a/src/DotNetOpenAuth.BuildTasks/MergeProjectWithVSTemplate.cs b/src/DotNetOpenAuth.BuildTasks/MergeProjectWithVSTemplate.cs index 601ff6f..d162cd6 100644 --- a/src/DotNetOpenAuth.BuildTasks/MergeProjectWithVSTemplate.cs +++ b/src/DotNetOpenAuth.BuildTasks/MergeProjectWithVSTemplate.cs @@ -7,6 +7,7 @@ namespace DotNetOpenAuth.BuildTasks { using System; using System.Collections.Generic; + using System.Collections.ObjectModel; using System.Diagnostics.Contracts; using System.Globalization; using System.IO; @@ -42,6 +43,8 @@ namespace DotNetOpenAuth.BuildTasks { [Required] public ITaskItem[] DestinationTemplates { get; set; } + public ITaskItem[] SourcePathExceptions { get; set; } + /// <summary> /// Gets or sets the maximum length a project item's relative path should /// be limited to, artificially renaming them as necessary. @@ -87,81 +90,50 @@ namespace DotNetOpenAuth.BuildTasks { // Figure out where every project item is in source, and where it will go in the destination, // taking into account a given maximum path length that may require that we shorten the path. - var sourceToDestinationProjectItemMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - //var oversizedItemPaths = projectItems.Where(item => item.Include.Length > this.MaximumRelativePathLength); - foreach (var item in projectItems) { - var source = item.Include; - var dest = item.Include; - - // if (this.MaximumRelativePathLength > 0) { - // if (item.Include.Length > this.MaximumRelativePathLength) { - // string leafName = Path.GetFileName(item.Include); - // int targetLeafLength = leafName.Length - (item.Include.Length - this.MaximumRelativePathLength); - // string shortenedFileName = CreateUniqueShortFileName(leafName, targetLeafLength); - // string shortenedRelativePath = Path.Combine(Path.GetDirectoryName(item.Include), shortenedFileName); - // if (shortenedRelativePath.Length <= this.MaximumRelativePathLength) { - // this.Log.LogMessage( - // "Renaming long project item '{0}' to '{1}' within project template to avoid MAX_PATH issues. The instantiated project will remain unchanged.", - // item.Include, - // shortenedRelativePath); - // projectItem.SetAttributeValue("TargetFileName", Path.GetFileName(item.Include)); - // projectItem.Value = shortenedFileName; - // string originalFullPath = Path.Combine(projectDirectory, item.Include); - // string shortenedFullPath = Path.Combine(projectDirectory, shortenedRelativePath); - // if (File.Exists(shortenedFullPath)) { - // File.Delete(shortenedFullPath); // File.Move can't overwrite files - // } - // File.Move(originalFullPath, shortenedFullPath); - - // // Document the change so the build system can account for it. - // TaskItem shortChange = new TaskItem(originalFullPath); - // shortChange.SetMetadata("ShortPath", shortenedFullPath); - // shortenedItems.Add(shortChange); - // } else { - // this.Log.LogError( - // "Project item '{0}' exceeds maximum allowable length {1} by {2} characters and it cannot be sufficiently shortened. Estimated full path is: '{3}'.", - // item.Include, - // this.MaximumRelativePathLength, - // item.Include.Length - this.MaximumRelativePathLength, - // item.Include); - // } - // } - //} - - sourceToDestinationProjectItemMap[source] = dest; - } + PathSegment root = new PathSegment(); + root.Add(projectItems.Select(item => item.Include)); + root.EnsureSelfAndChildrenNoLongerThan(this.MaximumRelativePathLength); // Collect the project items from the project that are appropriate // to include in the .vstemplate file. - var itemsByFolder = from item in projectItems - orderby item.Include - group item by Path.GetDirectoryName(item.Include); - - foreach (var folder in itemsByFolder) { + foreach (var folder in root.SelfAndDescendents.Where(path => !path.IsLeaf && path.LeafChildren.Any())) { XElement parentNode = projectElement; - parentNode = FindOrCreateParent(folder.Key, projectElement); - //parentNode.SetAttributeValue("TargetFolderName", folder.Key); + parentNode = FindOrCreateParent(folder.CurrentPath, projectElement); + if (folder.NameChanged) { + parentNode.SetAttributeValue("TargetFolderName", folder.OriginalName); + } - foreach (var item in folder) { - bool replaceParameters = this.ReplaceParametersExtensions.Contains(Path.GetExtension(item.Include)); + foreach (var item in folder.LeafChildren) { var itemName = XName.Get("ProjectItem", VSTemplateNamespace); - var projectItem = parentNode.Elements(itemName).FirstOrDefault(el => string.Equals(el.Value, Path.GetFileName(item.Include), StringComparison.OrdinalIgnoreCase)); + // The project item MAY be hard-coded in the .vstemplate file, under the original name. + var projectItem = parentNode.Elements(itemName).FirstOrDefault(el => string.Equals(el.Value, Path.GetFileName(item.OriginalName), StringComparison.OrdinalIgnoreCase)); if (projectItem == null) { - projectItem = new XElement(itemName, Path.GetFileName(item.Include)); + projectItem = new XElement(itemName, item.CurrentName); parentNode.Add(projectItem); } - if (replaceParameters) { + if (item.NameChanged) { + projectItem.Value = item.CurrentName; // set Value in case it was a hard-coded item in the .vstemplate file. + projectItem.SetAttributeValue("TargetFileName", item.OriginalName); + } + if (this.ReplaceParametersExtensions.Contains(Path.GetExtension(item.OriginalPath))) { projectItem.SetAttributeValue("ReplaceParameters", "true"); } } } template.Save(this.DestinationTemplates[iTemplate].ItemSpec); - foreach (var pair in sourceToDestinationProjectItemMap) { - TaskItem item = new TaskItem(Path.Combine(Path.GetDirectoryName(this.SourceTemplates[iTemplate].ItemSpec), pair.Key)); - item.SetMetadata("SourceFullPath", Path.GetFullPath(Path.Combine(Path.GetDirectoryName(this.SourceTemplates[iTemplate].ItemSpec), pair.Key))); - item.SetMetadata("DestinationFullPath", Path.GetFullPath(Path.Combine(Path.GetDirectoryName(this.DestinationTemplates[iTemplate].ItemSpec), pair.Value))); + foreach (var pair in root.LeafDescendents) { + TaskItem item = new TaskItem(Path.Combine(Path.GetDirectoryName(this.SourceTemplates[iTemplate].ItemSpec), pair.OriginalPath)); + string apparentSource = Path.Combine(Path.GetDirectoryName(this.SourceTemplates[iTemplate].ItemSpec), pair.OriginalPath); + var sourcePathException = this.SourcePathExceptions.FirstOrDefault(ex => string.Equals(ex.ItemSpec, apparentSource)); + if (sourcePathException != null) { + item.SetMetadata("SourceFullPath", sourcePathException.GetMetadata("ActualSource")); + } else { + item.SetMetadata("SourceFullPath", Path.GetFullPath(apparentSource)); + } + item.SetMetadata("DestinationFullPath", Path.GetFullPath(Path.Combine(Path.GetDirectoryName(this.DestinationTemplates[iTemplate].ItemSpec), pair.CurrentPath))); item.SetMetadata("RecursiveDir", Path.GetDirectoryName(this.SourceTemplates[iTemplate].ItemSpec)); + item.SetMetadata("Transform", this.ReplaceParametersExtensions.Contains(Path.GetExtension(pair.OriginalName)) ? "true" : "false"); projectItemsToCopy.Add(item); } } @@ -171,27 +143,6 @@ namespace DotNetOpenAuth.BuildTasks { return !Log.HasLoggedErrors; } - private static string CreateUniqueShortFileName(string fileName, int targetLength) { - Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(fileName)); - Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>())); - - // The filename may already full within the target length. - if (fileName.Length <= targetLength) { - return fileName; - } - - string hashSuffix = Utilities.SuppressCharacters(Math.Abs(fileName.GetHashCode() % 0xfff).ToString("x"), Path.GetInvalidFileNameChars(), '_'); - string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName); - string extension = Path.GetExtension(fileName); - string hashSuffixWithExtension = hashSuffix + extension; - - // If the target length is itself shorter than the hash code, then we won't meet our goal, - // but at least put the hash in there so it's unique, and we'll return a string that's too long. - string shortenedFileName = fileName.Substring(0, Math.Max(0, targetLength - hashSuffixWithExtension.Length)) + hashSuffixWithExtension; - - return shortenedFileName; - } - private static XElement FindOrCreateParent(string directoryName, XElement projectElement) { Contract.Requires<ArgumentNullException>(projectElement != null); diff --git a/src/DotNetOpenAuth.BuildTasks/PathSegment.cs b/src/DotNetOpenAuth.BuildTasks/PathSegment.cs new file mode 100644 index 0000000..56655ff --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/PathSegment.cs @@ -0,0 +1,321 @@ +//----------------------------------------------------------------------- +// <copyright file="PathSegment.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.BuildTasks { + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Diagnostics; + using System.Diagnostics.Contracts; + using System.IO; + using System.Linq; + using System.Text; + + internal class PathSegment { + private const float ParentChildResizeThreshold = 0.30f; + private readonly PathSegment parent; + private readonly string originalName; + private string currentName; + private bool minimized; + private static readonly string[] ReservedFileNames = "CON PRN AUX CLOCK$ NUL COM0 COM1 COM2 COM3 COM4 COM5 COM6 COM7 COM8 COM9 LPT0 LPT1 LPT2 LPT3 LPT4 LPT5 LPT6 LPT7 LPT8 LPT9".Split(' '); + + internal PathSegment() { + this.currentName = string.Empty; + this.originalName = string.Empty; + this.minimized = true; + this.Children = new Collection<PathSegment>(); + } + + private PathSegment(string originalName, PathSegment parent) + : this() { + Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(originalName)); + Contract.Requires<ArgumentNullException>(parent != null); + this.currentName = this.originalName = originalName; + this.parent = parent; + this.minimized = false; + } + + internal string OriginalPath { + get { + if (this.parent != null) { + return Path.Combine(this.parent.OriginalPath, this.originalName); + } else { + return this.originalName; + } + } + } + + internal string CurrentPath { + get { + if (this.parent != null) { + return Path.Combine(this.parent.CurrentPath, this.currentName); + } else { + return this.currentName; + } + } + } + + internal string CurrentName { + get { return this.currentName; } + } + + internal string OriginalName { + get { return this.originalName; } + } + + private int SegmentCount { + get { + int parents = this.parent != null ? this.parent.SegmentCount : 0; + return parents + 1; + } + } + + internal int FullLength { + get { + if (this.parent != null) { + int parentLength = this.parent.FullLength; + if (parentLength > 0) { + parentLength++; // allow for an in between slash + } + return parentLength + this.currentName.Length; + } else { + return this.currentName.Length; + } + } + } + + internal bool NameChanged { + get { return !string.Equals(this.currentName, this.originalName, StringComparison.OrdinalIgnoreCase); } + } + + internal bool IsLeaf { + get { return this.Children.Count == 0; } + } + + internal IEnumerable<PathSegment> Descendents { + get { + IEnumerable<PathSegment> result = this.Children; + foreach (PathSegment child in this.Children) { + result = result.Concat(child.Descendents); + } + + return result; + } + } + + internal IEnumerable<PathSegment> Ancestors { + get { + PathSegment parent = this.parent; + while (parent != null) { + yield return parent; + parent = parent.parent; + } + } + } + + internal IEnumerable<PathSegment> SelfAndDescendents { + get { + yield return this; + foreach (var child in this.Descendents) { + yield return child; + } + } + } + + internal IEnumerable<PathSegment> SelfAndAncestors { + get { + yield return this; + foreach (var parent in this.Ancestors) { + yield return parent; + } + } + } + + internal IEnumerable<PathSegment> LeafChildren { + get { return this.Children.Where(child => child.IsLeaf); } + } + + internal IEnumerable<PathSegment> LeafDescendents { + get { return this.Descendents.Where(child => child.IsLeaf); } + } + + internal IEnumerable<PathSegment> Siblings { + get { return this.parent != null ? this.parent.Children : Enumerable.Empty<PathSegment>(); } + } + + internal Collection<PathSegment> Children { get; private set; } + + public override string ToString() { + string path; + if (this.NameChanged) { + path = "{" + this.originalName + " => " + this.currentName + "}"; + } else { + path = this.currentName; + } + + if (path.Length > 0 && !this.IsLeaf) { + path += "\\"; + } + + if (this.parent != null) { + path = parent.ToString() + path; + } + + return path; + } + + internal PathSegment Add(string originalPath) { + Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(originalPath)); + Contract.Ensures(Contract.Result<PathSegment>() != null); + string[] segments = originalPath.Split(Path.DirectorySeparatorChar); + return this.Add(segments, 0); + } + + internal void Add(IEnumerable<string> originalPaths) { + foreach (string path in originalPaths) { + this.Add(path); + } + } + + internal int EnsureSelfAndChildrenNoLongerThan(int maxLength) { + Contract.Requires<ArgumentOutOfRangeException>(maxLength > 0, "A path can only have a positive length."); + Contract.Requires<ArgumentOutOfRangeException>(this.parent == null || maxLength > this.parent.FullLength + 1, "A child path cannot possibly be made shorter than its parent."); + Contract.Ensures(Contract.Result<int>() <= maxLength); + const int uniqueBase = 16; + + // Find the items that are too long, and always work on the longest one + var longPaths = this.SelfAndDescendents.Where(path => path.FullLength > maxLength).OrderByDescending(path => path.FullLength); + PathSegment longPath; + while ((longPath = longPaths.FirstOrDefault()) != null) { + // Keep working on this one until it's short enough. + do { + int tooLongBy = longPath.FullLength - maxLength; + var longSegments = longPath.SelfAndAncestors.Where(segment => !segment.minimized).OrderByDescending(segment => segment.CurrentName.Length); + PathSegment longestSegment = longSegments.FirstOrDefault(); + if (longestSegment == null) { + throw new InvalidOperationException("Unable to shrink path length sufficiently."); + } + PathSegment secondLongestSegment = longSegments.Skip(1).FirstOrDefault(); + int shortenByUpTo; + if (secondLongestSegment != null) { + shortenByUpTo = Math.Min(tooLongBy, Math.Max(1, longestSegment.CurrentName.Length - secondLongestSegment.CurrentName.Length)); + } else { + shortenByUpTo = tooLongBy; + } + int minimumGuaranteedUniqueLength = Math.Max(1, RoundUp(Math.Log(longestSegment.Siblings.Count(), uniqueBase))); + int allowableSegmentLength = Math.Max(minimumGuaranteedUniqueLength, longestSegment.CurrentName.Length - shortenByUpTo); + if (allowableSegmentLength >= longestSegment.CurrentName.Length) { + // We can't make this segment any shorter. + longestSegment.minimized = true; + } + longestSegment.currentName = longestSegment.CreateUniqueShortFileName(longestSegment.CurrentName, allowableSegmentLength); + } while (longPath.FullLength > maxLength); + } + + // Return the total length of self or longest child. + return this.SelfAndDescendents.Max(c => c.FullLength); + } + + internal PathSegment FindByOriginalPath(string originalPath) { + Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(originalPath)); + string[] segments = originalPath.Split(Path.DirectorySeparatorChar); + return this.FindByOriginalPath(segments, 0); + } + + private string GetUniqueShortName(string preferredPrefix, string preferredSuffix, int allowableLength) { + Contract.Requires<ArgumentNullException>(preferredPrefix != null); + Contract.Requires<ArgumentNullException>(preferredSuffix != null); + Contract.Requires<ArgumentException>(allowableLength > 0); + Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>())); + Contract.Ensures(Contract.Result<string>().Length <= allowableLength); + string candidateName = string.Empty; + int i; + for (i = -1; candidateName.Length == 0 || ReservedFileNames.Contains(candidateName, StringComparer.OrdinalIgnoreCase) || this.Siblings.Any(child => string.Equals(child.CurrentName, candidateName, StringComparison.OrdinalIgnoreCase)); i++) { + string unique = i < 0 ? string.Empty : i.ToString("x"); + if (allowableLength < unique.Length) { + throw new InvalidOperationException("Unable to shorten path sufficiently to fit constraints."); + } + + candidateName = unique; + + // Suffix gets higher priority than the prefix, but only if the entire suffix can be appended. + if (candidateName.Length + preferredSuffix.Length <= allowableLength) { + candidateName += preferredSuffix; + } + + // Now prepend as much of the prefix as fits. + candidateName = preferredPrefix.Substring(0, Math.Min(allowableLength - candidateName.Length, preferredPrefix.Length)) + candidateName; + } + + return candidateName; + } + + private static int RoundUp(double value) { + int roundedValue = (int)value; + if (roundedValue < value) { + roundedValue++; + } + + return roundedValue; + } + + private string CreateUniqueShortFileName(string fileName, int targetLength) { + Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(fileName)); + Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>())); + Contract.Ensures(Contract.Result<string>().Length <= targetLength); + + // The filename may already full within the target length. + if (fileName.Length <= targetLength) { + return fileName; + } + + string preferredPrefix = Path.GetFileNameWithoutExtension(fileName); + string preferredSuffix = Path.GetExtension(fileName); + + string shortenedFileName = GetUniqueShortName(preferredPrefix, preferredSuffix, targetLength); + return shortenedFileName; + } + + private void ShortenThis(int targetLength) { + this.currentName = CreateUniqueShortFileName(this.originalName, targetLength); + } + + private PathSegment Add(string[] segments, int segmentIndex) { + Contract.Requires<ArgumentNullException>(segments != null); + Contract.Requires<ArgumentOutOfRangeException>(segmentIndex < segments.Length); + Contract.Ensures(Contract.Result<PathSegment>() != null); + var match = this.Children.SingleOrDefault(child => String.Equals(child.originalName, segments[segmentIndex])); + if (match == null) { + match = new PathSegment(segments[segmentIndex], this); + this.Children.Add(match); + if (segments.Length == segmentIndex + 1) { + return match; + } + } + + return match.Add(segments, segmentIndex + 1); + } + + private PathSegment FindByOriginalPath(string[] segments, int segmentIndex) { + Contract.Requires<ArgumentNullException>(segments != null); + Contract.Requires<ArgumentOutOfRangeException>(segmentIndex < segments.Length); + if (string.Equals(this.originalName, segments[segmentIndex], StringComparison.OrdinalIgnoreCase)) { + if (segmentIndex == segments.Length - 1) { + return this; + } + + foreach (var child in this.Children) { + var match = child.FindByOriginalPath(segments, segmentIndex + 1); + if (match != null) { + return match; + } + } + } + + return null; + } + } +} diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj index 70b2710..80487fc 100644 --- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj +++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj @@ -735,6 +735,10 @@ http://opensource.org/licenses/ms-pl.html $(OutputPath)$(ProductName).Contracts.dll; " /> </ItemGroup> + <PropertyGroup> + <!-- Don't sign the non-unified version of the assembly. --> + <SuppressTargetPathDelaySignedAssembly>true</SuppressTargetPathDelaySignedAssembly> + </PropertyGroup> <Target Name="BuildUnifiedProduct" DependsOnTargets="Build" diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs index f89ec0a..c13c61c 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs @@ -643,11 +643,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { set { base.UsePersistentCookie = value; - // use conditional here to prevent infinite recursion - // with CheckedChanged event. - bool rememberMe = value != LogOnPersistence.Session; - if (this.rememberMeCheckBox.Checked != rememberMe) { - this.rememberMeCheckBox.Checked = rememberMe; + if (this.rememberMeCheckBox != null) { + // use conditional here to prevent infinite recursion + // with CheckedChanged event. + bool rememberMe = value != LogOnPersistence.Session; + if (this.rememberMeCheckBox.Checked != rememberMe) { + this.rememberMeCheckBox.Checked = rememberMe; + } } } } @@ -782,7 +784,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { cell = new TableCell(); this.rememberMeCheckBox = new CheckBox(); this.rememberMeCheckBox.Text = RememberMeTextDefault; - this.rememberMeCheckBox.Checked = RememberMeDefault; + this.rememberMeCheckBox.Checked = this.UsePersistentCookie != LogOnPersistence.Session; this.rememberMeCheckBox.Visible = RememberMeVisibleDefault; this.rememberMeCheckBox.CheckedChanged += this.RememberMeCheckBox_CheckedChanged; cell.Controls.Add(this.rememberMeCheckBox); diff --git a/tools/DotNetOpenAuth.props b/tools/DotNetOpenAuth.props index 91a5e5e..6815fca 100644 --- a/tools/DotNetOpenAuth.props +++ b/tools/DotNetOpenAuth.props @@ -21,6 +21,7 @@ <KeyPairContainer Condition="'$(KeyPairContainer)' == ''">DotNetOpenAuth</KeyPairContainer> <PublicKeyToken>2780CCD10D57B246</PublicKeyToken> <DelaySign>true</DelaySign> + <SignedSubPath>signed\</SignedSubPath> <ILMergeOutputAssemblyDirectory>$(OutputPath)unified\</ILMergeOutputAssemblyDirectory> <ILMergeOutputAssembly>$(ILMergeOutputAssemblyDirectory)$(ProductName).dll</ILMergeOutputAssembly> diff --git a/tools/DotNetOpenAuth.targets b/tools/DotNetOpenAuth.targets index 34aa424..cab4413 100644 --- a/tools/DotNetOpenAuth.targets +++ b/tools/DotNetOpenAuth.targets @@ -4,13 +4,23 @@ <Import Project="JavascriptPacker.targets" /> <UsingTask AssemblyFile="$(ProjectRoot)lib\MSBuild.Community.Tasks.dll" TaskName="ILMerge"/> + <!-- Prevent our own item types from appearing in Solution Explorer. --> + <ItemDefinitionGroup> + <SignDependsOn> + <Visible>false</Visible> + </SignDependsOn> + <DelaySignedAssemblies> + <Visible>false</Visible> + </DelaySignedAssemblies> + </ItemDefinitionGroup> + <PropertyGroup> <DefineConstants Condition=" '$(SignAssembly)' == 'true' ">$(DefineConstants);StrongNameSigned</DefineConstants> <DefineConstants Condition=" '$(ClrVersion)' == '4' ">$(DefineConstants);CLR4</DefineConstants> </PropertyGroup> <ItemGroup> - <DelaySignedAssemblies Include="$(TargetPath)" /> + <DelaySignedAssemblies Include="$(TargetPath)" Condition=" '$(SuppressTargetPathDelaySignedAssembly)' != 'true' "/> </ItemGroup> <ItemGroup Condition=" '$(ClrVersion)' != '4' "> @@ -54,23 +64,48 @@ </Publicize> </Target> - <Target Name="Sign" DependsOnTargets="@(SignDependsOn)" Condition=" '@(DelaySignedAssemblies)' != '' "> + <Target Name="Sign" DependsOnTargets="@(SignDependsOn)" Outputs="@(SignedDependencies);@(SignedAssemblyTargets)" Condition=" '@(DelaySignedAssemblies)' != '' "> + <!-- Make sure that all dependencies are also signed. --> + <MSBuild Projects="@(ProjectReference)" Targets="Sign" BuildInParallel="$(BuildInParallel)"> + <Output TaskParameter="TargetOutputs" ItemName="SignedDependencies"/> + </MSBuild> + <!-- Add the resource assemblies. --> + <ItemGroup> + <!-- Make sure that we consider the TargetPath's satellites even if TargetPath itself was suppressed. --> + <DelaySignedAssembliesForSatellites Include="@(DelaySignedAssemblies)" /> + <DelaySignedAssembliesForSatellites Include="$(TargetPath)" Condition=" '$(SuppressTargetPathDelaySignedAssembly)' == 'true' "/> + </ItemGroup> <PropertyGroup> - <DelaySignedSatelliteAssembliesPattern>@(DelaySignedAssemblies->'%(RootDir)%(Directory)*\%(FileName).resources.*')</DelaySignedSatelliteAssembliesPattern> + <DelaySignedSatelliteAssembliesPattern>@(DelaySignedAssembliesForSatellites->'%(RootDir)%(Directory)*\%(FileName).resources.*')</DelaySignedSatelliteAssembliesPattern> </PropertyGroup> <ItemGroup> <DelaySignedSatelliteAssemblies Include="$(DelaySignedSatelliteAssembliesPattern)" /> + <DelaySignedSatelliteAssemblies> + <CultureDir>$([System.IO.Path]::GetFileName($([System.IO.Path]::GetDirectoryName('%(Directory)'))))\</CultureDir> + </DelaySignedSatelliteAssemblies> + </ItemGroup> + + <!-- Don't sign assemblies in place. Lots of reasons for this, not the least of which is that + subsequent builds of web site projects will cause the satellite assemblies to be regenerated (bizarre) + and erase the signature. --> + <ItemGroup> + <AssembliesToSign Include="@(DelaySignedAssemblies);@(DelaySignedSatelliteAssemblies)" /> + <SignedAssemblyTargets Include="@(AssembliesToSign->'%(RootDir)%(Directory)$(SignedSubPath)%(FileName)%(Extension)')"> + <UnsignedAssemblyPath>%(AssembliesToSign.Identity)</UnsignedAssemblyPath> + <SymbolPath Condition="Exists('%(RootDir)%(Directory)%(FileName).pdb')">%(RootDir)%(Directory)%(FileName).pdb</SymbolPath> + </SignedAssemblyTargets> </ItemGroup> <Message Text="Signing delay-signed assemblies using key pair container $(KeyPairContainer)." /> + <Copy SourceFiles="@(AssembliesToSign)" DestinationFiles="@(SignedAssemblyTargets)" /> <ReSignDelaySignedAssemblies KeyContainer="$(KeyPairContainer)" - Assemblies="@(DelaySignedAssemblies);@(DelaySignedSatelliteAssemblies)" + Assemblies="@(SignedAssemblyTargets)" Condition="Exists(%(Identity))" /> </Target> - <Target Name="ResignDelaySignedAssemblies"> + <Target Name="ResignDelaySignedAssemblies" Outputs="@(ResignedAssembliesOutputs)"> <ItemGroup> <DelaySignedProjects Include=" $(ProjectRoot)src\dotnetopenauth\dotnetopenauth.csproj; @@ -78,6 +113,8 @@ $(ProjectRoot)samples\openidofflineprovider\openidofflineprovider.csproj; " /> </ItemGroup> - <MSBuild Projects="@(DelaySignedProjects)" Targets="Sign" BuildInParallel="$(BuildInParallel)" /> + <MSBuild Projects="@(DelaySignedProjects)" Targets="Sign" BuildInParallel="$(BuildInParallel)"> + <Output TaskParameter="TargetOutputs" ItemName="ResignedAssembliesOutputs"/> + </MSBuild> </Target> </Project> diff --git a/tools/drop.proj b/tools/drop.proj index 143d3b5..02fdd20 100644 --- a/tools/drop.proj +++ b/tools/drop.proj @@ -41,13 +41,16 @@ " Exclude="$(ProjectRoot)Doc\README.*.html;" /> <DropBinSourceFiles Include=" - $(ILMergeOutputAssemblyDirectory)$(ProductName).???; - $(OutputPath)**\$(ProductName).resources.dll; + $(ILMergeOutputAssemblyDirectory)$(SignedSubPath)$(ProductName).???; $(OutputPath)$(ProductName).xml; - $(OutputPath)$(ProductName).Contracts.???; + $(OutputPath)$(SignedSubPath)$(ProductName).Contracts.???; $(ProjectRoot)Doc\README.Bin.html; $(ProjectRoot)src\$(ProductName)\Configuration\$(ProductName).xsd; " /> + <DropSatelliteSourceFiles Include="$(OutputPath)**\$(SignedSubPath)$(ProductName).resources.dll" /> + <DropSatelliteSourceFiles> + <CultureDir>$([System.IO.Path]::GetDirectoryName('$([System.IO.Path]::GetDirectoryName('%(RecursiveDir)'))'))\</CultureDir> + </DropSatelliteSourceFiles> <DropLibSourceFiles Include=" $(ProjectRoot)Lib\log4net.*; " /> @@ -66,6 +69,7 @@ $(ProjectRoot)**\Settings.StyleCop; $(ProjectRoot)**\StyleCop.Cache; $(ProjectRoot)Samples\**\DotNetOpenAuth.???; + $(ProjectRoot)Samples\**\DotNetOpenAuth.resources.???; $(ProjectRoot)Samples\**\log4net.???; $(ProjectRoot)Samples\**\PresentationCore.dll; $(ProjectRoot)Samples\**\System.Printing.dll; @@ -78,6 +82,7 @@ <DropFiles Include="@(DropSourceFiles->'$(DropDirectory)%(RecursiveDir)%(FileName)%(Extension)')"/> <DropBinFiles Include="@(DropBinSourceFiles->'$(DropBinDirectory)%(RecursiveDir)%(FileName)%(Extension)')"/> + <DropSatelliteFiles Include="@(DropSatelliteSourceFiles->'$(DropBinDirectory)%(CultureDir)%(FileName)%(Extension)')" /> <DropLibFiles Include="@(DropLibSourceFiles->'$(DropLibDirectory)%(RecursiveDir)%(FileName)%(Extension)')"/> <DropProjectTemplatesFiles Include="@(DropProjectTemplatesSourceFiles->'$(DropProjectTemplatesDirectory)%(FileName)%(Extension)')" /> <DropVsixFiles Include="@(DropVsixSourceFiles->'$(DropProjectTemplatesDirectory)%(FileName)%(Extension)')" /> @@ -89,6 +94,7 @@ <AllDropSources Include=" @(DropSourceFiles); @(DropBinSourceFiles); + @(DropSatelliteSourceFiles); @(DropLibSourceFiles); @(DropProjectTemplatesSourceFiles); @(DropVsixSourceFiles); @@ -101,6 +107,7 @@ <AllDropTargets Include=" @(DropFiles); @(DropBinFiles); + @(DropSatelliteFiles); @(DropLibFiles); @(DropProjectTemplatesFiles); @(DropVsixFiles); diff --git a/vsi/vsi.proj b/vsi/vsi.proj index 04ac615..be0c73b 100644 --- a/vsi/vsi.proj +++ b/vsi/vsi.proj @@ -27,15 +27,14 @@ </VsiTransformSource> <VsiTransformLayout Include="@(VsiTransformSource->'$(ProjectTemplatesVsiDirectory)%(RecursiveDir)%(FileName)%(Extension)')" /> - <ProjectTemplateVsiContents Include=" - $(ProjectTemplatesVsiDirectory)*.zip; - @(VsiTransformLayout); - " /> - <ProjectTemplate2008ZipSource> <HardLink>true</HardLink> </ProjectTemplate2008ZipSource> <ProjectTemplate2008ZipTargets Include="@(ProjectTemplate2008ZipSource->'$(ProjectTemplatesVsiDirectory)%(FileName)%(Extension)')" /> + <ProjectTemplateVsiContents Include=" + @(VsiTransformLayout); + @(ProjectTemplate2008ZipTargets); + " /> </ItemGroup> <CopyWithTokenSubstitution SourceFiles="@(VsiTransformSource)" DestinationFiles="@(VsiTransformLayout)" /> diff --git a/vsix/vsix.proj b/vsix/vsix.proj index ffa1995..dcd0e85 100644 --- a/vsix/vsix.proj +++ b/vsix/vsix.proj @@ -68,7 +68,8 @@ <VSGalleryVsixSources Include="@(VSGalleryVsixZipSources)"> <TopLevelTemplate>%(FileName)</TopLevelTemplate> <VSGalleryVsix>$(DropsRoot)$(ProductName) %(FileName)-$(BuildVersion).vsix</VSGalleryVsix> - <TargetPath>$(IntermediatePath)%(FileName).vsix\%(RecursiveDir)%(FileName)%(Extension)</TargetPath> + <!-- The A in the path below used to be %(FileName), but to fit inside MAX_PATH when VS expands, we shorten it. --> + <TargetPath>$(IntermediatePath)%(FileName).vsix\%(RecursiveDir)A%(Extension)</TargetPath> </VSGalleryVsixSources> <VSGalleryVsixSources Include="@(ProjectTemplateZipTargets->'$(ProjectRoot)projecttemplates\%(FileName).vsixmanifest')"> |