Class: Bundler::CLI

Inherits:
Thor
  • Object
show all
Includes:
Thor::Actions
Defined in:
lib/bundler/cli.rb,
lib/bundler/cli/gem.rb

Defined Under Namespace

Modules: Common Classes: Add, Binstubs, Cache, Check, Clean, Config, Console, Doctor, Exec, Fund, Gem, Info, Init, Install, Issue, List, Lock, Open, Outdated, Platform, Plugin, Pristine, Remove, Show, Update

Constant Summary collapse

AUTO_INSTALL_CMDS =
%w[show binstubs outdated exec open console licenses clean].freeze
PARSEABLE_COMMANDS =
%w[check config help exec platform show version].freeze
EXTENSIONS =
["c", "rust", "go"].freeze
COMMAND_ALIASES =
{
  "check" => "c",
  "install" => "i",
  "plugin" => "",
  "list" => "ls",
  "exec" => ["e", "ex", "exe"],
  "cache" => ["package", "pack"],
  "version" => ["-v", "--version"],
}.freeze

Constants included from Thor::Actions

Thor::Actions::WARNINGS

Constants inherited from Thor

Thor::AmbiguousTaskError, Thor::Correctable, Thor::DynamicTask, Thor::HELP_MAPPINGS, Thor::HiddenTask, Thor::TEMPLATE_EXTNAME, Thor::THOR_RESERVED_WORDS, Thor::Task, Thor::UndefinedTaskError, Thor::VERSION

Instance Attribute Summary

Attributes included from Thor::Actions

#behavior

Attributes included from Thor::Base

#args, #options, #parent_options

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Thor::Actions

#action, #append_to_file, #apply, #chmod, #comment_lines, #copy_file, #create_file, #create_link, #destination_root, #destination_root=, #directory, #empty_directory, #find_in_source_paths, #get, #gsub_file, #gsub_file!, #in_root, included, #inject_into_class, #inject_into_module, #insert_into_file, #inside, #link_file, #prepend_to_file, #relative_to_original_destination_root, #remove_file, #run, #run_ruby_script, #source_paths, #template, #thor, #uncomment_lines

Methods inherited from Thor

check_unknown_options!, check_unknown_options?, command_exists?, command_help, deprecation_warning, desc, disable_required_check!, disable_required_check?, help, long_desc, map, method_at_least_one, method_exclusive, method_option, method_options, package_name, printable_commands, register, stop_on_unknown_option!, stop_on_unknown_option?, subcommand, subcommand_classes, subcommands

Methods included from Thor::Base

included, register_klass_file, subclass_files, subclasses

Constructor Details

#initialize(*args) ⇒ CLI

Returns a new instance of CLI.



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/bundler/cli.rb', line 59

def initialize(*args)
  super

  current_cmd = args.last[:current_command].name

  custom_gemfile = options[:gemfile] || Bundler.settings[:gemfile]
  if custom_gemfile && !custom_gemfile.empty?
    Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", File.expand_path(custom_gemfile)
    reset_settings = true
  end

  # lock --lockfile works differently than install --lockfile
  unless current_cmd == "lock"
    custom_lockfile = options[:lockfile] || ENV["BUNDLE_LOCKFILE"] || Bundler.settings[:lockfile]
    if custom_lockfile && !custom_lockfile.empty?
      Bundler::SharedHelpers.set_env "BUNDLE_LOCKFILE", File.expand_path(custom_lockfile)
      reset_settings = true
    end
  end

  Bundler.reset_settings_and_root! if reset_settings

  Bundler.auto_switch

  Bundler.settings.set_command_option_if_given :retry, options[:retry]

  Bundler.auto_install if AUTO_INSTALL_CMDS.include?(current_cmd)
rescue UnknownArgumentError => e
  raise InvalidOption, e.message
ensure
  self.options ||= {}
  unprinted_warnings = Bundler.ui.unprinted_warnings
  Bundler.ui = UI::Shell.new(options)
  Bundler.ui.level = "debug" if options[:verbose] || Bundler.settings[:verbose]
  unprinted_warnings.each {|w| Bundler.ui.warn(w) }
