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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.atom-build.json +22 -0
  3. data/.codeclimate.yml +22 -0
  4. data/.gitignore +40 -0
  5. data/.idea/encodings.xml +6 -0
  6. data/.idea/misc.xml +14 -0
  7. data/.idea/modules.xml +8 -0
  8. data/.idea/runConfigurations/All_Specs.xml +33 -0
  9. data/.idea/vcs.xml +6 -0
  10. data/.idea/warp-dir.iml +224 -0
  11. data/.rspec +4 -0
  12. data/.rubocop.yml +1156 -0
  13. data/.travis.yml +13 -0
  14. data/Gemfile +4 -0
  15. data/Guardfile +14 -0
  16. data/LICENSE +22 -0
  17. data/README.md +114 -0
  18. data/ROADMAP.md +96 -0
  19. data/Rakefile +24 -0
  20. data/bin/console +11 -0
  21. data/bin/setup +8 -0
  22. data/bin/warp-dir +13 -0
  23. data/bin/warp-dir.bash +25 -0
  24. data/lib/warp.rb +4 -0
  25. data/lib/warp/dir.rb +65 -0
  26. data/lib/warp/dir/app/cli.rb +162 -0
  27. data/lib/warp/dir/app/response.rb +133 -0
  28. data/lib/warp/dir/command.rb +120 -0
  29. data/lib/warp/dir/command/add.rb +16 -0
  30. data/lib/warp/dir/command/help.rb +80 -0
  31. data/lib/warp/dir/command/install.rb +78 -0
  32. data/lib/warp/dir/command/list.rb +13 -0
  33. data/lib/warp/dir/command/ls.rb +31 -0
  34. data/lib/warp/dir/command/remove.rb +16 -0
  35. data/lib/warp/dir/command/warp.rb +24 -0
  36. data/lib/warp/dir/commander.rb +71 -0
  37. data/lib/warp/dir/config.rb +87 -0
  38. data/lib/warp/dir/errors.rb +60 -0
  39. data/lib/warp/dir/formatter.rb +77 -0
  40. data/lib/warp/dir/point.rb +53 -0
  41. data/lib/warp/dir/serializer.rb +14 -0
  42. data/lib/warp/dir/serializer/base.rb +43 -0
  43. data/lib/warp/dir/serializer/dotfile.rb +36 -0
  44. data/lib/warp/dir/store.rb +129 -0
  45. data/lib/warp/dir/version.rb +6 -0
  46. data/spec/fixtures/warprc +2 -0
  47. data/spec/spec_helper.rb +71 -0
  48. data/spec/support/cli_expectations.rb +118 -0
  49. data/spec/warp/dir/app/cli_spec.rb +225 -0
  50. data/spec/warp/dir/app/response_spec.rb +131 -0
  51. data/spec/warp/dir/command_spec.rb +62 -0
  52. data/spec/warp/dir/commands/add_spec.rb +40 -0
  53. data/spec/warp/dir/commands/install_spec.rb +20 -0
  54. data/spec/warp/dir/commands/list_spec.rb +37 -0
  55. data/spec/warp/dir/config_spec.rb +45 -0
  56. data/spec/warp/dir/errors_spec.rb +16 -0
  57. data/spec/warp/dir/formatter_spec.rb +38 -0
  58. data/spec/warp/dir/point_spec.rb +35 -0
  59. data/spec/warp/dir/store_spec.rb +105 -0
  60. data/warp-dir.gemspec +56 -0
  61. metadata +228 -0
