/// <summary> /// Gets an instance of <see cref="ICacheConfigData"/> from cache configuration. /// </summary> internal static Possible <ICacheConfigData> TryGetCacheConfigData( PathTable pathTable, string cacheDirectory, ICacheConfiguration config, RootTranslator rootTranslator = null) { Contract.Requires(pathTable != null); Contract.Requires(pathTable.IsValid); Contract.Requires(config != null); Contract.Requires(config.CacheLogFilePath.IsValid); Contract.Requires(config.CacheConfigFile.IsValid); Contract.Requires(!string.IsNullOrWhiteSpace(cacheDirectory)); Possible <string> maybeConfigData = TryReadCacheConfigFile(config.CacheConfigFile.ToString(pathTable)); if (!maybeConfigData.Succeeded) { return(maybeConfigData.Failure); } // Update the cache config to dynamically set the cache path if it is configured to use the per-invocation path. // TODO: Ideally this would be exposed as config constructor parameters to BuildXL to not require manipulating the json config. // But for now we just modify the config text before passing it along to the cache. string cacheConfigContent = maybeConfigData.Result; cacheConfigContent = cacheConfigContent.Replace("[DominoSelectedLogPath]", config.CacheLogFilePath.ToString(pathTable).Replace(@"\", @"\\")); // Escape path separation chars to json format cacheConfigContent = cacheConfigContent.Replace("[BuildXLSelectedLogPath]", config.CacheLogFilePath.ToString(pathTable).Replace(@"\", @"\\")); // Escape path separation chars to json format cacheConfigContent = cacheConfigContent.Replace("[DominoSelectedRootPath]", cacheDirectory.Replace(@"\", @"\\")); cacheConfigContent = cacheConfigContent.Replace("[BuildXLSelectedRootPath]", cacheDirectory.Replace(@"\", @"\\")); cacheConfigContent = cacheConfigContent.Replace("[UseDedupStore]", config.UseDedupStore.ToString()); cacheConfigContent = cacheConfigContent.Replace("[ReplaceExistingFileOnMaterialization]", config.ReplaceExistingFileOnMaterialization.ToString()); var vfsCasRoot = config.VfsCasRoot.IsValid ? config.VfsCasRoot.ToString(pathTable) : ""; if (rootTranslator != null && !string.IsNullOrEmpty(vfsCasRoot)) { // VFS needs real path so use root translator to resolve to real path. vfsCasRoot = rootTranslator.Translate(vfsCasRoot); } // Escape path separation chars to json format vfsCasRoot = vfsCasRoot.Replace(@"\", @"\\"); cacheConfigContent = cacheConfigContent.Replace("[VfsCasRoot]", vfsCasRoot); ICacheConfigData cacheConfigData; Exception exception; if (!CacheFactory.TryCreateCacheConfigData(cacheConfigContent, out cacheConfigData, out exception)) { return(new Failure <string>(I($"Unable to create cache config data: {exception.GetLogEventMessage()}"))); } return(new Possible <ICacheConfigData>(cacheConfigData)); }
/// <summary> /// Gets the expanded path for the cache to use when putting/placing file. This allows /// the cache to pick a correct CAS root if CAS roots exist on various drives which /// would allow it to use a hardlink rather than copy if the appropriate CAS root is chosen. /// </summary> public string GetExpandedPathForCache(ExpandedAbsolutePath path) { if (m_rootTranslator == null) { return(path.ExpandedPath); } else { var translatedPath = m_rootTranslator.Translate(path.ExpandedPath); if (translatedPath[0].ToUpperInvariantFast() == path.ExpandedPath[0].ToUpperInvariantFast() && translatedPath.Length > path.ExpandedPath.Length) { // The path root did not change as a result of path translation and its longer // so , just return the original path since the cache only cares about the root // when deciding a particular CAS to hardlink from to avoid MAX_PATH issues return(path.ExpandedPath); } return(translatedPath); } }
private void TestRootTranslation(string path, string expectedPath) { var translatedPath = m_translator.Translate(path); Assert.Equal(expectedPath, translatedPath); }