Skip to content
This repository has been archived by the owner on Jun 1, 2023. It is now read-only.

class ShopifyCli::Context

Kevin O'Sullivan edited this page Jun 28, 2021 · 9 revisions

Context captures a lot about the current running command. It captures the environment, output, system and file operations. It is useful to have the context especially in tests so that you have a single access point to these resoures.

Constants

  • GEM_LATEST_URI
  • VERSION_CHECK_SECTION
  • LAST_CHECKED_AT_FIELD
  • VERSION_CHECK_INTERVAL

Attributes

  • messages

  • root is the directory root that the current command is running in. If you want to simulate a cd for the file operations, you can change this variable.

  • env is an accessor for environment variables. These variables are also added to any command run by the context.

Class Methods

load_messages

load_messages(messages) adds a new set of messages to be used by the CLI. The messages are expected to be a hash of symbols, and multiple levels are allowed. When fetching messages a dot notation is used to separate different levels. See Context::message for more information.

Parameters

  • messages - Hash containing the new keys to register
see source

# File lib/shopify-cli/context.rb, line 30
def load_messages(messages)
  @messages ||= {}
  @messages = @messages.merge(messages) do |key|
    Context.new.abort("Message key '#{key}' already exists and cannot be registered") if @messages.key?(key)
  end
end

message

message(key, *params) returns the user-facing messages for the given key. Returns the key if no message is available.

Parameters

  • key - a symbol representing the message
  • params - the parameters to format the string with
see source

# File lib/shopify-cli/context.rb, line 42
def message(key, *params)
  key_parts = key.split(".").map(&:to_sym)
  str = Context.messages.dig(*key_parts)
  str ? str % params : key
end

Instance Methods

os

os() will return which operating system that the cli is running on [:mac, :linux]

see source

# File lib/shopify-cli/context.rb, line 62
def os
  host = uname
  return :mac if /darwin/i.match(host)
  return :windows if /mswin|mingw|cygwin/i.match(host)
  return :linux if /linux|bsd/i.match(host)
  :unknown
end

mac?

mac?() will return true if the cli is running on an apple computer.

see source

# File lib/shopify-cli/context.rb, line 71
def mac?
  os == :mac
end

linux?

linux?() will return true if the cli is running on a linux distro

see source

# File lib/shopify-cli/context.rb, line 76
def linux?
  os == :linux
end

windows?

windows?() will return true if the cli is running on Windows

see source

# File lib/shopify-cli/context.rb, line 81
def windows?
  os == :windows
end

unknown_os?

unknown_os?() will return true if the os is unknown

see source

# File lib/shopify-cli/context.rb, line 86
def unknown_os?
  os == :unknown
end

tty?

tty?() will return true if being launched from a tty

see source

# File lib/shopify-cli/context.rb, line 91
def tty?
  $stdin.tty? && !testing?
end

system?

system?() will return true if the cli is being run from an installation, and not a development instance. The gem installation will not have a 'test' directory. See #development? for checking for development environment.

see source

# File lib/shopify-cli/context.rb, line 99
def system?
  !Dir.exist?(File.join(ShopifyCli::ROOT, "test"))
end

development?

development?() will return true if the cli is running on your development instance.

see source

# File lib/shopify-cli/context.rb, line 105
def development?
  !system? && !testing?
end

testing?

testing?() will return true while tests are running, either locally or on CI

see source

# File lib/shopify-cli/context.rb, line 110
def testing?
  ci? || ENV["TEST"]
end

ci?

ci?() will return true if the cli is being tested on CI

see source

# File lib/shopify-cli/context.rb, line 116
def ci?
  ENV["CI"]
end

debug?

debug?() will return true if the cli is running with the DEBUG flag

see source

# File lib/shopify-cli/context.rb, line 122
def debug?
  getenv("DEBUG")
end

getenv

getenv(name) get a environment variable value by name.

Parameters

  • name - the name of the environment variable that you want to fetch

Returns

  • value - will return the value, or nil if the variable does not exist
see source

# File lib/shopify-cli/context.rb, line 134
def getenv(name)
  v = @env[name]
  v == "" ? nil : v
end

setenv

setenv(key, value) set a environment variable value by name.

Parameters

  • key - the name of the environment variable that you want to set
  • value - the value of the variable
see source

# File lib/shopify-cli/context.rb, line 145
def setenv(key, value)
  @env[key] = value
