Handle CLI failure exit status at the top-level script (#28322)

This commit is contained in:
Matt Jankowski 2024-01-26 03:53:44 -05:00 committed by GitHub
parent 881e8c113c
commit 0e0a94f483
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 150 additions and 320 deletions

View File

@ -96,12 +96,11 @@ Rails/FilePath:
Rails/HttpStatus:
EnforcedStyle: numeric
# Reason: Allowed in `tootctl` CLI code and in boot ENV checker
# Reason: Allowed in boot ENV checker
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsexit
Rails/Exit:
Exclude:
- 'config/boot.rb'
- 'lib/mastodon/cli/*.rb'
# Reason: Conflicts with `Lint/UselessMethodDefinition` for inherited controller actions
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railslexicallyscopedactionfilter

View File

@ -6,8 +6,13 @@ require_relative '../lib/mastodon/cli/main'
begin
Chewy.strategy(:mastodon) do
Mastodon::CLI::Main.start(ARGV)
Mastodon::CLI::Main.start(ARGV, debug: true) # Enables the script to rescue `Thor::Error`
end
rescue Thor::Error => e
Thor::Shell::Color
.new
.say_error(e.message, :red)
exit(1)
rescue Interrupt
exit(130)
end

View File

@ -39,8 +39,7 @@ module Mastodon::CLI
rotate_keys_for_account(Account.find_local(username))
say('OK', :green)
else
say('No account(s) given', :red)
exit(1)
fail_with_message 'No account(s) given'
end
end
@ -74,10 +73,7 @@ module Mastodon::CLI
if options[:role]
role = UserRole.find_by(name: options[:role])
if role.nil?
say('Cannot find user role with that name', :red)
exit(1)
end
fail_with_message 'Cannot find user role with that name' if role.nil?
role_id = role.id
end
@ -114,7 +110,6 @@ module Mastodon::CLI
say("New password: #{password}")
else
report_errors(user.errors)
exit(1)
end
end
@ -152,18 +147,12 @@ module Mastodon::CLI
def modify(username)
user = Account.find_local(username)&.user
if user.nil?
say('No user with such username', :red)
exit(1)
end
fail_with_message 'No user with such username' if user.nil?
if options[:role]
role = UserRole.find_by(name: options[:role])
if role.nil?
say('Cannot find user role with that name', :red)
exit(1)
end
fail_with_message 'Cannot find user role with that name' if role.nil?
user.role_id = role.id
elsif options[:remove_role]
@ -185,7 +174,6 @@ module Mastodon::CLI
say("New password: #{password}") if options[:reset_password]
else
report_errors(user.errors)
exit(1)
end
end
@ -200,27 +188,19 @@ module Mastodon::CLI
LONG_DESC
def delete(username = nil)
if username.present? && options[:email].present?
say('Use username or --email, not both', :red)
exit(1)
fail_with_message 'Use username or --email, not both'
elsif username.blank? && options[:email].blank?
say('No username provided', :red)
exit(1)
fail_with_message 'No username provided'
end
account = nil
if username.present?
account = Account.find_local(username)
if account.nil?
say('No user with such username', :red)
exit(1)
end
fail_with_message 'No user with such username' if account.nil?
else
account = Account.left_joins(:user).find_by(user: { email: options[:email] })
if account.nil?
say('No user with such email', :red)
exit(1)
end
fail_with_message 'No user with such email' if account.nil?
end
say("Deleting user with #{account.statuses_count} statuses, this might take a while...#{dry_run_mode_suffix}")
@ -243,23 +223,18 @@ module Mastodon::CLI
username, domain = from_acct.split('@')
from_account = Account.find_remote(username, domain)
if from_account.nil? || from_account.local?
say("No such account (#{from_acct})", :red)
exit(1)
end
fail_with_message "No such account (#{from_acct})" if from_account.nil? || from_account.local?
username, domain = to_acct.split('@')
to_account = Account.find_remote(username, domain)
if to_account.nil? || to_account.local?
say("No such account (#{to_acct})", :red)
exit(1)
end
fail_with_message "No such account (#{to_acct})" if to_account.nil? || to_account.local?
if from_account.public_key != to_account.public_key && !options[:force]
say("Accounts don't have the same public key, might not be duplicates!", :red)
say('Override with --force', :red)
exit(1)
fail_with_message <<~ERROR
Accounts don't have the same public key, might not be duplicates!
Override with --force
ERROR
end
to_account.merge_with!(from_account)
@ -298,10 +273,7 @@ module Mastodon::CLI
def backup(username)
account = Account.find_local(username)
if account.nil?
say('No user with such username', :red)
exit(1)
end
fail_with_message 'No user with such username' if account.nil?
backup = account.user.backups.create!
BackupWorker.perform_async(backup.id)
@ -387,10 +359,7 @@ module Mastodon::CLI
user, domain = user.split('@')
account = Account.find_remote(user, domain)
if account.nil?
say('No such account', :red)
exit(1)
end
fail_with_message 'No such account' if account.nil?
next if dry_run?
@ -405,8 +374,7 @@ module Mastodon::CLI
say("OK#{dry_run_mode_suffix}", :green)
else
say('No account(s) given', :red)
exit(1)
fail_with_message 'No account(s) given'
end
end
@ -416,10 +384,7 @@ module Mastodon::CLI
def follow(username)
target_account = Account.find_local(username)
if target_account.nil?
say('No such account', :red)
exit(1)
end
fail_with_message 'No such account' if target_account.nil?
processed, = parallelize_with_progress(Account.local.without_suspended) do |account|
FollowService.new.call(account, target_account, bypass_limit: true)
@ -435,10 +400,7 @@ module Mastodon::CLI
username, domain = acct.split('@')
target_account = Account.find_remote(username, domain)
if target_account.nil?
say('No such account', :red)
exit(1)
end
fail_with_message 'No such account' if target_account.nil?
processed, = parallelize_with_progress(target_account.followers.local) do |account|
UnfollowService.new.call(account, target_account)
@ -459,17 +421,11 @@ module Mastodon::CLI
With the --followers option, the command removes all followers of the account.
LONG_DESC
def reset_relationships(username)
unless options[:follows] || options[:followers]
say('Please specify either --follows or --followers, or both', :red)
exit(1)
end
fail_with_message 'Please specify either --follows or --followers, or both' unless options[:follows] || options[:followers]
account = Account.find_local(username)
if account.nil?
say('No such account', :red)
exit(1)
end
fail_with_message 'No such account' if account.nil?
total = 0
total += account.following.reorder(nil).count if options[:follows]
@ -515,6 +471,8 @@ module Mastodon::CLI
account identified by its username.
LONG_DESC
def approve(username = nil)
fail_with_message 'Number must be positive' if options[:number]&.negative?
if options[:all]
User.pending.find_each(&:approve!)
say('OK', :green)
@ -524,16 +482,10 @@ module Mastodon::CLI
elsif username.present?
account = Account.find_local(username)
if account.nil?
say('No such account', :red)
exit(1)
end
fail_with_message 'No such account' if account.nil?
account.user&.approve!
say('OK', :green)
else
say('Number must be positive', :red) if options[:number]
exit(1)
end
end
@ -587,56 +539,34 @@ module Mastodon::CLI
redirects to a different account that the one specified.
LONG_DESC
def migrate(username)
if options[:replay].present? && options[:target].present?
say('Use --replay or --target, not both', :red)
exit(1)
end
fail_with_message 'Use --replay or --target, not both' if options[:replay].present? && options[:target].present?
if options[:replay].blank? && options[:target].blank?
say('Use either --replay or --target', :red)
exit(1)
end
fail_with_message 'Use either --replay or --target' if options[:replay].blank? && options[:target].blank?
account = Account.find_local(username)
if account.nil?
say("No such account: #{username}", :red)
exit(1)
end
fail_with_message "No such account: #{username}" if account.nil?
migration = nil
if options[:replay]
migration = account.migrations.last
if migration.nil?
say('The specified account has not performed any migration', :red)
exit(1)
end
fail_with_message 'The specified account has not performed any migration' if migration.nil?
unless options[:force] || migration.target_account_id == account.moved_to_account_id
say('The specified account is not redirecting to its last migration target. Use --force if you want to replay the migration anyway', :red)
exit(1)
end
fail_with_message 'The specified account is not redirecting to its last migration target. Use --force if you want to replay the migration anyway' unless options[:force] || migration.target_account_id == account.moved_to_account_id
end
if options[:target]
target_account = ResolveAccountService.new.call(options[:target])
if target_account.nil?
say("The specified target account could not be found: #{options[:target]}", :red)
exit(1)
end
fail_with_message "The specified target account could not be found: #{options[:target]}" if target_account.nil?
unless options[:force] || account.moved_to_account_id.nil? || account.moved_to_account_id == target_account.id
say('The specified account is redirecting to a different target account. Use --force if you want to change the migration target', :red)
exit(1)
end
fail_with_message 'The specified account is redirecting to a different target account. Use --force if you want to change the migration target' unless options[:force] || account.moved_to_account_id.nil? || account.moved_to_account_id == target_account.id
begin
migration = account.migrations.create!(acct: target_account.acct)
rescue ActiveRecord::RecordInvalid => e
say("Error: #{e.message}", :red)
exit(1)
fail_with_message "Error: #{e.message}"
end
end
@ -648,18 +578,18 @@ module Mastodon::CLI
private
def report_errors(errors)
errors.each do |error|
say('Failure/Error: ', :red)
say(error.attribute)
say(" #{error.type}", :red)
end
message = errors.map do |error|
<<~STRING
Failure/Error: #{error.attribute}
#{error.type}
STRING
end.join
fail_with_message message
end
def rotate_keys_for_account(account, delay = 0)
if account.nil?
say('No such account', :red)
exit(1)
end
fail_with_message 'No such account' if account.nil?
old_key = account.private_key
new_key = OpenSSL::PKey::RSA.new(2048)

View File

@ -18,6 +18,10 @@ module Mastodon
private
def fail_with_message(message)
raise Thor::Error, message
end
def pastel
@pastel ||= Pastel.new
end

View File

@ -31,8 +31,7 @@ module Mastodon::CLI
recount_status_stats(status)
end
else
say("Unknown type: #{type}", :red)
exit(1)
fail_with_message "Unknown type: #{type}"
end
say

View File

@ -41,11 +41,9 @@ module Mastodon::CLI
# Sanity check on command arguments
if options[:limited_federation_mode] && !domains.empty?
say('DOMAIN parameter not supported with --limited-federation-mode', :red)
exit(1)
fail_with_message 'DOMAIN parameter not supported with --limited-federation-mode'
elsif domains.empty? && !options[:limited_federation_mode]
say('No domain(s) given', :red)
exit(1)
fail_with_message 'No domain(s) given'
end
# Build scopes from command arguments

View File

@ -30,10 +30,7 @@ module Mastodon::CLI
it at the root.
LONG_DESC
def add(*domains)
if domains.empty?
say('No domain(s) given', :red)
exit(1)
end
fail_with_message 'No domain(s) given' if domains.empty?
skipped = 0
processed = 0
@ -76,10 +73,7 @@ module Mastodon::CLI
desc 'remove DOMAIN...', 'Remove e-mail domain blocks'
def remove(*domains)
if domains.empty?
say('No domain(s) given', :red)
exit(1)
end
fail_with_message 'No domain(s) given' if domains.empty?
skipped = 0
processed = 0

View File

@ -86,14 +86,8 @@ module Mastodon::CLI
category = CustomEmojiCategory.find_by(name: options[:category])
export_file_name = File.join(path, 'export.tar.gz')
if File.file?(export_file_name) && !options[:overwrite]
say("Archive already exists! Use '--overwrite' to overwrite it!")
exit 1
end
if category.nil? && options[:category]
say("Unable to find category '#{options[:category]}'!")
exit 1
end
fail_with_message "Archive already exists! Use '--overwrite' to overwrite it!" if File.file?(export_file_name) && !options[:overwrite]
fail_with_message "Unable to find category '#{options[:category]}'!" if category.nil? && options[:category]
File.open(export_file_name, 'wb') do |file|
Zlib::GzipWriter.wrap(file) do |gzip|

View File

@ -43,10 +43,10 @@ module Mastodon::CLI
say('Every deletion notice has been sent! You can safely delete all data and decomission your servers!', :green)
end
exit(0)
raise(SystemExit)
end
exit(1) unless ask('Type in the domain of the server to confirm:') == Rails.configuration.x.local_domain
fail_with_message 'Domains do not match. Stopping self-destruct initiation.' unless domain_match_confirmed?
say(<<~WARNING, :yellow)
This operation WILL NOT be reversible.
@ -54,19 +54,25 @@ module Mastodon::CLI
The deletion process itself may take a long time, and will be handled by Sidekiq, so do not shut it down until it has finished (you will be able to re-run this command to see the state of the self-destruct process).
WARNING
exit(1) if no?('Are you sure you want to proceed?')
fail_with_message 'Operation cancelled. Self-destruct will not begin.' if proceed_prompt_negative?
say(<<~INSTRUCTIONS, :green)
To switch Mastodon to self-destruct mode, add the following variable to your evironment (e.g. by adding a line to your `.env.production`) and restart all Mastodon processes:
SELF_DESTRUCT=#{self_destruct_value}
You can re-run this command to see the state of the self-destruct process.
INSTRUCTIONS
rescue Interrupt
exit(1)
end
private
def domain_match_confirmed?
ask('Type in the domain of the server to confirm:') == Rails.configuration.x.local_domain
end
def proceed_prompt_negative?
no?('Are you sure you want to proceed?')
end
def self_destruct_value
Rails
.application

View File

@ -27,17 +27,13 @@ module Mastodon::CLI
elsif username.present?
account = Account.find_local(username)
if account.nil?
say('No such account', :red)
exit(1)
end
fail_with_message 'No such account' if account.nil?
PrecomputeFeedService.new.call(account) unless dry_run?
say("OK #{dry_run_mode_suffix}", :green, true)
else
say('No account(s) given', :red)
exit(1)
fail_with_message 'No account(s) given'
end
end

View File

@ -20,10 +20,7 @@ module Mastodon::CLI
option to overwrite it.
LONG_DESC
def add(*addresses)
if addresses.empty?
say('No IP(s) given', :red)
exit(1)
end
fail_with_message 'No IP(s) given' if addresses.empty?
skipped = 0
processed = 0
@ -70,10 +67,7 @@ module Mastodon::CLI
cover the given IP(s).
LONG_DESC
def remove(*addresses)
if addresses.empty?
say('No IP(s) given', :red)
exit(1)
end
fail_with_message 'No IP(s) given' if addresses.empty?
processed = 0
skipped = 0

View File

@ -199,26 +199,24 @@ module Mastodon::CLI
def verify_schema_version!
if migrator_version < MIN_SUPPORTED_VERSION
say 'Your version of the database schema is too old and is not supported by this script.', :red
say 'Please update to at least Mastodon 3.0.0 before running this script.', :red
exit(1)
fail_with_message <<~ERROR
Your version of the database schema is too old and is not supported by this script.
Please update to at least Mastodon 3.0.0 before running this script.
ERROR
elsif migrator_version > MAX_SUPPORTED_VERSION
say 'Your version of the database schema is more recent than this script, this may cause unexpected errors.', :yellow
exit(1) unless yes?('Continue anyway? (Yes/No)')
fail_with_message 'Stopping maintenance script because data is more recent than script version.' unless yes?('Continue anyway? (Yes/No)')
end
end
def verify_sidekiq_not_active!
if Sidekiq::ProcessSet.new.any?
say 'It seems Sidekiq is running. All Mastodon processes need to be stopped when using this script.', :red
exit(1)
end
fail_with_message 'It seems Sidekiq is running. All Mastodon processes need to be stopped when using this script.' if Sidekiq::ProcessSet.new.any?
end
def verify_backup_warning!
say 'This task will take a long time to run and is potentially destructive.', :yellow
say 'Please make sure to stop Mastodon and have a backup.', :yellow
exit(1) unless yes?('Continue? (Yes/No)')
fail_with_message 'Maintenance process stopped.' unless yes?('Continue? (Yes/No)')
end
def deduplicate_accounts!

View File

@ -31,15 +31,9 @@ module Mastodon::CLI
following anyone locally are pruned.
DESC
def remove
if options[:prune_profiles] && options[:remove_headers]
say('--prune-profiles and --remove-headers should not be specified simultaneously', :red, true)
exit(1)
end
fail_with_message '--prune-profiles and --remove-headers should not be specified simultaneously' if options[:prune_profiles] && options[:remove_headers]
if options[:include_follows] && !(options[:prune_profiles] || options[:remove_headers])
say('--include-follows can only be used with --prune-profiles or --remove-headers', :red, true)
exit(1)
end
fail_with_message '--include-follows can only be used with --prune-profiles or --remove-headers' if options[:include_follows] && !(options[:prune_profiles] || options[:remove_headers])
time_ago = options[:days].days.ago
if options[:prune_profiles] || options[:remove_headers]
@ -156,11 +150,9 @@ module Mastodon::CLI
end
end
when :fog
say('The fog storage driver is not supported for this operation at this time', :red)
exit(1)
fail_with_message 'The fog storage driver is not supported for this operation at this time'
when :azure
say('The azure storage driver is not supported for this operation at this time', :red)
exit(1)
fail_with_message 'The azure storage driver is not supported for this operation at this time'
when :filesystem
require 'find'
@ -254,10 +246,7 @@ module Mastodon::CLI
username, domain = options[:account].split('@')
account = Account.find_remote(username, domain)
if account.nil?
say('No such account', :red)
exit(1)
end
fail_with_message 'No such account' if account.nil?
scope = MediaAttachment.where(account_id: account.id)
elsif options[:domain]
@ -265,8 +254,7 @@ module Mastodon::CLI
elsif options[:days].present?
scope = MediaAttachment.remote
else
say('Specify the source of media attachments', :red)
exit(1)
fail_with_message 'Specify the source of media attachments'
end
scope = scope.where('media_attachments.id > ?', Mastodon::Snowflake.id_at(options[:days].days.ago, with_random: false)) if options[:days].present?
@ -306,38 +294,25 @@ module Mastodon::CLI
path_segments = path.split('/')[2..]
path_segments.delete('cache')
unless VALID_PATH_SEGMENTS_SIZE.include?(path_segments.size)
say('Not a media URL', :red)
exit(1)
end
fail_with_message 'Not a media URL' unless VALID_PATH_SEGMENTS_SIZE.include?(path_segments.size)
model_name = path_segments.first.classify
record_id = path_segments[2..-2].join.to_i
unless PRELOAD_MODEL_WHITELIST.include?(model_name)
say("Cannot find corresponding model: #{model_name}", :red)
exit(1)
end
fail_with_message "Cannot find corresponding model: #{model_name}" unless PRELOAD_MODEL_WHITELIST.include?(model_name)
record = model_name.constantize.find_by(id: record_id)
record = record.status if record.respond_to?(:status)
unless record
say('Cannot find corresponding record', :red)
exit(1)
end
fail_with_message 'Cannot find corresponding record' unless record
display_url = ActivityPub::TagManager.instance.url_for(record)
if display_url.blank?
say('No public URL for this type of record', :red)
exit(1)
end
fail_with_message 'No public URL for this type of record' if display_url.blank?
say(display_url, :blue)
rescue Addressable::URI::InvalidURIError
say('Invalid URL', :red)
exit(1)
fail_with_message 'Invalid URL'
end
private

View File

@ -25,10 +25,7 @@ module Mastodon::CLI
end
def parallelize_with_progress(scope)
if options[:concurrency] < 1
say('Cannot run with this concurrency setting, must be at least 1', :red)
exit(1)
end
fail_with_message 'Cannot run with this concurrency setting, must be at least 1' if options[:concurrency] < 1
reset_connection_pools!

View File

@ -110,17 +110,11 @@ module Mastodon::CLI
end
def verify_deploy_concurrency!
return unless options[:concurrency] < 1
say('Cannot run with this concurrency setting, must be at least 1', :red)
exit(1)
fail_with_message 'Cannot run with this concurrency setting, must be at least 1' if options[:concurrency] < 1
end
def verify_deploy_batch_size!
return unless options[:batch_size] < 1
say('Cannot run with this batch_size setting, must be at least 1', :red)
exit(1)
fail_with_message 'Cannot run with this batch_size setting, must be at least 1' if options[:batch_size] < 1
end
def progress_output_options

View File

@ -26,10 +26,7 @@ module Mastodon::CLI
indices before commencing, and removes them afterward.
LONG_DESC
def remove
if options[:batch_size] < 1
say('Cannot run with this batch_size setting, must be at least 1', :red)
exit(1)
end
fail_with_message 'Cannot run with this batch_size setting, must be at least 1' if options[:batch_size] < 1
remove_statuses
vacuum_and_analyze_statuses

View File

@ -103,13 +103,11 @@ module Mastodon::CLI
end
def upgrade_storage_fog(_progress, _attachment, _style)
say('The fog storage driver is not supported for this operation at this time', :red)
exit(1)
fail_with_message 'The fog storage driver is not supported for this operation at this time'
end
def upgrade_storage_azure(_progress, _attachment, _style)
say('The azure storage driver is not supported for this operation at this time', :red)
exit(1)
fail_with_message 'The azure storage driver is not supported for this operation at this time'
end
def upgrade_storage_filesystem(progress, attachment, style)

View File

@ -65,8 +65,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message' do
expect { subject }
.to output_results('Failure/Error: email')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, %r{Failure/Error: email})
end
end
end
@ -127,8 +126,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message indicating the role name was not found' do
expect { subject }
.to output_results('Cannot find user role with that name')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'Cannot find user role with that name')
end
end
end
@ -191,8 +189,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message indicating the user was not found' do
expect { subject }
.to output_results('No user with such username')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No user with such username')
end
end
@ -214,8 +211,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message indicating the role was not found' do
expect { subject }
.to output_results('Cannot find user role with that name')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'Cannot find user role with that name')
end
end
@ -364,8 +360,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message' do
expect { subject }
.to output_results('Failure/Error: email')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, %r{Failure/Error: email})
end
end
end
@ -387,16 +382,14 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message indicating that only one should be used' do
expect { subject }
.to output_results('Use username or --email, not both')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'Use username or --email, not both')
end
end
context 'when neither username nor --email are provided' do
it 'exits with an error message indicating that no username was provided' do
expect { subject }
.to output_results('No username provided')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No username provided')
end
end
@ -425,8 +418,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message indicating that no user was found' do
expect { subject }
.to output_results('No user with such username')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No user with such username')
end
end
end
@ -458,8 +450,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message indicating that no user was found' do
expect { subject }
.to output_results('No user with such email')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No user with such email')
end
end
end
@ -511,8 +502,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message indicating that the number must be positive' do
expect { subject }
.to output_results('Number must be positive')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'Number must be positive')
end
end
@ -545,8 +535,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message indicating that no such account was found' do
expect { subject }
.to output_results('No such account')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No such account')
end
end
end
@ -560,8 +549,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message indicating that no account with the given username was found' do
expect { subject }
.to output_results('No such account')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No such account')
end
end
@ -596,8 +584,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message indicating that no account with the given username was found' do
expect { subject }
.to output_results('No such account')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No such account')
end
end
@ -634,8 +621,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message indicating that there is no such account' do
expect { subject }
.to output_results('No user with such username')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No user with such username')
end
end
@ -795,8 +781,7 @@ describe Mastodon::CLI::Accounts do
allow(Account).to receive(:find_remote).with(account_example_com_b.username, account_example_com_b.domain).and_return(nil)
expect { subject }
.to output_results('No such account')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No such account')
end
end
@ -892,8 +877,7 @@ describe Mastodon::CLI::Accounts do
context 'when neither a list of accts nor options are provided' do
it 'exits with an error message' do
expect { subject }
.to output_results('No account(s) given')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No account(s) given')
end
end
end
@ -904,8 +888,7 @@ describe Mastodon::CLI::Accounts do
context 'when neither username nor --all option are given' do
it 'exits with an error message' do
expect { subject }
.to output_results('No account(s) given')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No account(s) given')
end
end
@ -940,8 +923,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message when the specified username is not found' do
expect { subject }
.to output_results('No such account')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No such account')
end
end
@ -980,8 +962,7 @@ describe Mastodon::CLI::Accounts do
shared_examples 'an account not found' do |acct|
it 'exits with an error message indicating that there is no such account' do
expect { subject }
.to output_results("No such account (#{acct})")
.and raise_error(SystemExit)
.to raise_error(Thor::Error, "No such account (#{acct})")
end
end
@ -1031,8 +1012,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message indicating that the accounts do not have the same pub key' do
expect { subject }
.to output_results("Accounts don't have the same public key, might not be duplicates!\nOverride with --force")
.and raise_error(SystemExit)
.to raise_error(Thor::Error, "Accounts don't have the same public key, might not be duplicates!\nOverride with --force\n")
end
context 'with --force option' do
@ -1200,8 +1180,7 @@ describe Mastodon::CLI::Accounts do
context 'when no option is given' do
it 'exits with an error message indicating that at least one option is required' do
expect { subject }
.to output_results('Please specify either --follows or --followers, or both')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'Please specify either --follows or --followers, or both')
end
end
@ -1211,8 +1190,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message indicating that there is no such account' do
expect { subject }
.to output_results('No such account')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No such account')
end
end
@ -1368,16 +1346,14 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message indicating that using both options is not possible' do
expect { subject }
.to output_results('Use --replay or --target, not both')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'Use --replay or --target, not both')
end
end
context 'when no option is given' do
it 'exits with an error message indicating that at least one option must be used' do
expect { subject }
.to output_results('Use either --replay or --target')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'Use either --replay or --target')
end
end
@ -1387,8 +1363,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message indicating that there is no such account' do
expect { subject }
.to output_results("No such account: #{arguments.first}")
.and raise_error(SystemExit)
.to raise_error(Thor::Error, "No such account: #{arguments.first}")
end
end
@ -1398,8 +1373,7 @@ describe Mastodon::CLI::Accounts do
context 'when the specified account has no previous migrations' do
it 'exits with an error message indicating that the given account has no previous migrations' do
expect { subject }
.to output_results('The specified account has not performed any migration')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'The specified account has not performed any migration')
end
end
@ -1421,8 +1395,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message' do
expect { subject }
.to output_results('The specified account is not redirecting to its last migration target. Use --force if you want to replay the migration anyway')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'The specified account is not redirecting to its last migration target. Use --force if you want to replay the migration anyway')
end
end
@ -1449,8 +1422,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message indicating that there is no such account' do
expect { subject }
.to output_results("The specified target account could not be found: #{options[:target]}")
.and raise_error(SystemExit)
.to raise_error(Thor::Error, "The specified target account could not be found: #{options[:target]}")
end
end
@ -1474,8 +1446,7 @@ describe Mastodon::CLI::Accounts do
context 'when the migration record is invalid' do
it 'exits with an error indicating that the validation failed' do
expect { subject }
.to output_results('Error: Validation failed')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, /Error: Validation failed/)
end
end
@ -1486,8 +1457,7 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message' do
expect { subject }
.to output_results('The specified account is redirecting to a different target account. Use --force if you want to change the migration target')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'The specified account is redirecting to a different target account. Use --force if you want to change the migration target')
end
end

