bwrap 1.0.0 → 1.1.0.pre.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,6 +8,12 @@ require_relative "library"
8
8
  #
9
9
  # @see Config::Features
10
10
  class Bwrap::Args::Features < Hash
11
+ # Requires are here so there is no extra trickiness with namespaces.
12
+ #
13
+ # Feature implementations are not meant to be used outside of this class anyway.
14
+ require_relative "features/binds_base"
15
+ require_relative "features/ruby_binds"
16
+
11
17
  include Bwrap::Output
12
18
 
13
19
  # Implementation for Bash feature set.
@@ -45,44 +51,6 @@ class Bwrap::Args::Features < Hash
45
51
  end
46
52
  end
47
53
 
48
- # Implementation for Ruby feature set.
49
- #
50
- # @api private
51
- class RubyBinds
52
- # Returns mounts needed by Ruby feature set.
53
- attr_reader :mounts
54
-
55
- # Bind system paths so scripts works inside sandbox.
56
- def sitedir_mounts
57
- mounts = []
58
- mounts << "--ro-bind" << RbConfig::CONFIG["sitedir"] << RbConfig::CONFIG["sitedir"]
59
- mounts << "--ro-bind" << RbConfig::CONFIG["rubyhdrdir"] << RbConfig::CONFIG["rubyhdrdir"]
60
- mounts << "--ro-bind" << RbConfig::CONFIG["rubylibdir"] << RbConfig::CONFIG["rubylibdir"]
61
- mounts << "--ro-bind" << RbConfig::CONFIG["vendordir"] << RbConfig::CONFIG["vendordir"]
62
-
63
- mounts
64
- end
65
-
66
- # Create binds for required system libraries.
67
- #
68
- # These are in path like /usr/lib64/ruby/2.5.0/x86_64-linux-gnu/,
69
- # and as they are mostly shared libraries, they may have some extra
70
- # dependencies that also need to be bound inside the sandbox.
71
- def stdlib_mounts stdlib
72
- library_mounts = []
73
- library = Bwrap::Args::Library.new
74
- stdlib.each do |lib|
75
- path = "#{RbConfig::CONFIG["rubyarchdir"]}/#{lib}.so"
76
-
77
- library.needed_libraries(path).each do |requisite_library|
78
- library_mounts << "--ro-bind" << requisite_library << requisite_library
79
- end
80
- end
81
-
82
- library_mounts
83
- end
84
- end
85
-
86
54
  # `Array` of parameters passed to bwrap.
87
55
  attr_writer :args
88
56
 
@@ -104,7 +72,7 @@ class Bwrap::Args::Features < Hash
104
72
 
105
73
  binds = BashBinds.new
106
74
 
107
- @args.append binds.bash_mounts
75
+ @args.add :feature_binds, binds.bash_mounts
108
76
  end
109
77
 
110
78
  private def nscd_binds
@@ -112,7 +80,7 @@ class Bwrap::Args::Features < Hash
112
80
 
113
81
  binds = NscdBinds.new
114
82
 
115
- @args.append binds.custom_binds
83
+ @args.add :feature_binds, binds.custom_binds
116
84
  end
117
85
 
118
86
  # @note This does not allow development headers needed for compilation for now.
@@ -120,9 +88,9 @@ class Bwrap::Args::Features < Hash
120
88
  private def ruby_binds
121
89
  return unless @config.features.ruby.enabled?
122
90
 
123
- binds = RubyBinds.new
91
+ binds = RubyBinds.new @config
124
92
 
125
- @args.append binds.sitedir_mounts
126
- @args.append binds.stdlib_mounts(@config.features.ruby.stdlib)
93
+ @args.add :feature_binds, binds.sitedir_mounts
94
+ @args.add :feature_binds, binds.stdlib_mounts(@config.features.ruby.stdlib)
127
95
  end
128
96
  end
@@ -66,8 +66,6 @@ class Bwrap::Args::Library
66
66
  @needed_libraries
67
67
  end
68
68
 
69
- # Used by {Bwrap::Args::Bind#libs_command_requires}.
70
- #
71
69
  # @param binary_paths [String, Array] one or more paths to be resolved
72
70
  def needed_libraries binary_paths
73
71
  trace "Finding libraries #{binary_paths} requires"
@@ -105,7 +103,7 @@ class Bwrap::Args::Library
105
103
  libraries = libraries_line.split ","
106
104
 
107
105
  (@needed_libraries & libraries).each do |library|