end

Class Method Details

.aliases_for(command_name) ⇒ Object



55
56
57
# File 'lib/bundler/cli.rb', line 55

def self.aliases_for(command_name)
  COMMAND_ALIASES.select {|k, _| k == command_name }.invert
end

.all_aliasesObject



41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/bundler/cli.rb', line 41

def self.all_aliases
  @all_aliases ||= begin
                     command_aliases = {}

                     COMMAND_ALIASES.each do |name, aliases|
                       Array(aliases).each do |one_alias|
                         command_aliases[one_alias] = name
                       end
                     end

                     command_aliases
                   end
end

.check_invalid_ext_option(arguments) ⇒ Object



708
709
710
711
712
713
714
# File 'lib/bundler/cli.rb', line 708

def self.check_invalid_ext_option(arguments)
  # when invalid version of `--ext` is called
  if invalid_ext_value?(arguments)
    removed_message = "Extensions can now be generated using C or Rust, so `--ext` with no arguments has been removed. Please select a language, e.g. `--ext=rust` to generate a Rust extension."
    raise InvalidOption, removed_message
  end
end

.default_command(meth = nil) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/bundler/cli.rb', line 133

def self.default_command(meth = nil)
  return super if meth

  unless Bundler.settings[:default_cli_command]
    Bundler.ui.info <<~MSG
      In a future version of Bundler, running `bundle` without argument will no longer run `bundle install`.
      Instead, the `cli_help` command will be displayed. Please use `bundle install` explicitly for scripts like CI/CD.
      You can use the future behavior now with `bundle config set default_cli_command cli_help --global`,
      or you can continue to use the current behavior with `bundle config set default_cli_command install --global`.
      This message will be removed after a default_cli_command value is set.

    MSG
  end

  Bundler.settings[:default_cli_command] || "install"
end

.dispatchObject



34
35
36
37
38
39
# File 'lib/bundler/cli.rb', line 34

def self.dispatch(*)
  super do |i|
    i.send(:print_command)
    i.send(:warn_on_outdated_bundler)
  end
end

.handle_no_command_error(command, has_namespace = $thor_runner) ⇒ Object



187
188
189
190
191
192
193
194
195
# File 'lib/bundler/cli.rb', line 187

def self.handle_no_command_error(command, has_namespace = $thor_runner)
  if Bundler.settings[:plugins] && Bundler::Plugin.command?(command)
    return Bundler::Plugin.exec_command(command, ARGV[1..-1])
  end

  return super unless command_path = Bundler.which("bundler-#{command}")

  Kernel.exec(command_path, *ARGV[1..-1])
end

.invalid_ext_value?(arguments) ⇒ Boolean

Returns:

  • (Boolean)


716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
# File 'lib/bundler/cli.rb', line 716

def self.invalid_ext_value?(arguments)
  index = arguments.index("--ext")
  next_argument = arguments[index + 1]

  # it is ok when --ext is followed with valid extension value
  # for example `bundle gem hello --ext c`
  return false if EXTENSIONS.include?(next_argument)

  # invalid call when --ext is called with no value in last position
  # for example `bundle gem hello_gem --ext`
  return true if next_argument.nil?

  # invalid call when --ext is followed by other parameter
  # for example `bundle gem --ext --no-ci hello_gem`
  return true if next_argument.start_with?("-")

  # invalid call when --ext is followed by gem name
  # for example `bundle gem --ext hello_gem`
  return true if next_argument

  false
end

.reformatted_help_args(args) ⇒ Object

Reformat the arguments passed to bundle that include a –help flag into the corresponding ‘bundle help #command` call



682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
# File 'lib/bundler/cli.rb', line 682