end

write

write(fname, content) will write/overwrite a file with the provided contents, relative to the context root unless the file path is absolute.

Parameters

  • fname - filename of the file that you are writing, relative to root unless it is absolute.
  • content - the body contents of the file that you are writing

Example

@ctx.write('new.txt', 'hello world')
see source

# File lib/shopify-cli/context.rb, line 160
def write(fname, content)
  File.write(ctx_path(fname), content)
end

read

read(fname) will read a file relative to the context root unless the file path is absolute.

Parameters

  • fname - filename of the file that you are reading, relative to root unless it is absolute.

Example

@ctx.read('file.txt')
see source

# File lib/shopify-cli/context.rb, line 173
def read(fname)
  File.read(ctx_path(fname))
end

binread

binread(fname) will read a binary file relative to the context root unless the file path is absolute.

Parameters

  • fname - filename of the file that you are reading, relative to root unless it is absolute.

Example

@ctx.read('binary.out')
see source

# File lib/shopify-cli/context.rb, line 186
def binread(fname)
  File.binread(ctx_path(fname))
end

binwrite

binwrite(fname, content) will write/overwrite a binary file with the provided contents, relative to the context root unless the file path is absolute.

Parameters

  • fname - filename of the file that you are writing, relative to root unless it is absolute.
  • content - the body contents of the file that you are writing

Example

@ctx.binwrite('binary.out', 'ASCII-8BIT encoded binary')
see source

# File lib/shopify-cli/context.rb, line 201
def binwrite(fname, content)
  File.binwrite(ctx_path(fname), content)
end

chdir

chdir(path) will change directories and update the root, the filepath is relative to the command root unless absolute

Parameters

  • path - the file path to a directory, relative to the context root to remove from the FS
see source

# File lib/shopify-cli/context.rb, line 210
def chdir(path)
  Dir.chdir(ctx_path(path))
  self.root = ctx_path(path)
end

dir_exist?

dir_exist?(path) checks if a directory exists, the filepath is relative to the command root unless absolute

Parameters

  • path - the file path to a directory, relative to the context root to remove from the FS
see source

# File lib/shopify-cli/context.rb, line 220
def dir_exist?(path)
  Dir.exist?(ctx_path(path))
end

file_exist?

file_exist?(path) checks if a file exists, the filepath is relative to the command root unless absolute

Parameters

  • path - the file path to a file, relative to the context root to remove from the FS
see source

# File lib/shopify-cli/context.rb, line 229
def file_exist?(path)
  File.exist?(ctx_path(path))
end

cp_r

cp_r(from, to) will recursively copy a directory from the FS, the filepath is relative to the command root unless absolute

Parameters

  • from - the path of the original file
  • to - the destination path
see source

# File lib/shopify-cli/context.rb, line 240
def cp_r(from, to)
  FileUtils.cp_r(ctx_path(from), ctx_path(to))
end

cp

cp(from, to) will copy a directory from the FS, the filepath is relative to the command root unless absolute

Parameters

  • from - the path of the original file
  • to - the destination path
see source

# File lib/shopify-cli/context.rb, line 251
def cp(from, to)
  FileUtils.cp(ctx_path(from), ctx_path(to))
end

rename

rename(from, to) will rename a file from one place to another, relative to the command root unless the path is absolute.

Parameters

  • from - the path of the original file
  • to - the destination path
see source

# File lib/shopify-cli/context.rb, line 262
def rename(from, to)
  File.rename(ctx_path(from), ctx_path(to))
end

rm

rm(fname) will remove a plain file from the FS, the filepath is relative to the command root unless absolute.

Parameters

  • fname - the file path relative to the context root to remove from the FS
see source

# File lib/shopify-cli/context.rb, line 272
def rm(fname)
  FileUtils.rm(ctx_path(fname))
end

rm_r

rm_r(fname) will remove a directory from the FS, the filepath is relative to the command root unless absolute

Parameters

  • fname - the file path to a directory, relative to the context root to remove from the FS
see source

# File lib/shopify-cli/context.rb, line 282
def rm_r(fname)
  FileUtils.rm_r(ctx_path(fname))
end

rm_rf

rm_rf(fname) will force remove a directory from the FS, the filepath is relative to the command root unless absolute

Parameters

  • fname - the file path to a directory, relative to the context root to remove from the FS
see source

