diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2020-12-02 14:33:15 -0600 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2020-12-02 14:52:55 -0600 |
commit | 5a874790ba9ec6c2d3c9002699114c2fe4c493ae (patch) | |
tree | 4baa88262fbae45446363baf174d54a6877a9a9e | |
parent | 2a8f47e357bfbfe20c962cade4455793e45dae7c (diff) | |
download | wix-5a874790ba9ec6c2d3c9002699114c2fe4c493ae.tar.gz wix-5a874790ba9ec6c2d3c9002699114c2fe4c493ae.tar.bz2 wix-5a874790ba9ec6c2d3c9002699114c2fe4c493ae.zip |
MSI transaction cleanup.
9 files changed, 212 insertions, 15 deletions
diff --git a/src/WixToolset.Core.Burn/Bundles/OrderPackagesAndRollbackBoundariesCommand.cs b/src/WixToolset.Core.Burn/Bundles/OrderPackagesAndRollbackBoundariesCommand.cs index 9e27d5a3..44299fd5 100644 --- a/src/WixToolset.Core.Burn/Bundles/OrderPackagesAndRollbackBoundariesCommand.cs +++ b/src/WixToolset.Core.Burn/Bundles/OrderPackagesAndRollbackBoundariesCommand.cs | |||
@@ -44,9 +44,10 @@ namespace WixToolset.Core.Burn.Bundles | |||
44 | // We handle uninstall (aka: backwards) rollback boundaries after | 44 | // We handle uninstall (aka: backwards) rollback boundaries after |
45 | // we get these install/repair (aka: forward) rollback boundaries | 45 | // we get these install/repair (aka: forward) rollback boundaries |
46 | // defined. | 46 | // defined. |
47 | WixBundleRollbackBoundarySymbol previousRollbackBoundary = null; | 47 | WixBundleRollbackBoundarySymbol pendingRollbackBoundary = null; |
48 | WixBundleRollbackBoundarySymbol lastRollbackBoundary = null; | 48 | WixBundleRollbackBoundarySymbol lastRollbackBoundary = null; |
49 | var boundaryHadX86Package = false; | 49 | var boundaryHadX86Package = false; |
50 | var warnedMsiTransaction = false; | ||
50 | 51 | ||
51 | foreach (var groupSymbol in this.GroupSymbols) | 52 | foreach (var groupSymbol in this.GroupSymbols) |
52 | { | 53 | { |
@@ -54,24 +55,30 @@ namespace WixToolset.Core.Burn.Bundles | |||
54 | { | 55 | { |
55 | if (this.PackageFacades.TryGetValue(groupSymbol.ChildId, out var facade)) | 56 | if (this.PackageFacades.TryGetValue(groupSymbol.ChildId, out var facade)) |
56 | { | 57 | { |
57 | if (null != previousRollbackBoundary) | 58 | var insideMsiTransaction = lastRollbackBoundary != null && lastRollbackBoundary.Transaction.HasValue && lastRollbackBoundary.Transaction.Value; |
59 | if (null != pendingRollbackBoundary) | ||
58 | { | 60 | { |
59 | usedBoundaries.Add(previousRollbackBoundary); | 61 | if (insideMsiTransaction && !warnedMsiTransaction) |
60 | facade.PackageSymbol.RollbackBoundaryRef = previousRollbackBoundary.Id.Id; | 62 | { |
61 | previousRollbackBoundary = null; | 63 | warnedMsiTransaction = true; |
64 | this.Messaging.Write(WarningMessages.MsiTransactionLimitations(pendingRollbackBoundary.SourceLineNumbers)); | ||
65 | } | ||
62 | 66 | ||
63 | boundaryHadX86Package = facade.PackageSymbol.Win64; | 67 | usedBoundaries.Add(pendingRollbackBoundary); |
68 | facade.PackageSymbol.RollbackBoundaryRef = pendingRollbackBoundary.Id.Id; | ||
69 | pendingRollbackBoundary = null; | ||
70 | |||
71 | boundaryHadX86Package = !facade.PackageSymbol.Win64; | ||
64 | } | 72 | } |
65 | 73 | ||
66 | // Error if MSI transaction has x86 package preceding x64 packages | 74 | // Error if MSI transaction has x86 package preceding x64 packages |
67 | if ((lastRollbackBoundary != null) | 75 | if (insideMsiTransaction |
68 | && lastRollbackBoundary.Transaction == true | ||
69 | && boundaryHadX86Package | 76 | && boundaryHadX86Package |
70 | && facade.PackageSymbol.Win64) | 77 | && facade.PackageSymbol.Win64) |
71 | { | 78 | { |
72 | this.Messaging.Write(ErrorMessages.MsiTransactionX86BeforeX64(lastRollbackBoundary.SourceLineNumbers)); | 79 | this.Messaging.Write(ErrorMessages.MsiTransactionX86BeforeX64(facade.PackageSymbol.SourceLineNumbers)); |
73 | } | 80 | } |
74 | boundaryHadX86Package |= facade.PackageSymbol.Win64; | 81 | boundaryHadX86Package |= !facade.PackageSymbol.Win64; |
75 | 82 | ||
76 | orderedFacades.Add(facade); | 83 | orderedFacades.Add(facade); |
77 | } | 84 | } |
@@ -79,22 +86,21 @@ namespace WixToolset.Core.Burn.Bundles | |||
79 | { | 86 | { |
80 | // Discard the next rollback boundary if we have a previously defined boundary. | 87 | // Discard the next rollback boundary if we have a previously defined boundary. |
81 | var nextRollbackBoundary = this.Boundaries[groupSymbol.ChildId]; | 88 | var nextRollbackBoundary = this.Boundaries[groupSymbol.ChildId]; |
82 | if (null != previousRollbackBoundary) | 89 | if (null != pendingRollbackBoundary) |
83 | { | 90 | { |
84 | this.Messaging.Write(WarningMessages.DiscardedRollbackBoundary(nextRollbackBoundary.SourceLineNumbers, nextRollbackBoundary.Id.Id)); | 91 | this.Messaging.Write(WarningMessages.DiscardedRollbackBoundary(nextRollbackBoundary.SourceLineNumbers, nextRollbackBoundary.Id.Id)); |
85 | } | 92 | } |
86 | else | 93 | else |
87 | { | 94 | { |
88 | previousRollbackBoundary = nextRollbackBoundary; | 95 | lastRollbackBoundary = pendingRollbackBoundary = nextRollbackBoundary; |
89 | lastRollbackBoundary = nextRollbackBoundary; | ||
90 | } | 96 | } |
91 | } | 97 | } |
92 | } | 98 | } |
93 | } | 99 | } |
94 | 100 | ||
95 | if (null != previousRollbackBoundary) | 101 | if (null != pendingRollbackBoundary) |
96 | { | 102 | { |
97 | this.Messaging.Write(WarningMessages.DiscardedRollbackBoundary(previousRollbackBoundary.SourceLineNumbers, previousRollbackBoundary.Id.Id)); | 103 | this.Messaging.Write(WarningMessages.DiscardedRollbackBoundary(pendingRollbackBoundary.SourceLineNumbers, pendingRollbackBoundary.Id.Id)); |
98 | } | 104 | } |
99 | 105 | ||
100 | // With the forward rollback boundaries assigned, we can now go | 106 | // With the forward rollback boundaries assigned, we can now go |
diff --git a/src/test/WixToolsetTest.CoreIntegration/MsiTransactionFixture.cs b/src/test/WixToolsetTest.CoreIntegration/MsiTransactionFixture.cs new file mode 100644 index 00000000..5a29eb9e --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/MsiTransactionFixture.cs | |||
@@ -0,0 +1,129 @@ | |||
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.IO; | ||
6 | using WixBuildTools.TestSupport; | ||
7 | using WixToolset.Core.TestPackage; | ||
8 | using Xunit; | ||
9 | |||
10 | public class MsiTransactionFixture | ||
11 | { | ||
12 | [Fact] | ||
13 | public void CantBuildX64AfterX86Bundle() | ||
14 | { | ||
15 | var folder = TestData.Get(@"TestData"); | ||
16 | |||
17 | using (var fs = new DisposableFileSystem()) | ||
18 | { | ||
19 | var baseFolder = fs.GetFolder(); | ||
20 | var intermediateFolder = Path.Combine(baseFolder, "obj"); | ||
21 | var binFolder = Path.Combine(baseFolder, "bin"); | ||
22 | var exePath = Path.Combine(binFolder, "test.exe"); | ||
23 | |||
24 | BuildMsiPackages(folder, intermediateFolder, binFolder); | ||
25 | |||
26 | var result = WixRunner.Execute(new[] | ||
27 | { | ||
28 | "build", | ||
29 | Path.Combine(folder, "MsiTransaction", "X64AfterX86Bundle.wxs"), | ||
30 | Path.Combine(folder, "BundleWithPackageGroupRef", "Bundle.wxs"), | ||
31 | "-bindpath", Path.Combine(folder, "SimpleBundle", "data"), | ||
32 | "-bindpath", binFolder, | ||
33 | "-intermediateFolder", intermediateFolder, | ||
34 | "-o", exePath, | ||
35 | }); | ||
36 | |||
37 | Assert.Equal(390, result.ExitCode); | ||
38 | } | ||
39 | } | ||
40 | |||
41 | [Fact] | ||
42 | public void CanBuildX86AfterX64Bundle() | ||
43 | { | ||
44 | var folder = TestData.Get(@"TestData"); | ||
45 | |||
46 | using (var fs = new DisposableFileSystem()) | ||
47 | { | ||
48 | var baseFolder = fs.GetFolder(); | ||
49 | var intermediateFolder = Path.Combine(baseFolder, "obj"); | ||
50 | var binFolder = Path.Combine(baseFolder, "bin"); | ||
51 | var exePath = Path.Combine(binFolder, "test.exe"); | ||
52 | |||
53 | BuildMsiPackages(folder, intermediateFolder, binFolder); | ||
54 | |||
55 | var result = WixRunner.Execute(new[] | ||
56 | { | ||
57 | "build", | ||
58 | Path.Combine(folder, "MsiTransaction", "X86AfterX64Bundle.wxs"), | ||
59 | Path.Combine(folder, "BundleWithPackageGroupRef", "Bundle.wxs"), | ||
60 | "-bindpath", Path.Combine(folder, "SimpleBundle", "data"), | ||
61 | "-bindpath", binFolder, | ||
62 | "-intermediateFolder", intermediateFolder, | ||
63 | "-o", exePath, | ||
64 | }); | ||
65 | |||
66 | result.AssertSuccess(); | ||
67 | |||
68 | Assert.True(File.Exists(exePath)); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | private static void BuildMsiPackages(string folder, string intermediateFolder, string binFolder) | ||
73 | { | ||
74 | var result = WixRunner.Execute(new[] | ||
75 | { | ||
76 | "build", | ||
77 | Path.Combine(folder, "MsiTransaction", "FirstX86.wxs"), | ||
78 | Path.Combine(folder, "ProductWithComponentGroupRef", "MinimalComponentGroup.wxs"), | ||
79 | Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"), | ||
80 | "-bindpath", Path.Combine(folder, "SingleFile", "data"), | ||
81 | "-intermediateFolder", intermediateFolder, | ||
82 | "-o", Path.Combine(binFolder, "FirstX86.msi"), | ||
83 | }); | ||
84 | |||
85 | result.AssertSuccess(); | ||
86 | |||
87 | result = WixRunner.Execute(new[] | ||
88 | { | ||
89 | "build", | ||
90 | Path.Combine(folder, "MsiTransaction", "SecondX86.wxs"), | ||
91 | Path.Combine(folder, "ProductWithComponentGroupRef", "MinimalComponentGroup.wxs"), | ||
92 | Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"), | ||
93 | "-bindpath", Path.Combine(folder, "SingleFile", "data"), | ||
94 | "-intermediateFolder", intermediateFolder, | ||
95 | "-o", Path.Combine(binFolder, "SecondX86.msi"), | ||
96 | }); | ||
97 | |||
98 | result.AssertSuccess(); | ||
99 | |||
100 | result = WixRunner.Execute(new[] | ||
101 | { | ||
102 | "build", | ||
103 | Path.Combine(folder, "MsiTransaction", "FirstX64.wxs"), | ||
104 | Path.Combine(folder, "ProductWithComponentGroupRef", "MinimalComponentGroup.wxs"), | ||
105 | Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"), | ||
106 | "-bindpath", Path.Combine(folder, "SingleFile", "data"), | ||
107 | "-intermediateFolder", intermediateFolder, | ||
108 | "-arch", "x64", | ||
109 | "-o", Path.Combine(binFolder, "FirstX64.msi"), | ||
110 | }); | ||
111 | |||
112 | result.AssertSuccess(); | ||
113 | |||
114 | result = WixRunner.Execute(new[] | ||
115 | { | ||
116 | "build", | ||
117 | Path.Combine(folder, "MsiTransaction", "SecondX64.wxs"), | ||
118 | Path.Combine(folder, "ProductWithComponentGroupRef", "MinimalComponentGroup.wxs"), | ||
119 | Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"), | ||
120 | "-bindpath", Path.Combine(folder, "SingleFile", "data"), | ||
121 | "-intermediateFolder", intermediateFolder, | ||
122 | "-arch", "x64", | ||
123 | "-o", Path.Combine(binFolder, "SecondX64.msi"), | ||
124 | }); | ||
125 | |||
126 | result.AssertSuccess(); | ||
127 | } | ||
128 | } | ||
129 | } | ||
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/FirstX64.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/FirstX64.wxs new file mode 100644 index 00000000..e72b6402 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/FirstX64.wxs | |||
@@ -0,0 +1,8 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
3 | <Fragment> | ||
4 | <ComponentGroup Id="ProductComponents"> | ||
5 | <ComponentGroupRef Id="MinimalComponentGroup" /> | ||
6 | </ComponentGroup> | ||
7 | </Fragment> | ||
8 | </Wix> | ||
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/FirstX86.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/FirstX86.wxs new file mode 100644 index 00000000..e72b6402 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/FirstX86.wxs | |||
@@ -0,0 +1,8 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
3 | <Fragment> | ||
4 | <ComponentGroup Id="ProductComponents"> | ||
5 | <ComponentGroupRef Id="MinimalComponentGroup" /> | ||
6 | </ComponentGroup> | ||
7 | </Fragment> | ||
8 | </Wix> | ||
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/SecondX64.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/SecondX64.wxs new file mode 100644 index 00000000..e72b6402 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/SecondX64.wxs | |||
@@ -0,0 +1,8 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
3 | <Fragment> | ||
4 | <ComponentGroup Id="ProductComponents"> | ||
5 | <ComponentGroupRef Id="MinimalComponentGroup" /> | ||
6 | </ComponentGroup> | ||
7 | </Fragment> | ||
8 | </Wix> | ||
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/SecondX86.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/SecondX86.wxs new file mode 100644 index 00000000..e72b6402 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/SecondX86.wxs | |||
@@ -0,0 +1,8 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
3 | <Fragment> | ||
4 | <ComponentGroup Id="ProductComponents"> | ||
5 | <ComponentGroupRef Id="MinimalComponentGroup" /> | ||
6 | </ComponentGroup> | ||
7 | </Fragment> | ||
8 | </Wix> | ||
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/X64AfterX86Bundle.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/X64AfterX86Bundle.wxs new file mode 100644 index 00000000..8f4fc8bd --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/X64AfterX86Bundle.wxs | |||
@@ -0,0 +1,12 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
3 | <Fragment> | ||
4 | <PackageGroup Id="BundlePackages"> | ||
5 | <MsiPackage SourceFile="FirstX64.msi" /> | ||
6 | <RollbackBoundary Transaction="yes" /> | ||
7 | <MsiPackage SourceFile="FirstX86.msi" /> | ||
8 | <MsiPackage SourceFile="SecondX86.msi" /> | ||
9 | <MsiPackage SourceFile="SecondX64.msi" /> | ||
10 | </PackageGroup> | ||
11 | </Fragment> | ||
12 | </Wix> | ||
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/X86AfterX64Bundle.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/X86AfterX64Bundle.wxs new file mode 100644 index 00000000..221f06c5 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/X86AfterX64Bundle.wxs | |||
@@ -0,0 +1,12 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
3 | <Fragment> | ||
4 | <PackageGroup Id="BundlePackages"> | ||
5 | <MsiPackage SourceFile="FirstX86.msi" /> | ||
6 | <RollbackBoundary Transaction="yes" /> | ||
7 | <MsiPackage SourceFile="FirstX64.msi" /> | ||
8 | <MsiPackage SourceFile="SecondX64.msi" /> | ||
9 | <MsiPackage SourceFile="SecondX86.msi" /> | ||
10 | </PackageGroup> | ||
11 | </Fragment> | ||
12 | </Wix> | ||
diff --git a/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj b/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj index fdb56987..8e5a005c 100644 --- a/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj +++ b/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj | |||
@@ -64,6 +64,12 @@ | |||
64 | <Content Include="TestData\Font\TrueType.wxs" CopyToOutputDirectory="PreserveNewest" /> | 64 | <Content Include="TestData\Font\TrueType.wxs" CopyToOutputDirectory="PreserveNewest" /> |
65 | <Content Include="TestData\Icon\SampleIcon.wxs" CopyToOutputDirectory="PreserveNewest" /> | 65 | <Content Include="TestData\Icon\SampleIcon.wxs" CopyToOutputDirectory="PreserveNewest" /> |
66 | <Content Include="TestData\LockPermissions\EmptyPermissions.wxs" CopyToOutputDirectory="PreserveNewest" /> | 66 | <Content Include="TestData\LockPermissions\EmptyPermissions.wxs" CopyToOutputDirectory="PreserveNewest" /> |
67 | <Content Include="TestData\MsiTransaction\FirstX64.wxs" CopyToOutputDirectory="PreserveNewest" /> | ||
68 | <Content Include="TestData\MsiTransaction\FirstX86.wxs" CopyToOutputDirectory="PreserveNewest" /> | ||
69 | <Content Include="TestData\MsiTransaction\SecondX64.wxs" CopyToOutputDirectory="PreserveNewest" /> | ||
70 | <Content Include="TestData\MsiTransaction\SecondX86.wxs" CopyToOutputDirectory="PreserveNewest" /> | ||
71 | <Content Include="TestData\MsiTransaction\X64AfterX86Bundle.wxs" CopyToOutputDirectory="PreserveNewest" /> | ||
72 | <Content Include="TestData\MsiTransaction\X86AfterX64Bundle.wxs" CopyToOutputDirectory="PreserveNewest" /> | ||
67 | <Content Include="TestData\PatchFamilyFilter\.data\Av1.0.0.txt" CopyToOutputDirectory="PreserveNewest" /> | 73 | <Content Include="TestData\PatchFamilyFilter\.data\Av1.0.0.txt" CopyToOutputDirectory="PreserveNewest" /> |
68 | <Content Include="TestData\PatchFamilyFilter\.data\Av1.0.1.txt" CopyToOutputDirectory="PreserveNewest" /> | 74 | <Content Include="TestData\PatchFamilyFilter\.data\Av1.0.1.txt" CopyToOutputDirectory="PreserveNewest" /> |
69 | <Content Include="TestData\PatchFamilyFilter\.data\Bv1.0.0.txt" CopyToOutputDirectory="PreserveNewest" /> | 75 | <Content Include="TestData\PatchFamilyFilter\.data\Bv1.0.0.txt" CopyToOutputDirectory="PreserveNewest" /> |