private static async Task <(string, IEnumerable <PackageDependency>)> CopyBinaries(string path, IDictionary <string, string> fileMap) { using (var stream = File.OpenRead(path)) using (var packageReader = new PackageArchiveReader(stream)) { var unityPath = GetUnityPackagePath(); foreach (var kvp in fileMap) { var targetPath = Path.Combine(unityPath, kvp.Value); if (File.Exists(targetPath)) { File.Delete(targetPath); } packageReader.ExtractFile(kvp.Key, targetPath, NullLogger.Instance); } var dependencies = await packageReader.GetPackageDependenciesAsync(CancellationToken.None); var version = packageReader.NuspecReader.GetVersion().ToNormalizedString(); var packages = dependencies.FirstOrDefault(d => d.TargetFramework.DotNetFrameworkName == ".NETStandard,Version=v2.0")?.Packages; return(version, packages); } }
public void It_finds_commandName_and_put_in_setting_file() { const string explicitCommandName = "explicit_command_name"; TestAsset helloWorldAsset = _testAssetsManager .CopyTestAsset("PortableTool", "PackPortableToolToolCommandName") .WithSource() .WithProjectChanges(project => { XNamespace ns = project.Root.Name.Namespace; XElement propertyGroup = project.Root.Elements(ns + "PropertyGroup").First(); propertyGroup.Add(new XElement("ToolCommandName", explicitCommandName)); }) .Restore(Log); var packCommand = new PackCommand(Log, helloWorldAsset.TestRoot); packCommand.Execute(); var nugetPackage = packCommand.GetNuGetPackage(); using (var nupkgReader = new PackageArchiveReader(nugetPackage)) { var anyTfm = nupkgReader.GetSupportedFrameworks().First().GetShortFolderName(); var tmpfilePath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); string copiedFile = nupkgReader.ExtractFile($"tools/{anyTfm}/any/DotnetToolSettings.xml", tmpfilePath, null); XDocument.Load(copiedFile) .Element("DotNetCliTool") .Element("Commands") .Element("Command") .Attribute("Name") .Value .Should().Be(explicitCommandName); } }
private void CopyPackageAssetToToolLayout( string[] nupkgAssetNames, PackageArchiveReader nupkgReader, string tmpfilePathRoot, NuGetFramework framework) { var toolLayoutDirectory = Path.Combine( tmpfilePathRoot, ".store", _packageId, _packageVersion, _packageId, _packageVersion, "tools", framework.GetShortFolderName(), "any"); foreach (string nupkgAssetName in nupkgAssetNames) { var destinationFilePath = Path.Combine(toolLayoutDirectory, nupkgAssetName); nupkgReader.ExtractFile( $"tools/{framework.GetShortFolderName()}/any/{nupkgAssetName}", destinationFilePath, null); } }
private void AssertFiles(string nugetPackage) { using (var nupkgReader = new PackageArchiveReader(nugetPackage)) { var anyTfm = nupkgReader.GetSupportedFrameworks().First().GetShortFolderName(); var tmpfilePath = Path.Combine(_testRoot, "temp", Path.GetRandomFileName()); string copiedFile = nupkgReader.ExtractFile($"tools/{anyTfm}/any/DotnetToolSettings.xml", tmpfilePath, null); var allItems = nupkgReader.GetToolItems().SelectMany(i => i.Items).ToList(); allItems.Should().Contain($"tools/{anyTfm}/any/consoledemo.runtimeconfig.json"); XElement command = XDocument.Load(copiedFile) .Element("DotNetCliTool") .Element("Commands") .Element("Command"); command.Attribute("Name") .Value .Should().Be("consoledemo", "it should contain command name that is same as the msbuild well known properties $(TargetName)"); command.Attribute("EntryPoint") .Value .Should().Be("consoledemo.dll", "it should contain entry point dll that is same as the msbuild well known properties $(TargetFileName)"); } }
private void UnpackPackage(string extractDirectory, string packagePath) { using (var reader = new PackageArchiveReader(packagePath)) { var files = reader.GetFiles().Where(f => f.StartsWith(ContentFiles)); foreach (var file in files) { var fileDestination = Path.Combine(extractDirectory, Path.GetRelativePath(ContentFiles, file)); reader.ExtractFile(file, fileDestination, logger); } } File.Delete(packagePath); }
private string GetShaFromSamplePackage(string samplePackage) { var packageReader = new PackageArchiveReader(samplePackage); Directory.CreateDirectory(_tempDirectory.Value); FilePath targetFilePath = _tempDirectory.WithFile(Path.GetRandomFileName()); packageReader.ExtractFile(".signature.p7s", targetFilePath.Value, _logger); using var fs = new FileStream(targetFilePath.Value, FileMode.Open); PrimarySignature primarySignature = PrimarySignature.Load(fs); IX509CertificateChain certificateChain = SignatureUtility.GetCertificateChain(primarySignature); var shaFromPackage = certificateChain[0].GetCertHashString(HashAlgorithmName.SHA256); return(shaFromPackage); }
public void It_produces_valid_shims(bool multiTarget) { if (!Environment.Is64BitOperatingSystem) { // only sample test on win-x64 since shims are RID specific return; } var nugetPackage = SetupNuGetPackage(multiTarget); using (var nupkgReader = new PackageArchiveReader(nugetPackage)) { IEnumerable <NuGetFramework> supportedFrameworks = nupkgReader.GetSupportedFrameworks(); supportedFrameworks.Should().NotBeEmpty(); var simulateToolPathRoot = Path.Combine(_testRoot, "temp", Path.GetRandomFileName()); foreach (NuGetFramework framework in supportedFrameworks) { string[] portableAppContent = { "consoledemo.runtimeconfig.json", "consoledemo.deps.json", "consoledemo.dll", "Newtonsoft.Json.dll" }; CopyPackageAssetToToolLayout(portableAppContent, nupkgReader, simulateToolPathRoot, framework); string shimPath = Path.Combine(simulateToolPathRoot, $"{_customToolCommandName}.exe"); nupkgReader.ExtractFile( $"tools/{framework.GetShortFolderName()}/any/shims/win-x64/{_customToolCommandName}.exe", shimPath, null); var command = new ShimCommand(Log, shimPath) { WorkingDirectory = simulateToolPathRoot }; command.Execute().Should() .Pass() .And .HaveStdOutContaining("Hello World from Global Tool"); } } }
public void Extract(Stream nupkgStream, string targetPath) { var tempHashPath = Path.Combine(targetPath, Path.GetRandomFileName()); var targetNuspec = Path.Combine(targetPath, Path.GetRandomFileName()); var targetNupkg = Path.Combine(targetPath, Path.GetRandomFileName()); targetNupkg = Path.ChangeExtension(targetNupkg, ".nupkg"); var hashPath = Path.Combine(targetPath, Path.GetRandomFileName()); using (var packageReader = new PackageArchiveReader(nupkgStream)) { var nuspecFile = packageReader.GetNuspecFile(); if ((packageSaveMode & PackageSaveMode.Nuspec) == PackageSaveMode.Nuspec) { packageReader.ExtractFile(nuspecFile, targetNuspec); } if ((packageSaveMode & PackageSaveMode.Files) == PackageSaveMode.Files) { var nupkgFileName = Path.GetFileName(targetNupkg); var hashFileName = Path.GetFileName(hashPath); var packageFiles = packageReader.GetFiles() .Where(file => ShouldInclude(file, nupkgFileName, nuspecFile, hashFileName)); var packageFileExtractor = new PackageFileExtractor( packageFiles, XmlDocFileSaveMode.None); packageReader.CopyFiles( targetPath, packageFiles, packageFileExtractor.ExtractPackageFile, CancellationToken.None); } string packageHash; nupkgStream.Position = 0; packageHash = Convert.ToBase64String(new CryptoHashProvider("SHA512").CalculateHash(nupkgStream)); File.WriteAllText(tempHashPath, packageHash); } }
public void Given_wpf_project_It_contains_shim_with_WindowsGraphicalUserInterfaceBit() { ushort windowsGUISubsystem = 0x2; var testProject = new TestProject() { Name = "wpfTool", TargetFrameworks = "netcoreapp3.0", IsSdkProject = true, ProjectSdk = "Microsoft.NET.Sdk.WindowsDesktop", IsWinExe = true, }; testProject.AdditionalProperties.Add("UseWPF", "true"); testProject.AdditionalProperties.Add("PackAsToolShimRuntimeIdentifiers", "win-x64;osx.10.12-x64"); testProject.AdditionalProperties.Add("ToolCommandName", _customToolCommandName); testProject.AdditionalProperties.Add("PackAsTool", "true"); TestAsset asset = _testAssetsManager.CreateTestProject(testProject); var packCommand = new PackCommand(Log, Path.Combine(asset.Path, testProject.Name)); packCommand .Execute() .Should() .Pass(); var nugetPackage = packCommand.GetNuGetPackage(packageVersion: _packageVersion); using (var nupkgReader = new PackageArchiveReader(nugetPackage)) { IEnumerable <NuGetFramework> supportedFrameworks = nupkgReader.GetSupportedFrameworks(); supportedFrameworks.Should().NotBeEmpty(); var tmpfilePath = Path.Combine(asset.TestRoot, "temp", Path.GetRandomFileName()); string copiedFile = nupkgReader.ExtractFile( $"tools/netcoreapp3.0/any/shims/win-x64/{_customToolCommandName}.exe", tmpfilePath, null); HostModel.AppHost.PEUtils.GetWindowsGraphicalUserInterfaceBit(copiedFile).Should().Be(windowsGUISubsystem); } }
private static void ExtractFiles(DirectoryInfo directory, ILogger logger, MemoryStream packageStream) { using (var reader = new PackageArchiveReader(packageStream)) { var libs = reader.GetLibItems(); foreach (var lib in libs) { if (lib.TargetFramework == NuGet.Frameworks.NuGetFramework.Parse("netstandard2.0")) { foreach (var file in lib.Items) { var target = Path.Combine(directory.FullName, Path.GetFileName(file)); if (file.StartsWith("lib/netstandard2.0/Microsoft.", System.StringComparison.Ordinal) && !File.Exists(target)) { reader.ExtractFile(file, target, logger); } } } } } }
public void It_finds_the_entry_point_dll_and_command_name_and_put_in_setting_file(bool multiTarget) { var nugetPackage = SetupNuGetPackage(multiTarget); using (var nupkgReader = new PackageArchiveReader(nugetPackage)) { var anyTfm = nupkgReader.GetSupportedFrameworks().First().GetShortFolderName(); var tmpfilePath = Path.Combine(_testRoot, "temp", Path.GetRandomFileName()); string copiedFile = nupkgReader.ExtractFile($"tools/{anyTfm}/any/DotnetToolSettings.xml", tmpfilePath, null); XElement command = XDocument.Load(copiedFile) .Element("DotNetCliTool") .Element("Commands") .Element("Command"); command.Attribute("Name") .Value .Should().Be("consoledemo", "it should contain command name that is same as the msbuild well known properties $(TargetName)"); command.Attribute("EntryPoint") .Value .Should().Be("consoledemo.dll", "it should contain entry point dll that is same as the msbuild well known properties $(TargetFileName)"); } }
protected override void PersistPackageFile(FileInfo nupkgFile, NupkgV3PackageInfo packageInfo) { var hashPath = packageInfo.HashPath; var nuspecPath = packageInfo.NuspecPath; FileUtility.Delete(hashPath); FileUtility.Delete(nuspecPath); using (var fileStream = File.OpenRead(nupkgFile.FullName)) { var packageHash = Convert.ToBase64String(new CryptoHashProvider("SHA512").CalculateHash(fileStream)); fileStream.Seek(0, SeekOrigin.Begin); // Write nuspec using (var reader = new PackageArchiveReader(fileStream)) { var nuspecFile = reader.GetNuspecFile(); reader.ExtractFile(nuspecFile, nuspecPath, _deepLog); } // Write package hash File.WriteAllText(hashPath, packageHash); } }
private void AssertValidShim(string testRoot, string nugetPackage) { using (var nupkgReader = new PackageArchiveReader(nugetPackage)) { IEnumerable <NuGetFramework> supportedFrameworks = nupkgReader.GetSupportedFrameworks(); supportedFrameworks.Should().NotBeEmpty(); var simulateToolPathRoot = Path.Combine(testRoot, "temp", Path.GetRandomFileName()); foreach (NuGetFramework framework in supportedFrameworks) { string[] portableAppContent = { "consoledemo.runtimeconfig.json", "consoledemo.deps.json", "consoledemo.dll", "Newtonsoft.Json.dll" }; CopyPackageAssetToToolLayout(portableAppContent, nupkgReader, simulateToolPathRoot, framework); string shimPath = Path.Combine(simulateToolPathRoot, $"{_customToolCommandName}.exe"); nupkgReader.ExtractFile( $"tools/{framework.GetShortFolderName()}/any/shims/win-x64/{_customToolCommandName}.exe", shimPath, null); var command = new RunExeCommand(Log, shimPath) { WorkingDirectory = simulateToolPathRoot }; command.Execute().Should() .Pass() .And .HaveStdOutContaining("Hello World from Global Tool"); } } }
internal static async Task <FileInfo> DownloadNupkgV3Async( CatalogEntry entry, IEnumerable <DirectoryInfo> storagePaths, DownloadMode mode, ILogger log, ILogger deepLog, CancellationToken token) { FileInfo result = null; DirectoryInfo rootDir = null; var lastCreated = DateTimeOffset.MinValue; // Check if the nupkg already exists on another drive. foreach (var storagePath in storagePaths) { var currentResolver = new VersionFolderPathResolver(storagePath.FullName); var checkNupkgPath = currentResolver.GetPackageFilePath(entry.Id, entry.Version); if (File.Exists(checkNupkgPath)) { // Use the existing path lastCreated = File.GetCreationTimeUtc(checkNupkgPath); rootDir = storagePath; break; } } if (rootDir == null) { // Not found, use the path with the most space rootDir = GetPathWithTheMostFreeSpace(storagePaths); } // id/version/id.version.nupkg var versionFolderResolver = new VersionFolderPathResolver(rootDir.FullName); var outputDir = versionFolderResolver.GetInstallPath(entry.Id, entry.Version); var hashPath = versionFolderResolver.GetHashPath(entry.Id, entry.Version); var nuspecPath = versionFolderResolver.GetManifestFilePath(entry.Id, entry.Version); var nupkgPath = versionFolderResolver.GetPackageFilePath(entry.Id, entry.Version); // Download var nupkgFile = await entry.DownloadNupkgAsync(outputDir, mode, token); if (File.Exists(nupkgPath)) { var currentCreated = File.GetCreationTimeUtc(nupkgPath); // Clean up nuspec and hash if the file changed if (lastCreated < currentCreated || !File.Exists(hashPath) || !File.Exists(nuspecPath)) { result = nupkgFile; log.LogInformation(nupkgFile.FullName); FileUtility.Delete(hashPath); FileUtility.Delete(nuspecPath); using (var fileStream = File.OpenRead(nupkgFile.FullName)) { var packageHash = Convert.ToBase64String(new CryptoHashProvider("SHA512").CalculateHash(fileStream)); fileStream.Seek(0, SeekOrigin.Begin); // Write nuspec using (var reader = new PackageArchiveReader(fileStream)) { var nuspecFile = reader.GetNuspecFile(); reader.ExtractFile(nuspecFile, nuspecPath, deepLog); } // Write package hash File.WriteAllText(hashPath, packageHash); } } } return(result); }
/// <summary> /// 从文件中加载插件并管理(但不初始化) /// </summary> /// <param name="fileName">相对于运行目录的文件名</param> public async Task LoadPackageAsync(string fileName) { using var reader = new PackageArchiveReader(File.OpenRead(fileName), false); var nuspecReader = await reader.GetNuspecReaderAsync(CancellationToken.None); var identity = nuspecReader.GetId(); var groups = await reader.GetLibItemsAsync(CancellationToken.None); var group = groups.FirstOrDefault(); foreach (var packageFile in group !.Items) { if (!packageFile.EndsWith(".dll")) { continue; } var tmpPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); var path = reader.ExtractFile(packageFile, tmpPath, NullLogger.Instance); //Type type = Load(await File.ReadAllBytesAsync(path)); var type = Load(path); if (type == null) { continue; } var context = new PluginContext(); var meta = new PluginMeta(identity, fileName, Path.Combine(Environment.CurrentDirectory, "plugins", identity)); context.Meta = meta; if (!Directory.Exists(meta.SpaceDirectory)) { Directory.CreateDirectory(meta.SpaceDirectory); var item = (await reader.GetContentItemsAsync(CancellationToken.None)).FirstOrDefault(); if (item != null) { foreach (var file in item.Items) { if (file.EndsWith('/') || file.EndsWith('\\')) { continue; } var entry = reader.GetEntry(file); entry.SaveAsFile(Path.Combine(meta.SpaceDirectory, file.Substring(8)), NullLogger.Instance); } } } var configFile = Path.Combine(meta.SpaceDirectory, "config.json"); if (File.Exists(configFile)) { context.Configuration = new Lazy <IConfiguration>(() => { var builder = new ConfigurationBuilder(); builder.AddJsonFile(configFile); return(builder.Build()); }); } else { context.Configuration = new Lazy <IConfiguration>(() => new ConfigurationBuilder().Build()); } var dataFile = Path.Combine(meta.SpaceDirectory, "data.litedb.db"); context.Repository = new Lazy <IRepository>(() => new LiteDbRepository(new LiteDatabase(dataFile))); plugins.Add(type, context); } }
/// <summary> /// 从文件中加载插件并管理(但不初始化) /// </summary> /// <param name="fileName">相对于运行目录的文件名</param> public async Task LoadPackageAsync(string fileName) { using PackageArchiveReader reader = new PackageArchiveReader(File.OpenRead(fileName), false); NuspecReader nuspecReader = await reader.GetNuspecReaderAsync(CancellationToken.None); string identity = nuspecReader.GetId(); IEnumerable <FrameworkSpecificGroup> groups = await reader.GetLibItemsAsync(CancellationToken.None); FrameworkSpecificGroup group = groups.Where(x => x.TargetFramework.GetShortFolderName().StartsWith("netstandard")).OrderByDescending(x => x.TargetFramework.GetShortFolderName()).FirstOrDefault(); foreach (string packageFile in group.Items) { if (!packageFile.EndsWith(".dll")) { continue; } string tmpPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); string path = reader.ExtractFile(packageFile, tmpPath, NullLogger.Instance); //Type type = Load(await File.ReadAllBytesAsync(path)); Type type = Load(path); if (type != null)// 为null时则不是插件程序集, 但不一定不是依赖程序集 { PluginContext context = new PluginContext(); PluginMeta meta = new PluginMeta(identity, fileName, Path.Combine(Environment.CurrentDirectory, "plugins", identity)); context.Meta = meta; if (!Directory.Exists(meta.SpaceDirectory)) { Directory.CreateDirectory(meta.SpaceDirectory); FrameworkSpecificGroup item = (await reader.GetContentItemsAsync(CancellationToken.None)).FirstOrDefault(); if (item != null) { foreach (string file in item.Items) { if (file.EndsWith('/') || file.EndsWith('\\')) { continue; } ZipArchiveEntry entry = reader.GetEntry(file); entry.SaveAsFile(Path.Combine(meta.SpaceDirectory, file.Substring(8)), NullLogger.Instance); } } } string configFile = Path.Combine(meta.SpaceDirectory, "config.json"); if (File.Exists(configFile)) { context.Configuration = new Lazy <IConfiguration>(() => { ConfigurationBuilder builder = new ConfigurationBuilder(); builder.AddJsonFile(configFile); return(builder.Build()); }); } else { context.Configuration = new Lazy <IConfiguration>(() => (new ConfigurationBuilder().Build())); } string dataFile = Path.Combine(meta.SpaceDirectory, "data.db"); context.Repository = new Lazy <IRepository>(() => new LiteDbRepository(new LiteDatabase(dataFile))); plugins.Add(type, context); } } }
/// <summary> /// 加载安装包程序集 /// </summary> /// <param name="loadLocations"></param> private static void LoadPackageAssembly(HashSet <string> loadLocations) { //download var logger = NullLogger.Instance; CancellationToken cancellationToken = CancellationToken.None; //dll下载目录 var downloadPath = Directory.CreateDirectory(Path.Combine(AppContext.BaseDirectory, Consts.BambooScriptEnginePackageDownload)).FullName; ConcurrentBag <string> concurrentBag = new ConcurrentBag <string>(); //并行下载 ScriptEngineCSharpConfigHelper.GetInstallPackageSourceDic().AsParallel().ForAll(current => //foreach (var current in ScriptEngineCSharpConfigHelper.GetInstallPackageSourceDic())//Debug { SourceCacheContext cache = new SourceCacheContext(); var package = current.Key; var currentVersionPath = Path.Combine(downloadPath, package.PackageId.ToLower(), package.Version.ToLower()); //先查询本地文件是否存在,如果存在,就无需再去下载 if (Directory.Exists(currentVersionPath)) { var file = Directory.GetFiles(currentVersionPath, "*.dll", SearchOption.AllDirectories).FirstOrDefault(t => Path.GetFileName(t).Equals(string.Concat(package.PackageId, ".dll"))); if (file != null) { concurrentBag.Add(file); return; } } //标记是否当前包已经成功匹配,如果成功,则不会继续在后续的源中查找 bool isCurrentPackageMatchSuccess = false; foreach (var source in current.Value) { if (isCurrentPackageMatchSuccess) { break; } SourceRepository repository = Repository.Factory.GetCoreV3(source); FindPackageByIdResource resource = repository.GetResourceAsync <FindPackageByIdResource>().Result; //当前源没有找到这个包,换下一个源下载 if (!resource.DoesPackageExistAsync(package.PackageId, new NuGetVersion(package.Version), cache, logger, cancellationToken).Result) { continue; } using (MemoryStream packageStream = new MemoryStream()) { //复制包 if (!resource.CopyNupkgToStreamAsync(package.PackageId, new NuGetVersion(package.Version), packageStream, cache, logger, cancellationToken).Result) { _logger.LogError($"copy package of {package.PackageId} {package.Version} from source [{source}] error"); break; } using (PackageArchiveReader packageReader = new PackageArchiveReader(packageStream)) { _logger.LogDebug($"copy package of {package.PackageId} {package.Version} from source [{source}] success"); var files = packageReader.GetFiles().Where(t => Path.GetExtension(t).Equals(".dll")).ToArray(); foreach (var file in files) { if (isCurrentPackageMatchSuccess) { break; } //按顺序匹配对应版本的dll foreach (var matchItem in Consts.MatchDllVersionFromNugetPackageSequnce) { if (file.Contains(matchItem)) { var fileFullPath = Path.Combine(currentVersionPath, file); if (!File.Exists(fileFullPath)) { packageReader.ExtractFile(file, fileFullPath, logger); } concurrentBag.Add(fileFullPath); isCurrentPackageMatchSuccess = true; break; } } } } } } //}//DEBUG }); //添加到dll引用目录 loadLocations.AddRange(concurrentBag); }