Skip to content
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
64 changes: 64 additions & 0 deletions src/winapp-CLI/WinApp.Cli.Tests/MrtAssetHelperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,70 @@ public void ExpandManifestReferencedFiles_DeduplicatesAcrossReferences()

#endregion

#region ExpandManifestReferencedFiles — unplated variants

[TestMethod]
public void ExpandManifestReferencedFiles_IncludesUnplatedVariants()
{
// Arrange — create asset directory with base icon + unplated variants
var assetsDir = Directory.CreateDirectory(Path.Combine(_tempDir.FullName, "Assets"));
var assetFiles = new[]
{
"Square44x44Logo.png",
"Square44x44Logo.targetsize-16.png",
"Square44x44Logo.targetsize-16_altform-unplated.png",
"Square44x44Logo.targetsize-24.png",
"Square44x44Logo.targetsize-24_altform-unplated.png",
"Square44x44Logo.targetsize-48.png",
"Square44x44Logo.targetsize-48_altform-unplated.png",
"Square44x44Logo.scale-200.png",
};
foreach (var file in assetFiles)
{
File.WriteAllBytes(Path.Combine(assetsDir.FullName, file), [0]);
}

var result = MrtAssetHelper.ExpandManifestReferencedFiles(
_tempDir,
[@"Assets\Square44x44Logo.png"],
taskContext: null);

// Assert — all variants including unplated must be discovered for PRI generation
Assert.AreEqual(assetFiles.Length, result.Count, "Should expand to all MRT variants in the directory");
Assert.IsTrue(result.Any(f => f.RelativePath.Contains("altform-unplated", StringComparison.OrdinalIgnoreCase)),
"Should discover altform-unplated variants for taskbar icon resolution");
}

[TestMethod]
public void ExpandManifestReferencedFiles_IncludesLightUnplatedVariants()
{
var assetsDir = Directory.CreateDirectory(Path.Combine(_tempDir.FullName, "Assets"));
var assetFiles = new[]
{
"AppList.png",
"AppList.targetsize-32.png",
"AppList.targetsize-32_altform-unplated.png",
"AppList.targetsize-32_altform-lightunplated.png",
};
foreach (var file in assetFiles)
{
File.WriteAllBytes(Path.Combine(assetsDir.FullName, file), [0]);
}

var result = MrtAssetHelper.ExpandManifestReferencedFiles(
_tempDir,
[@"Assets\AppList.png"],
taskContext: null);

Assert.AreEqual(assetFiles.Length, result.Count);
Assert.IsTrue(result.Any(f => f.RelativePath.Contains("altform-unplated", StringComparison.OrdinalIgnoreCase)),
"Should discover altform-unplated variants");
Assert.IsTrue(result.Any(f => f.RelativePath.Contains("altform-lightunplated", StringComparison.OrdinalIgnoreCase)),
"Should discover altform-lightunplated variants");
}

#endregion

#region PriIncludedExtensions

[TestMethod]
Expand Down
71 changes: 69 additions & 2 deletions src/winapp-CLI/WinApp.Cli/Services/MsixService.Identity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -621,22 +621,89 @@ private async Task RunMtToolAsync(string arguments, bool printErrors, TaskContex

taskContext.AddDebugMessage($"{UiSymbols.Files} Created debug manifest: {debugManifestPath.FullName}");

// Step 6: Copy all assets
// Step 6: Copy all assets and generate resources.pri
var entryPointDir = Path.GetDirectoryName(entryPointPath);
if (!string.IsNullOrEmpty(entryPointDir))
{
var entryPointDirInfo = new DirectoryInfo(entryPointDir);
var originalManifestDir = originalManifestPath.DirectoryName;
var expandedFiles = MrtAssetHelper.GetExpandedManifestReferencedFiles(originalManifestPath, taskContext);

if (!string.Equals(originalManifestDir, entryPointDirInfo.FullName, StringComparison.OrdinalIgnoreCase))
{
var expandedFiles = MrtAssetHelper.GetExpandedManifestReferencedFiles(originalManifestPath, taskContext);
MrtAssetHelper.CopyAllAssets(expandedFiles, entryPointDirInfo, taskContext);
}
else
{
taskContext.AddDebugMessage($"{UiSymbols.Warning} Manifest directory and target directory are the same, skipping assets copy");
}

// Generate resources.pri in a temporary staging directory, then copy only the
// final resources.pri into the ExternalLocation (entry point directory). This avoids
// leaving intermediate files such as priconfig.xml and pri.resfiles alongside app output.
// Sparse packages look for resources.pri in the ExternalLocation, not alongside the manifest.
if (expandedFiles.Count > 0)
{
string? priStagingDir = null;

try
{
taskContext.AddDebugMessage($"{UiSymbols.Note} Generating PRI for asset resource resolution...");
var priResourceCandidates = expandedFiles.Select(file => file.RelativePath).ToArray();

priStagingDir = Path.Combine(
Path.GetTempPath(),
"WinAppCli-Pri-" + Guid.NewGuid().ToString("N"));

var priStagingDirInfo = Directory.CreateDirectory(priStagingDir);
MrtAssetHelper.CopyAllAssets(expandedFiles, priStagingDirInfo, taskContext);

await priService.CreatePriConfigAsync(
priStagingDirInfo,
taskContext,
precomputedPriResourceCandidates: priResourceCandidates,
cancellationToken: cancellationToken);
await priService.GeneratePriFileAsync(priStagingDirInfo, taskContext, cancellationToken: cancellationToken);

var stagedPriPath = Path.Combine(priStagingDirInfo.FullName, "resources.pri");
var targetPriPath = Path.Combine(entryPointDirInfo.FullName, "resources.pri");

if (!File.Exists(stagedPriPath))
{
throw new FileNotFoundException("Generated resources.pri was not found in the staging directory.", stagedPriPath);
}

if (File.Exists(targetPriPath))
{
File.Delete(targetPriPath);
}

File.Copy(stagedPriPath, targetPriPath);
taskContext.AddDebugMessage($"{UiSymbols.Check} Generated resources.pri in entry point directory");
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
taskContext.AddDebugMessage($"{UiSymbols.Warning} Failed to generate PRI: {ex.Message}");
}
Comment thread
chiaramooney marked this conversation as resolved.
finally
{
if (!string.IsNullOrWhiteSpace(priStagingDir) && Directory.Exists(priStagingDir))
{
try
{
Directory.Delete(priStagingDir, recursive: true);
}
catch (Exception cleanupEx)
{
taskContext.AddDebugMessage($"{UiSymbols.Warning} Failed to clean up PRI staging directory '{priStagingDir}': {cleanupEx.Message}");
}
}
}
}
}

return (debugManifestPath, debugIdentity);
Expand Down
Loading