Class: Gem::Commands::AwaitCommand

Inherits:
Gem::Command
  • Object
show all
Includes:
LocalRemoteOptions
Defined in:
lib/rubygems/commands/await_command.rb

Instance Method Summary collapse

Constructor Details

#initializeAwaitCommand

Returns a new instance of AwaitCommand.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/rubygems/commands/await_command.rb', line 11

def initialize
  require "rubygems/await"
  require "bundler"

  awaiters = Rubygems::Await::Awaiter.subclasses.each_with_object({}) { |a, h| h[a.awaiter_name] = a }
  skip = ["dependency api"]
  skip.push("versions", "names", "info") unless Bundler::SharedHelpers.md5_available?

  defaults = {
    timeout: 5 * 60,
    awaiters: awaiters,
    skip: ["dependency api"],
    only: nil
  }

  super "await", "Await pushed gems being available",
    defaults

  accept_uri_http

  add_option(:"Local/Remote", "-s", "--source URL", URI::HTTP,
             "Append URL to list of remote gem sources") do |source, options|
    options[:source] = source
  end

  add_option(:Timing, "-t", "--timeout DURATION", Integer,
             "Wait for the given duration before failing") do |timeout, options|
    options[:timeout] = timeout
  end

  add_option("--skip NAME", awaiters.keys,
             "Skip the given awaiter") do |name, options|
    options[:skip] ||= []
    options[:skip] << name
  end

  add_option("--include NAME", awaiters.keys,
             "Do not skip the given awaiter") do |name, options|
    options[:skip] ||= []
    options[:skip].delete(name)
  end

  add_option("--only NAME", awaiters.keys,
             "Only run the given awaiter") do |name, options|
    options[:only] ||= []
    options[:only] << name
    options[:skip]&.delete(name)
  end
end

Instance Method Details

#argumentsObject



134
135
136
# File 'lib/rubygems/commands/await_command.rb', line 134

def arguments
  "GEMNAME:VERSION[:PLATFORM]       name, version and (optional) platform of the gem to await"
end

#defaults_strObject



138
139
140
# File 'lib/rubygems/commands/await_command.rb', line 138

def defaults_str
  %(--timeout #{options[:timeout]} #{options[:skip].map { |a| "--skip #{a.dump}" }.join(" ")})
end

#descriptionObject



142
143
144
145
146
147
148
149
# File 'lib/rubygems/commands/await_command.rb', line 142

def description
  <<~DESC
    The await command will wait for pushed gems to be available on the given
    source. It will wait for the given timeout, or 5 minutes by default.

    The available awaiters are: #{options[:awaiters].keys.join(", ")}.
  DESC
end

#executeObject



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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/rubygems/commands/await_command.rb', line 61

def execute
  ui = Gem.ui

  Bundler.ui # initialize
  unless defined?(Bundler::Thor::Shell::Color::UNDERLINE)
    Bundler::Thor::Shell::Color.const_set(:UNDERLINE,
                                          "\e[4m")
  end
  Bundler.ui.level = "silent" if options[:silent]

  gems = options[:args].map do |s|
    if s.end_with?(".gem")
      require "rubygems/package"
      parts = Gem::Package.new(s).spec.name_tuple.to_a.compact.map(&:to_s)
    else
      parts = s.split(":", 3)
    end
    raise Gem::CommandLineError, "Please specify a name:version[:platform], given #{s.inspect}" if parts.size < 2

    unless Gem::Version.correct?(parts[1])
      raise Gem::CommandLineError,
            "Please specify a valid version, given #{s.inspect}"
    end

    Gem::NameTuple.new(*parts).freeze
  end.freeze

  raise Gem::CommandLineError, "Please specify at least one gem to await" if gems.empty?

  source = options[:source] || Gem.default_sources.first

  log do
    "Awaiting #{gems.map { Bundler.ui.add_color(_1.full_name, :bold) }.join(", ")} on #{Bundler.ui.add_color(
      Bundler::URICredentialsFilter.credential_filtered_uri(source), :underline
    )}"
  end

  start = Time.now
  @deadline = start + options[:timeout]

  missing = awaiters.map { _1.call(gems, source, @deadline, name_indent) }.map!(&:value)
  missing.reject!(&:empty?)

  if missing.empty?
    log do
      Bundler.ui.add_color("Found #{gems.map do |tuple|
                                      Bundler.ui.add_color(tuple.full_name, :bold, :white)
                                    end.join(", ")}", :green, :bold)
    end
  else
    all_missing = missing.flat_map do |m|
      case m
      when Set
        m.to_a
      when Hash
        m.values.flat_map(&:to_a)
      else
        raise "Unexpected #{m.inspect}"
      end
    end
    all_missing.uniq!
    all_missing.map! { Bundler.ui.add_color(_1.respond_to?(:full_name) ? _1.full_name : _1.to_s, :red, :bold) }
    log(level: "error") do
      Bundler.ui.add_color(+"Timed out", :red) << " after " <<
        Bundler.ui.add_color("#{Time.now.-(start).round(2)}s", :white, :bold) <<
        ". Check that #{all_missing.join(", ")} are published."
    end
    terminate_interaction 1
  end
ensure
  Bundler.rubygems.ui = ui
end

#usageObject



151
152
153
# File 'lib/rubygems/commands/await_command.rb', line 151

def usage
  "#{program_name} [OPTIONS] GEMNAME:VERSION[:PLATFORM] ..."
end