@@ -0,0 +1,131 @@
1
+ require 'spec_helper'
2
+ require 'warp/dir/app/response'
3
+
4
+ RSpec.describe Warp::Dir::App::Response do
5
+ let(:response_class) { ::Warp::Dir::App::Response }
6
+ let(:response_instance) { response_class.new }
7
+ let(:stream) { double }
8
+
9
+ before do
10
+ expect(Warp::Dir).to receive(:eval_context?).at_most(100).times.and_return(true)
11
+ end
12
+ after do
13
+ response_instance.messages.clear
14
+ response_instance.instance_variable_set(:@type, nil)
15
+ end
16
+
17
+ describe 'class and type' do
18
+ it 'should be able to create response_instance' do
19
+ expect(response_instance).to be_kind_of(response_class)
20
+ end
21
+
22
+ it 'should have constants of correct type' do
23
+ expect(Warp::Dir::App::Response::INFO).to be_kind_of(Warp::Dir::App::Response::Type)
24
+ end
25
+ end
26
+
27
+ describe 'accessors' do
28
+ it 'should allow setting type, code and messages' do
29
+ response_instance.type(Warp::Dir::App::Response::INFO)
30
+ response_instance.message('Hi')
31
+ response_instance.code(200)
32
+ expect(response_instance.type).to eql(Warp::Dir::App::Response::INFO)
33
+ expect(response_instance.message).to eql('Hi')
34
+ expect(response_instance.code).to eql(200)
35
+ end
36
+ end
37
+
38
+ describe '#configure' do
39
+ describe 'given a response_instance object' do
40
+ before do
41
+ response_instance.instance_variable_set(:@type, nil)
42
+ response_instance.configure do
43
+ type Warp::Dir::App::Response::INFO
44
+ message 'Hello'
45
+ message 'World'
46
+ code 255
47
+ end
48
+ end
49
+
50
+ describe '#messages' do
51
+ it 'should concatenate when merged' do
52
+ expect(response_instance.messages).to eql(%w(Hello World))
53
+ expect(response_instance.message).to eql('HelloWorld')
54
+ end
55
+ end
56
+ describe '#type' do
57
+ it 'be equal to the lookup result' do
58
+ expect(response_instance.type).to eql(Warp::Dir::App::Response::RETURN_TYPE[:success])
59
+ expect(response_instance.type).to eql(Warp::Dir::App::Response::INFO)
60
+ end
61
+ end
62
+ describe '#code' do
63
+ it 'should be as it was configured' do
64
+ expect(response_instance.code).to eql(255)
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+
71
+ describe '#exit' do
72
+ let(:exit_code) { 199 }
73
+ let(:fake_type) { Warp::Dir::App::Response::Type.new(exit_code, stream) }
74
+ before do
75
+ Warp::Dir::App::Response.enable_exit!
76
+ end
77
+ after do
78
+ Warp::Dir::App::Response.disable_exit!
79
+ end
80
+
81
+ describe 'without specifying type' do
82
+ it 'should throw an exception' do
83
+ expect { response_instance.exit! }.to raise_error(ArgumentError)
84
+ end
85
+ end
86
+
87
+ describe 'when type is user output' do
88
+ before do
89
+ response_instance.type(fake_type)
90
+ end
91
+
92
+ it 'should properly format messages for eval' do
93
+ expect(stream).to receive(:printf).with(%Q{printf -- 'Hello\\n';}).once
94
+ expect(stream).to receive(:printf).with(%Q{printf -- 'World\\n';}).once
95
+ response_instance.configure do
96
+ message 'Hello'
97
+ message 'World'
98
+ end
99
+ response_instance.print
100
+ end
101
+ it 'should properly exit via Kernel' do
102
+ expect(Kernel).to receive(:exit).with(exit_code).once
103
+ response_instance.configure do
104
+ code 199
105
+ end
106
+ response_instance.exit!
107
+ end
108
+ end
109
+
110
+ describe 'when type is shell' do
111
+ before do
112
+ @stream = Warp::Dir::App::Response::SHELL.stream
113
+ Warp::Dir::App::Response::SHELL.stream = stream
114
+ end
115
+ after do
116
+ Warp::Dir::App::Response::SHELL.stream = @stream
117
+ end
118
+
119
+ it 'should return proper exit code for shell commands' do
120
+ response_instance.type(Warp::Dir::App::Response::SHELL)
121
+ response_instance.configure do
122
+ message 'ls -al'
123
+ code 1231 # this should be ignored
124
+ end
125
+ expect(stream).to receive(:printf).with('ls -al;').once
126
+ expect(Kernel).to receive(:exit).with(2).once
127
+ response_instance.print.exit!
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Warp::Dir::Command do
4
+ include_context :initialized_store
5
+ installed_commands = Warp::Dir::Command.installed_commands.dup.freeze
6
+
7
+ let(:command) { Warp::Dir::Command }
8
+ let(:commander) { Warp::Dir::Commander.instance }
9
+
10
+ describe 'when we remove inherited hierarchy' do
11
+ before do
12
+ commander.commands.clear
13
+ end
14
+ after do
15
+ commander.commands.merge(installed_commands.dup)
16
+ end
17
+
18
+ it 'should start with a blank list' do
19
+ expect(commander.commands).to be_empty
20
+ end
21
+
22
+ it 'should add a subclass command to the list of installed Command' do
23
+ class Warp::Dir::Command::MyCommand < Warp::Dir::Command; def run; end; end
24
+ expect(commander.installed_commands).to eql([:mycommand])
25
+ expect(commander.find :mycommand).to eql(Warp::Dir::Command::MyCommand)
26
+ end
27
+
28
+ it 'should be possible to lookup the command by alias' do
29
+ class Warp::Dir::Command::CommandWithAlias < Warp::Dir::Command
30
+ aliases :with_alias, :without_alias
31
+ def run;
32
+ end;
33
+ end
34
+
35
+ expect(commander.installed_commands).to eql([:commandwithalias])
36
+ expect(commander.find :commandwithalias).to eql(Warp::Dir::Command::CommandWithAlias)
37
+ expect(commander.find :with_alias).to eql(Warp::Dir::Command::CommandWithAlias)
38
+ expect(commander.find :without_alias).to eql(Warp::Dir::Command::CommandWithAlias)
39
+
40
+ expect { commander.find :boo }.to raise_error Warp::Dir::Errors::InvalidCommand
41
+ end
42
+
43
+
44
+ describe '#validate!' do
45
+ it 'should raise exception when subclass command does not have a #run method ' do
46
+ class Warp::Dir::Command::Random < Warp::Dir::Command;
47
+ end
48
+ expect(commander.commands).to include(Warp::Dir::Command::Random)
49
+ expect { commander.send(:validate!) }.to raise_error(Warp::Dir::Errors::InvalidCommand)
50
+ end
51
+
52
+ it 'should not quietly remove any abstract classes ' do
53
+ class Warp::Dir::Command::Random < Warp::Dir::Command
54
+ def abstract_class?;
55
+ true;
56
+ end
57
+ end
58
+ expect(commander.commands).to eql(Set.new)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+ require 'warp/dir/store'
3
+
4
+ RSpec.describe Warp::Dir::Command::Add do
5
+ include_context :fake_serializer
6
+
7
+ let(:store) { double }
8
+ let(:command_class) { Warp::Dir::Command::Add }
9
+ let(:commander) { Warp::Dir::Commander.instance }
10
+
11
+ let(:wp_path) { ENV['HOME'] + '/workspace/tinker-mania' }
12
+ let(:wp_name) { 'harro' }
13
+ let(:point) { Warp::Dir::Point.new(wp_name, wp_path) }
14
+
15
+ let(:add_command) { command_class.new(store, wp_name, wp_path) }
16
+
17
+ before do
18
+ expect(store).to receive(:config).and_return(config).at_least(:once)
19
+ end
20
+
21
+ it 'should have the commander defined' do
22
+ expect(add_command.store).to_not be_nil
23
+ end
24
+
25
+ describe '#help' do
26
+ it 'should define a help message' do
27
+ expect(add_command.command_name).to eql(:add)
28
+ expect(add_command.description).to match(%r(Adds the current directory)i)
29
+ expect(add_command.help).to match /add/
30
+ expect(add_command.help).to match /Adds the current directory/
31
+ end
32
+ end
33
+
34
+ describe '#run' do
35
+ it 'should call #save! on store after adding new wp' do
36
+ expect(store).to receive(:insert).with(point_name: wp_name, point_path: wp_path, overwrite: false).and_return(point)
37
+ add_command.run
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require 'support/cli_expectations'
3
+ require 'warp/dir/formatter'
4
+
5
+ RSpec.describe Warp::Dir::Command::Install do
6
+
7
+ let(:commander) { Warp::Dir.commander }
8
+ let(:install) { Warp::Dir::Command::Install.new(store) }
9
+
10
+ describe '#run' do
11
+ include_context :fixture_file
12
+ include_context :initialized_store
13
+
14
+ context 'when shell files do not exist' do
15
+ it 'should return :error type response' do
16
+ expect('install --dotfile ~/.do_not_exist').to output(/not found/)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+ require 'warp/dir/formatter'
3
+
4
+ RSpec.describe Warp::Dir::Command::List do
5
+
6
+ let(:commander) { Warp::Dir.commander }
7
+ let(:list) { Warp::Dir::Command::List }
8
+
9
+ describe '#help' do
10
+ it 'should define a help message' do
11
+ expect(list.help).to match /list/
12
+ expect(list.help).to match /Print all stored warp points/
13
+ end
14
+ end
15
+
16
+ describe '#run' do
17
+ include_context :fake_serializer
18
+ include_context :initialized_store
19
+
20
+ let(:formatter) { Warp::Dir::Formatter.new(store) }
21
+ let(:output) { formatter.format_store(:ascii) }
22
+ before do
23
+ store.add(point: point)
24
+ end
25
+
26
+ it 'should return formatted warp points from the store' do
27
+ expect(output).to eql(%Q{harro -> ~/workspace/tinker-mania})
28
+ end
29
+
30
+ it 'should return response and print the listing' do
31
+ response = list.new(store).run
32
+ expect(response.messages.first).to eql(output.blue.bold)
33
+ expect(STDOUT).to receive(:printf).at_least(1).times
34
+ response.print
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Warp::Dir::Config do
4
+ let(:c1) { Warp::Dir::Config.new(blah: 'blah blah') }
5
+
6
+ it 'should have a default folder' do
7
+ expect(c1.warprc).to eql(ENV['HOME'] + '/.warprc')
8
+ end
9
+
10
+ it 'should automatically create accessors' do
11
+ expect(c1.blah).to eql('blah blah')
12
+ end
13
+
14
+ it 'should add new parameter to the params array' do
15
+ expect(c1.variables).to eql([:warprc, :shell, :force, :debug, :blah])
16
+ end
17
+
18
+ it 'should be able to create a attr_writer also' do
19
+ c1.blah = 'another blah'
20
+ expect(c1.blah).to eql('another blah')
21
+ end
22
+
23
+ it 'should be possible to add a new value after instance was created' do
24
+ c1.new_field = 'really new here'
25
+ expect(c1.new_field?).to be_truthy
26
+ expect(c1.new_field).to eql('really new here')
27
+ end
28
+
29
+ describe 'when another instance of the config is created' do
30
+ let(:c2) { Warp::Dir::Config.new(poo: 'boo') }
31
+
32
+ it 'should only have one parameter for this class' do
33
+ expect(c1.respond_to?(:poo)).to be_falsey
34
+ expect(c2.respond_to?(:poo)).to be_truthy
35
+
36
+ expect(c1.respond_to?(:blah)).to be_truthy
37
+ expect(c2.respond_to?(:blah)).to be_falsey
38
+ end
39
+
40
+ it 'should add new parameter to the params array' do
41
+ expect(c2.variables).to eql([:warprc, :shell, :force, :debug, :poo])
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,16 @@
1
+ require 'warp/dir'
2
+ require 'spec_helper'
3
+
4
+ RSpec.describe Warp::Dir::Errors do
5
+ include_context :fake_serializer
6
+ include_context :initialized_store
7
+
8
+ it 'should properly throw point already exists error' do
9
+ expect(store.class).to eql(Warp::Dir::Store)
10
+ expect(point.class).to eql(Warp::Dir::Point)
11
+
12
+ store.add(point: point.dup)
13
+ point.full_path = '~/booomania'
14
+ expect { store.add(point: point) }.to raise_error(Warp::Dir::Errors::PointAlreadyExists)
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+ require 'warp/dir/formatter'
3
+
4
+ RSpec.describe Warp::Dir::Formatter do
5
+ include_context :initialized_store
6
+
7
+ let(:path_absolute) { ENV['HOME'] + '/workspace' }
8
+ let(:path_relative) { '~/workspace' }
9
+ let(:p1) { Warp::Dir::Point.new('p', ENV['HOME'] + '/workspace') }
10
+ let(:p2) { Warp::Dir::Point.new('n', ENV['HOME'] + '/workspace/new-project') }
11
+
12
+ describe 'with empty store' do
13
+ before do
14
+ store.add(p1)
15
+ store.add(p2)
16
+ end
17
+
18
+
19
+ # it '#map,#each' do
20
+ # expect(collection.map(&:formatted)).to eql([
21
+ # 'p -> ~/workspace',
22
+ # 'n -> ~/workspace/new-project'
23
+ # ])
24
+ # paths = []
25
+ # collection.each { |p| paths << p.relative_path }
26
+ # expect(paths).to eql(%w(~/workspace ~/workspace/new-project))
27
+ # end
28
+ # it '#:[]' do
29
+ # expect(collection[1]).to eql(p2)
30
+ # end
31
+ # it '#formatted' do
32
+ # expect(collection.formatted).to eql("n -> ~/workspace/new-project\np -> ~/workspace")
33
+ # end
34
+ # it '#formatted sorted' do
35
+ # expect(collection.formatted(:ascii, :path)).to eql("p -> ~/workspace\nn -> ~/workspace/new-project")
36
+ # end
37
+ end
38
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+ require 'warp/dir'
3
+
4
+ RSpec.describe Warp::Dir::Point do
5
+ include_context :fake_serializer
6
+ include_context :initialized_store
7
+
8
+ let(:path_absolute) { ENV['HOME'] + '/workspace' }
9
+ let(:path_relative) { '~/workspace' }
10
+ let(:p1) { Warp::Dir::Point.new('p', ENV['HOME'] + '/workspace') }
11
+ let(:p2) { Warp::Dir::Point.new('n', ENV['HOME'] + '/workspace/new-project') }
12
+
13
+ describe 'with two distinct but identical objects' do
14
+ let(:p2) { Warp::Dir::Point.new('p', ENV['HOME'] + '/workspace') }
15
+ it 'correctly defines #eql?' do
16
+ expect(p1).to eql(p2)
17
+ end
18
+ it 'correctly defines #hash' do
19
+ expect(p1.hash).to eql(p2.hash)
20
+ end
21
+ it '#file.path' do
22
+ expect(file.path.length > 0).to be_truthy
23
+ end
24
+ end
25
+
26
+ describe 'instance methods' do
27
+ it '#to_s' do
28
+ expect(p1.to_s).to eql('p -> ~/workspace')
29
+ end
30
+ it '#inspect' do
31
+ expect(p1.inspect).to match(%r{name: '#{p1.name}', path: '#{p1.relative_path}'})
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,105 @@
1
+ require 'spec_helper'
2
+ require 'warp/dir'
3
+ require 'warp/dir/config'
4
+ require 'warp/dir/store'
5
+ require 'tempfile'
6
+
7
+ RSpec.describe Warp::Dir::Store do
8
+ include_context :fake_serializer
9
+ include_context :initialized_store
10
+
11
+ context 'when store responds to common methods on collections' do
12
+ let(:point_name) { 'moo' }
13
+ let(:point_path) { ENV['HOME'] + '/tmp/12398485' }
14
+ let(:store) { Warp::Dir::Store.new(config) }
15
+ let(:p1) { Warp::Dir::Point.new('p', ENV['HOME'] + '/workspace') }
16
+ let(:p2) { Warp::Dir::Point.new('n', ENV['HOME'] + '/workspace/new-project') }
17
+
18
+ it 'should be able to have an empty store' do
19
+ expect(store.points).to be_empty
20
+ end
21
+
22
+ it 'should respond to #size and return 0' do
23
+ expect(store.size).to eql(0)
24
+ end
25
+
26
+ it 'it should respond to #<< and add a new point' do
27
+ store.add(point: p1)
28
+ store.add(point: p2)
29
+ store << Warp::Dir::Point.new('123', '436')
30
+ expect(store.size).to eql(3)
31
+ end
32
+ end
33
+
34
+ context 'when the data storeis empty' do
35
+ let(:point_name) { 'moo' }
36
+ let(:point_path) { ENV['HOME'] + '/tmp/12398485' }
37
+ let(:store) { Warp::Dir::Store.new(config) }
38
+
39
+ it 'should be able to initialize the Store' do
40
+ expect(store.points).to be_empty
41
+ end
42
+
43
+ it 'should respond to #size and return 0' do
44
+ expect(store.size).to eql(0)
45
+ end
46
+
47
+ it 'it should respond to #<< and add a new point' do
48
+ expect(store.size).to eql(0)
49
+ store << Warp::Dir::Point.new('123', '436')
50
+ expect(store.size).to eql(1)
51
+ end
52
+
53
+ it 'should be able to add a new point to the Store' do
54
+ store.add(point_name: point_name, point_path: point_path)
55
+ corrected_path = Warp::Dir.absolute point_path
56
+ expect(store[point_name].path).to eql(corrected_path)
57
+ end
58
+
59
+ it 'should not be able to add a different point with the same name' do
60
+ store.add(point_name: point_name, point_path: point_path)
61
+ # double adding the same point is ok
62
+ expect { store.add(point_name: point_name, point_path: point_path) }.to_not raise_error
63
+ # adding another point pointing to the same name is not OK
64
+ expect { store.add(point_name: point_name, point_path: point_path + '98984') }.to raise_error(Warp::Dir::Errors::PointAlreadyExists)
65
+ end
66
+
67
+ it 'should be able to add multiple points to the Store' do
68
+ store.add(point_name: 'm1', point_path: '123')
69
+ store.add(point_name: 'm2', point_path: '456')
70
+ expect(store['m1'].path).to eql('123')
71
+ expect(store['m2'].path).to eql('456')
72
+ end
73
+ end
74
+
75
+ context 'data store contains some warp points already' do
76
+ let(:store) { Warp::Dir::Store.new(config) }
77
+ before do
78
+ store.add(point_name: 'm1', point_path: 'A1')
79
+ store.add(point_name: 'm2', point_path: 'A2')
80
+ store.save!
81
+ end
82
+
83
+ describe 'reading data' do
84
+ let(:new_store) { Warp::Dir::Store.new(config) }
85
+
86
+ it 'should restore correctly compared to last saved' do
87
+ expect(new_store['m1'].path).to eql('A1')
88
+ expect(new_store['m2'].path).to eql('A2')
89
+ end
90
+
91
+ it 'should not allow overwriting without a force flag' do
92
+ # adding another point pointing to the same name is not OK
93
+ expect { new_store.add(point_name: 'm1', point_path: '98984') }.to raise_error(Warp::Dir::Errors::PointAlreadyExists)
94
+ end
95
+
96
+ it 'should be able to find previously saved item' do
97
+ expect(new_store['m1']).to eql(Warp::Dir::Point.new('m1', 'A1'))
98
+ end
99
+
100
+ it 'should be able to handle when it doesnt find a given element' do
101
+ expect { new_store['ASDSADAS'] }.to raise_error(Warp::Dir::Errors::PointNotFound)
102
+ end
103
+ end
104
+ end
105
+ end