Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add default major upgrade. #478

Merged
merged 1 commit into from
Dec 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/api/wix/WixToolset.Data/Symbols/WixPackageSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ public enum WixPackageAttributes
PerMachine = 0x1,
}

public enum WixPackageUpgradeStrategy
{
None = 0x0,
MajorUpgrade = 0x1,
}

public class WixPackageSymbol : IntermediateSymbol
{
public WixPackageSymbol() : base(SymbolDefinitions.WixPackage, null, null)
Expand Down Expand Up @@ -106,6 +112,12 @@ public string Codepage
set => this.Set((int)WixPackageSymbolFields.Codepage, value);
}

public WixPackageUpgradeStrategy UpgradeStrategy
{
get => (WixPackageUpgradeStrategy)this.Fields[(int)WixPackageSymbolFields.Attributes].AsNumber();
set => this.Set((int)WixPackageSymbolFields.Attributes, (int)value);
}

public bool PerMachine => (this.Attributes & WixPackageAttributes.PerMachine) == WixPackageAttributes.PerMachine;
}
}
12 changes: 11 additions & 1 deletion src/api/wix/WixToolset.Data/WixStandardLibrary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,17 @@ public static Intermediate Build(Platform platform)

private static IEnumerable<Localization> YieldLocalizations()
{
var strings = new BindVariable[0];
var sourceLineNumber = new SourceLineNumber("wixstd.wixlib");

var strings = new[] {
new BindVariable()
{
SourceLineNumbers = sourceLineNumber,
Id = "WixDowngradePreventedMessage",
Value = "A newer version of [ProductName] is already installed.",
Overridable = true,
},
};

var localizedControls = new LocalizedControl[0];

Expand Down
5 changes: 5 additions & 0 deletions src/api/wix/WixToolset.Data/WixStandardLibraryIdentifiers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,10 @@ public static class WixStandardLibraryIdentifiers
/// Default feature name.
/// </summary>
public static readonly string DefaultFeatureName = "WixDefaultFeature";

/// <summary>
/// WiX Standard localization strings.
/// </summary>
public static readonly string WixStandardLocalizationStrings = "WixStandardLocalizationStrings";
}
}
17 changes: 17 additions & 0 deletions src/wix/WixToolset.Core/Compiler_Package.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ private void ParsePackageElement(XElement node)
var isPackageNameSet = false;
var isKeywordsSet = false;
var isPackageAuthorSet = false;
var upgradeStrategy = WixPackageUpgradeStrategy.MajorUpgrade;

this.GetDefaultPlatformAndInstallerVersion(out var platform, out var msiVersion);

Expand Down Expand Up @@ -111,6 +112,21 @@ private void ParsePackageElement(XElement node)
case "UpgradeCode":
upgradeCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false);
break;
case "UpgradeStrategy":
var strategy = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
switch (strategy)
{
case "majorUpgrade":
upgradeStrategy = WixPackageUpgradeStrategy.MajorUpgrade;
break;
case "none":
upgradeStrategy = WixPackageUpgradeStrategy.None;
break;
default:
this.Core.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, strategy, "majorUpgrade", "none"));
break;
}
break;
case "Version":
version = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib);
break;
Expand Down Expand Up @@ -382,6 +398,7 @@ private void ParsePackageElement(XElement node)
Manufacturer = manufacturer,
Attributes = isPerMachine ? WixPackageAttributes.PerMachine : WixPackageAttributes.None,
Codepage = codepage,
UpgradeStrategy = upgradeStrategy,
});

if (!isCommentsSet)
Expand Down
67 changes: 64 additions & 3 deletions src/wix/WixToolset.Core/Link/AddDefaultSymbolsCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace WixToolset.Core.Link
{
using System;
using System.Collections.Generic;
using System.Linq;
using WixToolset.Data;
Expand Down Expand Up @@ -49,20 +50,80 @@ public void Execute()
}
);
}

var symbols = this.Sections.SelectMany(section => section.Symbols);
var upgradeSymbols = symbols.OfType<UpgradeSymbol>();
if (!upgradeSymbols.Any())
{
var packageSymbol = this.Find.EntrySection.Symbols.OfType<WixPackageSymbol>().FirstOrDefault();

if (packageSymbol?.UpgradeStrategy == WixPackageUpgradeStrategy.MajorUpgrade
&& !String.IsNullOrEmpty(packageSymbol?.UpgradeCode))
robmen marked this conversation as resolved.
Show resolved Hide resolved
{
this.AddDefaultMajorUpgrade(packageSymbol);
}
}
}

