| File: Utilities\PathUtils.cs | Web Access |
| Project: src\src\Microsoft.ML.Core\Microsoft.ML.Core.csproj (Microsoft.ML.Core) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.IO; using System.Threading; using Microsoft.ML.Runtime; namespace Microsoft.ML.Internal.Utilities { internal static partial class Utils { /// <summary> /// Environment variable containing optional resources path. /// </summary> public const string CustomSearchDirEnvVariable = "MICROSOFTML_RESOURCE_PATH"; private static string _dllDir; private static string DllDir { get { string result = _dllDir; if (result == null) { string path = typeof(Utils).Assembly.Location; string directory = Path.GetDirectoryName(path); Interlocked.CompareExchange(ref _dllDir, directory, null); result = _dllDir; } return result; } } /// <summary> /// Attempts to find a file that is expected to be distributed with a TLC component. Searches /// in the following order: /// 1. In the customSearchDir directory, if it is provided. /// 2. In the custom search directory specified by the /// <seealso cref="CustomSearchDirEnvVariable"/> environment variable. /// 3. In the root folder of the provided assembly. /// 4. In the folder of this assembly. /// In each case it searches the file in the directory provided and combined with folderPrefix. /// /// If any of these locations contain the file, a full local path will be returned, otherwise this /// method will return null. /// </summary> /// <param name="fileName">File name to find</param> /// <param name="folderPrefix">folder prefix, relative to the current or customSearchDir</param> /// <param name="customSearchDir"> /// Custom directory to search for resources. /// If null, the path specified in the environment variable <seealso cref="CustomSearchDirEnvVariable"/> /// will be used. /// </param> /// <param name="assemblyForBasePath"> /// Assembly type to search the path of. /// </param> /// <returns> /// Path to the existing file. Null if not found. /// </returns> public static string FindExistentFileOrNull(string fileName, string folderPrefix = null, string customSearchDir = null, System.Type assemblyForBasePath = null) { Contracts.AssertNonWhiteSpace(fileName); string candidate; // 1. Search in customSearchDir. if (!string.IsNullOrWhiteSpace(customSearchDir) && TryFindFile(fileName, folderPrefix, customSearchDir, out candidate)) { return candidate; } // 2. Search in the path specified by the environment variable. var envDir = Environment.GetEnvironmentVariable(CustomSearchDirEnvVariable); if (!string.IsNullOrWhiteSpace(envDir) && TryFindFile(fileName, folderPrefix, envDir, out candidate)) { return candidate; } // 3. Search in the path specified by the assemblyForBasePath. if (assemblyForBasePath != null) { // For CoreTLC we have MLCore located in main folder, and dlls with learners and transforms located // in AutoLoad folder or (ClrWin|ClrLinux) folder so we need to check folder for provided type. var assemblyDir = Path.GetDirectoryName(assemblyForBasePath.Assembly.Location); if (assemblyDir != null && customSearchDir != null) assemblyDir = Path.Combine(assemblyDir, customSearchDir); if (TryFindFile(fileName, folderPrefix, assemblyDir, out candidate)) return candidate; } // 4. Fallback to the root path of the current assembly TryFindFile(fileName, folderPrefix, DllDir, out candidate); return candidate; } private static bool TryFindFile(string fileName, string folderPrefix, string dir, out string foundFile) { foundFile = null; var candidate = Path.Combine(dir, fileName); if (File.Exists(candidate)) { foundFile = candidate; return true; } if (!string.IsNullOrWhiteSpace(folderPrefix)) { candidate = Path.Combine(dir, folderPrefix, fileName); if (File.Exists(candidate)) { foundFile = candidate; return true; } } return false; } /// <summary> /// Given a folder path, create it if it doesn't exist. /// Fails if the folder name is empty, or can't create the folder. /// </summary> public static string CreateFolderIfNotExists(string folder) { if (Directory.Exists(folder)) return folder; if (!string.IsNullOrEmpty(folder)) { try { Directory.CreateDirectory(folder); return folder; } catch (Exception exc) { throw Contracts.ExceptParam(nameof(folder), $"Failed to create folder for the provided path: {folder}. \nException: {exc.Message}"); } } return null; } } }