/// <summary> /// In a dotnet-interactive REPL session (driver), nuget dependencies will be /// systematically added using <see cref="SparkContext.AddFile(string, bool)"/>. /// /// These files include: /// - "{packagename}.{version}.nupkg" /// The nuget packages /// - <see cref="DependencyProviderUtils.CreateFileName(long)"/> /// Serialized <see cref="DependencyProviderUtils.Metadata"/> object. /// /// On the Worker, in order to resolve the nuget dependencies referenced by /// the dotnet-interactive session, we instantiate a /// <see cref="DotNet.DependencyManager.DependencyProvider"/>. /// This provider will register an event handler to the Assembly Load Resolving event. /// By using <see cref="SparkFiles.GetRootDirectory"/>, we can access the /// required files added to the <see cref="SparkContext"/>. /// </summary> internal static void RegisterAssemblyHandler() { if (!s_runningREPL) { return; } string sparkFilesPath = SparkFiles.GetRootDirectory(); string[] metadataFiles = DependencyProviderUtils.GetMetadataFiles(sparkFilesPath); foreach (string metdatafile in metadataFiles) { // The execution of the delegate passed to GetOrAdd is not guaranteed to run once. // Multiple Lazy objects may be created, but only one of them will be added to the // ConcurrentDictionary. The Lazy value is retrieved to materialize the // DependencyProvider object if it hasn't already been created. Lazy <DependencyProvider> dependecyProvider = s_dependencyProviders.GetOrAdd( metdatafile, mdf => new Lazy <DependencyProvider>( () => { s_logger.LogInfo($"Creating {nameof(DependencyProvider)} using {mdf}"); return(new DependencyProvider( mdf, sparkFilesPath, Directory.GetCurrentDirectory())); })); _ = dependecyProvider.Value; } }
public void TestsUnpackPackages() { string packageFileName = "package.name.1.0.0.nupkg"; string packageName = "package.name"; string packageVersion = "1.0.0"; using var emptyFileDir = new TemporaryDirectory(); string emptyFileName = "emptyfile"; File.Create(Path.Combine(emptyFileDir.Path, emptyFileName)).Dispose(); using var nupkgDir = new TemporaryDirectory(); ZipFile.CreateFromDirectory( emptyFileDir.Path, Path.Combine(nupkgDir.Path, packageFileName)); var metadata = new DependencyProviderUtils.Metadata { AssemblyProbingPaths = new string[] { "/assembly/probe/path" }, NativeProbingPaths = new string[] { "/native/probe/path" }, NuGets = new DependencyProviderUtils.NuGetMetadata[] { new DependencyProviderUtils.NuGetMetadata { FileName = packageFileName, PackageName = packageName, PackageVersion = packageVersion } } }; using var unpackDir = new TemporaryDirectory(); string metadataFilePath = Path.Combine(nupkgDir.Path, DependencyProviderUtils.CreateFileName(1)); metadata.Serialize(metadataFilePath); // Files located in nupkgDir // nuget: package.name.1.0.0.nupkg // metadata file: dependencyProviderMetadata_00000000000000000001 var dependencyProvider = new DependencyProvider(metadataFilePath, nupkgDir.Path, unpackDir.Path); string expectedPackagePath = Path.Combine(unpackDir.Path, ".nuget", "packages", packageName, packageVersion); string expectedFilePath = Path.Combine(expectedPackagePath, emptyFileName); Assert.True(File.Exists(expectedFilePath)); }
public void TestFileNames() { using var tempDir = new TemporaryDirectory(); foreach (long num in Enumerable.Range(0, 3).Select(x => System.Math.Pow(10, x))) { string filePath = Path.Combine(tempDir.Path, DependencyProviderUtils.CreateFileName(num)); File.Create(filePath).Dispose(); } var expectedFiles = new string[] { "dependencyProviderMetadata_0000000000000000001", "dependencyProviderMetadata_0000000000000000010", "dependencyProviderMetadata_0000000000000000100", }; IOrderedEnumerable <string> actualFiles = DependencyProviderUtils .GetMetadataFiles(tempDir.Path) .Select(f => Path.GetFileName(f)) .OrderBy(s => s); Assert.True(expectedFiles.SequenceEqual(actualFiles)); }
/// <summary> /// Generates and serializes a <see cref="DependencyProviderUtils.Metadata"/> to /// <paramref name="writePath"/>. Returns a list of file paths which include the /// the serialized <see cref="DependencyProviderUtils.Metadata"/> and nuget file /// dependencies. /// </summary> /// <param name="writePath">Path to write metadata.</param> /// <returns> /// List of file paths of the serialized <see cref="DependencyProviderUtils.Metadata"/> /// and nuget file dependencies. /// </returns> internal IEnumerable <string> GetFiles(string writePath) { IEnumerable <ResolvedNuGetPackage> nugetPackagesToCopy = GetNewPackages(); var assemblyProbingPaths = new List <string>(); var nativeProbingPaths = new List <string>(); var nugetMetadata = new List <DependencyProviderUtils.NuGetMetadata>(); foreach (ResolvedNuGetPackage package in nugetPackagesToCopy) { ResolvedPackageReference resolvedPackage = package.ResolvedPackage; foreach (FileInfo asmPath in resolvedPackage.AssemblyPaths) { // asmPath.FullName // /path/to/packages/package.name/package.version/lib/framework/1.dll // resolvedPackage.PackageRoot // /path/to/packages/package.name/package.version/ // GetRelativeToPackages(..) // package.name/package.version/lib/framework/1.dll assemblyProbingPaths.Add( GetPathRelativeToPackages( asmPath.FullName, resolvedPackage.PackageRoot)); } foreach (DirectoryInfo probePath in resolvedPackage.ProbingPaths) { // probePath.FullName // /path/to/packages/package.name/package.version/ // resolvedPackage.PackageRoot // /path/to/packages/package.name/package.version/ // GetRelativeToPackages(..) // package.name/package.version nativeProbingPaths.Add( GetPathRelativeToPackages( probePath.FullName, resolvedPackage.PackageRoot)); } nugetMetadata.Add( new DependencyProviderUtils.NuGetMetadata { FileName = package.NuGetFile.Name, PackageName = resolvedPackage.PackageName, PackageVersion = resolvedPackage.PackageVersion }); yield return(package.NuGetFile.FullName); } if (nugetMetadata.Count > 0) { var metadataPath = Path.Combine( writePath, DependencyProviderUtils.CreateFileName( Interlocked.Increment(ref _metadataCounter))); new DependencyProviderUtils.Metadata { AssemblyProbingPaths = assemblyProbingPaths.ToArray(), NativeProbingPaths = nativeProbingPaths.ToArray(), NuGets = nugetMetadata.ToArray() }.Serialize(metadataPath); yield return(metadataPath); } }
public void TestPackageResolver() { using var tempDir = new TemporaryDirectory(); string packageName = "package.name"; string packageVersion = "0.1.0"; string packageRootPath = Path.Combine(tempDir.Path, "path", "to", "packages", packageName, packageVersion); string packageFrameworkPath = Path.Combine(packageRootPath, "lib", "framework"); Directory.CreateDirectory(packageRootPath); var nugetFile = new FileInfo( Path.Combine(packageRootPath, $"{packageName}.{packageVersion}.nupkg")); using (File.Create(nugetFile.FullName)) { } var assemblyPaths = new List <FileInfo> { new FileInfo(Path.Combine(packageFrameworkPath, "1.dll")), new FileInfo(Path.Combine(packageFrameworkPath, "2.dll")) }; var probingPaths = new List <DirectoryInfo> { new DirectoryInfo(packageRootPath) }; var mockPackageRestoreContextWrapper = new Mock <PackageRestoreContextWrapper>(); mockPackageRestoreContextWrapper .SetupGet(m => m.ResolvedPackageReferences) .Returns(new ResolvedPackageReference[] { new ResolvedPackageReference( packageName, packageVersion, assemblyPaths, new DirectoryInfo(packageRootPath), probingPaths) }); var packageResolver = new PackageResolver(mockPackageRestoreContextWrapper.Object); IEnumerable <string> actualFiles = packageResolver.GetFiles(tempDir.Path); string metadataFilePath = Path.Combine(tempDir.Path, DependencyProviderUtils.CreateFileName(1)); var expectedFiles = new string[] { nugetFile.FullName, metadataFilePath }; Assert.True(expectedFiles.SequenceEqual(actualFiles)); Assert.True(File.Exists(metadataFilePath)); DependencyProviderUtils.Metadata actualMetadata = DependencyProviderUtils.Metadata.Deserialize(metadataFilePath); var expectedMetadata = new DependencyProviderUtils.Metadata { AssemblyProbingPaths = new string[] { Path.Combine(packageName, packageVersion, "lib", "framework", "1.dll"), Path.Combine(packageName, packageVersion, "lib", "framework", "2.dll") }, NativeProbingPaths = new string[] { Path.Combine(packageName, packageVersion) }, NuGets = new DependencyProviderUtils.NuGetMetadata[] { new DependencyProviderUtils.NuGetMetadata { FileName = $"{packageName}.{packageVersion}.nupkg", PackageName = packageName, PackageVersion = packageVersion } } }; Assert.True(expectedMetadata.Equals(actualMetadata)); }