diff --git a/bin/vagrant b/bin/vagrant index 5f6725b50..ba7e40076 100755 --- a/bin/vagrant +++ b/bin/vagrant @@ -108,6 +108,7 @@ begin o.on("--debug", "Enable debug output") o.on("--timestamp", "Enable timestamps on log output") o.on("--debug-timestamp", "Enable debug output with timestamps") + o.on("--no-tty", "Enable non-interactive output") }) # Create a logger right away @@ -146,6 +147,12 @@ begin opts[:ui_class] = Vagrant::UI::MachineReadable end + # Setting to enable/disable showing progress bars + if argv.include?("--no-tty") + argv.delete("--no-tty") + opts[:ui_class] = Vagrant::UI::NonInteractive + end + # Default to colored output opts[:ui_class] ||= Vagrant::UI::Colored diff --git a/lib/vagrant/ui.rb b/lib/vagrant/ui.rb index ee3547fc8..a521fd105 100644 --- a/lib/vagrant/ui.rb +++ b/lib/vagrant/ui.rb @@ -75,6 +75,13 @@ module Vagrant def machine(type, *data) @logger.info("Machine: #{type} #{data.inspect}") end + + # Yields self (UI) + # Provides a way for selectively displaying or not displaying + # updating content like download progress. + def rewriting + yield self + end end # This is a UI implementation that does nothing. @@ -252,6 +259,31 @@ module Vagrant end end + + class NonInteractive < Basic + def initialize + super + end + + def rewriting + # no-op + end + + def report_progress(progress, total, show_parts=true) + # no-op + end + + def clear_line + @logger.warn("Using `clear line` in a non interactive ui") + say(:info, "\n", opts) + end + + def ask(*args) + # Non interactive can't ask for input + raise Errors::UIExpectsTTY + end + end + # Prefixed wraps an existing UI and adds a prefix to it. class Prefixed < Interface # The prefix for `output` messages. @@ -290,7 +322,9 @@ module Vagrant [:clear_line, :report_progress].each do |method| # By default do nothing, these aren't formatted - define_method(method) { |*args| @ui.send(method, *args) } + define_method(method) do |*args| + @ui.send(method, *args) + end end # For machine-readable output, set the prefix in the @@ -344,6 +378,13 @@ module Vagrant "#{prefix}#{target} #{line}" end.join("\n") end + + def rewriting + @ui.rewriting do |ui| + yield ui + end + end + end # This is a UI implementation that outputs color for various types diff --git a/lib/vagrant/util/curl_helper.rb b/lib/vagrant/util/curl_helper.rb index 67def5a82..8c3d205d9 100644 --- a/lib/vagrant/util/curl_helper.rb +++ b/lib/vagrant/util/curl_helper.rb @@ -37,8 +37,10 @@ module Vagrant source_host = source_uri.host.to_s.split(".", 2).last location_host = location_uri.host.to_s.split(".", 2).last if !redirect_notify && location_host != source_host && !SILENCED_HOSTS.include?(location_host) - ui.clear_line - ui.detail "Download redirected to host: #{location_uri.host}" + ui.rewriting do |ui| + ui.clear_line + ui.detail "Download redirected to host: #{location_uri.host}" + end end redirect_notify = true end @@ -82,10 +84,11 @@ module Vagrant # 9 - Time spent # 10 - Time left # 11 - Current speed - output = "Progress: #{columns[0]}% (Rate: #{columns[11]}/s, Estimated time remaining: #{columns[10]})" - ui.clear_line - ui.detail(output, new_line: false) + ui.rewriting do |ui| + ui.clear_line + ui.detail(output, new_line: false) + end end end diff --git a/plugins/providers/hyperv/action/export.rb b/plugins/providers/hyperv/action/export.rb index 28b5ab4be..34a540409 100644 --- a/plugins/providers/hyperv/action/export.rb +++ b/plugins/providers/hyperv/action/export.rb @@ -25,8 +25,10 @@ module VagrantPlugins @env[:ui].info I18n.t("vagrant.actions.vm.export.exporting") export_tmp_dir = Vagrant::Util::Platform.wsl_to_windows_path(@env["export.temp_dir"]) @env[:machine].provider.driver.export(export_tmp_dir) do |progress| - @env[:ui].clear_line - @env[:ui].report_progress(progress.percent, 100, false) + @env[:ui].rewriting do |ui| + ui.clear_line + ui.report_progress(progress.percent, 100, false) + end end # Clear the line a final time so the next data can appear diff --git a/plugins/providers/virtualbox/action/export.rb b/plugins/providers/virtualbox/action/export.rb index f9132c3c4..51c1621f3 100644 --- a/plugins/providers/virtualbox/action/export.rb +++ b/plugins/providers/virtualbox/action/export.rb @@ -23,8 +23,10 @@ module VagrantPlugins def export @env[:ui].info I18n.t("vagrant.actions.vm.export.exporting") @env[:machine].provider.driver.export(ovf_path) do |progress| - @env[:ui].clear_line - @env[:ui].report_progress(progress.percent, 100, false) + @env[:ui].rewriting do |ui| + ui.clear_line + ui.report_progress(progress.percent, 100, false) + end end # Clear the line a final time so the next data can appear diff --git a/plugins/providers/virtualbox/action/import.rb b/plugins/providers/virtualbox/action/import.rb index fb540f50a..704814b61 100644 --- a/plugins/providers/virtualbox/action/import.rb +++ b/plugins/providers/virtualbox/action/import.rb @@ -19,8 +19,10 @@ module VagrantPlugins env[:ui].info I18n.t("vagrant.actions.vm.clone.creating") env[:machine].id = env[:machine].provider.driver.clonevm( env[:clone_id], env[:clone_snapshot]) do |progress| - env[:ui].clear_line - env[:ui].report_progress(progress, 100, false) + env[:ui].rewriting do |ui| + ui.clear_line + ui.report_progress(progress, 100, false) + end end # Clear the line one last time since the progress meter doesn't @@ -51,8 +53,10 @@ module VagrantPlugins # Import the virtual machine ovf_file = env[:machine].box.directory.join("box.ovf").to_s id = env[:machine].provider.driver.import(ovf_file) do |progress| - env[:ui].clear_line - env[:ui].report_progress(progress, 100, false) + env[:ui].rewriting do |ui| + ui.clear_line + ui.report_progress(progress, 100, false) + end end # Set the machine ID diff --git a/plugins/providers/virtualbox/action/prepare_clone_snapshot.rb b/plugins/providers/virtualbox/action/prepare_clone_snapshot.rb index 08ce16a6d..653e61a91 100644 --- a/plugins/providers/virtualbox/action/prepare_clone_snapshot.rb +++ b/plugins/providers/virtualbox/action/prepare_clone_snapshot.rb @@ -55,8 +55,10 @@ module VagrantPlugins @logger.info("Creating base snapshot for master VM.") env[:machine].provider.driver.create_snapshot( env[:clone_id], name) do |progress| - env[:ui].clear_line - env[:ui].report_progress(progress, 100, false) + env[:ui].rewriting do |ui| + ui.clear_line + ui.report_progress(progress, 100, false) + end end end end diff --git a/plugins/providers/virtualbox/action/snapshot_delete.rb b/plugins/providers/virtualbox/action/snapshot_delete.rb index 1d8cecc73..74fac9440 100644 --- a/plugins/providers/virtualbox/action/snapshot_delete.rb +++ b/plugins/providers/virtualbox/action/snapshot_delete.rb @@ -12,8 +12,10 @@ module VagrantPlugins name: env[:snapshot_name])) env[:machine].provider.driver.delete_snapshot( env[:machine].id, env[:snapshot_name]) do |progress| - env[:ui].clear_line - env[:ui].report_progress(progress, 100, false) + env[:ui].rewriting do |ui| + ui.clear_line + ui.report_progress(progress, 100, false) + end end # Clear the line one last time since the progress meter doesn't disappear diff --git a/plugins/providers/virtualbox/action/snapshot_restore.rb b/plugins/providers/virtualbox/action/snapshot_restore.rb index f655471c1..922d51d84 100644 --- a/plugins/providers/virtualbox/action/snapshot_restore.rb +++ b/plugins/providers/virtualbox/action/snapshot_restore.rb @@ -12,8 +12,10 @@ module VagrantPlugins name: env[:snapshot_name])) env[:machine].provider.driver.restore_snapshot( env[:machine].id, env[:snapshot_name]) do |progress| - env[:ui].clear_line - env[:ui].report_progress(progress, 100, false) + env[:ui].rewriting do |ui| + ui.clear_line + ui.report_progress(progress, 100, false) + end end # Clear the line one last time since the progress meter doesn't disappear diff --git a/test/unit/bin/vagrant_test.rb b/test/unit/bin/vagrant_test.rb index 42245631b..bc11309aa 100644 --- a/test/unit/bin/vagrant_test.rb +++ b/test/unit/bin/vagrant_test.rb @@ -91,6 +91,15 @@ describe "vagrant bin" do with(hash_including(ui_class: Vagrant::UI::Colored)) end end + + describe "--no-tty" do + let(:argv) { ["--no-tty"] } + + it "should enable less verbose progress output" do + expect(Vagrant::Environment).to receive(:new). + with(hash_including(ui_class: Vagrant::UI::NonInteractive)) + end + end end context "default CLI flags" do diff --git a/test/unit/vagrant/ui_test.rb b/test/unit/vagrant/ui_test.rb index 5cc1722d8..4d1ded16e 100644 --- a/test/unit/vagrant/ui_test.rb +++ b/test/unit/vagrant/ui_test.rb @@ -110,6 +110,33 @@ describe Vagrant::UI::Basic do subject.detail(output) end end + + context "#rewriting" do + it "does output progress" do + expect { |b| subject.rewriting(&b) }.to yield_control + end + end +end + +describe Vagrant::UI::NonInteractive do + describe "#ask" do + it "raises an exception" do + expect{subject.ask("foo")}.to raise_error(Vagrant::Errors::UIExpectsTTY) + end + end + + describe "#report_progress" do + it "does not output progress" do + expect(subject).to_not receive(:info) + subject.report_progress(1, 1) + end + end + + describe "#rewriting" do + it "does not output progress" do + expect { |b| subject.rewriting(&b) }.to_not yield_control + end + end end describe Vagrant::UI::Colored do diff --git a/test/unit/vagrant/util/downloader_test.rb b/test/unit/vagrant/util/downloader_test.rb index 0aa29f5fd..973510259 100644 --- a/test/unit/vagrant/util/downloader_test.rb +++ b/test/unit/vagrant/util/downloader_test.rb @@ -38,6 +38,7 @@ describe Vagrant::Util::Downloader do before do allow(ui).to receive(:clear_line) allow(ui).to receive(:detail) + allow(ui).to receive(:rewriting).and_yield(ui) end after do