droxi 0.0.0 → 0.0.1
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 +4 -4
- data/LICENSE +19 -0
- data/README.md +21 -0
- data/Rakefile +56 -0
- data/droxi.1.template +9 -0
- data/droxi.gemspec +18 -0
- data/lib/droxi.rb +10 -3
- data/lib/droxi/commands.rb +15 -4
- data/lib/droxi/state.rb +2 -1
- data/spec/all.rb +4 -0
- data/spec/commands_spec.rb +206 -0
- data/spec/settings_spec.rb +56 -0
- data/spec/state_spec.rb +51 -0
- metadata +25 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e5303c28f4ee1e364769a554be98314b4c3c953
|
4
|
+
data.tar.gz: 5170d5affcbf11282c0a2c8e305c0c553ca961b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 335e2e4caa00193fb73a0f912ac819ba23b677ba42bb0185de8a143fc7fdb98bf9c5d51724df7ef7da4bd238b231e052f13b686ea17c52f0da4960a947aef294
|
7
|
+
data.tar.gz: ea91d29b4b67e3384f3605bb884f4ea07edb828bf6fac7e3c084d6e7320af748c9af878f378330dfd5b81cec1a92c4bd0f0a8f07113be46a61f65f6f4751d040
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2014 Brandon Mulcahy
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
droxi
|
2
|
+
=====
|
3
|
+
|
4
|
+
ftp-like command-line [Dropbox](https://www.dropbox.com/home) interface in
|
5
|
+
[Ruby](https://www.ruby-lang.org/en/)
|
6
|
+
|
7
|
+
installation
|
8
|
+
------------
|
9
|
+
|
10
|
+
gem install droxi
|
11
|
+
|
12
|
+
features
|
13
|
+
--------
|
14
|
+
|
15
|
+
- interface inspired by
|
16
|
+
[GNU coreutils](http://www.gnu.org/software/coreutils/),
|
17
|
+
[GNU ftp](http://www.gnu.org/software/inetutils/), and
|
18
|
+
[lftp](http://lftp.yar.ru/)
|
19
|
+
- context-sensitive tab completion and path globbing
|
20
|
+
- upload, download, and share files
|
21
|
+
- man page and interactive help
|
data/Rakefile
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
task :default => :test
|
2
|
+
|
3
|
+
desc 'run unit tests'
|
4
|
+
task :test do
|
5
|
+
sh 'ruby spec/all.rb'
|
6
|
+
end
|
7
|
+
|
8
|
+
desc 'run program'
|
9
|
+
task :run do
|
10
|
+
require_relative 'lib/droxi'
|
11
|
+
Droxi.run
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'install gem'
|
15
|
+
task :gem do
|
16
|
+
sh 'rm *.gem'
|
17
|
+
sh 'gem build droxi.gemspec'
|
18
|
+
sh 'gem install ./droxi-*.gem'
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'install man page (must have root permissions)'
|
22
|
+
task :man do
|
23
|
+
gemspec = IO.read('droxi.gemspec')
|
24
|
+
|
25
|
+
def date(gemspec)
|
26
|
+
require 'time'
|
27
|
+
Time.parse(/\d{4}-\d{2}-\d{2}/.match(gemspec)[0]).strftime('%B %Y')
|
28
|
+
end
|
29
|
+
|
30
|
+
def commands
|
31
|
+
require_relative 'lib/droxi/commands'
|
32
|
+
Commands::NAMES.sort.map do |name|
|
33
|
+
cmd = Commands.const_get(name.upcase.to_sym)
|
34
|
+
".TP\n#{cmd.usage}\n#{cmd.description}\n"
|
35
|
+
end.join.strip
|
36
|
+
end
|
37
|
+
|
38
|
+
contents = IO.read('droxi.1.template').
|
39
|
+
sub('{date}', date(gemspec)).
|
40
|
+
sub('{version}', /\d+\.\d+\.\d+/.match(gemspec)[0]).
|
41
|
+
sub('{commands}', commands)
|
42
|
+
|
43
|
+
Dir.mkdir('build') unless Dir.exists?('build')
|
44
|
+
IO.write('build/droxi.1', contents)
|
45
|
+
|
46
|
+
prefix = ENV['PREFIX'] || ENV['prefix'] || '/usr/local'
|
47
|
+
install_path = "#{prefix}/share/man/man1"
|
48
|
+
|
49
|
+
require 'fileutils'
|
50
|
+
begin
|
51
|
+
FileUtils.mkdir_p(install_path)
|
52
|
+
FileUtils.cp('build/droxi.1', install_path)
|
53
|
+
rescue
|
54
|
+
puts 'Failed to install man page. This target must be run as root.'
|
55
|
+
end
|
56
|
+
end
|
data/droxi.1.template
ADDED
data/droxi.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'droxi'
|
3
|
+
s.version = '0.0.1'
|
4
|
+
s.date = '2014-06-02'
|
5
|
+
s.summary = 'ftp-like command-line interface to Dropbox'
|
6
|
+
s.description = "a command-line Dropbox interface inspired by GNU \
|
7
|
+
coreutils, GNU ftp, and lftp. features smart tab \
|
8
|
+
completion, globbing, and interactive help.".squeeze(' ')
|
9
|
+
s.authors = ['Brandon Mulcahy']
|
10
|
+
s.email = 'brandon@jangler.info'
|
11
|
+
s.files = `git ls-files`.split
|
12
|
+
s.homepage = 'https://github.com/jangler/droxi'
|
13
|
+
s.license = 'MIT'
|
14
|
+
|
15
|
+
s.executables << 'droxi'
|
16
|
+
s.add_runtime_dependency 'dropbox-sdk', '~> 1.6', '>= 1.6.1'
|
17
|
+
s.required_ruby_version = '>= 2.0.0'
|
18
|
+
end
|
data/lib/droxi.rb
CHANGED
@@ -19,7 +19,13 @@ module Droxi
|
|
19
19
|
puts '2. Click "Allow" (you might have to log in first)'
|
20
20
|
puts '3. Copy the authorization code'
|
21
21
|
print 'Enter the authorization code here: '
|
22
|
-
code = gets
|
22
|
+
code = $stdin.gets
|
23
|
+
if code
|
24
|
+
code.strip!
|
25
|
+
else
|
26
|
+
puts
|
27
|
+
exit
|
28
|
+
end
|
23
29
|
|
24
30
|
# This will fail if the user gave us an invalid authorization code
|
25
31
|
begin
|
@@ -128,10 +134,11 @@ module Droxi
|
|
128
134
|
end
|
129
135
|
|
130
136
|
begin
|
131
|
-
while
|
137
|
+
while !state.exit_requested &&
|
138
|
+
line = Readline.readline(prompt(info, state), true)
|
132
139
|
Commands.exec(line.chomp, client, state)
|
133
140
|
end
|
134
|
-
puts
|
141
|
+
puts if !line
|
135
142
|
rescue Interrupt
|
136
143
|
puts
|
137
144
|
end
|
data/lib/droxi/commands.rb
CHANGED
@@ -25,7 +25,9 @@ module Commands
|
|
25
25
|
def num_args_ok?(num_args)
|
26
26
|
args = @usage.split.drop(1)
|
27
27
|
min_args = args.reject { |arg| arg.start_with?('[') }.length
|
28
|
-
if args.
|
28
|
+
if args.empty?
|
29
|
+
max_args = 0
|
30
|
+
elsif args.last.end_with?('...')
|
29
31
|
max_args = num_args
|
30
32
|
else
|
31
33
|
max_args = args.length
|
@@ -62,6 +64,14 @@ module Commands
|
|
62
64
|
end
|
63
65
|
)
|
64
66
|
|
67
|
+
EXIT = Command.new(
|
68
|
+
'exit',
|
69
|
+
"Exit the program.",
|
70
|
+
lambda do |client, state, args, output|
|
71
|
+
state.exit_requested = true
|
72
|
+
end
|
73
|
+
)
|
74
|
+
|
65
75
|
GET = Command.new(
|
66
76
|
'get REMOTE_FILE...',
|
67
77
|
"Download each specified remote file to a file of the same name in the \
|
@@ -220,9 +230,10 @@ module Commands
|
|
220
230
|
|
221
231
|
SHARE = Command.new(
|
222
232
|
'share REMOTE_FILE...',
|
223
|
-
"
|
224
|
-
|
225
|
-
|
233
|
+
"Create Dropbox links to publicly share remote files. The links are \
|
234
|
+
shortened and direct to 'preview' pages of the files. Links created by \
|
235
|
+
this method are set to expire far enough in the future so that \
|
236
|
+
expiration is effectively not an issue.",
|
226
237
|
lambda do |client, state, args, output|
|
227
238
|
state.expand_patterns(client, args).each do |path|
|
228
239
|
begin
|
data/lib/droxi/state.rb
CHANGED
@@ -2,13 +2,14 @@ require_relative 'settings'
|
|
2
2
|
|
3
3
|
class State
|
4
4
|
attr_reader :oldpwd, :pwd, :cache
|
5
|
-
attr_accessor :local_oldpwd
|
5
|
+
attr_accessor :local_oldpwd, :exit_requested
|
6
6
|
|
7
7
|
def initialize
|
8
8
|
@pwd = '/'
|
9
9
|
@oldpwd = Settings[:oldpwd] || '/'
|
10
10
|
@local_oldpwd = Dir.pwd
|
11
11
|
@cache = {}
|
12
|
+
@exit_requested = false
|
12
13
|
end
|
13
14
|
|
14
15
|
def have_all_info_for(path)
|
data/spec/all.rb
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
require 'dropbox_sdk'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
require_relative '../lib/droxi/commands'
|
5
|
+
require_relative '../lib/droxi/settings'
|
6
|
+
require_relative '../lib/droxi/state'
|
7
|
+
|
8
|
+
def ignore(error_class)
|
9
|
+
begin
|
10
|
+
yield
|
11
|
+
rescue error_class
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def put_temp_file(client, state)
|
16
|
+
`echo hello > #{TEMP_FILENAME}`
|
17
|
+
open(TEMP_FILENAME, 'rb') do |file|
|
18
|
+
Commands::PUT.exec(client, state, TEMP_FILENAME,
|
19
|
+
"/#{TEST_FOLDER}/#{TEMP_FILENAME}")
|
20
|
+
end
|
21
|
+
`rm #{TEMP_FILENAME}`
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete_temp_file(client, state)
|
25
|
+
Commands::RM.exec(client, state, "/#{TEST_FOLDER}/#{TEMP_FILENAME}")
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_output(cmd, client, state, *args)
|
29
|
+
lines = []
|
30
|
+
Commands.const_get(cmd).exec(client, state, *args) { |line| lines << line }
|
31
|
+
lines
|
32
|
+
end
|
33
|
+
|
34
|
+
describe Commands do
|
35
|
+
original_dir = Dir.pwd
|
36
|
+
|
37
|
+
client = DropboxClient.new(Settings[:access_token])
|
38
|
+
state = State.new
|
39
|
+
|
40
|
+
TEMP_FILENAME = 'test.txt'
|
41
|
+
TEMP_FOLDER = 'test'
|
42
|
+
TEST_FOLDER = 'testing'
|
43
|
+
|
44
|
+
ignore(DropboxError) { client.file_delete("/#{TEST_FOLDER}") }
|
45
|
+
ignore(DropboxError) { client.file_create_folder("/#{TEST_FOLDER}") }
|
46
|
+
|
47
|
+
describe 'when executing a shell command' do
|
48
|
+
it 'must yield the output' do
|
49
|
+
lines = []
|
50
|
+
Commands.shell('echo testing') { |line| lines << line }
|
51
|
+
lines.must_equal(['testing'])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'when executing the cd command' do
|
56
|
+
it 'must change to the root directory when given no args' do
|
57
|
+
state.pwd = '/testing'
|
58
|
+
Commands::CD.exec(client, state)
|
59
|
+
state.pwd.must_equal '/'
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'must change to the previous directory when given -' do
|
63
|
+
state.pwd = '/testing'
|
64
|
+
state.pwd = '/'
|
65
|
+
Commands::CD.exec(client, state, '-')
|
66
|
+
state.pwd.must_equal '/testing'
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'must change to the stated directory when given 1 arg' do
|
70
|
+
state.pwd = '/'
|
71
|
+
Commands::CD.exec(client, state, '/testing')
|
72
|
+
state.pwd.must_equal '/testing'
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'must set previous directory correctly' do
|
76
|
+
state.pwd = '/testing'
|
77
|
+
state.pwd = '/'
|
78
|
+
Commands::CD.exec(client, state, '/testing')
|
79
|
+
state.oldpwd.must_equal '/'
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'must not change to a bogus directory' do
|
83
|
+
state.pwd = '/'
|
84
|
+
Commands::CD.exec(client, state, '/bogus_dir')
|
85
|
+
state.pwd.must_equal '/'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'when executing the get command' do
|
90
|
+
it 'must get a file of the same name when given args' do
|
91
|
+
Dir.chdir(original_dir)
|
92
|
+
put_temp_file(client, state)
|
93
|
+
Commands::GET.exec(client, state, '/testing/test.txt')
|
94
|
+
delete_temp_file(client, state)
|
95
|
+
`ls test.txt`.chomp.must_equal 'test.txt'
|
96
|
+
`rm test.txt`
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe 'when executing the lcd command' do
|
101
|
+
it 'must change to home directory when given no args' do
|
102
|
+
Dir.chdir(original_dir)
|
103
|
+
Commands::LCD.exec(client, state)
|
104
|
+
Dir.pwd.must_equal File.expand_path('~')
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'must change to specific directory when specified' do
|
108
|
+
Dir.chdir(original_dir)
|
109
|
+
Commands::LCD.exec(client, state, '/home')
|
110
|
+
Dir.pwd.must_equal File.expand_path('/home')
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'must set oldpwd correctly' do
|
114
|
+
Dir.chdir(original_dir)
|
115
|
+
oldpwd = Dir.pwd
|
116
|
+
Commands::LCD.exec(client, state, '/')
|
117
|
+
state.local_oldpwd.must_equal oldpwd
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'must change to previous directory when given -' do
|
121
|
+
Dir.chdir(original_dir)
|
122
|
+
oldpwd = Dir.pwd
|
123
|
+
Commands::LCD.exec(client, state, '/')
|
124
|
+
Commands::LCD.exec(client, state, '-')
|
125
|
+
Dir.pwd.must_equal oldpwd
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'must fail if given bogus directory name' do
|
129
|
+
Dir.chdir(original_dir)
|
130
|
+
pwd = Dir.pwd
|
131
|
+
oldpwd = state.local_oldpwd
|
132
|
+
Commands::LCD.exec(client, state, '/bogus_dir')
|
133
|
+
Dir.pwd.must_equal pwd
|
134
|
+
state.local_oldpwd.must_equal oldpwd
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe 'when executing the ls command' do
|
139
|
+
it 'must list the working directory contents when given no args' do
|
140
|
+
Commands::MKDIR.exec(client, state, '/testing/test')
|
141
|
+
state.pwd = '/testing'
|
142
|
+
lines = []
|
143
|
+
Commands::LS.exec(client, state) { |line| lines << line }
|
144
|
+
lines.must_equal(['test '])
|
145
|
+
Commands::RM.exec(client, state, '/testing/test')
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'must list the stated directory contents when given args' do
|
149
|
+
state.pwd = '/'
|
150
|
+
Commands::MKDIR.exec(client, state, '/testing/test')
|
151
|
+
lines = []
|
152
|
+
Commands::LS.exec(client, state, '/testing') { |line| lines << line }
|
153
|
+
lines.must_equal(['test '])
|
154
|
+
Commands::RM.exec(client, state, '/testing/test')
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe 'when executing the mkdir command' do
|
159
|
+
it 'must create a directory when given args' do
|
160
|
+
Commands::MKDIR.exec(client, state, '/testing/test')
|
161
|
+
client.metadata('/testing/test')['is_deleted'].wont_equal true
|
162
|
+
Commands::RM.exec(client, state, '/testing/test')
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe 'when executing the put command' do
|
167
|
+
it 'must put a file of the same name when given 1 arg' do
|
168
|
+
Dir.chdir(original_dir)
|
169
|
+
state.pwd = '/testing'
|
170
|
+
`echo hello > test.txt`
|
171
|
+
Commands::PUT.exec(client, state, 'test.txt')
|
172
|
+
`rm test.txt`
|
173
|
+
client.metadata('/testing/test.txt')['is_deleted'].wont_equal true
|
174
|
+
Commands::RM.exec(client, state, '/testing/test.txt')
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'must put a file with the stated name when given 2 args' do
|
178
|
+
Dir.chdir(original_dir)
|
179
|
+
state.pwd = '/testing'
|
180
|
+
`echo hello > test.txt`
|
181
|
+
Commands::PUT.exec(client, state, 'test.txt', 'dest.txt')
|
182
|
+
`rm test.txt`
|
183
|
+
client.metadata('/testing/dest.txt')['is_deleted'].wont_equal true
|
184
|
+
Commands::RM.exec(client, state, '/testing/dest.txt')
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
describe 'when executing the share command' do
|
189
|
+
it 'must yield URL when given file path' do
|
190
|
+
put_temp_file(client, state)
|
191
|
+
to_path = "/#{TEST_FOLDER}/#{TEMP_FILENAME}"
|
192
|
+
lines = get_output(:SHARE, client, state, to_path)
|
193
|
+
delete_temp_file(client, state)
|
194
|
+
lines.length.must_equal 1
|
195
|
+
/https:\/\/.+\..+\//.match(lines[0]).wont_equal nil
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe 'when executing the rm command' do
|
200
|
+
it 'must remove the remote file when given args' do
|
201
|
+
Commands::MKDIR.exec(client, state, '/testing/test')
|
202
|
+
Commands::RM.exec(client, state, '/testing/test')
|
203
|
+
client.metadata('/testing/test')['is_deleted'].must_equal true
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
require_relative '../lib/droxi/settings'
|
4
|
+
|
5
|
+
describe Settings do
|
6
|
+
KEY, VALUE = :test_key, :test_value
|
7
|
+
|
8
|
+
describe 'when attempting access with a bogus key' do
|
9
|
+
it 'must return nil' do
|
10
|
+
Settings.delete(KEY)
|
11
|
+
Settings[KEY].must_equal nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'when attempting access with a valid key' do
|
16
|
+
it 'must return the associated value' do
|
17
|
+
Settings[KEY] = VALUE
|
18
|
+
Settings[KEY].must_equal VALUE
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'when assigning a value to a key' do
|
23
|
+
it 'must assign the value to the key and return the value' do
|
24
|
+
Settings.delete(KEY)
|
25
|
+
(Settings[KEY] = VALUE).must_equal VALUE
|
26
|
+
Settings[KEY].must_equal VALUE
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'when deleting a bogus key' do
|
31
|
+
it 'must return nil' do
|
32
|
+
Settings.delete(KEY)
|
33
|
+
Settings.delete(KEY).must_equal nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'when deleting a valid key' do
|
38
|
+
it 'must delete the key and return the associated value' do
|
39
|
+
Settings[KEY] = VALUE
|
40
|
+
Settings.delete(KEY).must_equal VALUE
|
41
|
+
Settings[KEY].must_equal nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'when checking inclusion of a key' do
|
46
|
+
it 'must return true for valid keys' do
|
47
|
+
Settings[KEY] = VALUE
|
48
|
+
Settings.include?(KEY).must_equal true
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'must return false for bogus keys' do
|
52
|
+
Settings.delete(KEY)
|
53
|
+
Settings.include?(KEY).must_equal false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/spec/state_spec.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
require_relative '../lib/droxi/state'
|
4
|
+
require_relative '../lib/droxi/settings'
|
5
|
+
|
6
|
+
describe State do
|
7
|
+
describe 'when initializing' do
|
8
|
+
it 'must set pwd to root' do
|
9
|
+
State.new.pwd.must_equal '/'
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'must set oldpwd to saved oldpwd' do
|
13
|
+
if Settings.include?(:oldpwd)
|
14
|
+
State.new.oldpwd.must_equal Settings[:oldpwd]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'when setting pwd' do
|
20
|
+
it 'must change pwd and set oldpwd to previous pwd' do
|
21
|
+
state = State.new
|
22
|
+
state.pwd = '/testing'
|
23
|
+
state.pwd.must_equal '/testing'
|
24
|
+
state.pwd = '/'
|
25
|
+
state.oldpwd.must_equal '/testing'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'when resolving path' do
|
30
|
+
state = State.new
|
31
|
+
|
32
|
+
it 'must resolve root to itself' do
|
33
|
+
state.resolve_path('/').must_equal '/'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'must resolve qualified path to itself' do
|
37
|
+
state.pwd = '/alpha'
|
38
|
+
state.resolve_path('/beta').must_equal '/beta'
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'must resolve unqualified path to relative path' do
|
42
|
+
state.pwd = '/alpha'
|
43
|
+
state.resolve_path('beta').must_equal '/alpha/beta'
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'must resolve .. to upper directory' do
|
47
|
+
state.pwd = '/alpha/beta/gamma'
|
48
|
+
state.resolve_path('../..').must_equal '/alpha'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
metadata
CHANGED
@@ -1,41 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: droxi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandon Mulcahy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: dropbox-sdk
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
17
20
|
- - ">="
|
18
21
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
20
|
-
type: :
|
22
|
+
version: 1.6.1
|
23
|
+
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.6'
|
24
30
|
- - ">="
|
25
31
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
27
|
-
description:
|
32
|
+
version: 1.6.1
|
33
|
+
description: a command-line Dropbox interface inspired by GNU coreutils, GNU ftp,
|
34
|
+
and lftp. features smart tab completion, globbing, and interactive help.
|
28
35
|
email: brandon@jangler.info
|
29
36
|
executables:
|
30
37
|
- droxi
|
31
38
|
extensions: []
|
32
39
|
extra_rdoc_files: []
|
33
40
|
files:
|
41
|
+
- LICENSE
|
42
|
+
- README.md
|
43
|
+
- Rakefile
|
34
44
|
- bin/droxi
|
45
|
+
- droxi.1.template
|
46
|
+
- droxi.gemspec
|
35
47
|
- lib/droxi.rb
|
36
48
|
- lib/droxi/commands.rb
|
37
49
|
- lib/droxi/settings.rb
|
38
50
|
- lib/droxi/state.rb
|
51
|
+
- spec/all.rb
|
52
|
+
- spec/commands_spec.rb
|
53
|
+
- spec/settings_spec.rb
|
54
|
+
- spec/state_spec.rb
|
39
55
|
homepage: https://github.com/jangler/droxi
|
40
56
|
licenses:
|
41
57
|
- MIT
|
@@ -48,7 +64,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
48
64
|
requirements:
|
49
65
|
- - ">="
|
50
66
|
- !ruby/object:Gem::Version
|
51
|
-
version:
|
67
|
+
version: 2.0.0
|
52
68
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
69
|
requirements:
|
54
70
|
- - ">="
|
@@ -59,5 +75,5 @@ rubyforge_project:
|
|
59
75
|
rubygems_version: 2.2.2
|
60
76
|
signing_key:
|
61
77
|
specification_version: 4
|
62
|
-
summary:
|
78
|
+
summary: ftp-like command-line interface to Dropbox
|
63
79
|
test_files: []
|