public override bool RunTask() { var intermediateFiles = new List <ITaskItem> (ResourceFiles.Length); var resolvedFiles = new List <ITaskItem> (ResourceFiles.Length); string[] prefixes = Prefixes != null?Prefixes.Split(';') : null; if (prefixes != null) { for (int i = 0; i < prefixes.Length; i++) { string p = prefixes [i]; char c = p [p.Length - 1]; if (c != '\\' && c != '/') { prefixes [i] = p + Path.DirectorySeparatorChar; } } } var nameCaseMap = new Dictionary <string, string> (ResourceFiles.Length, StringComparer.Ordinal); for (int i = 0; i < ResourceFiles.Length; i++) { var item = ResourceFiles [i]; if (Directory.Exists(item.ItemSpec)) { continue; } //compute the target path string rel; var logicalName = item.GetMetadata("LogicalName").Replace('\\', Path.DirectorySeparatorChar); if (item.GetMetadata("IsWearApplicationResource") == "True") { rel = item.ItemSpec.Substring(IntermediateDir.Length); } else if (!string.IsNullOrEmpty(logicalName)) { rel = logicalName; } else { rel = item.GetMetadata("Link").Replace('\\', Path.DirectorySeparatorChar); if (string.IsNullOrEmpty(rel)) { rel = item.GetMetadata("Identity"); if (!string.IsNullOrEmpty(ProjectDir)) { var fullRelPath = Path.GetFullPath(rel).Normalize(NormalizationForm.FormC); var fullProjectPath = Path.GetFullPath(ProjectDir).Normalize(NormalizationForm.FormC); if (fullRelPath.StartsWith(fullProjectPath)) { rel = fullRelPath.Replace(fullProjectPath, string.Empty); } } } } if (Path.IsPathRooted(rel)) { var root = Path.GetPathRoot(rel); rel = rel.Substring(root.Length); } if (prefixes != null) { foreach (var p in prefixes) { if (rel.StartsWith(p)) { rel = rel.Substring(p.Length); } } } string baseFileName = LowercaseFilenames ? rel.ToLowerInvariant() : rel; if (Aapt2.IsInvalidFilename(baseFileName)) { Log.LogDebugMessage($"Invalid filename, ignoring: {baseFileName}"); continue; } if (Path.GetExtension(baseFileName) == ".axml") { baseFileName = Path.ChangeExtension(baseFileName, ".xml"); } if (baseFileName != rel) { nameCaseMap [baseFileName] = rel; } string dest = Path.GetFullPath(Path.Combine(IntermediateDir, baseFileName)); string intermediateDirFullPath = Path.GetFullPath(IntermediateDir); // if the path ends up "outside" of our target intermediate directory, just use the filename if (String.Compare(intermediateDirFullPath, 0, dest, 0, intermediateDirFullPath.Length, StringComparison.OrdinalIgnoreCase) != 0) { dest = Path.GetFullPath(Path.Combine(IntermediateDir, Path.GetFileName(baseFileName))); } if (!File.Exists(item.ItemSpec)) { Log.LogCodedError("XA2001", file: item.ItemSpec, lineNumber: 0, message: Properties.Resources.XA2001, item.ItemSpec); continue; } var newItem = new TaskItem(dest); newItem.SetMetadata("LogicalName", rel); newItem.SetMetadata("_FlatFile", Monodroid.AndroidResource.CalculateAapt2FlatArchiveFileName(dest)); newItem.SetMetadata("_ArchiveDirectory", AndroidLibraryFlatFilesDirectory); item.CopyMetadataTo(newItem); intermediateFiles.Add(newItem); resolvedFiles.Add(item); } IntermediateFiles = intermediateFiles.ToArray(); ResolvedResourceFiles = resolvedFiles.ToArray(); MonoAndroidHelper.SaveResourceCaseMap(BuildEngine4, nameCaseMap); return(!Log.HasLoggedErrors); }
public override bool RunTask() { var libraryProjectDir = Path.GetFullPath(LibraryProjectIntermediatePath); foreach (var directory in Directories) { if (!Directory.Exists(directory.ItemSpec)) { Log.LogDebugMessage($"Directory does not exist, skipping: {directory.ItemSpec}"); continue; } string stampFile = directory.GetMetadata("StampFile"); string directoryHash = Files.HashString(directory.ItemSpec); if (string.IsNullOrEmpty(stampFile)) { if (Path.GetFullPath(directory.ItemSpec).StartsWith(libraryProjectDir)) { // If inside the `lp` directory stampFile = Path.GetFullPath(Path.Combine(directory.ItemSpec, "..", "..")) + ".stamp"; } else { // Otherwise use a hashed stamp file stampFile = Path.Combine(StampDirectory, $"{directoryHash}.stamp"); } } bool generateArchive = false; bool.TryParse(directory.GetMetadata(ResolveLibraryProjectImports.AndroidSkipResourceProcessing), out generateArchive); IEnumerable <string> files; string filesCache = directory.GetMetadata("FilesCache"); if (string.IsNullOrEmpty(filesCache)) { if (Path.GetFullPath(directory.ItemSpec).StartsWith(libraryProjectDir)) { filesCache = Path.Combine(directory.ItemSpec, "..", "files.cache"); } else { filesCache = Path.Combine(directory.ItemSpec, "..", $"{directoryHash}-files.cache"); } } DateTime lastwriteTime = File.Exists(stampFile) ? File.GetLastWriteTimeUtc(stampFile) : DateTime.MinValue; DateTime cacheLastWriteTime = File.Exists(filesCache) ? File.GetLastWriteTimeUtc(filesCache) : DateTime.MinValue; if (File.Exists(filesCache) && cacheLastWriteTime >= lastwriteTime) { Log.LogDebugMessage($"Reading cached Library resources list from {filesCache}"); files = File.ReadAllLines(filesCache); } else { if (!File.Exists(filesCache)) { Log.LogDebugMessage($"Cached Library resources list {filesCache} does not exist."); } else { Log.LogDebugMessage($"Cached Library resources list {filesCache} is out of date."); } if (generateArchive) { files = new string[1] { stampFile }; } else { files = Directory.EnumerateFiles(directory.ItemSpec, "*.*", SearchOption.AllDirectories); } } if (files.Any()) { if (!File.Exists(filesCache) || cacheLastWriteTime < lastwriteTime) { File.WriteAllLines(filesCache, files, Encoding.UTF8); } var taskItem = new TaskItem(directory.ItemSpec, new Dictionary <string, string> () { { "FileFound", files.First() }, }); directory.CopyMetadataTo(taskItem); if (string.IsNullOrEmpty(directory.GetMetadata("StampFile"))) { taskItem.SetMetadata("StampFile", stampFile); } else { Log.LogDebugMessage($"%(StampFile) already set: {stampFile}"); } if (string.IsNullOrEmpty(directory.GetMetadata("FilesCache"))) { taskItem.SetMetadata("FilesCache", filesCache); } else { Log.LogDebugMessage($"%(FilesCache) already set: {filesCache}"); } output.Add(taskItem); foreach (var file in files) { if (Aapt2.IsInvalidFilename(file)) { Log.LogDebugMessage($"Invalid filename, ignoring: {file}"); continue; } var fileTaskItem = new TaskItem(file, new Dictionary <string, string> () { { "ResourceDirectory", directory.ItemSpec }, { "StampFile", generateArchive ? stampFile : file }, { "FilesCache", filesCache }, { "Hash", stampFile }, { "_ArchiveDirectory", Path.Combine(directory.ItemSpec, "..", "flat" + Path.DirectorySeparatorChar) }, { "_FlatFile", generateArchive ? $"{Path.GetFileNameWithoutExtension (stampFile)}.flata" : Monodroid.AndroidResource.CalculateAapt2FlatArchiveFileName(file) }, }); libraryResourceFiles.Add(fileTaskItem); } } } return(!Log.HasLoggedErrors); }