108
- verb "Binding #{library} as dependency of #{binary_path}"
106
+ debug "Binding #{library} as dependency of #{binary_path}"
109
107
  end
110
108
 
111
109
  @needed_libraries |= libraries
@@ -9,25 +9,25 @@ module Bwrap::Args::Mount
9
9
  return unless @config.root
10
10
 
11
11
  debug "Binding #{@config.root} as /"
12
- @args.append %W{ --bind #{@config.root} / }
13
- @args.append %w{ --chdir / }
12
+ @args.add :root_mount, "--bind", @config.root, "/"
13
+ @args.add :root_mount, "--chdir", "/"
14
14
  end
15
15
 
16
16
  # Arguments for mounting devtmpfs to /dev.
17
17
  private def dev_mount
18
18
  debug "Mounting new devtmpfs to /dev"
19
- @args.append %w{ --dev /dev }
19
+ @args.add :dev_mounts, "--dev", "/dev"
20
20
  end
21
21
 
22
22
  # Arguments for mounting procfs to /proc.
23
23
  private def proc_mount
24
24
  debug "Mounting new procfs to /proc"
25
- @args.append %w{ --proc /proc }
25
+ @args.add :proc_mount, "--proc", "/proc"
26
26
  end
27
27
 
28
28
  # Arguments for mounting tmpfs to /tmp.
29
29
  private def tmp_as_tmpfs
30
30
  debug "Mounting tmpfs to /tmp"
31
- @args.append %w{ --tmpfs /tmp }
31
+ @args.add :tmp_mount, "--tmpfs", "/tmp"
32
32
  end
33
33
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bwrap/output"
4
+ require_relative "args"
5
+
6
+ # Network related binds.
7
+ class Bwrap::Args::Network
8
+ include Bwrap::Output
9
+
10
+ # Instance of {Config}.
11
+ attr_writer :config
12
+
13
+ # @param args [Bwrap::Args::Args] Arguments to be passed to bwrap.
14
+ def initialize args
15
+ @args = args
16
+ end
17
+
18
+ # Arguments to set hostname to whatever is configured.
19
+ def hostname
20
+ return unless @config.hostname
21
+
22
+ debug "Setting hostname to #{@config.hostname}"
23
+ @args.add :hostname, %W{ --hostname #{@config.hostname} }
24
+ end
25
+
26
+ # Arguments to read-only bind /etc/resolv.conf.
27
+ def resolv_conf
28
+ # We can’t really bind symlinks, so let’s resolve real path to resolv.conf, in case it is symlinked.
29
+ source_resolv_conf = Pathname.new "/etc/resolv.conf"
30
+ source_resolv_conf = source_resolv_conf.realpath
31
+
32
+ debug "Binding #{source_resolv_conf} as /etc/resolv.conf"
33
+ @args.add :resolv_conf, %W{ --ro-bind #{source_resolv_conf} /etc/resolv.conf }
34
+ end
35
+
36
+ # Arguments to allow network connection inside sandbox.
37
+ def share_net
38
+ return unless @config.share_net
39
+
40
+ verb "Sharing network"
41
+ @args.add :network, %w{ --share-net }
42
+ end
43
+ end
data/lib/bwrap/bwrap.rb CHANGED
@@ -55,7 +55,9 @@ class Bwrap::Bwrap
55
55
  construct = Bwrap::Args::Construct.new
56
56
  construct.command = command
57
57
  construct.config = @config
58
- bwrap_args = construct.construct_bwrap_args
58
+
59
+ construct.calculate
60
+ bwrap_args = construct.bwrap_arguments
59
61
 
60
62
  exec_command = [ "bwrap" ]
61
63
  exec_command += bwrap_args
@@ -89,7 +91,9 @@ class Bwrap::Bwrap
89
91
  construct = Bwrap::Args::Construct.new
90
92
  construct.command = command
91
93
  construct.config = config
92
- bwrap_args = construct.construct_bwrap_args
94
+
95
+ construct.calculate
96
+ bwrap_args = construct.bwrap_arguments
93
97
 
94
98
  exec_command = [ "bwrap" ]
95
99
  exec_command += bwrap_args
@@ -134,6 +138,9 @@ class Bwrap::Bwrap
134
138
  opt :trace,
135
139
  "Show trace output (noisiest, probably not useful for most of time)",
136
140
  short: :none
141
+ opt [ :quiet, :silent ],
142
+ "Hides notice messages. Warnings and errors are still shown.",
143
+ short: :none
137
144
  opt :version,
138
145
  "Print version and exit",
139
146
  short: "V"
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @abstract
4
+ #
5
+ # Base of all features.
6
+ class Bwrap::Config::Features::Base
7
+ # @param features [Bwrap::Config::Features] Instance of features object in {Config}
8
+ def initialize features
9
+ @features = features
10
+ end
11
+
12
+ # Checks if the feature has been enabled.
13
+ #
14
+ # @return [Boolean] whether feature is enabled
15
+ def enabled?
16
+ @enabled
17
+ end
18
+
19
+ # Enable the feature.
20
+ def enable
21
+ @enabled = true
22
+ end
23
+
24
+ # Disable the feature.
25
+ def disable
26
+ @enabled = false
27
+ end
28
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bwrap/execution"
4
+
5
+ # Defines Ruby feature set.
6
+ #
7
+ # Implies {Nscd} feature.
8
+ class Bwrap::Config::Features::Ruby < Bwrap::Config::Features::Base
9
+ include Bwrap::Execution
10
+
11
+ def initialize features
12
+ super features
13
+
14
+ @gem_env_paths = true
15
+ @stdlib = []
16
+ end
17
+
18
+ # @return true if bindirs from “gem environment” should be added to sandbox.
19
+ def gem_env_paths?
20
+ @gem_env_paths
21
+ end
22
+
23
+ # Enable Ruby feature set.
24
+ #
25
+ # Among others, binds `RbConfig::CONFIG["sitedir"]` so scripts works.
26
+ #
27
+ # @note This does not allow development headers needed for compilation for now.
28
+ # I’ll look at it after I have an use for it.
29
+ #
30
+ # @note Also enables {Nscd} feature.
31
+ def enable
32
+ super
33
+
34
+ @features.nscd.enable
35
+ end
36
+
37
+ # @return [Pathname|nil] path to Ruby interpreter.
38
+ def interpreter
39
+ @features.mime&.executable_path
40
+ end
41
+
42
+ # @return [Hash(String, String)] RbConfig::CONFIG from interpreter returned by {#interpreter}
43
+ def ruby_config
44
+ unless interpreter
45
+ raise "Interpreter is not set, so ruby_config() can’t be called yet."
46
+ end
47
+
48
+ return @ruby_config if @ruby_config
49
+
50
+ script = %q{RbConfig::CONFIG.each { |k, v| puts "#{k}=#{v}" }}
51
+ config_string = execvalue %W{ #{interpreter} -e #{script} }
52
+
53
+ ruby_config = {}
54
+ config_string.split("\n").each do |line|
55
+ key, value = line.split "=", 2
56
+ ruby_config[key] = value
57
+ end
58
+
59
+ @ruby_config = ruby_config
60
+ end
61
+
62
+ # Extra libraries to be loaded from script’s interpreter’s `RbConfig::CONFIG["rubyarchdir"]`.
63
+ #
64
+ # @note Existence of library paths are checked here, and not in {#stdlib=},
65
+ # to avoid error about missing interpreter, as it is set in {Bwrap::Bwrap#run},
66
+ # and config is meant to be created beforehand.
67
+ #
68
+ # @note This is only required to be called if extra dependencies are necessary.
69
+ # For example, psych.so requires libyaml.so.
70
+ #
71
+ # @return [Array] list of needed libraries.
72
+ def stdlib
73
+ # Just a little check to have error earlier.
74
+ @stdlib.each do |lib|
75
+ unless File.exist? "#{ruby_config["rubyarchdir"]}/#{lib}.so"
76
+ raise "Library “#{lib}” passed to Bwrap::Config::Ruby.stdlib= does not exist."
77
+ end
78
+ end
79
+
80
+ @stdlib
81
+ end
82
+
83
+ def stdlib= libs
84
+ @stdlib = libs
85
+ end
86
+ end
@@ -3,32 +3,14 @@
3
3
  class Bwrap::Config
4
4
  # Methods to enable or disable feature sets to control various aspects of sandboxing.
5
5
  class Features
6
- # @abstract
6
+ # Requires are here so there is no extra trickiness with namespaces.
7
7
  #
8
- # Base of all features.
9
- class Base
10
- # @param features [Bwrap::Config::Features] Instance of features object in {Config}
11
- def initialize features
12
- @features = features
13
- end
8
+ # Feature implementations are not meant to be used outside of this class anyway.
9
+ require_relative "features/base"
10
+ require_relative "features/ruby"
14
11
 
15
- # Checks if the feature has been enabled.
16
- #
17
- # @return [Boolean] whether feature is enabled
18
- def enabled?
19
- @enabled
20
- end
21
-
22
- # Enable the feature.
23
- def enable
24
- @enabled = true
25
- end
26
-
27
- # Disable the feature.
28
- def disable
29
- @enabled = false
30
- end
31
- end
12
+ # Instance of {Bwrap::Args::Bind::Mime}.
13
+ attr_accessor :mime
32
14
 
33
15
  # Defines Bash feature set.
34
16
  class Bash < Base
@@ -44,60 +26,6 @@ class Bwrap::Config
44
26
  # Nya.
45
27
  end
46
28
 
47
- # Defines Ruby feature set.
48
- #
49
- # Implies {Nscd} feature.
50
- class Ruby < Base
51
- # Extra libraries to be loaded from `RbConfig::CONFIG["rubyarchdir"]`.
52
- #
53
- # @note This is only required to be called if extra dependencies are necessary.
54
- # For example, psych.so requires libyaml.so.
55
- #
56
- # @return [Array] list of needed libraries.
57
- #
58
- # @overload stdlib
59
- # @overload stdlib=(libs)
60
- attr_reader :stdlib
61
-
62
- def initialize features
63
- super features
64
-
65
- @gem_env_paths = true
66
- @stdlib = []
67
- end
68
-
69
- # @return true if bindirs from “gem environment” should be added to sandbox.
70
- def gem_env_paths?
71
- @gem_env_paths
72
- end
73
-
74
- # Enable Ruby feature set.
75
- #
76
- # Among others, binds `RbConfig::CONFIG["sitedir"]` so scripts works.
77
- #
78
- # @note This does not allow development headers needed for compilation for now.
79
- # I’ll look at it after I have an use for it.
80
- #
81
- # @note Also enables {Nscd} feature.
82
- def enable
83
- super
84
-
85
- @features.nscd.enable
86
- end
87
-
88
- # @see #stdlib
89
- def stdlib= libs
90
- # Just a little check to have error earlier.
91
- libs.each do |lib|
92
- unless File.exist? "#{RbConfig::CONFIG["rubyarchdir"]}/#{lib}.so"
93
- raise "Library “#{lib}” passed to Bwrap::Config::Ruby.stdlib= does not exist."
94
- end
95
- end
96
-
97
- @stdlib = libs
98
- end
99
- end
100
-
101
29
  # @return [Bash] Instance of feature class for Bash
102
30
  def bash
103
31
  @bash ||= Bash.new self
@@ -7,6 +7,18 @@ module Bwrap::Execution
7
7
 
8
8
  # Signifies that command execution has failed.
9
9
  class ExecutionFailed < CommandError
10
+ # The command that was executed.
11
+ attr_reader :command
12
+
13
+ # Output of the command.
14
+ attr_reader :output
15
+
16
+ def initialize msg, command:, output:
17
+ @command = command
18
+ @output = output
19
+
20
+ super msg
21
+ end
10
22
  end
11
23
 
12
24
  # Thrown if given command was not found.
@@ -63,13 +63,17 @@ class Bwrap::Execution::Execute
63
63
  end
64
64
 
65
65
  # Checks whether execution failed and acts accordingly.
66
- def self.handle_execution_fail fail:, error:, output:
67
- return unless fail and !$CHILD_STATUS.success?
66
+ def self.handle_execution_fail fail:, error:, output:, command:
67
+ return unless fail and !execution_success?
68
68
 
69
69
  if error == :show and !output.empty?
70
70
  Bwrap::Output.warn_output "Command failed with output:\n“#{output}”"
71
71
  end
72
- raise Bwrap::Execution::ExecutionFailed, "Command execution failed.", caller
72
+
73
+ exception = Bwrap::Execution::ExecutionFailed.new "Command execution failed",
74
+ command: command,
75
+ output: output
76
+ raise exception, caller
73
77
  end
74
78
 
75
79
  # @note It makes sense for caller to just return if wait has been set and not check output.
@@ -101,6 +105,13 @@ class Bwrap::Execution::Execute
101
105
  "to add “self.prepend_rootcmd(command, rootcmd:)” method."
102
106
  end
103
107
 
108
+ # A wrapper to get status of an execution.
109
+ #
110
+ # Mainly here so test implementation is easier.
111
+ private_class_method def self.execution_success?
112
+ $CHILD_STATUS.success?
113
+ end
114
+
104
115
  # Used by `#handle_logging`.
105
116
  private_class_method def self.calculate_log_command command
106
117
  return command.dup unless command.respond_to?(:join)
@@ -61,7 +61,7 @@ module Bwrap::Execution
61
61
  end
62
62
 
63
63
  # If command is string, splat operator (the *) does not do anything. If array, it expand the arguments.
64
- # This causes spawning work correctly, as that’s how spawn() expects to have the argu
64
+ # This causes spawning work correctly, as that’s how spawn() expects to have the arguments.
65
65
  pid = spawn(env, *command, err: [ :child, :out ], out: Execute.w, unsetenv_others: clear_env)
66
66
  output = Execute.finish_execution(log: log, wait: wait, direct_output: direct_output)
67
67
  return pid unless wait
@@ -71,7 +71,7 @@ module Bwrap::Execution
71
71
  @last_status = $CHILD_STATUS
72
72
 
73
73
  output = Execute.process_output output: output
74
- Execute.handle_execution_fail fail: fail, error: error, output: output
74
+ Execute.handle_execution_fail fail: fail, error: error, output: output, command: command
75
75
  output
76
76
  ensure
77
77
  Execute.clean_variables
@@ -20,7 +20,7 @@ module Bwrap::Execution::Path
20
20
  #
21
21
  # @yield Command appended to each path in PATH environment variable
22
22
  # @yieldparam path [String] Full path to executable
23
- def self.each_env_path command, env_path_var: ENV["PATH"]
23
+ def self.each_env_path command, env_path_var: ENV.fetch("PATH", nil)
24
24
  exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [ "" ]
25
25
 
26
26
  env_path_var.split(File::PATH_SEPARATOR).each do |env_path|
@@ -39,7 +39,7 @@ module Bwrap::Execution::Path
39
39
  # @param command [String] executable to be resolved
40
40
  # @param env_path_var [String] PATH environment variable as string.
41
41
  # Defaults to `ENV["PATH"]`
42
- private def command_available? command, env_path_var: ENV["PATH"]
42
+ private def command_available? command, env_path_var: ENV.fetch("PATH", nil)
43
43
  # Special handling for absolute paths.
44
44
  path = Pathname.new command
45
45
  if path.absolute?
@@ -60,7 +60,7 @@ module Bwrap::Execution::Path
60
60
  # Returns path to given executable.
61
61
  #
62
62
  # @param (see #command_available?)
63
- private def which command, fail: true, env_path_var: ENV["PATH"]
63
+ private def which command, fail: true, env_path_var: ENV.fetch("PATH", nil)
64
64
  # Special handling for absolute paths.
65
65
  path = Pathname.new command
66
66
  if path.absolute?
@@ -8,7 +8,8 @@ class Bwrap::Output::Levels
8
8
 
9
9
  @@_verbose = false
10
10
  @@_debug = false
11
- @@_trace = ENV["BWRAP_TRACE"] && true || false
11
+ @@_trace = ENV.fetch("BWRAP_TRACE", nil) && true || false
12
+ @@_quiet = false
12
13
 
13
14
  # @see Bwrap::Output#verbose?
14
15
  def self.verbose?
@@ -25,8 +26,18 @@ class Bwrap::Output::Levels
25
26
  @@_trace
26
27
  end
27
28
 
29
+ # @see Bwrap::Output##quiet?
30
+ def self.quiet?
31
+ @@_quiet
32
+ end
33
+
28
34
  # Takes hash of options received from Optimist and checks output related flags.
29
35
  def self.handle_output_options options
36
+ if options[:quiet] or options[:silent]
37
+ quiet!
38
+ return
39
+ end
40
+
30
41
  # Set output level flags to true or false, if it was given.
31
42
  unless options[:trace].nil?
32
43
  @@_verbose = options[:trace]
@@ -64,6 +75,18 @@ class Bwrap::Output::Levels
64
75
  out
65
76
  end
66
77
 
78
+ # Formats given string and outputs it.
79
+ #
80
+ # @return formatted string
81
+ def self.info_print_formatted str, log_callback: 1
82
+ # TODO: Maybe have different color for NOTICE than for INFO?
83
+ out = "#{Bwrap::Output::Colors.color(130, 230, 130, bold: true)}[NOTICE]#{Bwrap::Output::Colors.stopcolor} #{str}"
84
+ out = append_caller out, log_callback: (log_callback + 1)
85
+ puts out
86
+
87
+ out
88
+ end
89
+
67
90
  # Formats given string and outputs it.
68
91
  #
69
92
  # @return formatted string
@@ -98,9 +121,16 @@ class Bwrap::Output::Levels
98
121
  # Appends caller information to given output.
99
122
  #
100
123
  # Used by *_print_formatted methods.
101
- def self.append_caller out, log_callback: 1
124
+ private_class_method def self.append_caller out, log_callback: 1
102
125
  out = "#{out} (called at #{caller_locations(log_callback, 1)[0]})" if @@_trace
103
126
  out
104
127
  end
105
- private_class_method :append_caller
128
+
129
+ # Sets variables so that no extra output is shown.
130
+ private_class_method def self.quiet!
131
+ @@_verbose = false
132
+ @@_debug = false
133
+ @@_trace = false
134
+ @@_quiet = true
135
+ end
106
136
  end
@@ -32,6 +32,8 @@ require_relative "log"
32
32
  # When using {Bwrap::Bwrap}, {Bwrap::Bwrap#parse_command_line_arguments}
33
33
  # causes output levels to be set if relevant CLI arguments have been
34
34
  # given. TODO: Add documentation about CLI args somewhere. Maybe README?
35
+ #
36
+ # TODO: Add new method info() which can then be silenced using --quiet or --silent.
35
37
  module Bwrap::Output
36
38
  # @see #verbose?
37
39
  def self.verbose?
@@ -43,6 +45,12 @@ module Bwrap::Output
43
45
  Bwrap::Output::Levels.debug?
44
46
  end
45
47
 
48
+ # @see #quiet?
49
+ # @see #info
50
+ def self.quiet?
51
+ Bwrap::Output::Levels.quiet?
52
+ end
53
+
46
54
  # @see #trace?
47
55
  def self.trace?
48
56
  Bwrap::Output::Levels.trace?
@@ -89,6 +97,18 @@ module Bwrap::Output
89
97
  Bwrap::Output::Log.puts_to_log out || str
90
98
  end
91
99
 
100
+ # Handler used by #info to output given string.
101
+ def self.info_output str, raw: false, log_callback: 1
102
+ return if quiet?
103
+
104
+ if raw
105
+ print str
106
+ else
107
+ out = Bwrap::Output::Levels.info_print_formatted str, log_callback: (log_callback + 1)
108
+ end
109
+ Bwrap::Output::Log.puts_to_log out || str
110
+ end
111
+
92
112
  # Handler used by #warn to output given string.
93
113
  def self.warn_output str, raw: false, log_callback: 1
94
114
  if raw
@@ -114,6 +134,13 @@ module Bwrap::Output
114
134
  exit exit_code
115
135
  end
116
136
 
137
+ # @see #info
138
+ #
139
+ # @return true if --quiet or --silent has been passed, false if not.
140
+ private def quiet?
141
+ Bwrap::Output::Levels.quiet?
142
+ end
143
+
117
144
  # @return true if --verbose, --debug or --trace has been passed, false if not.
118
145
  private def verbose?
119
146
  Bwrap::Output::Levels.verbose?
@@ -161,6 +188,33 @@ module Bwrap::Output
161
188
  Bwrap::Output.verb_output(str, raw: raw, log_callback: 2)
162
189
  end
163
190
 
191
+ # Outputs given string if info flag has been set.
192
+ #
193
+ # This is meant for notices, and the log will be labeled with
194
+ # [NOTICE].
195
+ #
196
+ # Output flags can be set with {.handle_output_options}.
197
+ #
198
+ # == Implementation hint
199
+ #
200
+ # Usually implementing --quiet and/or --silent flag
201
+ # to control these messages (and all other output) may make
202
+ # sense.
203
+ #
204
+ # That way it would be possible to have some important
205
+ # informational messages that should be shown, but for script
206
+ # usage, those could be muted.
207
+ #
208
+ # Warning messages are meant to be shown always. Error messages
209
+ # will always be printed, as execution is halted after the
210
+ # error message has been printed.
211
+ #
212
+ # @param str String to be outputted
213
+ # @param raw [Boolean] If true, disables output formatting
214
+ private def info str, raw: false
215
+ Bwrap::Output.info_output(str, raw: raw, log_callback: 2)
216
+ end
217
+
164
218
  # Outputs given string to `$stderr`.
165
219
  #
166
220
  # @param str String to be outputted
data/lib/bwrap/version.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Bwrap
4
4
  # Current version of bwrap.
5
- VERSION = "1.0.0"
5
+ VERSION = "1.1.0-rc1"
6
6
  end
7
7
 
8
8
  require "deep-cover" if ENV["DEEP_COVER"]