def self.reformatted_help_args(args)
  bundler_commands = (COMMAND_ALIASES.keys + COMMAND_ALIASES.values).flatten

  help_flags = %w[--help -h]
  exec_commands = ["exec"] + COMMAND_ALIASES["exec"]

  help_used = args.index {|a| help_flags.include? a }
  exec_used = args.index {|a| exec_commands.include? a }

  command = args.find {|a| bundler_commands.include? a }

  if exec_used && help_used
    if exec_used + help_used == 1
      %w[help exec]
    else
      args
    end
  elsif help_used
    args = args.dup
    args.delete_at(help_used)
    ["help", command || args].flatten.compact
  else
    args
  end
end

.source_rootObject



599
600
601
# File 'lib/bundler/cli.rb', line 599

def self.source_root
  File.expand_path("templates", __dir__)
end

.startObject



26
27
28
29
30
31
32
# File 'lib/bundler/cli.rb', line 26

def self.start(*)
  check_invalid_ext_option(ARGV) if ARGV.include?("--ext")

  super
ensure
  Bundler::SharedHelpers.print_major_deprecations!
end

Instance Method Details

#add(*gems) ⇒ Object



408
409
410
411
# File 'lib/bundler/cli.rb', line 408

def add(*gems)
  require_relative "cli/add"
  Add.new(options.dup, gems).run
end

#binstubs(*gems) ⇒ Object



383
384
385
386
387
388
# File 'lib/bundler/cli.rb', line 383

def binstubs(*gems)
  remembered_flag_deprecation("path", option_name: "bin")

  require_relative "cli/binstubs"
  Binstubs.new(options, gems).run
end

#cacheObject



466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
# File 'lib/bundler/cli.rb', line 466

def cache
  print_remembered_flag_deprecation("--all", "cache_all", "true") if ARGV.include?("--all")
  print_remembered_flag_deprecation("--no-all", "cache_all", "false") if ARGV.include?("--no-all")

  %w[frozen no-prune].each do |option|
    remembered_flag_deprecation(option)
  end

  if flag_passed?("--path")
    removed_message =
      "The `--path` flag has been removed because its semantics were unclear. " \
      "Use `bundle config cache_path` to configure the path of your cache of gems, " \
      "and `bundle config path` to configure the path where your gems are installed, " \
      "and stop using this flag"
    raise InvalidOption, removed_message
  end

  require_relative "cli/cache"
  Cache.new(options).run
end

#checkObject



219
220
221
222
223
224
# File 'lib/bundler/cli.rb', line 219

def check
  remembered_flag_deprecation("path")

  require_relative "cli/check"
  Check.new(options).run
end

#cleanObject



606
607
608
609
# File 'lib/bundler/cli.rb', line 606

def clean
  require_relative "cli/clean"
  Clean.new(options.dup).run
end

#cli_helpObject



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/bundler/cli.rb', line 100

def cli_help
  version
  Bundler.ui.info "\n"

  primary_commands = ["install", "update", "cache", "exec", "config", "help"]

  list = self.class.printable_commands(true)
  by_name = list.group_by {|name, _message| name.match(/^bundler? (\w+)/)[1] }
  utilities = by_name.keys.sort - primary_commands
  primary_commands.map! {|name| (by_name[name] || raise("no primary command #{name}")).first }
  utilities.map! {|name| by_name[name].first }

  shell.say "Bundler commands:\n\n"

  shell.say "  Primary commands:\n"
  shell.print_table(primary_commands, indent: 4, truncate: true)
  shell.say
  shell.say "  Utilities:\n"
  shell.print_table(utilities, indent: 4, truncate: true)
  shell.say
  self.class.send(:class_options_help, shell)
end

#console(group = nil) ⇒ Object



532
533
534
535
# File 'lib/bundler/cli.rb', line 532

def console(group = nil)
  require_relative "cli/console"
  Console.new(options, group).run
end

#envObject



647
648
649
# File 'lib/bundler/cli.rb', line 647

def env
  Env.write($stdout)
end

#exec(*args) ⇒ Object



497
498
499
500
501
502
503
504
505
# File 'lib/bundler/cli.rb', line 497

