Class: Travis::CLI::Command

Inherits:
Object
  • Object
show all
Extended by:
Forwardable, Parser, Tools::Assets
Includes:
Tools::Assets
Defined in:
lib/travis/cli/command.rb

Direct Known Subclasses

ApiCommand, Help, Version

Constant Summary collapse

MINUTE =
60
HOUR =
3600
DAY =
86_400
WEEK =
604_800

Constants included from Tools::Assets

Tools::Assets::BASE

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Tools::Assets

asset, asset_path

Methods included from Parser

new, on, on_initialize

Constructor Details

#initialize(options = {}) ⇒ Command

Returns a new instance of Command.



93
94
95
96
97
98
99
100
101
102
# File 'lib/travis/cli/command.rb', line 93

def initialize(options = {})
  @on_signal  = []
  @formatter  = Travis::Tools::Formatter.new
  self.output = $stdout
  self.input  = $stdin
  options.each do |key, value|
    public_send("#{key}=", value) if respond_to? "#{key}="
  end
  @arguments ||= []
end

Instance Attribute Details

#argumentsObject

Returns the value of attribute arguments.



89
90
91
# File 'lib/travis/cli/command.rb', line 89

def arguments
  @arguments
end

#configObject

Returns the value of attribute config.



89
90
91
# File 'lib/travis/cli/command.rb', line 89

def config
  @config
end

#debug(line) ⇒ Object

Returns the value of attribute debug.



89
90
91
# File 'lib/travis/cli/command.rb', line 89

def debug
  @debug
end

#force_interactiveObject

Returns the value of attribute force_interactive.



89
90
91
# File 'lib/travis/cli/command.rb', line 89

def force_interactive
  @force_interactive
end

#formatterObject

Returns the value of attribute formatter.



89
90
91
# File 'lib/travis/cli/command.rb', line 89

def formatter
  @formatter
end

#inputObject

Returns the value of attribute input.



90
91
92
# File 'lib/travis/cli/command.rb', line 90

def input
  @input
end

#outputObject

Returns the value of attribute output.



90
91
92
# File 'lib/travis/cli/command.rb', line 90

def output
  @output
end

Class Method Details

.abstractObject



60
61
62
# File 'lib/travis/cli/command.rb', line 60

def self.abstract
  @@abstract << self
end

.abstract?Boolean

Returns:

  • (Boolean)


56
57
58
# File 'lib/travis/cli/command.rb', line 56

def self.abstract?
  @@abstract.include? self
end

.command_nameObject



51
52
53
# File 'lib/travis/cli/command.rb', line 51

def self.command_name
  name[/[^:]*$/].split(/(?=[A-Z])/).map(&:downcase).join('-')
end

.description(description = nil) ⇒ Object



68
69
70
71
# File 'lib/travis/cli/command.rb', line 68

def self.description(description = nil)
  @description = description if description
  @description ||= ''
end

.skip(*names) ⇒ Object



64
65
66
# File 'lib/travis/cli/command.rb', line 64

def self.skip(*names)
  names.each { |n| define_method(n) {} }
end

.subcommands(*list) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/travis/cli/command.rb', line 73

def self.subcommands(*list)
  return @subcommands ||= [] if list.empty?

  @subcommands = list

  define_method :run do |subcommand, *args|
    error "Unknown subcommand. Available: #{list.join(', ')}." unless list.include? subcommand.to_sym
    send(subcommand, *args)
  end

  define_method :usage do
    usages = list.map { |c| color(usage_for("#{command_name} #{c}", c), :command) }
    "\nUsage: #{usages.join("\n       ")}\n\n"
  end
end

Instance Method Details

#check_completionObject



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/travis/cli/command.rb', line 174

def check_completion
  return if skip_completion_check? || !interactive?

  if config['checked_completion']
    Tools::Completion.update_completion if config['completion_version'] != Travis::VERSION
  else
    write_to($stderr) do
      next Tools::Completion.update_completion if Tools::Completion.completion_installed?
      next unless agree('Shell completion not installed. Would you like to install it now? ') do |q|
                    q.default = 'y'
                  end

      Tools::Completion.install_completion
    end
  end

  config['checked_completion'] = true
  config['completion_version'] = Travis::VERSION
end

#check_rubyObject



194
195
196
197
198
# File 'lib/travis/cli/command.rb', line 194

def check_ruby
  return if (RUBY_VERSION > '1.9.2') || skip_version_check?

  warn "Your Ruby version is outdated, please consider upgrading, as we will drop support for #{RUBY_VERSION} soon!"
end

#check_versionObject



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/travis/cli/command.rb', line 143

def check_version
  last_check.clear if last_check['version'] != Travis::VERSION
  seconds_since = Time.now.to_i - last_check['at'].to_i

  return if skip_version_check?
  return if seconds_since < MINUTE

  timeout = case seconds_since
            when MINUTE..HOUR then 0.5
            when HOUR..DAY then 1.0
            when DAY..WEEK then 2.0
            else 10.0
            end

  Timeout.timeout(timeout) do
    response              = Faraday.get('https://rubygems.org/api/v1/gems/travis.json', {},
                                        'If-None-Match' => last_check['etag'].to_s)
    last_check['etag']    = response.headers['etag']
    last_check['version'] = JSON.parse(response.body)['version'] if response.status == 200
  end

  last_check['at'] = Time.now.to_i
  unless Tools::System.recent_version? Travis::VERSION, last_check['version']
    warn 'Outdated CLI version, run `gem install travis`.'
  end
