Skip to content

Commit

Permalink
Merge pull request #45 from DannyBen/add/install-command
Browse files Browse the repository at this point in the history
Add `completely install` command
  • Loading branch information
DannyBen authored Apr 18, 2023
2 parents dfa5cff + ac276fb commit dc7190f
Show file tree
Hide file tree
Showing 13 changed files with 241 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ AllCops:
Naming/AccessorMethodName:
Exclude:
- 'lib/completely/tester.rb'

# The `bounce` method here is more readable without this cop
Style/GuardClause:
Exclude:
- 'lib/completely/commands/install.rb'
6 changes: 4 additions & 2 deletions lib/completely/cli.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
require 'mister_bin'
require 'completely/version'
require 'completely/commands/generate'
require 'completely/commands/init'
require 'completely/commands/install'
require 'completely/commands/preview'
require 'completely/commands/generate'
require 'completely/commands/test'
require 'completely/version'

module Completely
class CLI
Expand All @@ -16,6 +17,7 @@ def self.runner
runner.route 'preview', to: Commands::Preview
runner.route 'generate', to: Commands::Generate
runner.route 'test', to: Commands::Test
runner.route 'install', to: Commands::Install

runner
end
Expand Down
96 changes: 96 additions & 0 deletions lib/completely/commands/install.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
require 'completely/commands/base'

module Completely
module Commands
class Install < Base
TARGETS = %W[
/usr/share/bash-completion/completions
/usr/local/etc/bash_completion.d
#{Dir.home}/.bash_completion.d
]

summary 'Install a bash completion script'

help <<~HELP
This command will copy the specified file to one of the following directories:
#{TARGETS.map { |c| " - #{c}" }.join "\n"}
The target filename will be the program name, and sudo will be used if necessary.
HELP

usage 'completely install PROGRAM [SCRIPT_PATH --force --dry]'
usage 'completely install (-h|--help)'

option '-f --force', 'Overwrite target file if it exists'
option '-d --dry', 'Show the installation command but do not run it'

param 'PROGRAM', 'Name of the program the completions are for.'
param 'SCRIPT_PATH', 'Path to the source bash script [default: completely.bash].'

def run
bounce

if args['--dry']
puts command.join ' '
return
end

success = system(*command)
raise "Failed running command:\nnb`#{command.join ' '}`" unless success

say "Saved m`#{target_path}`"
say 'You may need to restart your session to test it'
end

private

def bounce
unless completions_path
raise 'Cannot determine system completions directory'
end

unless File.exist? script_path
raise "Cannot find script: m`#{script_path}`"
end

if target_exist? && !args['--force']
raise "File exists: m`#{target_path}`\nUse nb`--force` to overwrite"
end
end

def target_exist?
File.exist? target_path
end

def command
result = root? ? [] : %w[sudo]
result + %W[cp #{script_path} #{target_path}]
end

def script_path
args['SCRIPT_PATH'] || 'completely.bash'
end

def target_path
"#{completions_path}/#{args['PROGRAM']}"
end

def root?
Process.uid.zero?
end

def completions_path
@completions_path ||= completions_path!
end

def completions_path!
TARGETS.each do |tarnet|
return tarnet if Dir.exist? tarnet
end

nil
end
end
end
end
1 change: 1 addition & 0 deletions spec/approvals/cli/commands
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ Commands:
preview Generate the bash completion script to STDOUT
generate Generate the bash completion script to a file
test Test completions
install Install a bash completion script

Run completely COMMAND --help for more information
1 change: 1 addition & 0 deletions spec/approvals/cli/install/dry
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sudo cp README.md /usr/share/bash-completion/completions/completely-test
31 changes: 31 additions & 0 deletions spec/approvals/cli/install/help
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Install a bash completion script

This command will copy the specified file to one of the following directories:

- /usr/share/bash-completion/completions
- /usr/local/etc/bash_completion.d
- /home/vagrant/.bash_completion.d

The target filename will be the program name, and sudo will be used if
necessary.

Usage:
completely install PROGRAM [SCRIPT_PATH --force --dry]
completely install (-h|--help)

Options:
-f --force
Overwrite target file if it exists

-d --dry
Show the installation command but do not run it

-h --help
Show this help

Parameters:
PROGRAM
Name of the program the completions are for.

SCRIPT_PATH
Path to the source bash script [default: completely.bash].
2 changes: 2 additions & 0 deletions spec/approvals/cli/install/install-default
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Saved /usr/share/bash-completion/completions/completely-test
You may need to restart your session to test it
2 changes: 2 additions & 0 deletions spec/approvals/cli/install/install-specified
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Saved /usr/share/bash-completion/completions/completely-test
You may need to restart your session to test it
1 change: 1 addition & 0 deletions spec/approvals/cli/install/missing-script
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#<RuntimeError: Cannot find script: m`completely.bash`>
3 changes: 3 additions & 0 deletions spec/approvals/cli/install/no-args
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Usage:
completely install PROGRAM [SCRIPT_PATH --force --dry]
completely install (-h|--help)
1 change: 1 addition & 0 deletions spec/approvals/cli/install/no-completion-targets
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#<RuntimeError: Cannot determine system completions directory>
2 changes: 2 additions & 0 deletions spec/approvals/cli/install/target-exists
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#<RuntimeError: File exists: m`/usr/share/bash-completion/completions/completely-test`
Use nb`--force` to overwrite>
92 changes: 92 additions & 0 deletions spec/completely/commands/install_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
require 'spec_helper'

describe Commands::Install do
subject { described_class.new }

context 'with --help' do
it 'shows long usage' do
expect { subject.execute %w[install --help] }
.to output_approval('cli/install/help').diff(10)
end
end

context 'without arguments' do
it 'shows short usage' do
expect { subject.execute %w[install] }
.to output_approval('cli/install/no-args')
end
end

context 'with only the program name argument' do
context 'when the default script is not found' do
it 'raises an error' do
expect { subject.execute %w[install completely-test] }
.to raise_approval('cli/install/missing-script').diff(8)
end
end

context 'when the default script is found' do
let(:expected_args) do
%w[
sudo
cp
completely.bash
/usr/share/bash-completion/completions/completely-test
]
end

before do
reset_tmp_dir
File.write 'spec/tmp/completely.bash', 'not-important'
end

it 'copies the script' do
Dir.chdir 'spec/tmp' do
allow(subject).to receive(:system).with(*expected_args).and_return true
expect { subject.execute %w[install completely-test] }
.to output_approval('cli/install/install-default')
end
end
end
end

context 'with the program name argument and a script argument' do
let(:expected_args) do
%w[
sudo
cp
README.md
/usr/share/bash-completion/completions/completely-test
]
end

it 'copies the script' do
allow(subject).to receive(:system).with(*expected_args).and_return true
expect { subject.execute %w[install completely-test README.md] }
.to output_approval('cli/install/install-specified')
end
end

context 'with --dry' do
it 'shows the command' do
expect { subject.execute %w[install completely-test README.md --dry] }
.to output_approval('cli/install/dry')
end
end

context 'when none of the target directories is found' do
it 'raises an error' do
allow(subject).to receive(:completions_path).and_return nil
expect { subject.execute %w[install completely-test README.md] }
.to raise_approval('cli/install/no-completion-targets').diff(8)
end
end

context 'when the target file exists' do
it 'raises an error' do
allow(subject).to receive(:target_exist?).and_return true
expect { subject.execute %w[install completely-test README.md] }
.to raise_approval('cli/install/target-exists').diff(8)
end
end
end

0 comments on commit dc7190f

Please sign in to comment.