@joebigelow / wix-1 / commits / f676ceea

Support naked files.

Implements https://github.com/wixtoolset/issues/issues/7696. `File` elements can appear where `Component` elements do in WiX v4. The compiler generates an appropriate per-file component. Naked files under `Directory`, `DirectoryRef`, `Fragment`, `StandardDirectory`, or `Package` elements are included in a package via the [default-feature feature](https://github.com/wixtoolset/issues/issues/7581). Naked files appearing under `ComponentGroup`, `Feature`, `FeatureRef`, and `FeatureGroup` generate the component and the reference to the parent element. Components and naked Files default to being installed to INSTALLFOLDER (including a default INSTALLFOLDER if one isn't otherwise authored).

Bob Arnson committed Sep 10, 2023 at 22:34 UTC f676ceeaedbba4125d3e0c691959afcba182d008
27 files changed +751 -120
src/api/wix/WixToolset.Data/ErrorMessages.cs
+5
@@ -2256,6 +2256,11 @@ namespace WixToolset.Data
2256 return Message(sourceLineNumbers, Ids.IllegalInnerText, "The {0} element contains inner text which is obsolete. Use the {1} attribute instead.", elementName, attributeName);
2257 }
2258
2259 + public static Message IllegalAttributeWhenNested(SourceLineNumber sourceLineNumbers, string attributeName)
2260 + {
2261 + return Message(sourceLineNumbers, Ids.IllegalAttributeWhenNested, "The File element contains an attribute '{0}' that cannot be used in a File element that is a child of a Component element.", attributeName);
2262 + }
2263 +
2264 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args)
2265 {
2266 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args);
src/wix/WixToolset.Core/Compiler.cs
+276 -78
@@ -2252,9 +2252,11 @@ namespace WixToolset.Core
2252
2253 if (String.IsNullOrEmpty(directoryId))
2254 {
2255 - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Directory"));
2255 + directoryId = "INSTALLFOLDER";
2256 + this.Core.CreateSimpleReference(sourceLineNumbers, SymbolDefinitions.Directory, directoryId);
2257 }
2257 - else if (!String.IsNullOrEmpty(subdirectory))
2258 +
2259 + if (!String.IsNullOrEmpty(subdirectory))
2260 {
2261 directoryId = this.Core.CreateDirectoryReferenceFromInlineSyntax(sourceLineNumbers, directoryId, subdirectory);
2262 }
@@ -2427,6 +2429,7 @@ namespace WixToolset.Core
2429 keyBit = ComponentKeyPathType.File;
2430 keyPossible = possibleKeyPath.Id;
2431 break;
2432 +
2433 case PossibleKeyPathType.Directory:
2434 keyBit = ComponentKeyPathType.Directory;
2435 keyPossible = String.Empty;
@@ -2581,8 +2584,8 @@ namespace WixToolset.Core
2584 /// Parses a component group element.
2585 /// </summary>
2586 /// <param name="node">Element to parse.</param>
2584 - /// <param name="parentType"></param>
2585 - /// <param name="parentId"></param>
2587 + /// <param name="parentType">Type of complex reference parent. Will be Unknown if there is no parent.</param>
2588 + /// <param name="parentId">Optional identifier for primary parent.</param>
2589 private void ParseComponentGroupElement(XElement node, ComplexReferenceParentType parentType, string parentId)
2590 {
2591 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
@@ -2649,6 +2652,9 @@ namespace WixToolset.Core
2652 case "Component":
2653 this.ParseComponentElement(child, ComplexReferenceParentType.ComponentGroup, id.Id, null, CompilerConstants.IntegerNotSet, directoryId, source);
2654 break;
2655 + case "File":
2656 + this.ParseNakedFileElement(child, ComplexReferenceParentType.ComponentGroup, id.Id, directoryId, source);
2657 + break;
2658 default:
2659 this.Core.UnexpectedElement(node, child);
2660 break;
@@ -3872,6 +3878,9 @@ namespace WixToolset.Core
3878 case "Directory":
3879 this.ParseDirectoryElement(child, id.Id, diskId, fileSource);
3880 break;
3881 + case "File":
3882 + this.ParseNakedFileElement(child, ComplexReferenceParentType.Unknown, null, id.Id, fileSource);
3883 + break;
3884 case "Merge":
3885 this.ParseMergeElement(child, id.Id, diskId);
3886 break;
@@ -3984,6 +3993,9 @@ namespace WixToolset.Core
3993 case "Directory":
3994 this.ParseDirectoryElement(child, id, diskId, fileSource);
3995 break;
3996 + case "File":
3997 + this.ParseNakedFileElement(child, ComplexReferenceParentType.Unknown, null, id, fileSource);
3998 + break;
3999 case "Merge":
4000 this.ParseMergeElement(child, id, diskId);
4001 break;
@@ -4421,6 +4433,9 @@ namespace WixToolset.Core
4433 case "FeatureRef":
4434 this.ParseFeatureRefElement(child, ComplexReferenceParentType.Feature, id.Id);
4435 break;
4436 + case "File":
4437 + this.ParseNakedFileElement(child, ComplexReferenceParentType.Feature, id.Id, null, null);
4438 + break;
4439 case "Level":
4440 this.ParseLevelElement(child, id.Id);
4441 break;
@@ -4561,6 +4576,9 @@ namespace WixToolset.Core
4576 case "FeatureRef":
4577 this.ParseFeatureRefElement(child, ComplexReferenceParentType.Feature, id);
4578 break;
4579 + case "File":
4580 + this.ParseNakedFileElement(child, ComplexReferenceParentType.Feature, id, null, null);
4581 + break;
4582 case "MergeRef":
4583 this.ParseMergeRefElement(child, ComplexReferenceParentType.Feature, id);
4584 break;
@@ -4646,6 +4664,9 @@ namespace WixToolset.Core
4664 case "FeatureRef":
4665 this.ParseFeatureRefElement(child, ComplexReferenceParentType.FeatureGroup, id.Id);
4666 break;
4667 + case "File":
4668 + this.ParseNakedFileElement(child, ComplexReferenceParentType.FeatureGroup, id.Id, null, null);
4669 + break;
4670 case "MergeRef":
4671 this.ParseMergeRefElement(child, ComplexReferenceParentType.FeatureGroup, id.Id);
4672 break;
@@ -5029,9 +5050,8 @@ namespace WixToolset.Core
5050 }
5051 }
5052
5032 -
5053 /// <summary>
5034 - /// Parses a file element.
5054 + /// Parses a File element's attributes.
5055 /// </summary>
5056 /// <param name="node">File element to parse.</param>
5057 /// <param name="componentId">Parent's component id.</param>
@@ -5039,10 +5059,12 @@ namespace WixToolset.Core
5059 /// <param name="diskId">Disk id inherited from parent component.</param>
5060 /// <param name="sourcePath">Default source path of parent directory.</param>
5061 /// <param name="possibleKeyPath">This will be set with the possible keyPath for the parent component.</param>
5042 - /// <param name="win64Component">true if the component is 64-bit.</param>
5043 - /// <param name="componentGuid"></param>
5062 + /// <param name="componentGuid">Component GUID (including `*`).</param>
5063 + /// <param name="isNakedFile">Whether the File element being parsed is outside a Component element.</param>
5064 + /// <param name="fileSymbol">Outgoing file symbol containing parsed attributes.</param>
5065 + /// <param name="assemblySymbol">Outgoing assembly symbol containing parsed attributes.</param>
5066 /// <returns>Yes if this element was marked as the parent component's key path, No if explicitly marked as not being a key path, or NotSet otherwise.</returns>
5045 - private YesNoType ParseFileElement(XElement node, string componentId, string directoryId, int diskId, string sourcePath, out string possibleKeyPath, bool win64Component, string componentGuid)
5067 + private YesNoType ParseFileElementAttributes(XElement node, string componentId, string directoryId, int diskId, string sourcePath, out string possibleKeyPath, string componentGuid, bool isNakedFile, out FileSymbol fileSymbol, out AssemblySymbol assemblySymbol)
5068 {
5069 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
5070 Identifier id = null;
@@ -5083,12 +5105,25 @@ namespace WixToolset.Core
5105 var source = sourcePath; // assume we'll use the parents as the source for this file
5106 var sourceSet = false;
5107
5108 + fileSymbol = null;
5109 + assemblySymbol = null;
5110 +
5111 foreach (var attrib in node.Attributes())
5112 {
5113 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
5114 {
5115 switch (attrib.Name.LocalName)
5116 {
5117 + case "Bitness":
5118 + case "Condition":
5119 + case "Directory":
5120 + case "Subdirectory":
5121 + // Naked files handle their attributes in ParseNakedFileElement.
5122 + if (!isNakedFile)
5123 + {
5124 + this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, attrib.Name.LocalName));
5125 + }
5126 + break;
5127 case "Id":
5128 id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
5129 break;
@@ -5329,70 +5364,6 @@ namespace WixToolset.Core
5364 }
5365 }
5366
5332 - foreach (var child in node.Elements())
5333 - {
5334 - if (CompilerCore.WixNamespace == child.Name.Namespace)
5335 - {
5336 - switch (child.Name.LocalName)
5337 - {
5338 - case "AppId":
5339 - this.ParseAppIdElement(child, componentId, YesNoType.NotSet, id.Id, null, null);
5340 - break;
5341 - case "AssemblyName":
5342 - this.ParseAssemblyName(child, componentId);
5343 - break;
5344 - case "Class":
5345 - this.ParseClassElement(child, componentId, YesNoType.NotSet, id.Id, null, null, null);
5346 - break;
5347 - case "CopyFile":
5348 - this.ParseCopyFileElement(child, componentId, id.Id);
5349 - break;
5350 - case "IgnoreRange":
5351 - this.ParseRangeElement(child, ref ignoreOffsets, ref ignoreLengths);
5352 - break;
5353 - case "ODBCDriver":
5354 - this.ParseODBCDriverOrTranslator(child, componentId, id.Id, SymbolDefinitionType.ODBCDriver);
5355 - break;
5356 - case "ODBCTranslator":
5357 - this.ParseODBCDriverOrTranslator(child, componentId, id.Id, SymbolDefinitionType.ODBCTranslator);
5358 - break;
5359 - case "Permission":
5360 - this.ParsePermissionElement(child, id.Id, "File");
5361 - break;
5362 - case "PermissionEx":
5363 - this.ParsePermissionExElement(child, id.Id, "File");
5364 - break;
5365 - case "ProtectRange":
5366 - this.ParseRangeElement(child, ref protectOffsets, ref protectLengths);
5367 - break;
5368 - case "Shortcut":
5369 - this.ParseShortcutElement(child, componentId, node.Name.LocalName, id.Id, keyPath);
5370 - break;
5371 - case "SymbolPath":
5372 - if (null != symbols)
5373 - {
5374 - symbols += ";" + this.ParseSymbolPathElement(child);
5375 - }
5376 - else
5377 - {
5378 - symbols = this.ParseSymbolPathElement(child);
5379 - }
5380 - break;
5381 - case "TypeLib":
5382 - this.ParseTypeLibElement(child, componentId, id.Id, win64Component);
5383 - break;
5384 - default:
5385 - this.Core.UnexpectedElement(node, child);
5386 - break;
5387 - }
5388 - }
5389 - else
5390 - {
5391 - var context = new Dictionary<string, string>() { { "FileId", id?.Id }, { "ComponentId", componentId }, { "DirectoryId", directoryId }, { "Win64", win64Component.ToString() } };
5392 - this.Core.ParseExtensionElement(node, child, context);
5393 - }
5394 - }
5395 -
5367 if (!this.Core.EncounteredError)
5368 {
5369 var patchAttributes = PatchAttributeType.None;
@@ -5427,7 +5398,7 @@ namespace WixToolset.Core
5398 attributes |= compressed.HasValue && compressed == true ? FileSymbolAttributes.Compressed : 0;
5399 attributes |= compressed.HasValue && compressed == false ? FileSymbolAttributes.Uncompressed : 0;
5400
5430 - this.Core.AddSymbol(new FileSymbol(sourceLineNumbers, id)
5401 + fileSymbol = new FileSymbol(sourceLineNumbers, id)
5402 {
5403 ComponentRef = componentId,
5404 Name = name,
@@ -5454,11 +5425,11 @@ namespace WixToolset.Core
5425 IgnoreLengths = ignoreLengths,
5426 RetainOffsets = protectOffsets,
5427 SymbolPaths = symbols,
5457 - });
5428 + };
5429
5430 if (AssemblyType.NotAnAssembly != assemblyType)
5431 {
5461 - this.Core.AddSymbol(new AssemblySymbol(sourceLineNumbers, id)
5432 + assemblySymbol = new AssemblySymbol(sourceLineNumbers, id)
5433 {
5434 ComponentRef = componentId,
5435 FeatureRef = Guid.Empty.ToString("B"),
@@ -5466,7 +5437,7 @@ namespace WixToolset.Core
5437 ApplicationFileRef = assemblyApplication,
5438 Type = assemblyType,
5439 ProcessorArchitecture = procArch,
5469 - });
5440 + };
5441 }
5442 }
5443
@@ -5485,6 +5456,227 @@ namespace WixToolset.Core
5456 return keyPath;
5457 }
5458
5459 + /// <param name="node">File element to parse.</param>
5460 + /// <param name="fileSymbol">The partially-parsed file symbol.</param>
5461 + /// <param name="keyPath">Whether the file is the keypath of its component.</param>
5462 + /// <param name="win64Component">true if the component is 64-bit.</param>
5463 + private void ParseFileElementChildren(XElement node, FileSymbol fileSymbol, YesNoType keyPath, bool win64Component)
5464 + {
5465 + var directoryId = fileSymbol.DirectoryRef;
5466 + var componentId = fileSymbol.ComponentRef;
5467 + var id = fileSymbol.Id;
5468 + var ignoreOffsets = fileSymbol.IgnoreOffsets;
5469 + var ignoreLengths = fileSymbol.IgnoreLengths;
5470 + var protectOffsets = fileSymbol.RetainOffsets;
5471 + var protectLengths = fileSymbol.RetainLengths;
5472 + var symbols = fileSymbol.SymbolPaths;
5473 +
5474 + foreach (var child in node.Elements())
5475 + {
5476 + if (CompilerCore.WixNamespace == child.Name.Namespace)
5477 + {
5478 + switch (child.Name.LocalName)
5479 + {
5480 + case "AppId":
5481 + this.ParseAppIdElement(child, componentId, YesNoType.NotSet, id.Id, null, null);
5482 + break;
5483 + case "AssemblyName":
5484 + this.ParseAssemblyName(child, componentId);
5485 + break;
5486 + case "Class":
5487 + this.ParseClassElement(child, componentId, YesNoType.NotSet, id.Id, null, null, null);
5488 + break;
5489 + case "CopyFile":
5490 + this.ParseCopyFileElement(child, componentId, id.Id);
5491 + break;
5492 + case "IgnoreRange":
5493 + this.ParseRangeElement(child, ref ignoreOffsets, ref ignoreLengths);
5494 + break;
5495 + case "ODBCDriver":
5496 + this.ParseODBCDriverOrTranslator(child, componentId, id.Id, SymbolDefinitionType.ODBCDriver);
5497 + break;
5498 + case "ODBCTranslator":
5499 + this.ParseODBCDriverOrTranslator(child, componentId, id.Id, SymbolDefinitionType.ODBCTranslator);
5500 + break;
5501 + case "Permission":
5502 + this.ParsePermissionElement(child, id.Id, "File");
5503 + break;
5504 + case "PermissionEx":
5505 + this.ParsePermissionExElement(child, id.Id, "File");
5506 + break;
5507 + case "ProtectRange":
5508 + this.ParseRangeElement(child, ref protectOffsets, ref protectLengths);
5509 + break;
5510 + case "Shortcut":
5511 + this.ParseShortcutElement(child, componentId, node.Name.LocalName, id.Id, keyPath);
5512 + break;
5513 + case "SymbolPath":
5514 + if (null != symbols)
5515 + {
5516 + symbols += ";" + this.ParseSymbolPathElement(child);
5517 + }
5518 + else
5519 + {
5520 + symbols = this.ParseSymbolPathElement(child);
5521 + }
5522 + break;
5523 + case "TypeLib":
5524 + this.ParseTypeLibElement(child, componentId, id.Id, win64Component);
5525 + break;
5526 + default:
5527 + this.Core.UnexpectedElement(node, child);
5528 + break;
5529 + }
5530 + }
5531 + else
5532 + {
5533 + var context = new Dictionary<string, string>() { { "FileId", id?.Id }, { "ComponentId", componentId }, { "DirectoryId", directoryId }, { "Win64", win64Component.ToString() } };
5534 + this.Core.ParseExtensionElement(node, child, context);
5535 + }
5536 + }
5537 +
5538 + fileSymbol.IgnoreOffsets = ignoreOffsets;
5539 + fileSymbol.IgnoreLengths = ignoreLengths;
5540 + fileSymbol.RetainOffsets = protectOffsets;
5541 + fileSymbol.RetainLengths = protectLengths;
5542 + fileSymbol.SymbolPaths = symbols;
5543 + }
5544 +
5545 +
5546 + /// <summary>
5547 + /// Parses a File element.
5548 + /// </summary>
5549 + /// <param name="node">File element to parse.</param>
5550 + /// <param name="componentId">Parent's component id.</param>
5551 + /// <param name="directoryId">Ancestor's directory id.</param>
5552 + /// <param name="diskId">Disk id inherited from parent component.</param>
5553 + /// <param name="sourcePath">Default source path of parent directory.</param>
5554 + /// <param name="possibleKeyPath">This will be set with the possible keyPath for the parent component.</param>
5555 + /// <param name="win64Component">true if the component is 64-bit.</param>
5556 + /// <param name="componentGuid">Component GUID (including `*`).</param>
5557 + /// <returns>Yes if this element was marked as the parent component's key path, No if explicitly marked as not being a key path, or NotSet otherwise.</returns>
5558 + private YesNoType ParseFileElement(XElement node, string componentId, string directoryId, int diskId, string sourcePath, out string possibleKeyPath, bool win64Component, string componentGuid)
5559 + {
5560 + var keyPath = this.ParseFileElementAttributes(node, componentId, directoryId, diskId, sourcePath, out possibleKeyPath, componentGuid, isNakedFile: false, out var fileSymbol, out var assemblySymbol);
5561 +
5562 + if (!this.Core.EncounteredError)
5563 + {
5564 + this.Core.AddSymbol(fileSymbol);
5565 +
5566 + if (assemblySymbol != null)
5567 + {
5568 + this.Core.AddSymbol(assemblySymbol);
5569 + }
5570 +
5571 + this.ParseFileElementChildren(node, fileSymbol, keyPath, win64Component);
5572 + }
5573 +
5574 + return keyPath;
5575 + }
5576 +
5577 + /// <summary>
5578 + /// Parses a file element outside a component.
5579 + /// </summary>
5580 + /// <param name="node">File element to parse.</param>
5581 + /// <param name="parentType">Type of complex reference parent. Will be Unknown if there is no parent.</param>
5582 + /// <param name="parentId">Optional identifier for primary parent.</param>
5583 + /// <param name="directoryId">Ancestor's directory id.</param>
5584 + /// <param name="sourcePath">Default source path of parent directory.</param>
5585 + /// <returns>Yes if this element was marked as the parent component's key path, No if explicitly marked as not being a key path, or NotSet otherwise.</returns>
5586 + private void ParseNakedFileElement(XElement node, ComplexReferenceParentType parentType, string parentId, string directoryId, string sourcePath)
5587 + {
5588 + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
5589 + var win64 = this.Context.IsCurrentPlatform64Bit;
5590 + string condition = null;
5591 + string subdirectory = null;
5592 +
5593 + var keyPath = this.ParseFileElementAttributes(node, "@WixTemporaryComponentId", directoryId, diskId: CompilerConstants.IntegerNotSet, sourcePath, out var _, componentGuid: "*", isNakedFile: true, out var fileSymbol, out var assemblySymbol);
5594 +
5595 + if (!this.Core.EncounteredError)
5596 + {
5597 + // Naked files have additional attributes to handle common component attributes.
5598 + foreach (var attrib in node.Attributes())
5599 + {
5600 + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
5601 + {
5602 + switch (attrib.Name.LocalName)
5603 + {
5604 + case "Bitness":
5605 + var bitnessValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
5606 + switch (bitnessValue)
5607 + {
5608 + case "always32":
5609 + win64 = false;
5610 + break;
5611 + case "always64":
5612 + win64 = true;
5613 + break;
5614 + case "default":
5615 + case "":
5616 + break;
5617 + default:
5618 + this.Core.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, bitnessValue, "default", "always32", "always64"));
5619 + break;
5620 + }
5621 + break;
5622 + case "Condition":
5623 + condition = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
5624 + break;
5625 + case "Directory":
5626 + directoryId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
5627 + this.Core.CreateSimpleReference(sourceLineNumbers, SymbolDefinitions.Directory, directoryId);
5628 + break;
5629 + case "Subdirectory":
5630 + subdirectory = this.Core.GetAttributeLongFilename(sourceLineNumbers, attrib, allowRelative: true);
5631 + break;
5632 + }
5633 + }
5634 + }
5635 +
5636 + if (String.IsNullOrEmpty(directoryId))
5637 + {
5638 + directoryId = "INSTALLFOLDER";
5639 + this.Core.CreateSimpleReference(sourceLineNumbers, SymbolDefinitions.Directory, directoryId);
5640 + }
5641 +
5642 + directoryId = this.HandleSubdirectory(sourceLineNumbers, node, directoryId, subdirectory, "Directory", "Subdirectory");
5643 +
5644 + this.Core.AddSymbol(new ComponentSymbol(sourceLineNumbers, fileSymbol.Id)
5645 + {
5646 + ComponentId = "*",
5647 + DirectoryRef = directoryId,
5648 + Location = ComponentLocation.LocalOnly,
5649 + Condition = condition,
5650 + KeyPath = fileSymbol.Id.Id,
5651 + KeyPathType = ComponentKeyPathType.File,
5652 + DisableRegistryReflection = false,
5653 + NeverOverwrite = false,
5654 + Permanent = false,
5655 + SharedDllRefCount = false,
5656 + Shared = false,
5657 + Transitive = false,
5658 + UninstallWhenSuperseded = false,
5659 + Win64 = win64,
5660 + });
5661 +
5662 + fileSymbol.ComponentRef = fileSymbol.Id.Id;
5663 + this.Core.AddSymbol(fileSymbol);
5664 +
5665 + if (assemblySymbol != null)
5666 + {
5667 + this.Core.AddSymbol(assemblySymbol);
5668 + }
5669 +
5670 + this.ParseFileElementChildren(node, fileSymbol, keyPath, win64);
5671 +
5672 + if (ComplexReferenceParentType.Unknown != parentType && null != parentId) // if parent was provided, add a complex reference to that.
5673 + {
5674 + // If the naked file's component is defined directly under a feature, then mark the complex reference primary.
5675 + this.Core.CreateComplexReference(sourceLineNumbers, parentType, parentId, null, ComplexReferenceChildType.Component, fileSymbol.Id.Id, ComplexReferenceParentType.Feature == parentType);
5676 + }
5677 + }
5678 + }
5679 +
5680 /// <summary>
5681 /// Parses a file search element.
5682 /// </summary>
@@ -5802,6 +5994,9 @@ namespace WixToolset.Core
5994 case "FeatureRef":
5995 this.ParseFeatureRefElement(child, ComplexReferenceParentType.Unknown, null);
5996 break;
5997 + case "File":
5998 + this.ParseNakedFileElement(child, ComplexReferenceParentType.Unknown, null, null, null);
5999 + break;
6000 case "Icon":
6001 this.ParseIconElement(child);
6002 break;
@@ -7149,6 +7344,9 @@ namespace WixToolset.Core
7344 case "Directory":
7345 this.ParseDirectoryElement(child, id, diskId: CompilerConstants.IntegerNotSet, fileSource: String.Empty);
7346 break;
7347 + case "File":
7348 + this.ParseNakedFileElement(child, ComplexReferenceParentType.Unknown, null, id, null);
7349 + break;
7350 case "Merge":
7351 this.ParseMergeElement(child, id, diskId: CompilerConstants.IntegerNotSet);
7352 break;
@@ -7300,7 +7498,7 @@ namespace WixToolset.Core
7498 /// Parses a merge reference element.
7499 /// </summary>
7500 /// <param name="node">Element to parse.</param>
7303 - /// <param name="parentType">Parents complex reference type.</param>
7501 + /// <param name="parentType">Parent's complex reference type.</param>
7502 /// <param name="parentId">Identifier for parent feature or feature group.</param>
7503 private void ParseMergeRefElement(XElement node, ComplexReferenceParentType parentType, string parentId)
7504 {
src/wix/WixToolset.Core/Compiler_Module.cs
+3
@@ -175,6 +175,9 @@ namespace WixToolset.Core
175 case "Exclusion":
176 this.ParseExclusionElement(child);
177 break;
178 + case "File":
179 + this.ParseNakedFileElement(child, ComplexReferenceParentType.Module, this.activeName, null, null);
180 + break;
181 case "Icon":
182 this.ParseIconElement(child);
183 break;
src/wix/WixToolset.Core/Compiler_Package.cs
+3
@@ -303,6 +303,9 @@ namespace WixToolset.Core
303 case "FeatureGroupRef":
304 this.ParseFeatureGroupRefElement(child, ComplexReferenceParentType.Product, productCode);
305 break;
306 + case "File":
307 + this.ParseNakedFileElement(child, ComplexReferenceParentType.Product, productCode, null, null);
308 + break;
309 case "Icon":
310 this.ParseIconElement(child);
311 break;
src/wix/WixToolset.Core/Link/AddDefaultSymbolsCommand.cs
+4
@@ -32,6 +32,7 @@ namespace WixToolset.Core.Link
32 return;
33 }
34
35 + // If a directory with id INSTALLFOLDER hasn't been authored, provide a default one.
36 if (!this.Find.SymbolsByName.ContainsKey(WixStandardInstallFolderReference))
37 {
38 var sourceLineNumber = new SourceLineNumber("DefaultInstallFolder");
@@ -51,6 +52,9 @@ namespace WixToolset.Core.Link
52 );
53 }
54
55 + // If an upgrade hasn't been authored and the upgrade strategy is MajorUpgrade,
56 + // conjure a default major upgrade with the stdlib localization string for the
57 + // downgrade error message.
58 var symbols = this.Sections.SelectMany(section => section.Symbols);
59 var upgradeSymbols = symbols.OfType<UpgradeSymbol>();
60 if (!upgradeSymbols.Any())
src/wix/WixToolset.Core/Link/SymbolWithSection.cs
+2
@@ -4,6 +4,7 @@ namespace WixToolset.Core.Link
4 {
5 using System;
6 using System.Collections.Generic;
7 + using System.Diagnostics;
8 using System.Linq;
9 using WixToolset.Data;
10 using WixToolset.Data.Symbols;
@@ -11,6 +12,7 @@ namespace WixToolset.Core.Link
12 /// <summary>
13 /// Symbol with section representing a single unique symbol.
14 /// </summary>
15 + [DebuggerDisplay("{Symbol.DebuggerDisplay}")]
16 internal class SymbolWithSection
17 {
18 private List<WixSimpleReferenceSymbol> directReferences;
src/wix/test/WixToolsetTest.CoreIntegration/ComponentFixture.cs
-29
@@ -41,34 +41,5 @@ namespace WixToolsetTest.CoreIntegration
41 }, errors.Select(e => e.Id).ToArray());
42 }
43 }
44 -
45 - [Fact]
46 - public void CannotBuildMissingDirectoryAttributeWithSubdirectory()
47 - {
48 - var folder = TestData.Get(@"TestData");
49 -
50 - using (var fs = new DisposableFileSystem())
51 - {
52 - var baseFolder = fs.GetFolder();
53 - var intermediateFolder = Path.Combine(baseFolder, "obj");
54 - var msiPath = Path.Combine(baseFolder, "bin", "test.msi");
55 -
56 - var result = WixRunner.Execute(new[]
57 - {
58 - "build",
59 - Path.Combine(folder, "Component", "MissingDirectoryWithSubdirectory.wxs"),
60 - Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"),
61 - "-bindpath", Path.Combine(folder, "SingleFile", "data"),
62 - "-intermediateFolder", intermediateFolder,
63 - "-o", msiPath
64 - });
65 -
66 - var errors = result.Messages.Select(m => m.ToString()).ToArray();
67 - WixAssert.CompareLineByLine(new[]
68 - {
69 - "The Component/@Directory attribute was not found; it is required."
70 - }, errors);
71 - }
72 - }
44 }
45 }
src/wix/test/WixToolsetTest.CoreIntegration/NakedFileFixture.cs new
+247
@@ -0,0 +1,247 @@
1 +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2 +
3 +namespace WixToolsetTest.CoreIntegration
4 +{
5 + using System.Data;
6 + using System.IO;
7 + using System.Linq;
8 + using WixInternal.Core.TestPackage;
9 + using WixInternal.TestSupport;
10 + using WixToolset.Data.WindowsInstaller;
11 + using Xunit;
12 +
13 + public class NakedFileFixture
14 + {
15 + [Fact]
16 + public void CanBuildNakedFilesInComponentGroup()
17 + {
18 + var rows = BuildAndQueryComponentAndFileTables("ComponentGroup.wxs");
19 +
20 + AssertFileComponentIds(2, rows);
21 + }
22 +
23 + [Fact]
24 + public void CanBuildNakedFilesInFeature()
25 + {
26 + var rows = BuildAndQueryComponentAndFileTables("Feature.wxs");
27 +
28 + AssertFileComponentIds(2, rows);
29 + }
30 +
31 + [Fact]
32 + public void CanBuildNakedFilesInDirectory()
33 + {
34 + var rows = BuildAndQueryComponentAndFileTables("Directory.wxs");
35 +
36 + AssertFileComponentIds(2, rows);
37 + }
38 +
39 + [Fact]
40 + public void CanBuildNakedFilesInDirectoryRef()
41 + {
42 + var rows = BuildAndQueryComponentAndFileTables("DirectoryRef.wxs");
43 +
44 + AssertFileComponentIds(2, rows);
45 + }
46 +
47 + [Fact]
48 + public void CanBuildNakedFilesInFeatureRef()
49 + {
50 + var rows = BuildAndQueryComponentAndFileTables("FeatureRef.wxs");
51 +
52 + AssertFileComponentIds(2, rows);
53 + }
54 +
55 + [Fact]
56 + public void CanBuildNakedFilesInFeatureGroup()
57 + {
58 + var rows = BuildAndQueryComponentAndFileTables("FeatureGroup.wxs");
59 +
60 + AssertFileComponentIds(2, rows);
61 + }
62 +
63 + [Fact]
64 + public void CanBuildNakedFilesInFragments()
65 + {
66 + var rows = BuildAndQueryComponentAndFileTables("Fragment.wxs");
67 +
68 + AssertFileComponentIds(2, rows);
69 + }
70 +
71 + [Fact]
72 + public void CanBuildNakedFilesInStandardDirectory()
73 + {
74 + var rows = BuildAndQueryComponentAndFileTables("StandardDirectory.wxs");
75 +
76 + AssertFileComponentIds(2, rows);
77 + }
78 +
79 + [Fact]
80 + public void CanBuildNakedFilesInModule()
81 + {
82 + var rows = BuildAndQueryComponentAndFileTables("Module.wxs", isPackage: false);
83 +
84 + AssertFileComponentIds(2, rows);
85 + }
86 +
87 + [Fact]
88 + public void CanBuildNakedFilesWithConditions()
89 + {
90 + var rows = BuildAndQueryComponentAndFileTables("Condition.wxs");
91 + var componentRows = rows.Where(row => row.StartsWith("Component:")).ToArray();
92 +
93 + // Coincidentally, the files' ids are the same as the component conditions.
94 + foreach (var componentRow in componentRows)
95 + {
96 + var columns = componentRow.Split(':', '\t');
97 + Assert.Equal(columns[1], columns[5]);
98 + }
99 + }
100 +
101 + [Fact]
102 + public void CanBuildNakedFilesUnderPackage()
103 + {
104 + var rows = BuildAndQueryComponentAndFileTables("Package.wxs");
105 + AssertFileComponentIds(4, rows);
106 + }
107 +
108 + [Fact]
109 + public void CanBuildNakedFilesUnderPackageWithDefaultInstallFolder()
110 + {
111 + var rows = BuildAndQueryComponentAndFileTables("PackageWithDefaultInstallFolder.wxs");
112 + AssertFileComponentIds(4, rows);
113 + }
114 +
115 + [Fact]
116 + public void NakedFilesUnderPackageWithAuthoredFeatureAreOrphaned()
117 + {
118 + var messages = BuildAndQueryComponentAndFileTables("PackageWithoutDefaultFeature.wxs", isPackage: true, 267);
119 + Assert.Equal(new[]
120 + {
121 + "267",
122 + "267",
123 + }, messages);
124 + }
125 +
126 + [Fact]
127 + public void IllegalAttributesWhenNonNakedFailTheBuild()
128 + {
129 + var messages = BuildAndQueryComponentAndFileTables("BadAttributes.wxs", isPackage: true, 62);
130 + Assert.Equal(new[]
131 + {
132 + "62",
133 + "62",
134 + "62",
135 + "62",
136 + }, messages);
137 + }
138 +
139 + [Fact]
140 + public void CanBuildNakedFileFromWixlibComponentGroup()
141 + {
142 + var rows = BuildPackageWithWixlib("WixlibComponentGroup.wxs", "WixlibComponentGroupPackage.wxs");
143 +
144 + AssertFileComponentIds(2, rows);
145 + }
146 +
147 + private static string[] BuildPackageWithWixlib(string wixlibSourcePath, string msiSourcePath)
148 + {
149 + var folder = TestData.Get("TestData", "NakedFile");
150 +
151 + using (var fs = new DisposableFileSystem())
152 + {
153 + var baseFolder = fs.GetFolder();
154 + var intermediateFolder = Path.Combine(baseFolder, "obj");
155 + var binFolder = Path.Combine(baseFolder, "bin");
156 + var wixlibPath = Path.Combine(binFolder, Path.ChangeExtension(wixlibSourcePath, ".wixlib"));
157 +
158 + var result = WixRunner.Execute(new[]
159 + {
160 + "build",
161 + Path.Combine(folder, wixlibSourcePath),
162 + "-intermediateFolder", intermediateFolder,
163 + "-bindpath", folder,
164 + "-o", wixlibPath,
165 + });
166 +
167 + result.AssertSuccess();
168 +
169 + var msiPath = Path.Combine(binFolder, "test.msi");
170 +
171 + result = WixRunner.Execute(new[]
172 + {
173 + "build",
174 + Path.Combine(folder, msiSourcePath),
175 + wixlibPath,
176 + "-intermediateFolder", intermediateFolder,
177 + "-bindpath", folder,
178 + "-o", msiPath,
179 + });
180 + result.AssertSuccess();
181 +
182 + return Query.QueryDatabase(msiPath, new[] { "Component", "File" })
183 + .OrderBy(s => s)
184 + .ToArray();
185 + }
186 + }
187 +
188 + private static string[] BuildAndQueryComponentAndFileTables(string file, bool isPackage = true, int? exitCode = null)
189 + {
190 + var folder = TestData.Get("TestData", "NakedFile");
191 +
192 + using (var fs = new DisposableFileSystem())
193 + {
194 + var baseFolder = fs.GetFolder();
195 + var intermediateFolder = Path.Combine(baseFolder, "obj");
196 + var binFolder = Path.Combine(baseFolder, "bin");
197 + var msiPath = Path.Combine(binFolder, isPackage ? "test.msi" : "test.msm");
198 +
199 + var result = WixRunner.Execute(new[]
200 + {
201 + "build",
202 + Path.Combine(folder, file),
203 + "-intermediateFolder", intermediateFolder,
204 + "-bindpath", folder,
205 + "-o", msiPath,
206 + });
207 +
208 + if (exitCode.HasValue)
209 + {
210 + Assert.Equal(exitCode.Value, result.ExitCode);
211 +
212 + return result.Messages.Select(m => m.Id.ToString()).ToArray();
213 + }
214 + else
215 + {
216 + result.AssertSuccess();
217 +
218 + return Query.QueryDatabase(msiPath, new[] { "Component", "File" })
219 + .OrderBy(s => s)
220 + .ToArray();
221 + }
222 + }
223 + }
224 +
225 + private static void AssertFileComponentIds(int fileCount, string[] rows)
226 + {
227 + var componentRows = rows.Where(row => row.StartsWith("Component:")).ToArray();
228 + var fileRows = rows.Where(row => row.StartsWith("File:")).ToArray();
229 +
230 + Assert.Equal(fileCount, componentRows.Length);
231 + Assert.Equal(componentRows.Length, fileRows.Length);
232 +
233 + // Component id == Component keypath == File id
234 + foreach (var componentRow in componentRows)
235 + {
236 + var columns = componentRow.Split(':', '\t');
237 + Assert.Equal(columns[1], columns[6]);
238 + }
239 +
240 + foreach (var fileRow in fileRows)
241 + {
242 + var columns = fileRow.Split(':', '\t');
243 + Assert.Equal(columns[1], columns[2]);
244 + }
245 + }
246 + }
247 +}
src/wix/test/WixToolsetTest.CoreIntegration/TestData/Component/MissingDirectoryWithSubdirectory.wxs deleted
-10
@@ -1,10 +0,0 @@
1 -<?xml version="1.0" encoding="utf-8"?>
2 -<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3 - <Fragment>
4 - <ComponentGroup Id="ProductComponents">
5 - <Component Subdirectory="fails\without\Directory\attribute">
6 - <File Source="test.txt" />
7 - </Component>
8 - </ComponentGroup>
9 - </Fragment>
10 -</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/BadAttributes.wxs new
+11
@@ -0,0 +1,11 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 + <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4 +
5 + <Feature Id="ProductFeature">
6 + <Component Directory="ProgramFilesFolder" Subdirectory="MsiPackage">
7 + <File Source="test.txt" Bitness="always64" Condition="BLAHBLAHBLAH" Directory="ProgramFilesFolder" Subdirectory="MsiPackage" />
8 + </Component>
9 + </Feature>
10 + </Package>
11 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/ComponentGroup.wxs new
+14
@@ -0,0 +1,14 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 + <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4 +
5 + <Feature Id="ProductFeature">
6 + <ComponentGroupRef Id="Files" />
7 + </Feature>
8 +
9 + <ComponentGroup Id="Files" Directory="ProgramFilesFolder" Subdirectory="MsiPackage">
10 + <File Source="test.txt" />
11 + <File Source="test.txt" Name="test2.txt" />
12 + </ComponentGroup>
13 + </Package>
14 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/Condition.wxs new
+10
@@ -0,0 +1,10 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 + <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4 +
5 + <Feature Id="ProductFeature">
6 + <File Id="FILE1" Condition="FILE1" Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" />
7 + <File Id="FILE2" Condition="FILE2" Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" Name="test2.txt" />
8 + </Feature>
9 + </Package>
10 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/Directory.wxs new
+13
@@ -0,0 +1,13 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 + <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4 +
5 + <StandardDirectory Id="ProgramFilesFolder">
6 + <Directory Id="INSTALLFOLDER" Name="MsiPackage">
7 + <!-- Relies on default-feature feature to include naked files in package. -->
8 + <File Id="test.txt" Source="test.txt" />
9 + <File Id="test2.txt" Source="test.txt" Name="test2.txt" />
10 + </Directory>
11 + </StandardDirectory>
12 + </Package>
13 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/DirectoryRef.wxs new
+17
@@ -0,0 +1,17 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 + <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4 +
5 + <DirectoryRef Id="INSTALLFOLDER">
6 + <!-- Relies on default-feature feature to include naked files in package. -->
7 + <File Id="test.txt" Source="test.txt" />
8 + <File Id="test2.txt" Source="test.txt" Name="test2.txt" />
9 + </DirectoryRef>
10 + </Package>
11 +
12 + <Fragment>
13 + <StandardDirectory Id="ProgramFilesFolder">
14 + <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
15 + </StandardDirectory>
16 + </Fragment>
17 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/Feature.wxs new
+10
@@ -0,0 +1,10 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 + <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4 +
5 + <Feature Id="ProductFeature">
6 + <File Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" />
7 + <File Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" Name="test2.txt" />
8 + </Feature>
9 + </Package>
10 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/FeatureGroup.wxs new
+22
@@ -0,0 +1,22 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 + <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4 +
5 + <Feature Id="ProductFeature">
6 + <FeatureGroupRef Id="ProductFeatureGroup" />
7 + </Feature>
8 + </Package>
9 +
10 + <Fragment>
11 + <StandardDirectory Id="ProgramFilesFolder">
12 + <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
13 + </StandardDirectory>
14 + </Fragment>
15 +
16 + <Fragment>
17 + <FeatureGroup Id="ProductFeatureGroup">
18 + <File Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" />
19 + <File Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" Name="test2.txt" />
20 + </FeatureGroup>
21 + </Fragment>
22 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/FeatureRef.wxs new
+20
@@ -0,0 +1,20 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 + <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4 +
5 + <FeatureRef Id="ProductFeature">
6 + <File Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" />
7 + <File Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" Name="test2.txt" />
8 + </FeatureRef>
9 + </Package>
10 +
11 + <Fragment>
12 + <StandardDirectory Id="ProgramFilesFolder">
13 + <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
14 + </StandardDirectory>
15 + </Fragment>
16 +
17 + <Fragment>
18 + <Feature Id="ProductFeature" />
19 + </Fragment>
20 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/Fragment.wxs new
+24
@@ -0,0 +1,24 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 + <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4 +
5 + <FeatureGroupRef Id="FeatureGroup1" />
6 + <PropertyRef Id="Property2" />
7 + </Package>
8 +
9 + <Fragment>
10 + <StandardDirectory Id="ProgramFilesFolder">
11 + <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
12 + </StandardDirectory>
13 + </Fragment>
14 +
15 + <Fragment>
16 + <FeatureGroup Id="FeatureGroup1" />
17 + <File Id="test.txt" Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" />
18 + </Fragment>
19 +
20 + <Fragment>
21 + <Property Id="Property2" Hidden="yes" />
22 + <File Id="test2.txt" Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" Name="test2.txt" />
23 + </Fragment>
24 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/Module.wxs new
+6
@@ -0,0 +1,6 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Module Id="MergeModule" Guid="e535b765-1019-4a4f-b3ea-ae28870e6d73" Language="1033" Version="1.0.0.0">
3 + <File Id="FILE1" Condition="FILE1" Directory="ProgramFilesFolder" Subdirectory="MergeModule" Source="test.txt" />
4 + <File Id="FILE2" Condition="FILE2" Directory="ProgramFilesFolder" Subdirectory="MergeModule" Source="test.txt" Name="test2.txt" />
5 + </Module>
6 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/Package.wxs new
+10
@@ -0,0 +1,10 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 + <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4 +
5 + <File Directory="INSTALLFOLDER" Source="test.txt" />
6 + <File Directory="INSTALLFOLDER" Source="test.txt" Name="test2.txt" />
7 + <File Directory="INSTALLFOLDER" Source="test.txt" Name="test3.txt" />
8 + <File Directory="INSTALLFOLDER" Source="test.txt" Name="test4.txt" />
9 + </Package>
10 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/PackageWithDefaultInstallFolder.wxs new
+10
@@ -0,0 +1,10 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 + <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4 +
5 + <File Source="test.txt" />
6 + <File Source="test.txt" Name="test2.txt" />
7 + <File Source="test.txt" Name="test3.txt" />
8 + <File Source="test.txt" Name="test4.txt" />
9 + </Package>
10 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/PackageWithoutDefaultFeature.wxs new
+17
@@ -0,0 +1,17 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 + <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4 +
5 + <File Source="test.txt" Name="test3.txt" />
6 + <File Source="test.txt" Name="test4.txt" />
7 +
8 + <Feature Id="ProductFeature">
9 + <ComponentGroupRef Id="Files" />
10 + </Feature>
11 +
12 + <ComponentGroup Id="Files" Directory="ProgramFilesFolder" Subdirectory="MsiPackage">
13 + <File Source="test.txt" />
14 + <File Source="test.txt" Name="test2.txt" />
15 + </ComponentGroup>
16 + </Package>
17 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/StandardDirectory.wxs new
+11
@@ -0,0 +1,11 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 + <MajorUpgrade DowngradeErrorMessage="Downgrade error message." />
4 +
5 + <StandardDirectory Id="ProgramFilesFolder">
6 + <!-- Relies on default-feature feature to include naked files in package. -->
7 + <File Id="test.txt" Source="test.txt" />
8 + <File Id="test2.txt" Source="test.txt" Name="test2.txt" />
9 + </StandardDirectory>
10 + </Package>
11 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/WixlibComponentGroup.wxs new
+8
@@ -0,0 +1,8 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Fragment>
3 + <ComponentGroup Id="WixlibFiles">
4 + <File Id="test.txt" Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" />
5 + <File Id="test2.txt" Directory="ProgramFilesFolder" Subdirectory="MsiPackage" Source="test.txt" Name="test2.txt" />
6 + </ComponentGroup>
7 + </Fragment>
8 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/WixlibComponentGroupPackage.wxs new
+5
@@ -0,0 +1,5 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 + <ComponentGroupRef Id="WixlibFiles" />
4 + </Package>
5 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/NakedFile/test.txt new
+1
@@ -0,0 +1 @@
1 +This is test.txt.
src/wix/test/WixToolsetTest.CoreIntegration/TestData/SingleFile/PackageComponents.wxs
+2 -3
@@ -2,9 +2,8 @@
2 <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3 <Fragment>
4 <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
5 - <Component>
6 - <File Source="test.txt" />
7 - </Component>
5 + <File Source="test.txt" />
6 +
7 <Component Id="Shared.dll" Shared="yes">
8 <File Name="Shared.dll" Source="test.txt" />
9 </Component>