summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2010-02-20 13:43:17 -0800
committerAndrew Arnott <andrewarnott@gmail.com>2010-02-20 13:43:17 -0800
commitf1718afbd134c9b4a5db2dfe3c3ec1f804312123 (patch)
treefc4e04018874e30bf93e1cbb4f0c4874fbcbc193
parent1cc3bef4af253d5e82a5561049b5bdf412013cb5 (diff)
parent79b38d534537eec6b3e49bd428e768f600a3d370 (diff)
downloadDotNetOpenAuth-f1718afbd134c9b4a5db2dfe3c3ec1f804312123.zip
DotNetOpenAuth-f1718afbd134c9b4a5db2dfe3c3ec1f804312123.tar.gz
DotNetOpenAuth-f1718afbd134c9b4a5db2dfe3c3ec1f804312123.tar.bz2
Merge branch 'v3.4'
-rw-r--r--lib/DotNetOpenAuth.BuildTasks.dllbin76800 -> 91648 bytes
-rw-r--r--lib/DotNetOpenAuth.BuildTasks.pdbbin163328 -> 196096 bytes
-rw-r--r--projecttemplates/projecttemplates.proj51
-rw-r--r--samples/tools.proj25
-rw-r--r--src/DotNetOpenAuth.BuildTasks/AddProjectItems.cs7
-rw-r--r--src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj1
-rw-r--r--src/DotNetOpenAuth.BuildTasks/MergeProjectWithVSTemplate.cs111
-rw-r--r--src/DotNetOpenAuth.BuildTasks/PathSegment.cs321
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj4
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs14
-rw-r--r--tools/DotNetOpenAuth.props1
-rw-r--r--tools/DotNetOpenAuth.targets49
-rw-r--r--tools/drop.proj13
-rw-r--r--vsi/vsi.proj9
-rw-r--r--vsix/vsix.proj3
15 files changed, 467 insertions, 142 deletions
diff --git a/lib/DotNetOpenAuth.BuildTasks.dll b/lib/DotNetOpenAuth.BuildTasks.dll
index d26f276..b3c6244 100644
--- a/lib/DotNetOpenAuth.BuildTasks.dll
+++ b/lib/DotNetOpenAuth.BuildTasks.dll
Binary files differ
diff --git a/lib/DotNetOpenAuth.BuildTasks.pdb b/lib/DotNetOpenAuth.BuildTasks.pdb
index 0169338..676ff46 100644
--- a/lib/DotNetOpenAuth.BuildTasks.pdb
+++ b/lib/DotNetOpenAuth.BuildTasks.pdb
Binary files differ
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')">