private bool SaveReport(string report) { try { if (!_outputFile.Directory.Exists) { _outputFile.Directory.Create(); } File.WriteAllText(path: _outputFile.FullName, contents: report); if (_outputFile.Exists) { _standardConsole.MarkupLine($"[green]Saved report to {_outputFile}[/]"); return(true); } } catch (UnauthorizedAccessException e) { _errorConsole.WriteLine(e.Message); } catch (Exception e) { _errorConsole.WriteLine($"Unexpected error occurred while saving report {e.Message}"); } return(false); }
public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings) { _writer.MarkupLine( "[yellow]Spectre.Cli[/] version [aqua]{0}[/]", VersionHelper.GetVersion(typeof(VersionCommand)?.Assembly)); _writer.MarkupLine( "[yellow]Spectre.Console[/] version [aqua]{0}[/]", VersionHelper.GetVersion(typeof(IAnsiConsole)?.Assembly)); return(0); }
public void ReportFinalState() { _progressBar.Tick(string.Format(LoggingFormat, _numberOfMutantsRan, _mutantsToBeTested, _mutantsKilledCount, _mutantsSurvivedCount, _mutantsTimeoutCount, RemainingTime())); Dispose(); var length = _mutantsToBeTested.ToString().Length; _console.WriteLine(); _console.MarkupLine($"Killed: [Magenta]{_mutantsKilledCount.ToString().PadLeft(length)}[/]"); _console.MarkupLine($"Survived: [Magenta]{_mutantsSurvivedCount.ToString().PadLeft(length)}[/]"); _console.MarkupLine($"Timeout: [Magenta]{_mutantsTimeoutCount.ToString().PadLeft(length)}[/]"); }
public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings) { var projectsToAnalyze = PathUtility.GetProjectPaths(settings.ProjectOrSolutionPath, out var entry); // Remove all projects that we want to skip. projectsToAnalyze.RemoveAll(p => { var projectName = Path.GetFileNameWithoutExtension(p); return(settings.Skip?.Contains(projectName, StringComparer.OrdinalIgnoreCase) ?? false); }); var targetFramework = settings.TargetFramework; var analyzerResults = new List <ProjectAnalyzerResult>(); var projectCache = new HashSet <Project>(new ProjectComparer()); _console.WriteLine(); return(_console.Status().Start($"Analyzing...", ctx => { ctx.Refresh(); _console.MarkupLine($"Analyzing [yellow]{Path.GetFileName(entry)}[/]"); foreach (var projectToAnalyze in projectsToAnalyze) { // Perform a design time build of the project. var buildResult = _builder.Build( projectToAnalyze, targetFramework, settings.Skip, projectCache); // Update the cache of built projects. projectCache.Add(buildResult.Project); foreach (var item in buildResult.Dependencies) { projectCache.Add(item); } // Analyze the project. var analyzeResult = _analyzer.Analyze(buildResult.Project); if (settings.Exclude?.Length > 0) { // Filter packages that should be excluded. analyzeResult = analyzeResult.Filter(settings.Exclude); } analyzerResults.Add(analyzeResult); } // Write the rport to the console _reporter.WriteToConsole(analyzerResults); // Return the correct exit code. return GetExitCode(settings, analyzerResults); })); }
public void Log <TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func <TState, Exception, string> formatter) { if (!IsEnabled(logLevel)) { return; } if (_config.EventId == 0 || _config.EventId == eventId.Id) { var prefix = _config.IncludePrefix ? GetLevelMarkup(logLevel) : string.Empty; var categoryStr = _config.IncludeEventId ? _name + $"[grey][[{eventId.Id}]][/]" : _name; _console.MarkupLine(prefix + categoryStr); _console.MarkupLine(string.Empty.PadRight(6) + formatter(state, exception)); } }
public void OnAllMutantsTested(IReadOnlyProjectComponent reportComponent) { var mutationReport = JsonReport.Build(_options, reportComponent); var reportUri = _dashboardClient.PublishReport(mutationReport, _options.ProjectVersion).Result; if (reportUri != null) { if (_options.ReportTypeToOpen == Options.Inputs.ReportType.Dashboard) { _processWrapper.Open(reportUri); } else { _console.Write("[Cyan]Hint: by passing \"--open-report:dashboard or -o:dashboard\" the report will open automatically once Stryker is done.[/]"); } _console.WriteLine(); _console.MarkupLine("[Green]Your report has been uploaded at:[/]"); if (_console.Profile.Capabilities.Links) { // We must print the report path as the link text because on some terminals links might be supported but not actually clickable: https://github.com/spectreconsole/spectre.console/issues/764 _console.MarkupLine($"[Green][link={reportUri}]{reportUri}[/][/]"); } else { _console.MarkupLine($"[Green]{reportUri}[/]"); } _console.MarkupLine("[Green]You can open it in your browser of choice.[/]"); } else { _logger.LogError("Uploading to stryker dashboard failed..."); } _console.WriteLine(); _console.WriteLine(); }
private void HandleStrykerRunResult(IStrykerInputs inputs, StrykerRunResult result) { var logger = ApplicationLogging.LoggerFactory.CreateLogger <StrykerCli>(); if (double.IsNaN(result.MutationScore)) { logger.LogInformation("Stryker was unable to calculate a mutation score"); } else { logger.LogInformation("The final mutation score is {MutationScore:P2}", result.MutationScore); } if (result.ScoreIsLowerThanThresholdBreak()) { var thresholdBreak = (double)inputs.ValidateAll().Thresholds.Break / 100; logger.LogWarning("Final mutation score is below threshold break. Crashing..."); _console.WriteLine(); _console.MarkupLine($"[Red]The mutation score is lower than the configured break threshold of {thresholdBreak:P0}.[/]"); _console.MarkupLine(" [Red]Looks like you've got some work to do :smiling_face_with_halo:[/]"); ExitCode = ExitCodes.BreakThresholdViolated; } }
public void OnAllMutantsTested(IReadOnlyProjectComponent reportComponent) { var mutationReport = JsonReport.Build(_options, reportComponent); var filename = _options.ReportFileName + ".json"; var reportPath = Path.Combine(_options.OutputPath, "reports", filename); var reportUri = "file://" + reportPath.Replace("\\", "/"); WriteReportToJsonFile(reportPath, mutationReport); _console.WriteLine(); _console.MarkupLine("[Green]Your json report has been generated at:[/]"); if (_console.Profile.Capabilities.Links) { // We must print the report path as the link text because on some terminals links might be supported but not actually clickable: https://github.com/spectreconsole/spectre.console/issues/764 _console.MarkupLine($"[Green][link={reportUri}]{reportPath}[/][/]"); } else { _console.MarkupLine($"[Green]{reportUri}[/]"); } }
/// <inheritdoc cref="ILogger.Log{TState}(LogLevel, EventId, TState, Exception?, Func{TState, Exception?, string})"/> public void Log <TState>(LogLevel logLevel, EventId eventId, TState state, Exception?exception, Func <TState, Exception?, string> formatter) { if (!IsEnabled(logLevel)) { return; } var stringBuilder = new StringBuilder(80); stringBuilder.Append(GetLevelMarkup(logLevel)); stringBuilder.AppendFormat("[dim grey]{0}[/] ", _name); stringBuilder.Append(Markup.Escape(formatter(state, exception))); _console.MarkupLine(stringBuilder.ToString()); }
public void OnAllMutantsTested(IReadOnlyProjectComponent reportComponent) { var mutationReport = JsonReport.Build(_options, reportComponent); var filename = _options.ReportFileName + ".html"; var reportPath = Path.Combine(_options.OutputPath, "reports", filename); reportPath = FilePathUtils.NormalizePathSeparators(reportPath); WriteHtmlReport(reportPath, mutationReport.ToJsonHtmlSafe()); var reportUri = "file://" + reportPath.Replace("\\", "/"); if (_options.ReportTypeToOpen == Options.Inputs.ReportType.Html) { _processWrapper.Open(reportUri); } else { _console.MarkupLine("[Cyan]Hint: by passing \"--open-report or -o\" the report will open automatically once Stryker is done.[/]"); } _console.WriteLine(); _console.MarkupLine("[Green]Your html report has been generated at:[/]"); if (_console.Profile.Capabilities.Links) { // We must print the report path as the link text because on some terminals links might be supported but not actually clickable: https://github.com/spectreconsole/spectre.console/issues/764 _console.MarkupLine($"[Green][link={reportUri}]{reportPath}[/][/]"); } else { _console.MarkupLine($"[Green]{reportUri}[/]"); } _console.MarkupLine("[Green]You can open it in your browser of choice.[/]"); }
public async Task <int> RunAll(IRemainingArguments remaining) { var examples = _finder.FindExamples(); foreach (var(_, first, _, example) in examples.Enumerate()) { if (!first) { _console.WriteLine(); } _console.Write(new Rule($"Example: [silver]{example.Name}[/]").LeftAligned().RuleStyle("grey")); var exitCode = await Run(example.Name, remaining).ConfigureAwait(false); if (exitCode != 0) { _console.MarkupLine($"[red]Error:[/] Example [u]{example.Name}[/] did not return a successful exit code."); return(exitCode); } } return(0); }
public void Log <TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func <TState, Exception, string> formatter) { if (!IsEnabled(logLevel)) { return; } if (_config.EventId == 0 || _config.EventId == eventId.Id) { var prefix = _config.IncludePrefix ? GetLevelMarkup(logLevel) : string.Empty; var eventIdStr = _config.IncludeEventId ? GetEventIdMarkup(eventId) + " " : string.Empty; _console.MarkupLine(prefix + eventIdStr + formatter(state, exception)); } }
public void List() { var examples = _finder.FindExamples(); if (examples.Count == 0) { _console.Markup("[yellow]No examples could be found.[/]"); return; } _console.WriteLine(); var rows = new Grid().Collapse(); rows.AddColumn(); foreach (var group in examples.GroupBy(ex => ex.Group)) { rows.AddRow(CreateTable(group.Key, group)); rows.AddEmptyRow(); } _console.Write(rows); _console.MarkupLine("Type [blue]dotnet example --help[/] for help"); }
public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings) { _console.MarkupLine($"Hello [yellow]{settings.Name.EscapeMarkup()}[/]!"); return(0); }
public override async Task <int> ExecuteAsync(CommandContext context, BrentOptions settings) { var archives = new List <BrentArchive>() { new("https://downloads.brentozar.com/StackOverflow-SQL-Server-2010.torrent", "Small: 10GB database as of 2010", "small"), new("https://downloads.brentozar.com/StackOverflow2013.torrent", "Medium: 50GB database as of 2013", "medium"), new("https://downloads.brentozar.com/StackOverflowCore.torrent", "Large 150GB database as of 2019", "large"), new("https://downloads.brentozar.com/StackOverflow-SQL-Server-202006.torrent", "Extra-Large: current 381GB database as of 2020/06", "extra-large"), }; var archiveName = settings.Archive; if (string.IsNullOrWhiteSpace(archiveName)) { var choice = _console.Prompt( new SelectionPrompt <BrentArchive>() .PageSize(10) .Title("Pick an archive to download") .AddChoices(archives)); archiveName = choice.ShortName; } var archive = archives.FirstOrDefault(a => a.ShortName.Equals(archiveName, StringComparison.InvariantCultureIgnoreCase)); if (archive == null) { throw new SoddiException($"Could not find an archive matching \"{archiveName}\""); } var outputPath = settings.Output; if (string.IsNullOrWhiteSpace(outputPath)) { outputPath = _fileSystem.Directory.GetCurrentDirectory(); } if (!_fileSystem.Directory.Exists(outputPath)) { throw new SoddiException($"Output path {outputPath} not found"); } var downloadedFiles = await _torrentDownloader.Download(archive.Url, settings.EnablePortForwarding, outputPath, CancellationToken.None); var sevenZipFiles = downloadedFiles.Where(i => _fileSystem.Path.GetExtension(i).Equals(".7z", StringComparison.InvariantCultureIgnoreCase)); var stopWatch = Stopwatch.StartNew(); var progressBar = _console.Progress() .AutoClear(false) .Columns(new ProgressColumn[] { new SpinnerColumn { CompletedText = Emoji.Known.CheckMark }, new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new TransferSpeedColumn(), new RemainingTimeColumn() }); progressBar.Start(ctx => { foreach (var sevenZipFile in sevenZipFiles) { using var stream = _fileSystem.File.OpenRead(sevenZipFile); using var sevenZipArchive = SevenZipArchive.Open(stream); var tasks = sevenZipArchive.Entries.ToImmutableDictionary( e => e.Key, e => ctx.AddTask(e.Key, new ProgressTaskSettings { MaxValue = e.Size, AutoStart = false })); foreach (var entry in sevenZipArchive.Entries) { var currentTask = tasks[entry.Key]; currentTask.StartTask(); var totalRead = 0L; void Handler(object?sender, CompressedBytesReadEventArgs args) { var diff = args.CurrentFilePartCompressedBytesRead - totalRead; currentTask.Increment(diff); totalRead = args.CurrentFilePartCompressedBytesRead; } sevenZipArchive.CompressedBytesRead += Handler; entry.WriteToDirectory(outputPath, new ExtractionOptions { Overwrite = true }); sevenZipArchive.CompressedBytesRead -= Handler; } } }); stopWatch.Stop(); _console.MarkupLine($"Extraction complete in [blue]{stopWatch.Elapsed.Humanize()}[/]."); return(0); }
public override async Task <int> ExecuteAsync(CommandContext context, ImportOptions request) { var cancellationToken = CancellationToken.None; var requestPath = await CheckAndFixupPath(request.Path, cancellationToken); var dbName = _databaseHelper.GetDbNameFromPathOption(request.DatabaseName, requestPath); var tasks = new Queue <(string name, ITask task)>(); var(masterConnectionString, databaseConnectionString) = _databaseHelper.GetMasterAndDbConnectionStrings(request.ConnectionString, dbName); ImmutableDictionary <string, long>?insertReport = null; var processor = _processorFactory.VerifyAndCreateProcessor(requestPath); if (request.DropAndRecreate) { tasks.Enqueue(("Create new database", new CreateDatabase(masterConnectionString, dbName))); } else { tasks.Enqueue(("Verify database exists", new VerifyDatabaseExists(masterConnectionString, dbName))); } tasks.Enqueue(("Create schema", new CreateSchema(databaseConnectionString, !request.SkipTags))); if (!request.SkipPrimaryKeys) { tasks.Enqueue(("Add constraints", new AddConstraints(databaseConnectionString))); } tasks.Enqueue(("Insert type values", new InsertTypeValues(databaseConnectionString))); tasks.Enqueue(("Insert data from archive", new InsertData( databaseConnectionString, dbName, processor, !request.SkipTags, d => insertReport = d, request.BlockSize))); var progressBar = _console.Progress() .AutoClear(false) .Columns(new ProgressColumn[] { new SpinnerColumn { CompletedText = Emoji.Known.CheckMark }, new FixedTaskDescriptionColumn(40), new ProgressBarColumn(), new PercentageColumn(), new RemainingTimeColumn(), }); var stopWatch = Stopwatch.StartNew(); progressBar.Start(ctx => { foreach (var(description, task) in tasks) { var progressTasks = new ConcurrentDictionary <string, ProgressTask>(); var progress = new Progress <(string taskId, string message, double weight, double maxValue)>(i => { var(taskId, message, weight, maxValue) = i; var progressBarTask = progressTasks.GetOrAdd(taskId, _ => ctx.AddTask(description)); progressBarTask.MaxValue(maxValue); progressBarTask.Increment(weight); progressBarTask.Description(message); }); task.Go(progress); foreach (var progressTask in progressTasks.Values) { progressTask.Increment(progressTask.MaxValue - progressTask.Value); } } }); stopWatch.Stop(); if (insertReport != null) { var counter = 1; var chart = new BreakdownChart() .Compact() .Width(60) .UseValueFormatter(d => d.ToMetric()) .FullSize() .AddItems(insertReport, pair => new BreakdownChartItem(pair.Key, pair.Value, counter++) ); _console.MarkupLine("[blue]Rows inserted[/]"); _console.Render(chart); } _console.WriteLine(); _console.MarkupLine($"Import complete in [blue]{stopWatch.Elapsed.Humanize()}[/]."); return(0); }
public void WriteToConsole([NotNull] List <ProjectAnalyzerResult> results) { var resultsWithPackageToRemove = results.Where(r => r.CanBeRemoved.Count > 0).ToList(); var resultsWithPackageMayBeRemove = results.Where(r => r.MightBeRemoved.Count > 0).ToList(); if (results.All(x => x.NoPackagesToRemove)) { // Output the result. _console.WriteLine(); _console.MarkupLine("[green]Everything looks good![/]"); _console.WriteLine(); return; } var report = new Grid(); report.AddColumn(); if (resultsWithPackageToRemove.Count > 0) { foreach (var(_, _, last, result) in resultsWithPackageToRemove.Enumerate()) { var table = new Table().BorderColor(Color.Grey).Expand(); table.AddColumns("[grey]Package[/]", "[grey]Referenced by[/]"); foreach (var item in result.CanBeRemoved) { table.AddRow( $"[green]{item.Package.Name}[/]", $"[aqua]{item.Original.Project.Name}[/]"); } report.AddRow($" [yellow]Packages that can be removed from[/] [aqua]{result.Project}[/]:"); report.AddRow(table); if (!last || (last && resultsWithPackageMayBeRemove.Count > 0)) { report.AddEmptyRow(); } } } if (resultsWithPackageMayBeRemove.Count > 0) { foreach (var(_, _, last, result) in resultsWithPackageMayBeRemove.Enumerate()) { var table = new Table().BorderColor(Color.Grey).Expand(); table.AddColumns("[grey]Package[/]", "[grey]Version[/]", "[grey]Reason[/]"); foreach (var item in result.MightBeRemoved) { if (item.Package.IsGreaterThan(item.Original.Package, out var indeterminate)) { var name = item.Original.Project.Name; var version = item.Original.Package.GetVersionString(); var verb = indeterminate ? "Might be updated from" : "Updated from"; var reason = $"[grey]{verb}[/] [silver]{version}[/] [grey]in[/] [aqua]{name}[/]"; table.AddRow( $"[green]{item.Package.Name}[/]", item.Package.GetVersionString(), reason); } else { var name = item.Original.Project.Name; var version = item.Original.Package.GetVersionString(); var verb = indeterminate ? "Does not match" : "Downgraded from"; var reason = $"[grey]{verb}[/] [silver]{version}[/] [grey]in[/] [aqua]{name}[/]"; table.AddRow( $"[green]{item.Package.Name}[/]", item.Package.GetVersionString(), reason); } } report.AddRow($" [yellow]Packages that [u]might[/] be removed from[/] [aqua]{result.Project}[/]:"); report.AddRow(table); if (!last) { report.AddEmptyRow(); } } } _console.WriteLine(); _console.Render( new Panel(report) .RoundedBorder() .BorderColor(Color.Grey)); }
private Project Build( AnalyzerManager manager, string path, string?tfm, string[]?skip, Dictionary <string, Project> built, int indentation = 0) { if (manager == null) { throw new ArgumentNullException(nameof(manager)); } if (built == null) { throw new ArgumentNullException(nameof(built)); } path = Path.GetFullPath(path); // Already built this project? if (built.TryGetValue(Path.GetFileName(path), out var project)) { return(project); } project = new Project(path); var result = Build(manager, project, tfm, indentation); if (result == null) { throw new InvalidOperationException($"Could not build {path}."); } // Get the asset path. var assetPath = result.GetProjectAssetsFilePath(); if (!string.IsNullOrWhiteSpace(assetPath)) { if (!File.Exists(assetPath)) { // Todo: Make sure this exists in future throw new InvalidOperationException($"{assetPath} not found. Please restore the project's dependencies before running Snitch."); } } else { var prefix = new string(' ', indentation * 2); if (indentation > 0) { prefix += " "; } _console.MarkupLine($"{prefix}[yellow]WARN:[/] Old CSPROJ format can't be analyzed"); } // Set project information. project.TargetFramework = result.TargetFramework; project.LockFilePath = assetPath; // Add the project to the built list. built.Add(Path.GetFileName(path), project); // Get the package references. foreach (var packageReference in result.PackageReferences) { if (packageReference.Value.TryGetValue("Version", out var version)) { project.Packages.Add(new Package(packageReference.Key, version)); } } // Analyze all project references. foreach (var projectReference in result.ProjectReferences) { var projectReferencePath = PathUtility.GetPathRelativeToProject(project, projectReference); if (skip != null) { var projectName = Path.GetFileNameWithoutExtension(projectReferencePath); if (skip.Contains(projectName, StringComparer.OrdinalIgnoreCase)) { continue; } } if (!projectReferencePath.EndsWith("csproj", StringComparison.OrdinalIgnoreCase)) { _console.MarkupLine("Skipping Non C# Project [aqua]{project.Name}[/]"); if (!string.IsNullOrWhiteSpace(tfm)) { _console.MarkupLine("Skipping Non C# Project [aqua]{project.Name}[/] [grey] ({tfm})[/]"); } else { _console.MarkupLine("Skipping Non C# Project [aqua]{project.Name}[/]"); } _console.WriteLine(); continue; } var analyzedProjectReference = Build(manager, projectReferencePath, project.TargetFramework, skip, built, indentation + 1); project.ProjectReferences.Add(analyzedProjectReference); } return(project); }
/// <inheritdoc/> public async Task <T> ShowAsync(IAnsiConsole console, CancellationToken cancellationToken) { if (console is null) { throw new ArgumentNullException(nameof(console)); } return(await console.RunExclusive(async() => { var promptStyle = PromptStyle ?? Style.Plain; var converter = Converter ?? TypeConverterHelper.ConvertToString; var choices = Choices.Select(choice => converter(choice)).ToList(); var choiceMap = Choices.ToDictionary(choice => converter(choice), choice => choice, _comparer); WritePrompt(console); while (true) { var input = await console.ReadLine(promptStyle, IsSecret, choices, cancellationToken).ConfigureAwait(false); // Nothing entered? if (string.IsNullOrWhiteSpace(input)) { if (DefaultValue != null) { console.Write(IsSecret ? "******" : converter(DefaultValue.Value), promptStyle); console.WriteLine(); return DefaultValue.Value; } if (!AllowEmpty) { continue; } } console.WriteLine(); T?result; if (Choices.Count > 0) { if (choiceMap.TryGetValue(input, out result) && result != null) { return result; } else { console.MarkupLine(InvalidChoiceMessage); WritePrompt(console); continue; } } else if (!TypeConverterHelper.TryConvertFromString <T>(input, out result) || result == null) { console.MarkupLine(ValidationErrorMessage); WritePrompt(console); continue; } // Run all validators if (!ValidateResult(result, out var validationMessage)) { console.MarkupLine(validationMessage); WritePrompt(console); continue; } return result; } }).ConfigureAwait(false)); }
public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings) { var samples = typeof(BaseSample).Assembly .GetTypes() .Where(i => i.IsClass && i.IsAbstract == false && i.IsSubclassOf(typeof(BaseSample))) .Select(Activator.CreateInstance) .Cast <BaseSample>(); var selectedSample = settings.Sample; if (settings.List) { selectedSample = AnsiConsole.Prompt( new SelectionPrompt <string>() .Title("Select an example to record") .PageSize(25) .AddChoices(samples.Select(x => x.Name()))); } if (!string.IsNullOrWhiteSpace(selectedSample)) { var desiredSample = samples.FirstOrDefault(i => i.Name().Equals(selectedSample, StringComparison.OrdinalIgnoreCase)); if (desiredSample == null) { _console.MarkupLine($"[red]Error:[/] could not find sample [blue]{selectedSample}[/]"); return(-1); } samples = new List <BaseSample> { desiredSample }; } // from here on out everything we write will be recorded. var recorder = _console.WrapWithAsciiCastRecorder(); foreach (var sample in samples) { var sampleName = sample.Name(); var originalWidth = _console.Profile.Width; var originalHeight = _console.Profile.Height; _console.Profile.Encoding = Encoding.UTF8; _console.Profile.Width = sample.ConsoleSize.Cols; _console.Profile.Height = sample.ConsoleSize.Rows; foreach (var(capabilityName, action) in sample.GetCapabilities()) { action(_console.Profile.Capabilities); sample.Run(_console); var json = recorder.GetCastJson($"{sampleName} ({capabilityName})", sample.ConsoleSize.Cols + 2, sample.ConsoleSize.Rows); File.WriteAllText(Path.Combine(settings.OutputPath, $"{sampleName}-{capabilityName}.cast"), json); } _console.Profile.Width = originalWidth; _console.Profile.Height = originalHeight; } return(0); }
public async Task <ImmutableList <string> > Download(string url, List <string>?potentialArchives, bool enablePortForwarding, string outputPath, CancellationToken cancellationToken) { var stopWatch = Stopwatch.StartNew(); var paddingFolder = _fileSystem.Path.Combine(outputPath, ".____padding_file"); var doesPaddingFolderExistToStart = _fileSystem.Directory.Exists(paddingFolder); var progressBar = _console.Progress() .AutoClear(false) .Columns(new ProgressColumn[] { new SpinnerColumn { CompletedText = Emoji.Known.CheckMark }, new DownloadedColumnExtended(), new TaskDescriptionColumn(), new TorrentProgressBarColumn(), new PercentageColumn(), new TransferSpeedColumn(), new RemainingTimeColumn() }); ImmutableList <TorrentFile>?downloadedFiles = null; await progressBar.StartAsync(async ctx => { _console.WriteLine("Loading torrent..."); var httpClient = new HttpClient(); var torrentContents = await httpClient.GetByteArrayAsync(url, cancellationToken); var settings = new EngineSettings { AllowedEncryption = EncryptionTypes.All, SavePath = outputPath, MaximumHalfOpenConnections = 16 }; _console.WriteLine("Initializing BitTorrent engine..."); var engine = new ClientEngine(settings); if (enablePortForwarding) { _console.WriteLine("Attempting to forward ports"); await engine.EnablePortForwardingAsync(cancellationToken); } var torrent = await Torrent.LoadAsync(torrentContents); if (potentialArchives != null) { foreach (var torrentFile in torrent.Files) { if (!potentialArchives.Contains(torrentFile.Path)) { torrentFile.Priority = Priority.DoNotDownload; } } } var manager = new TorrentManager( torrent, outputPath, new TorrentSettings { MaximumConnections = 250 }, string.Empty); await engine.Register(manager); await engine.StartAll(); downloadedFiles = manager.Torrent.Files .Where(i => i.Priority != Priority.DoNotDownload).ToImmutableList(); var fileTasks = downloadedFiles .ToDictionary( i => i.Path, file => ctx.AddTask(file.Path, new ProgressTaskSettings { MaxValue = file.Length, AutoStart = false }) ); while (manager.State != TorrentState.Stopped && manager.State != TorrentState.Seeding) { foreach (var torrentFile in downloadedFiles) { var progressTask = fileTasks[torrentFile.Path]; if (torrentFile.BytesDownloaded > 0 && progressTask.IsStarted == false) { progressTask.StartTask(); } progressTask.Increment(torrentFile.BytesDownloaded - progressTask.Value); progressTask.State.Update <BitSmuggler>("torrentBits", _ => new BitSmuggler(torrentFile.BitField)); } await Task.Delay(100, cancellationToken); } await manager.StopAsync(); await engine.StopAllAsync(); try { // the stackoverflow torrent files, and I think all of archive.org // seem to have these padding files that sneak into the download even // if they aren't included in the file list. not quite sure how to prevent that // so I'm gonna delete them after the fact I guess if (!doesPaddingFolderExistToStart && _fileSystem.Directory.Exists(paddingFolder)) { _fileSystem.Directory.Delete(paddingFolder, true); } } catch { /* swallow */ } foreach (var progressTask in fileTasks) { progressTask.Value.StopTask(); } }); stopWatch.Stop(); _console.MarkupLine($"Download complete in [blue]{stopWatch.Elapsed.Humanize()}[/]."); return(downloadedFiles?.Select(i => _fileSystem.Path.Combine(outputPath, i.Path)).ToImmutableList() ?? ImmutableList <string> .Empty); }
public override async Task <int> ExecuteAsync(CommandContext context, DownloadOptions request) { var cancellationToken = CancellationToken.None; var outputPath = request.Output; if (string.IsNullOrWhiteSpace(outputPath)) { outputPath = _fileSystem.Directory.GetCurrentDirectory(); } if (!_fileSystem.Directory.Exists(outputPath)) { throw new SoddiException($"Output path {outputPath} not found"); } var archiveUrl = await _availableArchiveParser.FindOrPickArchive(request.Archive, request.Pick, cancellationToken); var stopWatch = Stopwatch.StartNew(); await _console.Progress() .AutoClear(false) .Columns(new ProgressColumn[] { new SpinnerColumn { CompletedText = Emoji.Known.CheckMark }, new DownloadedColumn(), new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new TransferSpeedColumn(), new RemainingTimeColumn(), }).StartAsync(async ctx => { var tasks = new List <(ProgressTask Task, Archive.UriWithSize UriWithSize)>(); foreach (var archive in archiveUrl) { tasks.AddRange(archive.Uris .Select(uriWithSize => (ctx.AddTask(uriWithSize.Description(false)), uriWithSize)) .ToList()); } while (!ctx.IsFinished) { foreach (var(task, uriWithSize) in tasks) { var progress = new Progress <(int downloadedInBytes, int totalSizeInBytes)>(i => { var progressTask = task; var(downloadedInBytes, totalSizeInBytes) = i; progressTask.Increment(downloadedInBytes); progressTask.MaxValue(totalSizeInBytes); } ); var downloader = new ArchiveDownloader(outputPath, progress); await downloader.Go(uriWithSize.Uri, cancellationToken); } } }); stopWatch.Stop(); _console.MarkupLine($"Download complete in [blue]{stopWatch.Elapsed.Humanize()}[/]."); return(await Task.FromResult(0)); }
/// <summary> /// Shows the prompt and requests input from the user. /// </summary> /// <param name="console">The console to show the prompt in.</param> /// <returns>The user input converted to the expected type.</returns> /// <inheritdoc/> public T Show(IAnsiConsole console) { if (console is null) { throw new ArgumentNullException(nameof(console)); } var promptStyle = PromptStyle ?? Style.Plain; WritePrompt(console); while (true) { var input = console.ReadLine(promptStyle, IsSecret); // Nothing entered? if (string.IsNullOrWhiteSpace(input)) { if (DefaultValue != null) { console.Write(TextPrompt <T> .GetTypeConverter().ConvertToInvariantString(DefaultValue.Value), promptStyle); console.WriteLine(); return(DefaultValue.Value); } if (!AllowEmpty) { continue; } } console.WriteLine(); // Try convert the value to the expected type. if (!TextPrompt <T> .TryConvert(input, out var result) || result == null) { console.MarkupLine(ValidationErrorMessage); WritePrompt(console); continue; } if (Choices.Count > 0) { if (Choices.Contains(result)) { return(result); } else { console.MarkupLine(InvalidChoiceMessage); WritePrompt(console); continue; } } // Run all validators if (!ValidateResult(result, out var validationMessage)) { console.MarkupLine(validationMessage); WritePrompt(console); continue; } return(result); } }