Beispiel #1
0
        public override bool Execute()
        {
            var filesToRemove   = new List <ITaskItem>();
            var assetCandidates = new List <ITaskItem>();

            try
            {
                if (ProjectAssembly.Length != 1)
                {
                    Log.LogError("Invalid number of project assemblies '{0}'", string.Join("," + Environment.NewLine, ProjectAssembly.Select(a => a.ItemSpec)));
                    return(true);
                }

                if (ProjectDebugSymbols.Length > 1)
                {
                    Log.LogError("Invalid number of symbol assemblies '{0}'", string.Join("," + Environment.NewLine, ProjectDebugSymbols.Select(a => a.ItemSpec)));
                    return(true);
                }

                for (int i = 0; i < Candidates.Length; i++)
                {
                    var candidate = Candidates[i];
                    if (ShouldFilterCandidate(candidate, TimeZoneSupport, InvariantGlobalization, CopySymbols, out var reason))
                    {
                        Log.LogMessage("Skipping asset '{0}' because '{1}'", candidate.ItemSpec, reason);
                        filesToRemove.Add(candidate);
                        continue;
                    }

                    var satelliteAssembly = SatelliteAssemblies.FirstOrDefault(s => s.ItemSpec == candidate.ItemSpec);
                    if (satelliteAssembly != null)
                    {
                        var inferredCulture = satelliteAssembly.GetMetadata("DestinationSubDirectory").Trim('\\', '/');
                        Log.LogMessage("Found satellite assembly '{0}' asset for candidate '{1}' with inferred culture '{2}'", satelliteAssembly.ItemSpec, candidate.ItemSpec, inferredCulture);

                        var assetCandidate = new TaskItem(satelliteAssembly);
                        assetCandidate.SetMetadata("AssetKind", "Build");
                        assetCandidate.SetMetadata("AssetRole", "Related");
                        assetCandidate.SetMetadata("AssetTraitName", "Culture");
                        assetCandidate.SetMetadata("AssetTraitValue", inferredCulture);
                        assetCandidate.SetMetadata("RelativePath", $"_framework/{inferredCulture}/{satelliteAssembly.GetMetadata("FileName")}{satelliteAssembly.GetMetadata("Extension")}");
                        assetCandidate.SetMetadata("RelatedAsset", Path.GetFullPath(Path.Combine(OutputPath, "wwwroot", "_framework", Path.GetFileName(assetCandidate.GetMetadata("ResolvedFrom")))));

                        assetCandidates.Add(assetCandidate);
                        continue;
                    }

                    var destinationSubPath = candidate.GetMetadata("DestinationSubPath");
                    if (candidate.GetMetadata("FileName") == "dotnet" && candidate.GetMetadata("Extension") == ".js")
                    {
                        var itemHash = FileHasher.GetFileHash(candidate.ItemSpec);
                        var cacheBustedDotNetJSFileName = $"dotnet.{BundledNETCoreAppPackageVersion}.{itemHash}.js";

                        var originalFileFullPath  = Path.GetFullPath(candidate.ItemSpec);
                        var originalFileDirectory = Path.GetDirectoryName(originalFileFullPath);

                        var cacheBustedDotNetJSFullPath = Path.Combine(originalFileDirectory, cacheBustedDotNetJSFileName);

                        var newDotNetJs = new TaskItem(cacheBustedDotNetJSFullPath, candidate.CloneCustomMetadata());
                        newDotNetJs.SetMetadata("OriginalItemSpec", candidate.ItemSpec);

                        var newRelativePath = $"_framework/{cacheBustedDotNetJSFileName}";
                        newDotNetJs.SetMetadata("RelativePath", newRelativePath);

                        newDotNetJs.SetMetadata("AssetTraitName", "BlazorWebAssemblyResource");
                        newDotNetJs.SetMetadata("AssetTraitValue", "native");

                        assetCandidates.Add(newDotNetJs);
                        continue;
                    }
                    else if (string.IsNullOrEmpty(destinationSubPath))
                    {
                        var relativePath = candidate.GetMetadata("FileName") + candidate.GetMetadata("Extension");
                        candidate.SetMetadata("RelativePath", $"_framework/{relativePath}");
                    }
                    else
                    {
                        candidate.SetMetadata("RelativePath", $"_framework/{destinationSubPath}");
                    }

                    var culture = candidate.GetMetadata("Culture");
                    if (!string.IsNullOrEmpty(culture))
                    {
                        candidate.SetMetadata("AssetKind", "Build");
                        candidate.SetMetadata("AssetRole", "Related");
                        candidate.SetMetadata("AssetTraitName", "Culture");
                        candidate.SetMetadata("AssetTraitValue", culture);
                        var fileName         = candidate.GetMetadata("FileName");
                        var suffixIndex      = fileName.Length - ".resources".Length;
                        var relatedAssetPath = Path.GetFullPath(Path.Combine(
                                                                    OutputPath,
                                                                    "wwwroot",
                                                                    "_framework",
                                                                    fileName.Substring(0, suffixIndex) + ProjectAssembly[0].GetMetadata("Extension")));

                        candidate.SetMetadata("RelatedAsset", relatedAssetPath);

                        Log.LogMessage("Found satellite assembly '{0}' asset for inferred candidate '{1}' with culture '{2}'", candidate.ItemSpec, relatedAssetPath, culture);
                    }

                    assetCandidates.Add(candidate);
                }

                var intermediateAssembly = new TaskItem(ProjectAssembly[0]);
                intermediateAssembly.SetMetadata("RelativePath", $"_framework/{intermediateAssembly.GetMetadata("FileName")}{intermediateAssembly.GetMetadata("Extension")}");
                assetCandidates.Add(intermediateAssembly);

                if (ProjectDebugSymbols.Length > 0)
                {
                    var debugSymbols = new TaskItem(ProjectDebugSymbols[0]);
                    debugSymbols.SetMetadata("RelativePath", $"_framework/{debugSymbols.GetMetadata("FileName")}{debugSymbols.GetMetadata("Extension")}");
                    assetCandidates.Add(debugSymbols);
                }

                for (int i = 0; i < ProjectSatelliteAssemblies.Length; i++)
                {
                    var projectSatelliteAssembly = ProjectSatelliteAssemblies[i];
                    var candidateCulture         = projectSatelliteAssembly.GetMetadata("Culture");
                    Log.LogMessage(
                        "Found satellite assembly '{0}' asset for project '{1}' with culture '{2}'",
                        projectSatelliteAssembly.ItemSpec,
                        intermediateAssembly.ItemSpec,
                        candidateCulture);

                    var assetCandidate           = new TaskItem(Path.GetFullPath(projectSatelliteAssembly.ItemSpec), projectSatelliteAssembly.CloneCustomMetadata());
                    var projectAssemblyAssetPath = Path.GetFullPath(Path.Combine(
                                                                        OutputPath,
                                                                        "wwwroot",
                                                                        "_framework",
                                                                        ProjectAssembly[0].GetMetadata("FileName") + ProjectAssembly[0].GetMetadata("Extension")));

                    var normalizedPath = assetCandidate.GetMetadata("TargetPath").Replace('\\', '/');

                    assetCandidate.SetMetadata("AssetKind", "Build");
                    assetCandidate.SetMetadata("AssetRole", "Related");
                    assetCandidate.SetMetadata("AssetTraitName", "Culture");
                    assetCandidate.SetMetadata("AssetTraitValue", candidateCulture);
                    assetCandidate.SetMetadata("RelativePath", Path.Combine("_framework", normalizedPath));
                    assetCandidate.SetMetadata("RelatedAsset", projectAssemblyAssetPath);

                    assetCandidates.Add(assetCandidate);
                }

                for (var i = 0; i < assetCandidates.Count; i++)
                {
                    var candidate = assetCandidates[i];
                    ApplyUniqueMetadataProperties(candidate);
                }
            }
            catch (Exception ex)
            {
                Log.LogError(ex.ToString());
                return(false);
            }

            FilesToRemove   = filesToRemove.ToArray();
            AssetCandidates = assetCandidates.ToArray();

            return(!Log.HasLoggedErrors);
        }
