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);
        }
Beispiel #2
0
        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);
        }