View File

@ -64,8 +64,7 @@ describe Mastodon::CLI::Cache do
it 'Exits with an error message' do
expect { subject }
.to output_results('Unknown')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, /Unknown/)
end
end
end

View File

@ -35,8 +35,7 @@ describe Mastodon::CLI::EmailDomainBlocks do
context 'without any options' do
it 'warns about usage and exits' do
expect { subject }
.to output_results('No domain(s) given')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No domain(s) given')
end
end
@ -72,8 +71,7 @@ describe Mastodon::CLI::EmailDomainBlocks do
context 'without any options' do
it 'warns about usage and exits' do
expect { subject }
.to output_results('No domain(s) given')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No domain(s) given')
end
end

View File

@ -42,8 +42,7 @@ describe Mastodon::CLI::Feeds do
it 'displays an error and exits' do
expect { subject }
.to output_results('No such account')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No such account')
end
end
end

View File

@ -144,8 +144,7 @@ describe Mastodon::CLI::IpBlocks do
it 'exits with an error message' do
expect { subject }
.to output_results('No IP(s) given')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No IP(s) given')
end
end
end
@ -235,8 +234,7 @@ describe Mastodon::CLI::IpBlocks do
context 'when no IP address is provided' do
it 'exits with an error message' do
expect { subject }
.to output_results('No IP(s) given')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No IP(s) given')
end
end
end