Beispiel #2
0
        private List <ITaskItem> ProcessNativeAssets(
            Dictionary <string, ITaskItem> nativeAssets,
            IDictionary <string, ITaskItem> resolvedPublishFilesToRemove,
            Dictionary <string, ITaskItem> resolvedNativeAssetToPublish,
            Dictionary <string, ITaskItem> compressedRepresentations,
            List <ITaskItem> filesToRemove)
        {
            var nativeStaticWebAssets = new List <ITaskItem>();

            // Keep track of the updated assets to determine what compressed assets we can reuse
            var updateMap = new Dictionary <string, ITaskItem>();

            foreach (var kvp in nativeAssets)
            {
                var key          = kvp.Key;
                var asset        = kvp.Value;
                var isDotNetJs   = IsDotNetJs(key);
                var isDotNetWasm = IsDotNetWasm(key);
                if (!isDotNetJs && !isDotNetWasm)
                {
                    if (resolvedNativeAssetToPublish.TryGetValue(Path.GetFileName(asset.GetMetadata("OriginalItemSpec")), out var existing))
                    {
                        if (!resolvedPublishFilesToRemove.TryGetValue(existing.ItemSpec, out var removed))
                        {
                            // This is a native asset like timezones.blat or similar that was not filtered and that needs to be updated
                            // to a publish asset.
                            var newAsset = new TaskItem(asset);
                            ApplyPublishProperties(newAsset);
                            nativeStaticWebAssets.Add(newAsset);
                            filesToRemove.Add(existing);
                            updateMap.Add(asset.ItemSpec, newAsset);
                            Log.LogMessage(MessageImportance.Low, "Promoting asset '{0}' to Publish asset.", asset.ItemSpec);
                        }
                        else
                        {
                            // This was a file that was filtered, so just remove it, we don't need to add any publish static web asset
                            filesToRemove.Add(removed);

                            // Remove the file from the list to avoid double processing later when we process other files we filtered.
                            resolvedPublishFilesToRemove.Remove(existing.ItemSpec);
                        }
                    }

                    continue;
                }

                if (isDotNetJs)
                {
                    var       aotDotNetJs = WasmAotAssets.SingleOrDefault(a => $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}" == "dotnet.js");
                    ITaskItem newDotNetJs = null;
                    if (aotDotNetJs != null)
                    {
                        newDotNetJs = new TaskItem(Path.GetFullPath(aotDotNetJs.ItemSpec), asset.CloneCustomMetadata());
                        newDotNetJs.SetMetadata("OriginalItemSpec", aotDotNetJs.ItemSpec);
                        newDotNetJs.SetMetadata("RelativePath", $"_framework/{$"dotnet.{DotNetJsVersion}.{FileHasher.GetFileHash(aotDotNetJs.ItemSpec)}.js"}");

                        updateMap.Add(asset.ItemSpec, newDotNetJs);
                        Log.LogMessage(MessageImportance.Low, "Replacing asset '{0}' with AoT version '{1}'", asset.ItemSpec, newDotNetJs.ItemSpec);
                    }
                    else
                    {
                        newDotNetJs = new TaskItem(asset);
                        Log.LogMessage(MessageImportance.Low, "Promoting asset '{0}' to Publish asset.", asset.ItemSpec);
                    }

                    ApplyPublishProperties(newDotNetJs);
                    nativeStaticWebAssets.Add(newDotNetJs);
                    if (resolvedNativeAssetToPublish.TryGetValue("dotnet.js", out var resolved))
                    {
                        filesToRemove.Add(resolved);
                    }
                    continue;
                }

                if (isDotNetWasm)
                {
                    var       aotDotNetWasm = WasmAotAssets.SingleOrDefault(a => $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}" == "dotnet.wasm");
                    ITaskItem newDotNetWasm = null;
                    if (aotDotNetWasm != null)
                    {
                        newDotNetWasm = new TaskItem(Path.GetFullPath(aotDotNetWasm.ItemSpec), asset.CloneCustomMetadata());
                        newDotNetWasm.SetMetadata("OriginalItemSpec", aotDotNetWasm.ItemSpec);
                        updateMap.Add(asset.ItemSpec, newDotNetWasm);
                        Log.LogMessage(MessageImportance.Low, "Replacing asset '{0}' with AoT version '{1}'", asset.ItemSpec, newDotNetWasm.ItemSpec);
                    }
                    else
                    {
                        newDotNetWasm = new TaskItem(asset);
                        Log.LogMessage(MessageImportance.Low, "Promoting asset '{0}' to Publish asset.", asset.ItemSpec);
                    }

                    ApplyPublishProperties(newDotNetWasm);
                    nativeStaticWebAssets.Add(newDotNetWasm);
                    if (resolvedNativeAssetToPublish.TryGetValue("dotnet.wasm", out var resolved))
                    {
                        filesToRemove.Add(resolved);
                    }
                    continue;
                }
            }

            var compressedUpdatedFiles = ProcessCompressedAssets(compressedRepresentations, nativeAssets, updateMap);

            foreach (var f in compressedUpdatedFiles)
            {
                nativeStaticWebAssets.Add(f);
            }

            return(nativeStaticWebAssets);