private void AddDefaultMajorUpgrade(WixPackageSymbol packageSymbol)
{
this.AddSymbols(this.Find.EntrySection,
new UpgradeSymbol(packageSymbol.SourceLineNumbers)
{
UpgradeCode = packageSymbol.UpgradeCode,
MigrateFeatures = true,
ActionProperty = WixUpgradeConstants.UpgradeDetectedProperty,
VersionMax = packageSymbol.Version,
Language = packageSymbol.Language,
},
new UpgradeSymbol(packageSymbol.SourceLineNumbers)
{
UpgradeCode = packageSymbol.UpgradeCode,
VersionMin = packageSymbol.Version,
Language = packageSymbol.Language,
OnlyDetect = true,
ActionProperty = WixUpgradeConstants.DowngradeDetectedProperty,
},
new LaunchConditionSymbol(packageSymbol.SourceLineNumbers)
{
Condition = WixUpgradeConstants.DowngradePreventedCondition,
Description = "!(loc.WixDowngradePreventedMessage)",
},
new WixActionSymbol(packageSymbol.SourceLineNumbers,
new Identifier(AccessModifier.Global, SequenceTable.InstallExecuteSequence, "RemoveExistingProducts"))
{
SequenceTable = SequenceTable.InstallExecuteSequence,
Action = "RemoveExistingProducts",
After = "InstallValidate",
},
new WixSimpleReferenceSymbol(packageSymbol.SourceLineNumbers)
{
Table = SymbolDefinitions.WixAction.Name,
PrimaryKeys = "InstallExecuteSequence/InstallValidate",
});
}

private void AddSymbolsToNewSection(string sectionId, params IntermediateSymbol[] symbols)
{
var section = new IntermediateSection(sectionId, SectionType.Fragment);

this.Sections.Add(section);

this.AddSymbols(section, symbols);
}

private void AddSymbols(IntermediateSection section, params IntermediateSymbol[] symbols)
{
foreach (var symbol in symbols)
{
section.AddSymbol(symbol);

var symbolWithSection = new SymbolWithSection(section, symbol);
var fullName = symbolWithSection.GetFullName();
this.Find.SymbolsByName.Add(fullName, symbolWithSection);
if (!String.IsNullOrEmpty(symbol.Id?.Id))
{
var symbolWithSection = new SymbolWithSection(section, symbol);
var fullName = symbolWithSection.GetFullName();
this.Find.SymbolsByName.Add(fullName, symbolWithSection);
}
}
}
}
Expand Down
7 changes: 6 additions & 1 deletion src/wix/WixToolset.Core/Linker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public Intermediate Link(ILinkContext context)
if (library.Localizations?.Count > 0)
{
// Include localizations from the extension data and be sure to note that the localization came from
// an extension. It is important to remember whiche localization came from an extension when filtering
// an extension. It is important to remember which localization came from an extension when filtering
// localizations during the resolve process later.
localizations.AddRange(library.Localizations.Select(l => l.UpdateLocation(LocalizationLocation.Extension)));
}
Expand All @@ -103,6 +103,11 @@ public Intermediate Link(ILinkContext context)
var stdlib = WixStandardLibrary.Build(this.Context.Platform);

sections.AddRange(stdlib.Sections);

if (stdlib.Localizations?.Count > 0)
{
localizations.AddRange(stdlib.Localizations);
}
}

var multipleFeatureComponents = new Hashtable();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Package Name="MajorUpgradeDowngradeMessage" Language="1033" Version="2.0.0" Manufacturer="Example Corporation" UpgradeCode="7ab24276-c628-43db-9e65-a184d052909b" Scope="perMachine">
<Feature Id="ProductFeature" Title="MsiPackageTitle">
</Feature>
</Package>

<Fragment>
<StandardDirectory Id="ProgramFiles6432Folder">
<Directory Id="INSTALLFOLDER" Name="MsiPackage" />
</StandardDirectory>
</Fragment>
</Wix>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Package Name="MajorUpgradeDowngradeMessage" UpgradeStrategy="none" Language="1033" Version="2.0.0" Manufacturer="Example Corporation" UpgradeCode="7ab24276-c628-43db-9e65-a184d052909b" Scope="perMachine">
<Feature Id="ProductFeature" Title="MsiPackageTitle">
</Feature>
</Package>

<Fragment>
<StandardDirectory Id="ProgramFiles6432Folder">
<Directory Id="INSTALLFOLDER" Name="MsiPackage" />
</StandardDirectory>
</Fragment>
</Wix>
25 changes: 25 additions & 0 deletions src/wix/test/WixToolsetTest.CoreIntegration/UpgradeFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,31 @@ public void MajorUpgradeDowngradeMessagePopulatesRowsAsExpected()
}, results);
}

[Fact]
public void DefaultMajorUpgradePopulatesUpgradeRowsAsExpected()
{
var folder = TestData.Get("TestData", "DefaultMajorUpgrade");
var build = new Builder(folder, new Type[] { }, new[] { folder });

var results = build.BuildAndQuery(Build, "Upgrade", "LaunchCondition");
WixAssert.CompareLineByLine(new[]
{
"LaunchCondition:NOT WIX_DOWNGRADE_DETECTED\tA newer version of [ProductName] is already installed.",
"Upgrade:{7AB24276-C628-43DB-9E65-A184D052909B}\t\t2.0.0\t1033\t1\t\tWIX_UPGRADE_DETECTED",
"Upgrade:{7AB24276-C628-43DB-9E65-A184D052909B}\t2.0.0\t\t1033\t2\t\tWIX_DOWNGRADE_DETECTED",
}, results);
}

[Fact]
public void UpgradeStrategyNoneDoesNotCreateDefaultMajorUpgrade()
{
var folder = TestData.Get("TestData", "DefaultMajorUpgradeNone");
var build = new Builder(folder, new Type[] { }, new[] { folder });

var results = build.BuildAndQuery(Build, "Upgrade", "LaunchCondition");
Assert.Empty(results);
}

private static void Build(string[] args)
{
var result = WixRunner.Execute(args);
Expand Down