# File lib/shopify-cli/context.rb, line 292
def rm_rf(fname)
  FileUtils.rm_rf(ctx_path(fname))
end

mkdir_p

mkdir_p(path) will create a directory, recursively if it does not exist. So if you create a directory foo/bar/dun, this will also create the directories foo and foo/bar if they do not exist. The path will be made relative to the command root unless absolute

Parameters

  • path - file path of the directory that you want to create
see source

# File lib/shopify-cli/context.rb, line 304
def mkdir_p(path)
  FileUtils.mkdir_p(path)
end

open_url!

open_url!(uri) will output to the console a link for the user to either copy/paste or click on.

Parameters

  • uri - a http URI to open in a browser
see source

# File lib/shopify-cli/context.rb, line 314
def open_url!(uri)
  help = message("core.context.open_url", uri)
  puts(help)
end

open_browser_url!

open_browser_url!(uri) will output to the console a link for the user to either copy/paste or click on.

Parameters

  • uri - a http URI to open in a browser
see source

# File lib/shopify-cli/context.rb, line 325
def open_browser_url!(uri)
  if tty?
    if linux? && which("xdg-open")
      system("xdg-open", uri.to_s)
    elsif windows?
      system("start", uri.to_s)
    elsif mac?
      system("open", uri.to_s)
    else
      open_url!(uri)
    end
  else
    open_url!(uri)
  end
end

print_task

print_task(text) will output a message, prefixed by a yellow star, indicating that task started.

Parameters

  • text - a string message to output
see source

# File lib/shopify-cli/context.rb, line 347
def print_task(text)
  puts "{{yellow:*}} #{text}"
end

puts

puts(*args) a wrapper around Kernel.puts to allow for easy formatting

Parameters

  • text - a string message to output
see source

# File lib/shopify-cli/context.rb, line 356
def puts(*args)
  Kernel.puts(CLI::UI.fmt(*args))
end

warn

warn(*args) a wrapper around Kernel.warn to allow for easy formatting

Parameters

  • text - a string message to output
see source

# File lib/shopify-cli/context.rb, line 365
def warn(*args)
  Kernel.warn(CLI::UI.fmt(*args))
end

done

done(text) outputs a message, prefixed by a checkmark indicating that something completed

Parameters

  • text - a string message to output
see source

# File lib/shopify-cli/context.rb, line 374
def done(text)
  puts("{{v}} #{text}")
end

abort

abort(text) aborts the current running command and outputs an error message, prefixed by a red x

Parameters

  • text - a string message to output
see source

# File lib/shopify-cli/context.rb, line 384
def abort(text)
  raise ShopifyCli::Abort, "{{x}} #{text}"
end

debug

debug(text) outputs a message, prefixed by a red DEBUG tag. This will only output to the console if you have DEBUG=1 set in your shell environment.

Parameters

  • text - a string message to output
see source

# File lib/shopify-cli/context.rb, line 394
def debug(text)
  puts("{{red:DEBUG}} #{text}") if debug?
end

message

message(key, *params) proxy call to Context.message.

Parameters

  • key - a symbol representing the message
  • params - the parameters to format the string with
see source

# File lib/shopify-cli/context.rb, line 403
def message(key, *params)
  Context.message(key, *params)
end

uname

uname() will grab the host info of the computer running the cli. This indicates the computer architecture and operating system

see source

# File lib/shopify-cli/context.rb, line 409
def uname
  @uname ||= RbConfig::CONFIG["host"]
end

system

system(*args, **kwargs) Execute a command in the user's environment Outputs result of the command without capturing it

