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



704
705
706
707
708
709
710
# File 'lib/bundler/cli.rb', line 704

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



183
184
185
186
187
188
189
190
191
# File 'lib/bundler/cli.rb', line 183

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)


712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
# File 'lib/bundler/cli.rb', line 712

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



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

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



595
596
597
# File 'lib/bundler/cli.rb', line 595

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



404
405
406
407
# File 'lib/bundler/cli.rb', line 404

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

#binstubs(*gems) ⇒ Object



379
380
381
382
383
384
# File 'lib/bundler/cli.rb', line 379

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

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

#cacheObject



462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
# File 'lib/bundler/cli.rb', line 462

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



215
216
217
218
219
220
# File 'lib/bundler/cli.rb', line 215

def check
  remembered_flag_deprecation("path")

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

#cleanObject



602
603
604
605
# File 'lib/bundler/cli.rb', line 602

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(/^bundle (\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



528
529
530
531
# File 'lib/bundler/cli.rb', line 528

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

#envObject



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

def env
  Env.write($stdout)
end

#exec(*args) ⇒ Object



493
494
495
496
497
498
499
500
501
# File 'lib/bundler/cli.rb', line 493

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



441
442
443
444
# File 'lib/bundler/cli.rb', line 441

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

#gem(name) ⇒ Object

Raises:



583
584
585
586
587
588
589
590
591
592
593
# File 'lib/bundler/cli.rb', line 583

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
# File 'lib/bundler/cli.rb', line 155

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

  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



362
363
364
365
# File 'lib/bundler/cli.rb', line 362

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

#initObject



201
202
203
204
# File 'lib/bundler/cli.rb', line 201

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

#injectObject



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

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

#installObject



273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/bundler/cli.rb', line 273

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



652
653
654
655
# File 'lib/bundler/cli.rb', line 652

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

#licensesObject



550
551
552
553
554
555
556
557
558
559
560
561
# File 'lib/bundler/cli.rb', line 550

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



352
353
354
355
# File 'lib/bundler/cli.rb', line 352

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

#lockObject



637
638
639
640
# File 'lib/bundler/cli.rb', line 637

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

#open(name) ⇒ Object



522
523
524
525
# File 'lib/bundler/cli.rb', line 522

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

#outdated(*gems) ⇒ Object



434
435
436
437
# File 'lib/bundler/cli.rb', line 434

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

#platformObject



609
610
611
612
# File 'lib/bundler/cli.rb', line 609

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

#pristine(*gems) ⇒ Object



663
664
665
666
667
668
# File 'lib/bundler/cli.rb', line 663

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

#remove(*gems) ⇒ Object



229
230
231
232
233
234
235
236
237
# File 'lib/bundler/cli.rb', line 229

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



337
338
339
340
341
342
343
344
# File 'lib/bundler/cli.rb', line 337

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



323
324
325
326
327
328
# File 'lib/bundler/cli.rb', line 323

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

#versionObject



534
535
536
537
538
539
540
541
542
543
544
545
# File 'lib/bundler/cli.rb', line 534

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



564
565
566
# File 'lib/bundler/cli.rb', line 564

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