private (string identity, bool computed) ComputeCandidateIdentity(ITaskItem candidate, string contentRoot, string relativePath, Matcher matcher) { var candidateFullPath = Path.GetFullPath(candidate.GetMetadata("FullPath")); if (contentRoot == null) { Log.LogMessage(MessageImportance.Low, "Identity for candidate '{0}' is '{1}' because content root is not defined.", candidate.ItemSpec, candidateFullPath); return(candidateFullPath, false); } var normalizedContentRoot = StaticWebAsset.NormalizeContentRootPath(contentRoot); if (candidateFullPath.StartsWith(normalizedContentRoot)) { Log.LogMessage(MessageImportance.Low, "Identity for candidate '{0}' is '{1}' because it starts with content root '{2}'.", candidate.ItemSpec, candidateFullPath, normalizedContentRoot); return(candidateFullPath, false); } else { // We want to support assets that are part of the source codebase but that might get transformed during the build or // publish processes, so we want to allow defining these assets by setting up a different content root path from their // original location in the project. For example the asset can be wwwroot\my-prod-asset.js, the content root can be // obj\transform and the final asset identity can be <<FullPathTo>>\obj\transform\my-prod-asset.js var matchResult = matcher?.Match(candidate.ItemSpec); if (matcher == null) { // If no relative path pattern was specified, we are going to suggest that the identity is `%(ContentRoot)\RelativePath\OriginalFileName` // We don't want to use the relative path file name since multiple assets might map to that and conflicts might arise. // Alternatively, we could be explicit here and support ContentRootSubPath to indicate where it needs to go. var identitySubPath = Path.GetDirectoryName(relativePath); var itemSpecFileName = Path.GetFileName(candidateFullPath); var finalIdentity = Path.Combine(normalizedContentRoot, identitySubPath, itemSpecFileName); Log.LogMessage(MessageImportance.Low, "Identity for candidate '{0}' is '{1}' because it did not start with the content root '{2}'", candidate.ItemSpec, finalIdentity, normalizedContentRoot); return(finalIdentity, true); } else if (!matchResult.HasMatches) { Log.LogMessage(MessageImportance.Low, "Identity for candidate '{0}' is '{1}' because it didn't match the relative path pattern", candidate.ItemSpec, candidateFullPath); return(candidateFullPath, false); } else { var stem = matchResult.Files.Single().Stem; var assetIdentity = Path.GetFullPath(Path.Combine(normalizedContentRoot, stem)); Log.LogMessage(MessageImportance.Low, "Computed identity '{0}' for candidate '{1}'", assetIdentity, candidate.ItemSpec); return(assetIdentity, true); } } }
private string GetCandidateMatchPath(ITaskItem candidate) { var relativePath = candidate.GetMetadata("RelativePath"); if (!string.IsNullOrEmpty(relativePath)) { var normalizedPath = StaticWebAsset.Normalize(relativePath, allowEmpyPath: true); Log.LogMessage(MessageImportance.Low, "RelativePath '{0}' normalized to '{1}' found for candidate '{2}' and will be used for matching.", relativePath, normalizedPath, candidate.ItemSpec); return(normalizedPath); } var targetPath = candidate.GetMetadata("TargetPath"); if (!string.IsNullOrEmpty(targetPath)) { var normalizedPath = StaticWebAsset.Normalize(targetPath, allowEmpyPath: true); Log.LogMessage(MessageImportance.Low, "TargetPath '{0}' normalized to '{1}' found for candidate '{2}' and will be used for matching.", targetPath, normalizedPath, candidate.ItemSpec); return(normalizedPath); } var linkPath = candidate.GetMetadata("Link"); if (!string.IsNullOrEmpty(linkPath)) { var normalizedPath = StaticWebAsset.Normalize(linkPath, allowEmpyPath: true); Log.LogMessage(MessageImportance.Low, "Link '{0}' normalized to '{1}' found for candidate '{2}' and will be used for matching.", linkPath, normalizedPath, candidate.ItemSpec); return(linkPath); } var normalizedContentRoot = StaticWebAsset.NormalizeContentRootPath(string.IsNullOrEmpty(candidate.GetMetadata(nameof(StaticWebAsset.ContentRoot))) ? ContentRoot : candidate.GetMetadata(nameof(StaticWebAsset.ContentRoot))); var normalizedAssetPath = Path.GetFullPath(candidate.GetMetadata("FullPath")); if (normalizedAssetPath.StartsWith(normalizedContentRoot)) { return(normalizedAssetPath.Substring(normalizedContentRoot.Length)); } else { return(candidate.ItemSpec); } }
public override bool Execute() { var copyToOutputFolder = new List <ITaskItem>(); var normalizedOutputPath = StaticWebAsset.NormalizeContentRootPath(Path.GetFullPath(OutputPath)); try { foreach (var asset in Assets.Select(StaticWebAsset.FromTaskItem)) { string fileOutputPath = null; if (!(asset.IsDiscovered() || asset.IsComputed())) { Log.LogMessage(MessageImportance.Low, "Skipping asset '{0}' since source type is '{1}'", asset.Identity, asset.SourceType); continue; } if (asset.IsForReferencedProjectsOnly()) { Log.LogMessage(MessageImportance.Low, "Skipping asset '{0}' since asset mode is '{1}'", asset.Identity, asset.AssetMode); } if (asset.ShouldCopyToOutputDirectory()) { // We have an asset we want to copy to the output folder. fileOutputPath = Path.Combine(normalizedOutputPath, asset.RelativePath); string source = null; if (asset.IsComputed()) { if (asset.Identity.StartsWith(normalizedOutputPath, StringComparison.Ordinal)) { Log.LogMessage(MessageImportance.Low, "Source for asset '{0}' is '{1}' since the identity points to the output path.", asset.Identity, asset.OriginalItemSpec); source = asset.OriginalItemSpec; } else if (File.Exists(asset.Identity)) { Log.LogMessage(MessageImportance.Low, "Source for asset '{0}' is '{0}' since the asset exists.", asset.Identity); source = asset.Identity; } else { Log.LogMessage(MessageImportance.Low, "Source for asset '{0}' is '{1}' since the asset does not exist.", asset.Identity, asset.OriginalItemSpec); source = asset.OriginalItemSpec; } } else { source = asset.Identity; } copyToOutputFolder.Add(new TaskItem(source, new Dictionary <string, string> { ["OriginalItemSpec"] = asset.Identity, ["TargetPath"] = fileOutputPath, ["CopyToOutputDirectory"] = asset.CopyToOutputDirectory })); } else { Log.LogMessage(MessageImportance.Low, "Skipping asset '{0}' since copy to output directory option is '{1}'", asset.Identity, asset.CopyToOutputDirectory); } } AssetsToCopy = copyToOutputFolder.ToArray(); } catch (Exception ex) { Log.LogError(ex.ToString()); } return(!Log.HasLoggedErrors); }