View File

@ -104,9 +104,9 @@ describe Mastodon::CLI::Main do
answer_hostname_incorrectly
end
it 'exits silently' do
it 'exits with mismatch error message' do
expect { subject }
.to raise_error(SystemExit)
.to raise_error(Thor::Error, /Domains do not match/)
end
end
@ -119,7 +119,7 @@ describe Mastodon::CLI::Main do
it 'passes first step but stops before instructions' do
expect { subject }
.to output_results('operation WILL NOT')
.and raise_error(SystemExit)
.and raise_error(Thor::Error, /Self-destruct will not begin/)
end
end

View File

@ -22,8 +22,7 @@ describe Mastodon::CLI::Maintenance do
it 'Exits with error message' do
expect { subject }
.to output_results('is too old')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, /is too old/)
end
end
@ -36,7 +35,7 @@ describe Mastodon::CLI::Maintenance do
it 'Exits with error message' do
expect { subject }
.to output_results('more recent')
.and raise_error(SystemExit)
.and raise_error(Thor::Error, /more recent/)
end
end
@ -48,8 +47,7 @@ describe Mastodon::CLI::Maintenance do
it 'Exits with error message' do
expect { subject }
.to output_results('Sidekiq is running')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, /Sidekiq is running/)
end
end

View File

@ -20,8 +20,7 @@ describe Mastodon::CLI::Media do
it 'warns about usage and exits' do
expect { subject }
.to output_results('--prune-profiles and --remove-headers should not be specified simultaneously')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, '--prune-profiles and --remove-headers should not be specified simultaneously')
end
end
@ -30,8 +29,7 @@ describe Mastodon::CLI::Media do
it 'warns about usage and exits' do
expect { subject }
.to output_results('--include-follows can only be used with --prune-profiles or --remove-headers')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, '--include-follows can only be used with --prune-profiles or --remove-headers')
end
end
@ -98,8 +96,7 @@ describe Mastodon::CLI::Media do
it 'warns about url and exits' do
expect { subject }
.to output_results('Not a media URL')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'Not a media URL')
end
end
@ -121,8 +118,7 @@ describe Mastodon::CLI::Media do
context 'without any options' do
it 'warns about usage and exits' do
expect { subject }
.to output_results('Specify the source')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, /Specify the source/)
end
end
@ -147,8 +143,7 @@ describe Mastodon::CLI::Media do
it 'warns about usage and exits' do
expect { subject }
.to output_results('No such account')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, 'No such account')
end
end
@ -221,8 +216,7 @@ describe Mastodon::CLI::Media do
it 'warns about usage and exits' do
expect { subject }
.to output_results('azure storage driver is not supported')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, /azure storage driver is not supported/)
end
end
@ -233,8 +227,7 @@ describe Mastodon::CLI::Media do
it 'warns about usage and exits' do
expect { subject }
.to output_results('fog storage driver is not supported')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, /fog storage driver is not supported/)
end
end

View File

@ -20,8 +20,7 @@ describe Mastodon::CLI::Search do
it 'Exits with error message' do
expect { subject }
.to output_results('this concurrency setting')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, /this concurrency setting/)
end
end
@ -30,8 +29,7 @@ describe Mastodon::CLI::Search do
it 'Exits with error message' do
expect { subject }
.to output_results('this batch_size setting')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, /this batch_size setting/)
end
end

View File

@ -20,8 +20,7 @@ describe Mastodon::CLI::Statuses do
it 'exits with error message' do
expect { subject }
.to output_results('Cannot run')
.and raise_error(SystemExit)
.to raise_error(Thor::Error, /Cannot run/)
end
end