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 /src | |
| parent | 2a8f47e357bfbfe20c962cade4455793e45dae7c (diff) | |
| download | wix-5a874790ba9ec6c2d3c9002699114c2fe4c493ae.tar.gz wix-5a874790ba9ec6c2d3c9002699114c2fe4c493ae.tar.bz2 wix-5a874790ba9ec6c2d3c9002699114c2fe4c493ae.zip | |
MSI transaction cleanup.
Diffstat (limited to 'src')
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" /> |