Parameters

  • *args: A splat of arguments evaluated as a command. (e.g. 'rm', folder is equivalent to rm #{folder})
  • **kwargs: additional keyword arguments to pass to Process.spawn

Returns

  • status: The Process::Status result of the command execution.

Usage

stat = @ctx.system('ls', 'a_folder')
see source

# File lib/shopify-cli/context.rb, line 427
def system(*args, **kwargs)
  process_status = CLI::Kit::System.system(*args, env: @env, **kwargs)
  unless process_status.success?
    abort("System call failed: #{args.join(" ")}")
  end
  process_status
end

capture2

capture2(*args, **kwargs) Execute a command in the user's environment This is meant to be largely equivalent to backticks, only with the env passed in. Captures the results of the command without output to the console

Parameters

  • *args: A splat of arguments evaluated as a command. (e.g. 'rm', folder is equivalent to rm #{folder})
  • **kwargs: additional arguments to pass to Open3.capture2

Returns

  • output: output (STDOUT) of the command execution
  • status: boolean success status of the command execution

Usage

out, stat = @ctx.capture2('ls', 'a_folder')
see source

# File lib/shopify-cli/context.rb, line 451
def capture2(*args, **kwargs)
  CLI::Kit::System.capture2(*args, env: @env, **kwargs)
end

capture2e

capture2e(*args, **kwargs) Execute a command in the user's environment This is meant to be largely equivalent to backticks, only with the env passed in. Captures the results of the command without output to the console

Parameters

  • *args: A splat of arguments evaluated as a command. (e.g. 'rm', folder is equivalent to rm #{folder})
  • **kwargs: additional arguments to pass to Open3.capture2e

Returns

  • output: output (STDOUT merged with STDERR) of the command execution
  • status: boolean success status of the command execution

Usage

out_and_err, stat = @ctx.capture2e('ls', 'a_folder')
see source

# File lib/shopify-cli/context.rb, line 471
def capture2e(*args, **kwargs)
  CLI::Kit::System.capture2e(*args, env: @env, **kwargs)
end

capture3

capture3(*args, **kwargs) Execute a command in the user's environment This is meant to be largely equivalent to backticks, only with the env passed in. Captures the results of the command without output to the console

Parameters

  • *args: A splat of arguments evaluated as a command. (e.g. 'rm', folder is equivalent to rm #{folder})
  • **kwargs: additional arguments to pass to Open3.capture3

Returns

  • output: STDOUT of the command execution
  • error: STDERR of the command execution
  • status: boolean success status of the command execution

Usage

out, err, stat = @ctx.capture3('ls', 'a_folder')
see source

# File lib/shopify-cli/context.rb, line 492
def capture3(*args, **kwargs)
  CLI::Kit::System.capture3(*args, env: @env, **kwargs)
end

on_siginfo

on_siginfo() { || ... } captures the info signal (ctrl-T) and provide a handler to it.

Example

@ctx.on_siginfo do
  @ctx.open_url!("http://google.com")
end
see source

# File lib/shopify-cli/context.rb, line 504
def on_siginfo
  # Reset any previous SIGINFO handling we had so the only action we take is the given block
  trap("INFO", "DEFAULT")

  fork do
    begin
      r, w = IO.pipe
      @signal = false
      trap("SIGINFO") do
        @signal = true
        w.write(0)
      end
      while r.read(1)
        next unless @signal
        @signal = false
        yield
      end
    rescue Interrupt
      exit(0)
    end
  end
end

which

which(cmd) Checks if the given command exists in the system

Parameters

  • cmd: The command to test

Returns The path of the executable if it is found

@todo This is currently a duplicate of CLI::Kit::System.which() - we should make that method public when we make Kit changes and make this a wrapper instead.

see source

# File lib/shopify-cli/context.rb, line 537
def which(cmd)
  exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""]
  ENV["PATH"].split(File::PATH_SEPARATOR).each do |path|
    exts.each do |ext|
      exe = File.join(File.expand_path(path), "#{cmd}#{ext}")
      return exe if File.executable?(exe) && !File.directory?(exe)
    end
  end

  nil
end

new_version

new_version() Checks if there's a newer version of the CLI available and returns version string if this should be conveyed to the user (i.e., if it's been over 24 hours since last check)

Parameters

Returns

  • version: string of newer version available, IFF new version is available AND it's time to inform user, : nil otherwise
see source

# File lib/shopify-cli/context.rb, line 558
def new_version
  if (time_of_last_check + VERSION_CHECK_INTERVAL) < (now = Time.now.to_i)
    update_time_of_last_check(now)
    latest_version = retrieve_latest_gem_version
    latest_version unless latest_version == ShopifyCli::VERSION
  end
end

executable_file_extension

executable_file_extension(ext = ".exe") Returns file extension depending on OS since windows has multiple extensions, the default is .exe unless otherwise specified

Parameters

  • ext: optional extension for windows file

Returns

  • ext: string for file extension on windows : empty string otherwise
see source

# File lib/shopify-cli/context.rb, line 575
def executable_file_extension(ext = ".exe")
  if windows?
    ext
  else
    ""
  end
end

Clone this wiki locally