def exec(*args)
  if ARGV.include?("--no-keep-file-descriptors")
    removed_message = "The `--no-keep-file-descriptors` has been removed. `bundle exec` no longer mess with your file descriptors. Close them in the exec'd script if you need to"
    raise InvalidOption, removed_message
  end

  require_relative "cli/exec"
  Exec.new(options, args).run
end

#fundObject



445
446
447
448
# File 'lib/bundler/cli.rb', line 445

def fund
  require_relative "cli/fund"
  Fund.new(options).run
end

#gem(name) ⇒ Object

Raises:



587
588
589
590
591
592
593
594
595
596
597
# File 'lib/bundler/cli.rb', line 587

def gem(name)
  require_relative "cli/gem"

  raise InvalidOption, "--rubocop has been removed, use --linter=rubocop" if ARGV.include?("--rubocop")
  raise InvalidOption, "--no-rubocop has been removed, use --no-linter" if ARGV.include?("--no-rubocop")

  cmd_args = args + [self]
  cmd_args.unshift(options)

  Gem.new(*cmd_args).run
end

#help(cli = nil) ⇒ Object



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/bundler/cli.rb', line 155

def help(cli = nil)
  cli = self.class.all_aliases[cli] if self.class.all_aliases[cli]

  if Bundler.settings[:plugins] && Bundler::Plugin.command?(cli) && !self.class.all_commands.key?(cli)
    return Bundler::Plugin.exec_command(cli, ["--help"])
  end

  case cli
  when "gemfile" then command = "gemfile"
  when nil       then command = "bundle"
  else command = "bundle-#{cli}"
  end

  man_path = File.expand_path("man", __dir__)
  man_pages = Hash[Dir.glob(File.join(man_path, "**", "*")).grep(/.*\.\d*\Z/).collect do |f|
    [File.basename(f, ".*"), f]
  end]

  if man_pages.include?(command)
    man_page = man_pages[command]
    if Bundler.which("man") && !man_path.match?(%r{^(?:file:/.+!|uri:classloader:)/META-INF/jruby.home/.+})
      Kernel.exec("man", man_page)
    else
      puts File.read("#{man_path}/#{File.basename(man_page)}.ronn")
    end
  elsif command_path = Bundler.which("bundler-#{cli}")
    Kernel.exec(command_path, "--help")
  else
    super
  end
end

#info(gem_name) ⇒ Object



366
367
368
369
# File 'lib/bundler/cli.rb', line 366

def info(gem_name)
  require_relative "cli/info"
  Info.new(options, gem_name).run
end

#initObject



205
206
207
208
# File 'lib/bundler/cli.rb', line 205

def init
  require_relative "cli/init"
  Init.new(options.dup).run
end

#injectObject



619
620
621
# File 'lib/bundler/cli.rb', line 619

def inject(*)
  SharedHelpers.feature_removed! "The `inject` command has been replaced by the `add` command"
end

#installObject



277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/bundler/cli.rb', line 277

def install
  %w[clean deployment frozen no-prune path shebang without with].each do |option|
    remembered_flag_deprecation(option)
  end

  print_remembered_flag_deprecation("--system", "path.system", "true") if ARGV.include?("--system")

  remembered_flag_deprecation("deployment", negative: true)

  if ARGV.include?("--binstubs")
    removed_message = "The --binstubs option has been removed in favor of `bundle binstubs --all`"
    raise InvalidOption, removed_message
  end

  require_relative "cli/install"
  options = self.options.dup
  options["lockfile"] ||= ENV["BUNDLE_LOCKFILE"]
  Bundler.settings.temporary(no_install: false) do
    Install.new(options).run
  end
rescue GemfileNotFound => error
  invoke_other_command("cli_help")
  raise error # re-raise to show the error and get a failing exit status
end

#install_or_cli_helpObject



124
125
126
127
128
129
130
131
# File 'lib/bundler/cli.rb', line 124

