Add default rollback boundary in the Burn binder instead of the compiler
Fixes wixtoolset/issues#6312
Rob Mensching committed
Mar 11, 2021 at 18:47 UTC
574785ab1421c9b67336c13ade5c2263e665ca07
4 files changed
+35
-31
src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
+1
-4
@@ -357,10 +357,7 @@ namespace WixToolset.Core.Burn
357
IEnumerable<PackageFacade> orderedFacades;
358
IEnumerable<WixBundleRollbackBoundarySymbol> boundaries;
359
{
360
- var groupSymbols = section.Symbols.OfType<WixGroupSymbol>();
361
- var boundarySymbolsById = section.Symbols.OfType<WixBundleRollbackBoundarySymbol>().ToDictionary(b => b.Id.Id);
362
-
363
- var command = new OrderPackagesAndRollbackBoundariesCommand(this.Messaging, groupSymbols, boundarySymbolsById, facades);
360
+ var command = new OrderPackagesAndRollbackBoundariesCommand(this.Messaging, section, facades);
361
command.Execute();
362
363
orderedFacades = command.OrderedPackageFacades;
src/WixToolset.Core.Burn/Bundles/OrderPackagesAndRollbackBoundariesCommand.cs
+31
-21
@@ -4,27 +4,27 @@ namespace WixToolset.Core.Burn.Bundles
4
{
5
using System;
6
using System.Collections.Generic;
7
+ using System.Linq;
8
using WixToolset.Data;
9
using WixToolset.Data.Symbols;
10
using WixToolset.Extensibility.Services;
11
12
internal class OrderPackagesAndRollbackBoundariesCommand
13
{
13
- public OrderPackagesAndRollbackBoundariesCommand(IMessaging messaging, IEnumerable<WixGroupSymbol> groupSymbols, Dictionary<string, WixBundleRollbackBoundarySymbol> boundarySymbols, IDictionary<string, PackageFacade> packageFacades)
14
+ private const string DefaultBoundaryId = "WixDefaultBoundary";
15
+
16
+ public OrderPackagesAndRollbackBoundariesCommand(IMessaging messaging, IntermediateSection section, IDictionary<string, PackageFacade> packageFacades)
17
{
18
this.Messaging = messaging;
16
- this.GroupSymbols = groupSymbols;
17
- this.Boundaries = boundarySymbols;
19
+ this.Section = section;
20
this.PackageFacades = packageFacades;
21
}
22
23
private IMessaging Messaging { get; }
24
23
- public IEnumerable<WixGroupSymbol> GroupSymbols { get; }
24
-
25
- public Dictionary<string, WixBundleRollbackBoundarySymbol> Boundaries { get; }
25
+ private IntermediateSection Section { get; }
26
27
- public IDictionary<string, PackageFacade> PackageFacades { get; }
27
+ private IDictionary<string, PackageFacade> PackageFacades { get; }
28
29
public IEnumerable<PackageFacade> OrderedPackageFacades { get; private set; }
30
@@ -32,6 +32,9 @@ namespace WixToolset.Core.Burn.Bundles
32
33
public void Execute()
34
{
35
+ var groupSymbols = this.Section.Symbols.OfType<WixGroupSymbol>().ToList();
36
+ var boundariesById = this.Section.Symbols.OfType<WixBundleRollbackBoundarySymbol>().ToDictionary(b => b.Id.Id);
37
+
38
var orderedFacades = new List<PackageFacade>();
39
var usedBoundaries = new List<WixBundleRollbackBoundarySymbol>();
40
@@ -44,20 +47,27 @@ namespace WixToolset.Core.Burn.Bundles
47
// We handle uninstall (aka: backwards) rollback boundaries after
48
// we get these install/repair (aka: forward) rollback boundaries
49
// defined.
47
- WixBundleRollbackBoundarySymbol pendingRollbackBoundary = null;
48
- WixBundleRollbackBoundarySymbol lastRollbackBoundary = null;
50
+ var pendingRollbackBoundary = new WixBundleRollbackBoundarySymbol(null, new Identifier(AccessModifier.Section, DefaultBoundaryId)) { Vital = true };
51
+ var lastRollbackBoundary = pendingRollbackBoundary;
52
var boundaryHadX86Package = false;
53
var warnedMsiTransaction = false;
54
52
- foreach (var groupSymbol in this.GroupSymbols)
55
+ foreach (var groupSymbol in groupSymbols)
56
{
57
if (ComplexReferenceChildType.Package == groupSymbol.ChildType && ComplexReferenceParentType.PackageGroup == groupSymbol.ParentType && "WixChain" == groupSymbol.ParentId)
58
{
59
if (this.PackageFacades.TryGetValue(groupSymbol.ChildId, out var facade))
60
{
58
- var insideMsiTransaction = lastRollbackBoundary != null && lastRollbackBoundary.Transaction.HasValue && lastRollbackBoundary.Transaction.Value;
61
+ var insideMsiTransaction = lastRollbackBoundary?.Transaction ?? false;
62
+
63
if (null != pendingRollbackBoundary)
64
{
65
+ // If we used the default boundary, ensure the symbol is added to the section.
66
+ if (pendingRollbackBoundary.Id.Id == DefaultBoundaryId)
67
+ {
68
+ this.Section.Symbols.Add(pendingRollbackBoundary);
69
+ }
70
+
71
if (insideMsiTransaction && !warnedMsiTransaction)
72
{
73
warnedMsiTransaction = true;
@@ -72,12 +82,11 @@ namespace WixToolset.Core.Burn.Bundles
82
}
83
84
// Error if MSI transaction has x86 package preceding x64 packages
75
- if (insideMsiTransaction
76
- && boundaryHadX86Package
77
- && facade.PackageSymbol.Win64)
85
+ if (insideMsiTransaction && boundaryHadX86Package && facade.PackageSymbol.Win64)
86
{
87
this.Messaging.Write(ErrorMessages.MsiTransactionX86BeforeX64(facade.PackageSymbol.SourceLineNumbers));
88
}
89
+
90
boundaryHadX86Package |= !facade.PackageSymbol.Win64;
91
92
orderedFacades.Add(facade);
@@ -85,15 +94,16 @@ namespace WixToolset.Core.Burn.Bundles
94
else // must be a rollback boundary.
95
{
96
// Discard the next rollback boundary if we have a previously defined boundary.
88
- var nextRollbackBoundary = this.Boundaries[groupSymbol.ChildId];
97
+ var nextRollbackBoundary = boundariesById[groupSymbol.ChildId];
98
if (null != pendingRollbackBoundary)
99
{
91
- this.Messaging.Write(WarningMessages.DiscardedRollbackBoundary(nextRollbackBoundary.SourceLineNumbers, nextRollbackBoundary.Id.Id));
92
- }
93
- else
94
- {
95
- lastRollbackBoundary = pendingRollbackBoundary = nextRollbackBoundary;
100
+ if (pendingRollbackBoundary.Id.Id != DefaultBoundaryId)
101
+ {
102
+ this.Messaging.Write(WarningMessages.DiscardedRollbackBoundary(nextRollbackBoundary.SourceLineNumbers, nextRollbackBoundary.Id.Id));
103
+ }
104
}
105
+
106
+ lastRollbackBoundary = pendingRollbackBoundary = nextRollbackBoundary;
107
}
108
}
109
}
@@ -135,7 +145,7 @@ namespace WixToolset.Core.Burn.Bundles
145
string previousRollbackBoundaryId = null;
146
PackageFacade previousFacade = null;
147
138
- foreach (PackageFacade package in orderedFacades)
148
+ foreach (var package in orderedFacades)
149
{
150
if (null != package.PackageSymbol.RollbackBoundaryRef)
151
{
src/WixToolset.Core/Compiler_Bundle.cs
+2
-5
@@ -1726,11 +1726,8 @@ namespace WixToolset.Core
1726
}
1727
}
1728
1729
- // Ensure there is always a rollback boundary at the beginning of the chain.
1730
- this.CreateRollbackBoundary(sourceLineNumbers, new Identifier(AccessModifier.Global, "WixDefaultBoundary"), YesNoType.Yes, YesNoType.No, ComplexReferenceParentType.PackageGroup, "WixChain", ComplexReferenceChildType.Unknown, null);
1731
-
1732
- var previousId = "WixDefaultBoundary";
1733
- var previousType = ComplexReferenceChildType.Package;
1729
+ string previousId = null;
1730
+ var previousType = ComplexReferenceChildType.Unknown;
1731
1732
foreach (var child in node.Elements())
1733
{
src/test/WixToolsetTest.CoreIntegration/RollbackBoundaryFixture.cs
+1
-1
@@ -9,7 +9,7 @@ namespace WixToolsetTest.CoreIntegration
9
10
public class RollbackBoundaryFixture
11
{
12
- [Fact(Skip = "Test demonstrates failure")]
12
+ [Fact]
13
public void CanStartChainWithRollbackBoundary()
14
{
15
var folder = TestData.Get(@"TestData");