rescue Timeout::Error, Faraday::ClientError => e
  debug "#{e.class}: #{e.message}"
rescue JSON::ParserError
  warn 'Unable to determine the most recent travis gem version. http://rubygems.org may be down.'
end

#command_nameObject



239
240
241
# File 'lib/travis/cli/command.rb', line 239

def command_name
  self.class.command_name
end

#debug?Object

Returns the value of attribute debug.



91
92
93
# File 'lib/travis/cli/command.rb', line 91

def debug
  @debug
end

#error(message, &block) ⇒ Object



307
308
309
310
# File 'lib/travis/cli/command.rb', line 307

def error(message, &block)
  warn(message, &block)
  exit 1
end

#executeObject



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/travis/cli/command.rb', line 200

def execute
  setup_trap
  check_ruby
  check_arity(method(:run), *arguments)
  load_config
  check_version
  check_completion
  setup
  run(*arguments)
  clear_error
  store_config
rescue Travis::Client::NotLoggedIn => e
  raise(e) if explode?

  error "#{e.message} - try running #{command("login#{endpoint_option}")}"
rescue Travis::Client::RepositoryMigrated => e
  raise(e) if explode?

  error e.message
rescue Travis::Client::NotFound => e
  raise(e) if explode?

  error "resource not found (#{e.message})"
rescue Travis::Client::Error => e
  raise(e) if explode?

  error e.message
rescue StandardError => e
  raise(e) if explode?

  message = e.message
  if interactive?
    message += color("\nfor a full error report, run #{command("report#{endpoint_option}")}",
                     :error)
  end
  store_error(e)
  error(message)
end

#help(info = '') ⇒ Object



263
264
265
266
# File 'lib/travis/cli/command.rb', line 263

def help(info = '')
  parser.banner = usage
  "#{self.class.description.sub(/./) { |c| c.upcase }}.\n#{info}#{parser}"
end

#info(line) ⇒ Object



290
291
292
293
294
# File 'lib/travis/cli/command.rb', line 290

def info(line)
  write_to($stderr) do
    say color(line, :info)
  end
end

#last_checkObject



135
136
137
138
139
140
141
# File 'lib/travis/cli/command.rb', line 135

def last_check
  config['last_check'] ||= {
    # migrate from old values
    'at' => config.delete('last_version_check'),
    'etag' => config.delete('etag')
  }
end

#on_signal(&block) ⇒ Object



296
297
298
# File 'lib/travis/cli/command.rb', line 296

def on_signal(&block)
  @on_signal << block
end

#parse(args) ⇒ Object



126
127
128
129
130
131
# File 'lib/travis/cli/command.rb', line 126

def parse(args)
  rest = parser.parse(args)
  arguments.concat(rest)
rescue OptionParser::ParseError => e
  error e.message
end

#say(data, format = nil, style = nil) ⇒ Object



268
269
270
# File 'lib/travis/cli/command.rb', line 268

def say(data, format = nil, style = nil)
  terminal.say format(data, format, style)
end

#setupObject



133
# File 'lib/travis/cli/command.rb', line 133

def setup; end

#terminalObject



104
105
106
# File 'lib/travis/cli/command.rb', line 104

def terminal
  @terminal ||= HighLine.new(input, output)
end

#time(info, callback = Proc.new) ⇒ Object



280
281
282
283
284
285
286
287
288
# File 'lib/travis/cli/command.rb', line 280

def time(info, callback = Proc.new)
  return callback.call unless debug?

  start = Time.now
  debug(info)
  callback.call
  duration = Time.now - start
  debug('  took %.2g seconds' % duration)
end

#usageObject



243
244
245
# File 'lib/travis/cli/command.rb', line 243

def usage
  'Usage: ' << color(usage_for(command_name, :run), :command)
end

#usage_for(prefix, method) ⇒ Object



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/travis/cli/command.rb', line 247

def usage_for(prefix, method)
  usage = "travis #{prefix}"
  method = method(method)
  if method.respond_to? :parameters
    method.parameters.each do |type, name|
      name = name.upcase
      name = "[#{name}]"   if type == :opt
      name = "[#{name}..]" if type == :rest
      usage << " #{name}"
    end
  elsif method.arity != 0
    usage << ' ...'
  end
  usage << ' [OPTIONS]'
end

#warn(message) ⇒ Object



300
301
302
303
304
305
# File 'lib/travis/cli/command.rb', line 300

def warn(message)
  write_to($stderr) do
    say color(message, :error)
    yield if block_given?
  end
end

#write_to(io) ⇒ Object



118
119
120
121
122
123
124
# File 'lib/travis/cli/command.rb', line 118

def write_to(io)
  io_was = output
  self.output = io
  yield
ensure
  self.output = io_was if io_was
end