def install_or_cli_help
  Bundler.ui.warn <<~MSG
    `bundle install_or_cli_help` is a deprecated alias of `bundle install`.
    It might be called due to the 'default_cli_command' being set to 'install_or_cli_help',
    if so fix that by running `bundle config set default_cli_command install --global`.
  MSG
  invoke_other_command("install")
end

#issueObject



656
657
658
659
# File 'lib/bundler/cli.rb', line 656

def issue
  require_relative "cli/issue"
  Issue.new.run
end

#licensesObject



554
555
556
557
558
559
560
561
562
563
564
565
# File 'lib/bundler/cli.rb', line 554

def licenses
  Bundler.load.specs.sort_by {|s| s.license.to_s }.reverse_each do |s|
    gem_name = s.name
    license  = s.license || s.licenses

    if license.empty?
      Bundler.ui.warn "#{gem_name}: Unknown"
    else
      Bundler.ui.info "#{gem_name}: #{license}"
    end
  end
end

#listObject



356
357
358
359
# File 'lib/bundler/cli.rb', line 356

def list
  require_relative "cli/list"
  List.new(options).run
end

#lockObject



641
642
643
644
# File 'lib/bundler/cli.rb', line 641

def lock
  require_relative "cli/lock"
  Lock.new(options).run
end

#open(name) ⇒ Object



526
527
528
529
# File 'lib/bundler/cli.rb', line 526

def open(name)
  require_relative "cli/open"
  Open.new(options, name).run
end

#outdated(*gems) ⇒ Object



438
439
440
441
# File 'lib/bundler/cli.rb', line 438

def outdated(*gems)
  require_relative "cli/outdated"
  Outdated.new(options, gems).run
end

#platformObject



613
614
615
616
# File 'lib/bundler/cli.rb', line 613

def platform
  require_relative "cli/platform"
  Platform.new(options).run
end

#pristine(*gems) ⇒ Object



667
668
669
670
671
672
# File 'lib/bundler/cli.rb', line 667

def pristine(*gems)
  require_relative "cli/pristine"
  Bundler.settings.temporary(no_install: false) do
    Pristine.new(gems).run
  end
end

#remove(*gems) ⇒ Object



233
234
235
236
237
238
239
240
241
# File 'lib/bundler/cli.rb', line 233

def remove(*gems)
  if ARGV.include?("--install")
    removed_message = "The `--install` flag has been removed. `bundle install` is triggered by default."
    raise InvalidOption, removed_message
  end

  require_relative "cli/remove"
  Remove.new(gems, options).run
end

#show(gem_name = nil) ⇒ Object



341
342
343
344
345
346
347
348
# File 'lib/bundler/cli.rb', line 341

def show(gem_name = nil)
  if ARGV.include?("--outdated")
    removed_message = "the `--outdated` flag to `bundle show` has been removed in favor of `bundle show --verbose`"
    raise InvalidOption, removed_message
  end
  require_relative "cli/show"
  Show.new(options, gem_name).run
end

#update(*gems) ⇒ Object



327
328
329
330
331
332
# File 'lib/bundler/cli.rb', line 327

def update(*gems)
  require_relative "cli/update"
  Bundler.settings.temporary(no_install: false) do
    Update.new(options, gems).run
  end
end

#versionObject



538
539
540
541
542
543
544
545
546
547
548
549
# File 'lib/bundler/cli.rb', line 538

def version
  cli_help = current_command.name == "cli_help"
  if cli_help || ARGV.include?("version")
    build_info = " (#{BuildMetadata.timestamp} commit #{BuildMetadata.git_commit_sha})"
  end

  if !cli_help
    Bundler.ui.info "#{Bundler.verbose_version}#{build_info}"
  else
    Bundler.ui.info "Bundler version #{Bundler.verbose_version}#{build_info}"
  end
end

#vizObject



568
569
570
# File 'lib/bundler/cli.rb', line 568

def viz
  SharedHelpers.feature_removed! "The `viz` command has been renamed to `graph` and moved to a plugin. See https://github.com/rubygems/bundler-graph"
end