warp-dir 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.atom-build.json +22 -0
- data/.codeclimate.yml +22 -0
- data/.gitignore +40 -0
- data/.idea/encodings.xml +6 -0
- data/.idea/misc.xml +14 -0
- data/.idea/modules.xml +8 -0
- data/.idea/runConfigurations/All_Specs.xml +33 -0
- data/.idea/vcs.xml +6 -0
- data/.idea/warp-dir.iml +224 -0
- data/.rspec +4 -0
- data/.rubocop.yml +1156 -0
- data/.travis.yml +13 -0
- data/Gemfile +4 -0
- data/Guardfile +14 -0
- data/LICENSE +22 -0
- data/README.md +114 -0
- data/ROADMAP.md +96 -0
- data/Rakefile +24 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/bin/warp-dir +13 -0
- data/bin/warp-dir.bash +25 -0
- data/lib/warp.rb +4 -0
- data/lib/warp/dir.rb +65 -0
- data/lib/warp/dir/app/cli.rb +162 -0
- data/lib/warp/dir/app/response.rb +133 -0
- data/lib/warp/dir/command.rb +120 -0
- data/lib/warp/dir/command/add.rb +16 -0
- data/lib/warp/dir/command/help.rb +80 -0
- data/lib/warp/dir/command/install.rb +78 -0
- data/lib/warp/dir/command/list.rb +13 -0
- data/lib/warp/dir/command/ls.rb +31 -0
- data/lib/warp/dir/command/remove.rb +16 -0
- data/lib/warp/dir/command/warp.rb +24 -0
- data/lib/warp/dir/commander.rb +71 -0
- data/lib/warp/dir/config.rb +87 -0
- data/lib/warp/dir/errors.rb +60 -0
- data/lib/warp/dir/formatter.rb +77 -0
- data/lib/warp/dir/point.rb +53 -0
- data/lib/warp/dir/serializer.rb +14 -0
- data/lib/warp/dir/serializer/base.rb +43 -0
- data/lib/warp/dir/serializer/dotfile.rb +36 -0
- data/lib/warp/dir/store.rb +129 -0
- data/lib/warp/dir/version.rb +6 -0
- data/spec/fixtures/warprc +2 -0
- data/spec/spec_helper.rb +71 -0
- data/spec/support/cli_expectations.rb +118 -0
- data/spec/warp/dir/app/cli_spec.rb +225 -0
- data/spec/warp/dir/app/response_spec.rb +131 -0
- data/spec/warp/dir/command_spec.rb +62 -0
- data/spec/warp/dir/commands/add_spec.rb +40 -0
- data/spec/warp/dir/commands/install_spec.rb +20 -0
- data/spec/warp/dir/commands/list_spec.rb +37 -0
- data/spec/warp/dir/config_spec.rb +45 -0
- data/spec/warp/dir/errors_spec.rb +16 -0
- data/spec/warp/dir/formatter_spec.rb +38 -0
- data/spec/warp/dir/point_spec.rb +35 -0
- data/spec/warp/dir/store_spec.rb +105 -0
- data/warp-dir.gemspec +56 -0
- metadata +228 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Warp
|
|
2
|
+
module Dir
|
|
3
|
+
module Serializer
|
|
4
|
+
class Base
|
|
5
|
+
attr_accessor :store
|
|
6
|
+
|
|
7
|
+
def initialize store
|
|
8
|
+
self.store = store
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def config
|
|
12
|
+
self.store.config
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.inherited subclass
|
|
16
|
+
Warp::Dir::SERIALIZERS[subclass.name] = subclass
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
#
|
|
20
|
+
# restore method should read the values from somewhere (i.e. database?)
|
|
21
|
+
# and perform the following operation:
|
|
22
|
+
#
|
|
23
|
+
# for each [ shortcut, path ] do
|
|
24
|
+
# self.store.add(shortcut, path)
|
|
25
|
+
# end
|
|
26
|
+
|
|
27
|
+
def restore!
|
|
28
|
+
raise NotImplementedError.new('Abstract Method')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
#
|
|
32
|
+
# save shortcuts to the persistence layer
|
|
33
|
+
#
|
|
34
|
+
# store.points.each_pair |shortcut, path| do
|
|
35
|
+
# save(shortcut, path)
|
|
36
|
+
# end
|
|
37
|
+
def persist!
|
|
38
|
+
raise NotImplementedError.new('Abstract Method')
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require_relative '../errors'
|
|
2
|
+
require_relative '../../dir'
|
|
3
|
+
module Warp
|
|
4
|
+
module Dir
|
|
5
|
+
module Serializer
|
|
6
|
+
class Dotfile < Base
|
|
7
|
+
|
|
8
|
+
def restore!
|
|
9
|
+
File.open(Warp::Dir.absolute(config.warprc), "r") do |f|
|
|
10
|
+
f.each_line do |line|
|
|
11
|
+
line = line.chomp
|
|
12
|
+
next if line.blank?
|
|
13
|
+
name, path = line.split(/:/)
|
|
14
|
+
if name.nil? || path.nil?
|
|
15
|
+
raise Warp::Dir::Errors::StoreFormatError.new("File may be corrupt - #{config.warprc}:#{line}", line)
|
|
16
|
+
end
|
|
17
|
+
store.add point_name: name, point_path: path
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def persist!
|
|
23
|
+
File.open(Warp::Dir.absolute(config.warprc), 'w') do |file|
|
|
24
|
+
buffer = ''
|
|
25
|
+
store.points.each do |point|
|
|
26
|
+
buffer << "#{point.name}:#{point.relative_path}\n"
|
|
27
|
+
end
|
|
28
|
+
file.write(buffer)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
require_relative 'point'
|
|
2
|
+
require_relative 'errors'
|
|
3
|
+
require_relative 'serializer'
|
|
4
|
+
require 'forwardable'
|
|
5
|
+
|
|
6
|
+
module Warp
|
|
7
|
+
module Dir
|
|
8
|
+
|
|
9
|
+
# We want to keep around only one store, so we follow the Singleton patter.
|
|
10
|
+
# Due to us wanting to pass parameters to the singleton class's #new method,
|
|
11
|
+
# using standard Singleton becomes more hassle than it's worth.
|
|
12
|
+
class Store
|
|
13
|
+
extend Forwardable
|
|
14
|
+
|
|
15
|
+
def_delegators :@points_collection, :size, :clear, :each, :map
|
|
16
|
+
def_delegators :@config, :warprc, :shell
|
|
17
|
+
|
|
18
|
+
attr_reader :config, :serializer, :points_collection
|
|
19
|
+
|
|
20
|
+
def initialize(config, serializer_class = Warp::Dir::Serializer.default)
|
|
21
|
+
@config = config
|
|
22
|
+
serializer_class ||= Warp::Dir::Serializer.default
|
|
23
|
+
@serializer = serializer_class.new(self)
|
|
24
|
+
restore!
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def restore!
|
|
28
|
+
@points_collection = Set.new
|
|
29
|
+
self.serializer.restore!
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def [](name)
|
|
33
|
+
find_point(name)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def first
|
|
37
|
+
points_collection.to_a.sort.first
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def last
|
|
41
|
+
points_collection.to_a.sort.last
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def <<(value)
|
|
45
|
+
raise ArgumentError.new("#{value} is not a Point") unless value.is_a?(Point)
|
|
46
|
+
self.add(point: value)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def remove(point_name: nil)
|
|
50
|
+
point = point_name.is_a?(Warp::Dir::Point) ? point_name : self[point_name]
|
|
51
|
+
self.points_collection.delete(point) if point
|
|
52
|
+
save!
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def points
|
|
56
|
+
points_collection.to_a
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def find_point(name_or_point)
|
|
60
|
+
return if name_or_point.nil?
|
|
61
|
+
result = if name_or_point.is_a?(Warp::Dir::Point)
|
|
62
|
+
self.find_point(name_or_point.name)
|
|
63
|
+
else
|
|
64
|
+
matching_set = self.points_collection.classify { |p| p.name.to_sym }[name_or_point.to_sym]
|
|
65
|
+
(matching_set && !matching_set.empty?) ? matching_set.first : nil
|
|
66
|
+
end
|
|
67
|
+
raise ::Warp::Dir::Errors::PointNotFound.new(name_or_point) unless result
|
|
68
|
+
result
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def save!
|
|
72
|
+
serializer.persist!
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# a version of add that save right after.
|
|
76
|
+
def insert(*args)
|
|
77
|
+
add(*args)
|
|
78
|
+
save!
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# add to memory representation only
|
|
82
|
+
def add(point: nil,
|
|
83
|
+
point_name: nil,
|
|
84
|
+
point_path: nil,
|
|
85
|
+
overwrite: false)
|
|
86
|
+
unless point
|
|
87
|
+
if !(point_name && point_path)
|
|
88
|
+
raise ArgumentError.new('invalid arguments')
|
|
89
|
+
end
|
|
90
|
+
point = Warp::Dir::Point.new(point_name, point_path)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Three use-cases here.
|
|
94
|
+
# if we found this WarpPoint by name, and it's path is different from the incoming...
|
|
95
|
+
existing = begin
|
|
96
|
+
self[point]
|
|
97
|
+
rescue Warp::Dir::Errors::PointNotFound
|
|
98
|
+
nil
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
if existing.eql?(point) # found, but it's identical
|
|
102
|
+
if config.debug
|
|
103
|
+
puts "Point being added #{point} is identical to existing #{existing}, ignore."
|
|
104
|
+
end
|
|
105
|
+
return
|
|
106
|
+
elsif existing # found, but it's different
|
|
107
|
+
if overwrite # replace it
|
|
108
|
+
if config.debug
|
|
109
|
+
puts "Point being added #{point} is replacing the existing #{existing}."
|
|
110
|
+
end
|
|
111
|
+
replace(point, existing)
|
|
112
|
+
else # reject it
|
|
113
|
+
if config.debug
|
|
114
|
+
puts "Point being added #{point} already exists, but no overwrite was set"
|
|
115
|
+
end
|
|
116
|
+
raise Warp::Dir::Errors::PointAlreadyExists.new(point)
|
|
117
|
+
end
|
|
118
|
+
else # no lookup found
|
|
119
|
+
self.points_collection << point # add it
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def replace(point, existing_point)
|
|
124
|
+
remove(point_name: existing_point)
|
|
125
|
+
insert(point: point)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
require 'codeclimate-test-reporter'
|
|
2
|
+
require 'warp/dir'
|
|
3
|
+
require 'rspec/core'
|
|
4
|
+
|
|
5
|
+
CodeClimate::TestReporter.start
|
|
6
|
+
|
|
7
|
+
module Warp
|
|
8
|
+
module Dir
|
|
9
|
+
module App
|
|
10
|
+
class Response
|
|
11
|
+
class << self
|
|
12
|
+
attr_accessor :exit_disabled
|
|
13
|
+
|
|
14
|
+
def enable_exit!
|
|
15
|
+
self.exit_disabled = false
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def disable_exit!
|
|
19
|
+
self.exit_disabled = true
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def exit_disabled?
|
|
23
|
+
self.exit_disabled
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
RSpec.configure do |config|
|
|
32
|
+
config.before do
|
|
33
|
+
Warp::Dir::App::Response.disable_exit!
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
RSpec.shared_context :fake_serializer do
|
|
38
|
+
let(:file) { @file ||= ::Tempfile.new('warp-dir') }
|
|
39
|
+
let(:config) { Warp::Dir::Config.new(config: file.path) }
|
|
40
|
+
let(:serializer) {
|
|
41
|
+
@initialized_store ||= FakeSerializer ||= Class.new(Warp::Dir::Serializer::Base) do
|
|
42
|
+
def persist!;
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def restore!;
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
after do
|
|
51
|
+
file.close
|
|
52
|
+
file.unlink
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
RSpec.shared_context :fixture_file do
|
|
57
|
+
let(:fixture_file) { 'spec/fixtures/warprc'}
|
|
58
|
+
let(:config_path) { '/tmp/warprc' }
|
|
59
|
+
let(:file) {
|
|
60
|
+
FileUtils.cp(fixture_file, config_path)
|
|
61
|
+
File.new(config_path)
|
|
62
|
+
}
|
|
63
|
+
let(:config) { Warp::Dir::Config.new(config: file.path) }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
RSpec.shared_context :initialized_store do
|
|
67
|
+
let(:store) { Warp::Dir::Store.new(config) }
|
|
68
|
+
let(:wp_path) { ENV['HOME'] + '/workspace/tinker-mania' }
|
|
69
|
+
let(:wp_name) { 'harro' }
|
|
70
|
+
let(:point) { Warp::Dir::Point.new(wp_name, wp_path) }
|
|
71
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
require 'rspec/expectations'
|
|
2
|
+
require 'warp/dir/app/cli'
|
|
3
|
+
require 'rspec/expectations'
|
|
4
|
+
|
|
5
|
+
module Warp
|
|
6
|
+
module Dir
|
|
7
|
+
module CLIHelper
|
|
8
|
+
|
|
9
|
+
def run_command!(arguments)
|
|
10
|
+
argv = arguments.is_a?(Array) ? arguments : arguments.split(' ')
|
|
11
|
+
cli = Warp::Dir::App::CLI.new(argv)
|
|
12
|
+
cli.run
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def validate!(arguments, yield_before_validation: false)
|
|
16
|
+
argv = arguments.is_a?(Array) ? arguments : arguments.split(' ')
|
|
17
|
+
cli = Warp::Dir::App::CLI.new(argv)
|
|
18
|
+
if yield_before_validation
|
|
19
|
+
yield(cli) if block_given?
|
|
20
|
+
end
|
|
21
|
+
cli.validate
|
|
22
|
+
unless yield_before_validation
|
|
23
|
+
yield(cli) if block_given?
|
|
24
|
+
end
|
|
25
|
+
cli.run
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def output_matches(output, expected)
|
|
29
|
+
if expected.is_a?(Regexp)
|
|
30
|
+
expected.match(output)
|
|
31
|
+
elsif expected.is_a?(String)
|
|
32
|
+
output.include?(expected)
|
|
33
|
+
else
|
|
34
|
+
nil
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
RSpec::Matchers.define :output do |*expectations|
|
|
42
|
+
include Warp::Dir::CLIHelper
|
|
43
|
+
match do |actual|
|
|
44
|
+
@response = nil
|
|
45
|
+
@command = "wd #{actual.is_a?(Array) ? actual.join(' ') : actual}"
|
|
46
|
+
expectations.all? do |expected|
|
|
47
|
+
@response = run_command!(actual)
|
|
48
|
+
@response.messages.any? { |m| output_matches(m, expected) }
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
failure_message do |actual|
|
|
52
|
+
"#{@command} was supposed to produce something matching or containing:\nexpected: '#{expected}',\n actual: #{@response.messages}"
|
|
53
|
+
end
|
|
54
|
+
match_when_negated do |actual|
|
|
55
|
+
@response = nil
|
|
56
|
+
@command = "wd #{actual.is_a?(Array) ? actual.join(' ') : actual}"
|
|
57
|
+
expectations.none? do |expected|
|
|
58
|
+
@response = run_command!(actual)
|
|
59
|
+
@response.messages.any? { |m| output_matches(m, expected) }
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
failure_message_when_negated do |actual|
|
|
63
|
+
"expected #{actual} not to contain #{expected}, got #{@response}"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
RSpec::Matchers.define :validate do |expected|
|
|
68
|
+
include Warp::Dir::CLIHelper
|
|
69
|
+
match do |actual|
|
|
70
|
+
if expected == true || expected == false
|
|
71
|
+
yield_before_validation = expected
|
|
72
|
+
end
|
|
73
|
+
expected = block_arg
|
|
74
|
+
if expected.is_a?(Proc)
|
|
75
|
+
begin
|
|
76
|
+
@response = validate!(actual, yield_before_validation: yield_before_validation) do |cli|
|
|
77
|
+
expected.call(cli)
|
|
78
|
+
end
|
|
79
|
+
rescue Exception => e
|
|
80
|
+
STDERR.puts(e.inspect)
|
|
81
|
+
STDERR.puts(e.backtrace.join("\n"))
|
|
82
|
+
raise
|
|
83
|
+
end
|
|
84
|
+
else
|
|
85
|
+
raise TypeError.new('Expected must be a block')
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
failure_message do |actual|
|
|
89
|
+
"expected #{actual} to validate that the block evaluates to true"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
RSpec::Matchers.define :exit_with do |expected|
|
|
95
|
+
include Warp::Dir::CLIHelper
|
|
96
|
+
|
|
97
|
+
match do |actual|
|
|
98
|
+
response = run_command!(actual)
|
|
99
|
+
response.code == expected
|
|
100
|
+
end
|
|
101
|
+
match_when_negated do |actual|
|
|
102
|
+
response = run_command!(actual)
|
|
103
|
+
response.code != expected
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# RSpec::Matchers.define :eval_to_true_after_validate do |expected|
|
|
108
|
+
# match do |actual|
|
|
109
|
+
# expected_type = expected.is_a?(Symbol) ?
|
|
110
|
+
# Warp::Dir::App::Response::RETURN_TYPE[expected_type] :
|
|
111
|
+
# expected
|
|
112
|
+
# response = run_and_yield(expected)
|
|
113
|
+
# response.type == expected_type
|
|
114
|
+
# end
|
|
115
|
+
# failure_message_for_should_not do |actual|
|
|
116
|
+
# "expected #{expected} to produce return type #{}"
|
|
117
|
+
# end
|
|
118
|
+
# end
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'support/cli_expectations'
|
|
3
|
+
require 'warp/dir'
|
|
4
|
+
require 'warp/dir/config'
|
|
5
|
+
require 'warp/dir/app/cli'
|
|
6
|
+
require 'pp'
|
|
7
|
+
require 'fileutils'
|
|
8
|
+
|
|
9
|
+
RSpec.describe Warp::Dir::App::CLI do
|
|
10
|
+
include_context :fixture_file
|
|
11
|
+
include_context :initialized_store
|
|
12
|
+
|
|
13
|
+
let(:config_args) { ['--config', config.warprc] }
|
|
14
|
+
let(:warprc) { config_args.join(' ') }
|
|
15
|
+
|
|
16
|
+
describe 'when parsing argument list' do
|
|
17
|
+
let(:cli) { Warp::Dir::App::CLI.new(argv) }
|
|
18
|
+
before do
|
|
19
|
+
cli.config = config
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe 'with suffix flags' do
|
|
23
|
+
subject { cli.send(:extract_suffix_flags, argv) }
|
|
24
|
+
describe 'and with at leats two arguments' do
|
|
25
|
+
let(:argv) { 'command argument --flag1 --flag2 -- --suffix1 --suffix2 suffix-argument'.split(' ')}
|
|
26
|
+
it 'extracts them well' do
|
|
27
|
+
should eql(%w(--suffix1 --suffix2 suffix-argument))
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe 'with only one argument' do
|
|
33
|
+
let(:result) { cli.send(:shift_non_flag_commands) }
|
|
34
|
+
|
|
35
|
+
describe "that's a list command" do
|
|
36
|
+
let(:argv) { %w(list --verbose) }
|
|
37
|
+
|
|
38
|
+
it 'should assign the command' do
|
|
39
|
+
expect(cli.argv).to eql(%w(list --verbose))
|
|
40
|
+
expect(result[:command]).to eql(:list)
|
|
41
|
+
expect(cli.argv).to eql(['--verbose'])
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe "that's a warp point" do
|
|
46
|
+
let(:argv) { %w(awesome-point) }
|
|
47
|
+
|
|
48
|
+
it 'should default to the :warp command' do
|
|
49
|
+
expect(result[:command]).to eql(:warp)
|
|
50
|
+
expect(result[:point]).to eql(:'awesome-point')
|
|
51
|
+
expect(cli.argv).to be_empty
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe 'with two command args' do
|
|
57
|
+
let(:argv) { %w(add mypoint) }
|
|
58
|
+
let(:result) { cli.send(:shift_non_flag_commands) }
|
|
59
|
+
|
|
60
|
+
it 'should interpret as a command and a point' do
|
|
61
|
+
expect(result[:command]).to eql(:add)
|
|
62
|
+
expect(result[:point]).to eql(:mypoint)
|
|
63
|
+
expect(cli.argv).to be_empty
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
describe 'when parsing flags' do
|
|
69
|
+
describe 'and found --help' do
|
|
70
|
+
let(:argv) { ['--help', *config_args] }
|
|
71
|
+
it 'should print the help message' do
|
|
72
|
+
expect(argv).to output(/<point>/, /Usage:/)
|
|
73
|
+
expect(argv).not_to output(/^cd /)
|
|
74
|
+
end
|
|
75
|
+
it 'should exit with zero status' do
|
|
76
|
+
expect(argv).to exit_with(0)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
describe 'and a flag is no found' do
|
|
81
|
+
let(:argv) { [ '--boo mee --moo', *config_args ] }
|
|
82
|
+
it 'should report invalid option' do
|
|
83
|
+
expect(argv).to output( /unknown option/)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
describe 'when an exception error occurs' do
|
|
88
|
+
let(:argv) { [ %w(boo dkk --debug), *config_args ].flatten }
|
|
89
|
+
context 'and --debug is given' do
|
|
90
|
+
it 'should print backtrace' do
|
|
91
|
+
expect(argv.join(' ')).to eql('boo dkk --debug --config /tmp/warprc')
|
|
92
|
+
expect(STDERR).to receive(:puts).twice
|
|
93
|
+
expect(argv).to validate(false) { |cli|
|
|
94
|
+
expect(cli.config.debug).to be_truthy
|
|
95
|
+
}
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
describe 'when running command' do
|
|
102
|
+
describe 'without a parameter' do
|
|
103
|
+
describe 'such as list' do
|
|
104
|
+
let(:argv) { ['list', *config_args] }
|
|
105
|
+
|
|
106
|
+
it 'should return listing of all points' do
|
|
107
|
+
expect("list #{warprc}").to output %r{log -> /var/log}
|
|
108
|
+
expect("list #{warprc}").to output %r{tmp -> /tmp}
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it 'should exit with zero status' do
|
|
112
|
+
expect("list #{warprc}").to exit_with(0)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
describe 'with a point arg, such as ' do
|
|
118
|
+
let(:wp_name) { store.last.name }
|
|
119
|
+
let(:wp_path) { store.last.path }
|
|
120
|
+
let(:warp_args) { "#{wp_name} #{warprc}" }
|
|
121
|
+
|
|
122
|
+
describe 'warp <point>' do
|
|
123
|
+
it "should return response with a 'cd' to a warp point" do
|
|
124
|
+
warp_point = wp_name
|
|
125
|
+
expect(warp_args).to validate { |cli|
|
|
126
|
+
expect(cli.config.point).to eql(warp_point)
|
|
127
|
+
expect(cli.config.command).to eql(:warp)
|
|
128
|
+
expect(cli.store[warp_point]).to eql(Warp::Dir::Point.new(wp_name, wp_path))
|
|
129
|
+
}
|
|
130
|
+
expect(warp_args).to output("cd #{wp_path}")
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
describe 'remove <point>' do
|
|
135
|
+
let(:warp_args) { "remove #{wp_name} #{warprc}" }
|
|
136
|
+
|
|
137
|
+
it 'should show that point is removed ' do
|
|
138
|
+
expect(warp_args).to output(/has been removed/)
|
|
139
|
+
end
|
|
140
|
+
it 'should change warp point count ' do
|
|
141
|
+
expect(store.size).to eq(2)
|
|
142
|
+
expect {
|
|
143
|
+
expect(warp_args).to validate { |cli|
|
|
144
|
+
expect(cli.config.point).to eql(point.name)
|
|
145
|
+
expect(cli.config.command).to eql(:remove)
|
|
146
|
+
}
|
|
147
|
+
store.restore!
|
|
148
|
+
}.to change(store, :size).by(-1)
|
|
149
|
+
expect(store.size).to eq(1)
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
describe 'add <point>' do
|
|
154
|
+
context 'when point exists' do
|
|
155
|
+
context 'without --force flag' do
|
|
156
|
+
let(:warp_args) { "add #{wp_name} #{warprc}" }
|
|
157
|
+
|
|
158
|
+
it 'should show error without' do
|
|
159
|
+
expect(warp_args).to output(/already exists/)
|
|
160
|
+
expect(warp_args).to exit_with(1)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
context 'with --force' do
|
|
164
|
+
let(:warp_args) { "add #{wp_name} #{warprc} --force" }
|
|
165
|
+
it 'should overwrite existing point' do
|
|
166
|
+
|
|
167
|
+
expect(Warp::Dir.pwd).to_not eql(wp_path)
|
|
168
|
+
|
|
169
|
+
existing_point = store[wp_name]
|
|
170
|
+
expect(existing_point).to be_kind_of(Warp::Dir::Point)
|
|
171
|
+
expect(existing_point.path).to eql(wp_path)
|
|
172
|
+
|
|
173
|
+
expect {
|
|
174
|
+
response = expect(warp_args).to validate { |cli|
|
|
175
|
+
expect(cli.config.point).to eql(point.name)
|
|
176
|
+
expect(cli.config.command).to eql(:add)
|
|
177
|
+
expect(cli.store[point.name]).to_not be_nil
|
|
178
|
+
}
|
|
179
|
+
expect(response.type).to eql(Warp::Dir::App::Response::INFO), response.message
|
|
180
|
+
store.restore!
|
|
181
|
+
updated_point = store[wp_name]
|
|
182
|
+
expect(updated_point.relative_path).to eql(Warp::Dir::pwd)
|
|
183
|
+
}.to_not change(store, :size)
|
|
184
|
+
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
describe 'ls <point>' do
|
|
191
|
+
context 'no flags' do
|
|
192
|
+
let(:warp_args) { "ls #{wp_name} #{warprc}" }
|
|
193
|
+
it 'should default to -al' do
|
|
194
|
+
expect(warp_args).to output(%r{total \d+\n}, %r{ warprc\n})
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
context '-- -l' do
|
|
198
|
+
let(:warp_args) { "ls #{wp_name} #{warprc} -- -l" }
|
|
199
|
+
it 'should extract flags' do
|
|
200
|
+
expect(warp_args).to validate { |cli|
|
|
201
|
+
expect(cli.flags).to eql(['-l'])
|
|
202
|
+
}
|
|
203
|
+
end
|
|
204
|
+
it 'should ls folder in long format' do
|
|
205
|
+
expect(warp_args).to output(%r{total \d+\n}, %r{ warprc\n})
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
context '-- -1' do
|
|
209
|
+
let(:warp_args) { "ls #{wp_name} #{warprc} -- -1" }
|
|
210
|
+
it 'should not list directory in long format' do
|
|
211
|
+
expect(warp_args).not_to output(%r{total \d+\n}, %r{ warprc\n})
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
context '-- -elf' do
|
|
215
|
+
let(:warp_args) { "ls #{wp_name} #{warprc} -- -alF" }
|
|
216
|
+
[%r{total \d+\n}, %r{ warprc\n}].each do |reg|
|
|
217
|
+
it "should list directory and match #{reg}" do
|
|
218
|
+
expect(warp_args).to output(reg)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|