/// <summary> /// Converts the full path to a VFS root relative path /// </summary> internal VirtualPath ToVirtualPath(VfsFilePlacementData data, FullPath path) { // Use the same index (0) for ReadOnly/Hardlink files var shouldHardlink = FileSystemContentStoreInternal.ShouldAttemptHardLink(path, data.AccessMode, data.RealizationMode); // All hardlinks of a hash share the same file under the vfs root so just // use index 0 to represent that file. Otherwise, create a unique index so // that copies get unique files var index = shouldHardlink ? 0 : Interlocked.Increment(ref _nextVfsCasTargetFileUniqueId); VirtualPath casRelativePath = VfsUtilities.CreateCasRelativePath(data, index); var virtualPath = _configuration.VfsCasRelativeRoot / casRelativePath; return(virtualPath.Path); }
/// <summary> /// Attempts to create a symlink which points to a virtualized file materialized with the given data /// </summary> public Result <VirtualPath> TryCreateSymlink(OperationContext context, AbsolutePath sourcePath, VfsFilePlacementData data, bool replaceExisting) { return(context.PerformOperation( Tracer, () => { _fileSystem.CreateDirectory(sourcePath.Parent); if (replaceExisting) { FileUtilities.DeleteFile(sourcePath.Path); } var index = Interlocked.Increment(ref _nextVfsCasTargetFileUniqueId); VirtualPath casRelativePath = VfsUtilities.CreateCasRelativePath(data, index); var virtualPath = _configuration.VfsCasRelativeRoot / casRelativePath; var fullTargetPath = _configuration.VfsCasRootPath / casRelativePath; var now = DateTime.UtcNow; var tempFilePath = _tempDirectory.CreateRandomFileName(); var result = FileUtilities.TryCreateSymbolicLink(symLinkFileName: tempFilePath.Path, targetFileName: fullTargetPath.Path, isTargetFile: true); if (result.Succeeded) { var attributes = FileUtilities.GetFileAttributes(tempFilePath.Path); attributes |= FileAttributes.Offline; FileUtilities.SetFileAttributes(tempFilePath.Path, attributes); _fileSystem.MoveFile(tempFilePath, sourcePath, replaceExisting: replaceExisting); return Result.Success(virtualPath.Path); } else { return Result.FromErrorMessage <VirtualPath>(result.Failure.DescribeIncludingInnerFailures()); } }, extraStartMessage: $"SourcePath={sourcePath}, Hash={data.Hash}", messageFactory: r => $"SourcePath={sourcePath}, Hash={data.Hash}, TargetPath={r.GetValueOrDefault()}", counter: Counters[VfsCounters.TryCreateSymlink])); }
internal Result <VirtualPath> TryCreateSymlink(OperationContext context, AbsolutePath sourcePath, VfsFilePlacementData data, bool replace) { return(context.PerformOperation( _tracer, () => { _fileSystem.CreateDirectory(sourcePath.Parent); if (replace) { FileUtilities.DeleteFile(sourcePath.Path); } var index = Interlocked.Increment(ref _nextVfsCasTargetFileUniqueId); VirtualPath casRelativePath = VfsUtilities.CreateCasRelativePath(data, index); var virtualPath = _configuration.VfsCasRelativeRoot / casRelativePath; Tree.AddFileNode(virtualPath.Path, data); // Ensure existence of the virtual directory in the VFS CAS root //Tree.GetOrAddDirectoryNode((_configuration.VfsCasRelativeRoot / casRelativePath).Parent.Path); var fullTargetPath = _configuration.VfsCasRootPath / casRelativePath; var result = FileUtilities.TryCreateSymbolicLink(symLinkFileName: sourcePath.Path, targetFileName: fullTargetPath.Path, isTargetFile: true); if (result.Succeeded) { return Result.Success(virtualPath.Path); } else { return Result.FromErrorMessage <VirtualPath>(result.Failure.DescribeIncludingInnerFailures()); } }, extraStartMessage: $"SourcePath={sourcePath}, Hash={data.Hash}", messageFactory: r => $"SourcePath={sourcePath}, Hash={data.Hash}, TargetPath={r.GetValueOrDefault()}", counter: Counters[VfsCounters.TryCreateSymlink])); }