rb1drv-tools 0.0.0placeholder → 0.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 +4 -4
- data/.gitignore +11 -0
- data/.travis.yml +4 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +66 -0
- data/README.md +23 -1
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/1d +8 -0
- data/lib/rb1drv-tools.rb +13 -0
- data/lib/rb1drv-tools/cli.rb +73 -0
- data/lib/rb1drv-tools/command/cd.rb +15 -0
- data/lib/rb1drv-tools/command/common.rb +17 -0
- data/lib/rb1drv-tools/command/help.rb +72 -0
- data/lib/rb1drv-tools/command/info.rb +24 -0
- data/lib/rb1drv-tools/command/ls.rb +47 -0
- data/lib/rb1drv-tools/command/profile.rb +63 -0
- data/lib/rb1drv-tools/command/upload.rb +138 -0
- data/lib/rb1drv-tools/profile.rb +82 -0
- data/lib/rb1drv-tools/utils.rb +64 -0
- data/lib/rb1drv-tools/version.rb +1 -1
- data/rb1drv-tools.gemspec +5 -1
- metadata +68 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ce495e7400324adf72beecc7e7b9ecc99e2b4be30c7493a5a4c9eed5285d7a07
|
4
|
+
data.tar.gz: 885f0b728020e2850f027448e46d87d227d00c8dbae6437c3aabaa399ea534e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3db17c8b96ba1401ca2672b4dd2abd2b5faa955b158a291400e34879895660ec858f6c6d858ba40bf74959ba28ce668c3e733771806281e2e9bc7fd2bfde3ac1
|
7
|
+
data.tar.gz: 5e7bd497cd1f661511f62a8aff8b9ac2bf99483121999977cbc94be68ae3f47f1fd7de94f1e60b78b6454e74d37a9fe01bac17298041ab0acb82fa598dd82603
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
rb1drv-tools (0.1.0)
|
5
|
+
rb1drv (~> 0.1)
|
6
|
+
tty-progressbar (~> 0)
|
7
|
+
tty-prompt (~> 0)
|
8
|
+
tty-screen (~> 0)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
equatable (0.5.0)
|
14
|
+
excon (0.62.0)
|
15
|
+
faraday (0.12.2)
|
16
|
+
multipart-post (>= 1.2, < 3)
|
17
|
+
hitimes (1.2.6)
|
18
|
+
jwt (1.5.6)
|
19
|
+
multi_json (1.13.1)
|
20
|
+
multi_xml (0.6.0)
|
21
|
+
multipart-post (2.0.0)
|
22
|
+
necromancer (0.4.0)
|
23
|
+
oauth2 (1.4.0)
|
24
|
+
faraday (>= 0.8, < 0.13)
|
25
|
+
jwt (~> 1.0)
|
26
|
+
multi_json (~> 1.3)
|
27
|
+
multi_xml (~> 0.5)
|
28
|
+
rack (>= 1.2, < 3)
|
29
|
+
pastel (0.7.2)
|
30
|
+
equatable (~> 0.5.0)
|
31
|
+
tty-color (~> 0.4.0)
|
32
|
+
rack (2.0.5)
|
33
|
+
rake (10.5.0)
|
34
|
+
rb1drv (0.1.4)
|
35
|
+
excon (~> 0.62)
|
36
|
+
oauth2 (~> 1.4)
|
37
|
+
timers (4.1.2)
|
38
|
+
hitimes
|
39
|
+
tty-color (0.4.2)
|
40
|
+
tty-cursor (0.5.0)
|
41
|
+
tty-progressbar (0.14.0)
|
42
|
+
tty-cursor (~> 0.5.0)
|
43
|
+
tty-screen (~> 0.6.4)
|
44
|
+
tty-prompt (0.16.1)
|
45
|
+
necromancer (~> 0.4.0)
|
46
|
+
pastel (~> 0.7.0)
|
47
|
+
timers (~> 4.0)
|
48
|
+
tty-cursor (~> 0.5.0)
|
49
|
+
tty-reader (~> 0.3.0)
|
50
|
+
tty-reader (0.3.0)
|
51
|
+
tty-cursor (~> 0.5.0)
|
52
|
+
tty-screen (~> 0.6.4)
|
53
|
+
wisper (~> 2.0.0)
|
54
|
+
tty-screen (0.6.4)
|
55
|
+
wisper (2.0.0)
|
56
|
+
|
57
|
+
PLATFORMS
|
58
|
+
ruby
|
59
|
+
|
60
|
+
DEPENDENCIES
|
61
|
+
bundler (~> 1.16)
|
62
|
+
rake (~> 10.0)
|
63
|
+
rb1drv-tools!
|
64
|
+
|
65
|
+
BUNDLED WITH
|
66
|
+
1.16.1
|
data/README.md
CHANGED
@@ -1 +1,23 @@
|
|
1
|
-
# Rb1drv-
|
1
|
+
# Rb1drv-Tools
|
2
|
+
|
3
|
+
[](https://travis-ci.org/msg7086/rb1drv-tools)
|
4
|
+
|
5
|
+
Rb1drv-tools provides basic file operations on OneDrive.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Install it yourself as:
|
10
|
+
|
11
|
+
$ gem install rb1drv-tools --no-ri
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
TODO: Write usage instructions here
|
16
|
+
|
17
|
+
## Contributing
|
18
|
+
|
19
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/msg7086/rb1drv-tools.
|
20
|
+
|
21
|
+
## License
|
22
|
+
|
23
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "rb1drv/tools"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/exe/1d
ADDED
data/lib/rb1drv-tools.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
module Rb1drvTools
|
2
|
+
class CLI
|
3
|
+
CLI_DELIMITER = '-,-'
|
4
|
+
def initialize(*args)
|
5
|
+
CLI.set_od(*args)
|
6
|
+
|
7
|
+
@profiles = Profile.all
|
8
|
+
@profile_index = nil
|
9
|
+
@profile = nil
|
10
|
+
|
11
|
+
ARGV << 'help' if ARGV.empty?
|
12
|
+
|
13
|
+
set_profile
|
14
|
+
split_args.each do |args|
|
15
|
+
dispatch_command args
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def set_profile
|
20
|
+
if ARGV.first[0] == ':'
|
21
|
+
@profile_index = ARGV.shift[1..-1]
|
22
|
+
Profile.profile_index = @profile_index
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def split_args
|
27
|
+
argv = ARGV.dup
|
28
|
+
@profile_index = argv.shift[1..-1] if argv.first[0] == ':'
|
29
|
+
Enumerator.new do |y|
|
30
|
+
while delimiter_pos = argv.index(CLI_DELIMITER)
|
31
|
+
y << argv[0...delimiter_pos]
|
32
|
+
argv = argv[(delimiter_pos+1)..-1]
|
33
|
+
end
|
34
|
+
y << argv
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def dispatch_command(args)
|
39
|
+
return if args.empty?
|
40
|
+
cmd = args.shift
|
41
|
+
method = "cmd_#{cmd}"
|
42
|
+
unless Command.respond_to?(method)
|
43
|
+
puts "Unknown command #{cmd}"
|
44
|
+
return
|
45
|
+
end
|
46
|
+
Command.send(method, args)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.cwd
|
50
|
+
@cwd ||= CLI.od.root
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.cwd=value
|
54
|
+
@cwd = value
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.set_od(*args)
|
58
|
+
@logger = args[3]
|
59
|
+
@od = OneDrive.new(*args)
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.od
|
63
|
+
@od
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.logger
|
67
|
+
@logger
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
Dir.chdir(File.expand_path('..', File.dirname(__FILE__))) do
|
72
|
+
Dir['rb1drv-tools/command/*.rb'].each{ |file| require file }
|
73
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Rb1drvTools
|
2
|
+
module Command
|
3
|
+
def self.cmd_cd(args)
|
4
|
+
Profile.profile
|
5
|
+
dir = args.first
|
6
|
+
dir_obj = get_obj(dir)
|
7
|
+
if dir_obj.is_a? OneDriveDir
|
8
|
+
CLI.cwd = dir_obj
|
9
|
+
else
|
10
|
+
dir = File.join(CLI.cwd.absolute_path, dir)
|
11
|
+
puts "cd: cannot access '#{dir}': No such file or directory"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Rb1drvTools
|
2
|
+
module Command
|
3
|
+
def self.get_obj(target)
|
4
|
+
if target == '.'
|
5
|
+
CLI.cwd
|
6
|
+
elsif target == '/'
|
7
|
+
CLI.od.root
|
8
|
+
elsif target[0] == '/'
|
9
|
+
target = File.expand_path('/./' + target)
|
10
|
+
CLI.root.get(target)
|
11
|
+
else
|
12
|
+
target = File.expand_path('/./' + target)
|
13
|
+
CLI.cwd.get(target)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Rb1drvTools
|
2
|
+
module Command
|
3
|
+
def self.cmd_help(args)
|
4
|
+
cmd_version(args)
|
5
|
+
me = File.basename($0, File.extname($0))
|
6
|
+
puts <<~EOF
|
7
|
+
Usage:
|
8
|
+
#{me} [:<profile>] <Command> [-,- <Command>]...
|
9
|
+
|
10
|
+
Command:
|
11
|
+
help Display this help
|
12
|
+
|
13
|
+
profile new Create a new profile to access your files
|
14
|
+
profile ls List profiles
|
15
|
+
profile default Set chosen profile as default
|
16
|
+
profile del Delete profile to revoke access
|
17
|
+
|
18
|
+
ls [-ustrl] [<target>] List information about files
|
19
|
+
ll [-ustrl] [<target>] Long listing format of ls
|
20
|
+
-u Do not sort by name
|
21
|
+
-s Sort by size, smallest first
|
22
|
+
-t Sort by modified time, oldest first
|
23
|
+
-r Reverse order while sorting
|
24
|
+
-l Use a long listing format
|
25
|
+
directory List contents of this directory
|
26
|
+
file List information of this file
|
27
|
+
|
28
|
+
cd <directory> Change current directory, only effective in single execution
|
29
|
+
|
30
|
+
mkdir <directory> Create the directory recursively
|
31
|
+
|
32
|
+
upload [-fs] <files> [@target] Upload files into directory recursively, skipping existing files
|
33
|
+
download [-f] <r-files> [@target] Download files into directory recursively, skipping existing files
|
34
|
+
-f Overwrite existing files regardless
|
35
|
+
-s Overwrite existing files with different size or older date
|
36
|
+
@directory/ Upload or download into directory as children, if:
|
37
|
+
- target directory exists
|
38
|
+
- target ends with a slash
|
39
|
+
- multiple source files are given
|
40
|
+
- wildcard matching multiple source files
|
41
|
+
@file Upload or download as a single file, if:
|
42
|
+
- target file exists
|
43
|
+
- target does not end with a slash, and only one source file is given
|
44
|
+
files Local source files to upload, wildcard accepted in Ruby glob syntax
|
45
|
+
r-files Remote source files to download, wildcard accepted with limitations:
|
46
|
+
- no ** matching
|
47
|
+
- can only match names under current directory
|
48
|
+
|
49
|
+
info Show information about this drive
|
50
|
+
|
51
|
+
Examples:
|
52
|
+
#{me} profile new student_account
|
53
|
+
#{me} profile new personal
|
54
|
+
#{me} :personal profile default -,- profile ls
|
55
|
+
#{me} :student_account cd class101/slides -,- download slides-2\\*.pdf @slides/
|
56
|
+
#{me} upload slides -,- ls -l slides -,- info
|
57
|
+
|
58
|
+
EOF
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.cmd_version(args)
|
62
|
+
puts <<~EOF
|
63
|
+
Ruby-OneDrive-Tools #{Rb1drvTools::VERSION}, SDK #{Rb1drv::VERSION}
|
64
|
+
Copyright (c) 2018 Xinyue Lu, The MIT License.
|
65
|
+
|
66
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
|
67
|
+
You may not hold the author liable. Check LICENSE.txt for Full Text.
|
68
|
+
|
69
|
+
EOF
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Rb1drvTools
|
2
|
+
module Command
|
3
|
+
def self.cmd_info(args)
|
4
|
+
Profile.profile
|
5
|
+
format = '%10s: %s'
|
6
|
+
CLI.od.request('drives').dig('value').each do |drive|
|
7
|
+
{
|
8
|
+
'ID' => drive.dig('id'),
|
9
|
+
'Site' => drive.dig('webUrl'),
|
10
|
+
'Type' => drive.dig('driveType'),
|
11
|
+
'Owner' => '%s <%s>' % [drive.dig('owner', 'user', 'displayName'), drive.dig('owner', 'user', 'email')],
|
12
|
+
'Size' => Utils.humanize_size(drive.dig('quota', 'total')),
|
13
|
+
'Used' => Utils.humanize_size(drive.dig('quota', 'used')),
|
14
|
+
'Deleted' => Utils.humanize_size(drive.dig('quota', 'deleted')),
|
15
|
+
'Free' => Utils.humanize_size(drive.dig('quota', 'remaining'))
|
16
|
+
}.each do |row|
|
17
|
+
puts format % row
|
18
|
+
end
|
19
|
+
puts
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Rb1drvTools
|
2
|
+
module Command
|
3
|
+
def self.cmd_ll(args)
|
4
|
+
args.unshift('-l')
|
5
|
+
cmd_ls(args)
|
6
|
+
end
|
7
|
+
def self.cmd_ls(args)
|
8
|
+
Profile.profile
|
9
|
+
column = :name
|
10
|
+
order = :asc
|
11
|
+
long = false
|
12
|
+
dirs = []
|
13
|
+
args.each do |arg|
|
14
|
+
next dirs << arg if arg[0] != '-'
|
15
|
+
arg[1..-1].each_char do |flag|
|
16
|
+
case flag
|
17
|
+
when 'l'
|
18
|
+
long = true
|
19
|
+
when 'u'
|
20
|
+
column = nil
|
21
|
+
when 's'
|
22
|
+
column = :size
|
23
|
+
when 't'
|
24
|
+
column = :mtime
|
25
|
+
when 'r'
|
26
|
+
order = :desc
|
27
|
+
else
|
28
|
+
puts "Warning: unknown flag '#{flag}'."
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
dirs << '.' if dirs.empty?
|
33
|
+
dirs.each do |dir|
|
34
|
+
dir_obj = get_obj(dir)
|
35
|
+
if dir_obj.is_a? OneDrive404
|
36
|
+
dir = File.join(CLI.cwd.absolute_path, dir)
|
37
|
+
puts "ls: cannot access '#{dir}': No such file or directory"
|
38
|
+
elsif dir_obj.file?
|
39
|
+
puts Utils.ls([dir_obj], column, order, long)
|
40
|
+
else
|
41
|
+
puts Utils.ls(dir_obj.children, column, order, long)
|
42
|
+
puts "#{dir_obj.child_count} items"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
module Rb1drvTools
|
3
|
+
module Command
|
4
|
+
def self.cmd_profile(args)
|
5
|
+
request = args.shift
|
6
|
+
case request
|
7
|
+
when nil, 'ls'
|
8
|
+
cmd_profile_ls(args)
|
9
|
+
when 'new'
|
10
|
+
cmd_profile_new(args)
|
11
|
+
when 'default'
|
12
|
+
cmd_profile_default(args)
|
13
|
+
when 'del', 'delete', 'rm'
|
14
|
+
cmd_profile_del(args)
|
15
|
+
else
|
16
|
+
puts "Unknown request #{request}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.cmd_profile_ls(args)
|
21
|
+
Profile.all.map(&:name).each do |p|
|
22
|
+
puts "Profile: #{p}"
|
23
|
+
end
|
24
|
+
puts "Default: #{Profile.default_profile_index || 'none'}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.cmd_profile_new(args)
|
28
|
+
name = args.first || SecureRandom.hex(4)
|
29
|
+
print <<~EOF.chomp
|
30
|
+
Creating profile #{name}.
|
31
|
+
|
32
|
+
To create a new OneDrive profile, open the following link in your browser, sign in with your account, and approve our access to your files.
|
33
|
+
|
34
|
+
#{CLI.od.auth_url}
|
35
|
+
|
36
|
+
Paste your authorization code here:
|
37
|
+
EOF
|
38
|
+
auth_code = ''
|
39
|
+
loop do
|
40
|
+
auth_code = STDIN.gets.strip
|
41
|
+
break unless auth_code.empty?
|
42
|
+
end
|
43
|
+
access_token = CLI.od.auth_access(auth_code)
|
44
|
+
p = Profile.new
|
45
|
+
p.name = name
|
46
|
+
p.update_token(access_token)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.cmd_profile_del(args)
|
50
|
+
name = Profile.profile.name
|
51
|
+
path = Profile.profile.file
|
52
|
+
prompt = TTY::Prompt.new
|
53
|
+
puts "You asked to delete your local profile #{name}."
|
54
|
+
puts "Doing so will revoke our access to your files."
|
55
|
+
puts "You can regain access by `profile add` later."
|
56
|
+
File.unlink(path) if prompt.yes?("Proceed to delete?", convert: :bool, default: false)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.cmd_profile_default(args)
|
60
|
+
Profile.default_profile_index = Profile.profile_index
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module Rb1drvTools
|
2
|
+
module Command
|
3
|
+
def self.cmd_upload(args)
|
4
|
+
Profile.profile
|
5
|
+
return if args.empty?
|
6
|
+
file_mode = true
|
7
|
+
overwrite = false
|
8
|
+
overwrite_smarter = false
|
9
|
+
|
10
|
+
items = []
|
11
|
+
args.each do |arg|
|
12
|
+
next items << arg if arg[0] != '-'
|
13
|
+
arg[1..-1].each_char do |flag|
|
14
|
+
case flag
|
15
|
+
when 's'
|
16
|
+
overwrite_smarter = true
|
17
|
+
when 'f'
|
18
|
+
overwrite = true
|
19
|
+
else
|
20
|
+
puts "Warning: unknown flag '#{flag}'."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
if overwrite && overwrite_smarter
|
26
|
+
puts "Error: -s and -f are mutually exclusive, make your decision first."
|
27
|
+
return
|
28
|
+
end
|
29
|
+
|
30
|
+
target = '.'
|
31
|
+
target = items.pop[1..-1] if items.last[0] == '@'
|
32
|
+
target_obj = get_obj(target)
|
33
|
+
return if items.empty?
|
34
|
+
|
35
|
+
# p items
|
36
|
+
# p target_obj
|
37
|
+
|
38
|
+
# Directory mode if:
|
39
|
+
# target directory exists
|
40
|
+
file_mode = false if target_obj.dir?
|
41
|
+
# target ends with a slash
|
42
|
+
file_mode = false if target.end_with?('/')
|
43
|
+
# multiple source files are given
|
44
|
+
file_mode = false if items.size > 1
|
45
|
+
file_mode = false if File.directory?(items.first)
|
46
|
+
# wildcard matching files on server
|
47
|
+
file_mode = false if Dir[items.first].size > 1
|
48
|
+
|
49
|
+
overwrite_policy = if overwrite
|
50
|
+
:overwrite
|
51
|
+
elsif overwrite_smarter
|
52
|
+
:overwrite_smarter
|
53
|
+
else
|
54
|
+
:skip
|
55
|
+
end
|
56
|
+
|
57
|
+
if file_mode
|
58
|
+
target_dir = get_obj(File.dirname(target))
|
59
|
+
CLI.cwd.mkdir(File.dirname(target))
|
60
|
+
target_name = File.basename(target)
|
61
|
+
upload(items.first, target_dir, File.basename(target), overwrite_policy: overwrite_policy)
|
62
|
+
else
|
63
|
+
items.each do |item|
|
64
|
+
unless target_obj.dir?
|
65
|
+
base = if target[0] == '/'
|
66
|
+
CLI.root
|
67
|
+
else
|
68
|
+
CLI.cwd
|
69
|
+
end
|
70
|
+
target = File.expand_path('/./' + target)
|
71
|
+
target_obj = base.mkdir(target)
|
72
|
+
end
|
73
|
+
Dir[item].each do |match|
|
74
|
+
if File.directory?(match)
|
75
|
+
traverse_dir(match, target_obj.mkdir(match))
|
76
|
+
else
|
77
|
+
upload(match, target_obj, File.basename(match), overwrite_policy: overwrite_policy)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.traverse_dir(source_directory, target_directory)
|
85
|
+
Dir.children(source_directory).sort.each do |child|
|
86
|
+
new_path = File.join(source_directory, child)
|
87
|
+
if File.directory?(child)
|
88
|
+
new_dir = target_directory.get_child(child)
|
89
|
+
new_dir = target_directory.mkdir(child) unless new_dir.dir?
|
90
|
+
traverse_dir(new_path, new_dir)
|
91
|
+
else
|
92
|
+
upload(new_path, target_directory, child)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.upload(source_file, target_directory, target_name, overwrite_policy: :skip)
|
98
|
+
return if source_file.include?('.1drv_upload')
|
99
|
+
printf "%s => %s :: %s\n", source_file, target_directory.absolute_path, target_name
|
100
|
+
target_obj = target_directory.get_child(target_name)
|
101
|
+
return puts 'Target is a directory, skipped' if target_obj.dir?
|
102
|
+
if overwrite_policy != :overwrite && target_obj.file?
|
103
|
+
return puts 'Skipped' if overwrite_policy == :skip
|
104
|
+
return puts 'Remote file is up to date, skipped' if target_obj.mtime >= File.mtime(source_file) - 2
|
105
|
+
end
|
106
|
+
screen_width = TTY::Screen.width
|
107
|
+
if STDOUT.tty? && screen_width >= 50
|
108
|
+
multibar = TTY::ProgressBar::Multi.new
|
109
|
+
bar = multibar.register("%s :current_byte / :total_byte :byte_rate/s [:bar] :eta :percent" % source_file[0..29], total: File.size(source_file), frequency: 2, head: '>')
|
110
|
+
bar.start
|
111
|
+
end
|
112
|
+
subbar = nil
|
113
|
+
# trap(:WINCH) { bar.resize if bar }
|
114
|
+
|
115
|
+
target_directory.upload(source_file, target_name: target_name, overwrite: true) do |ev, st|
|
116
|
+
case ev
|
117
|
+
when :new_segment
|
118
|
+
subbar = multibar.register("%4d-%-4d :current_byte / :total_byte [:bar]" % [st[:from] / 1048576, st[:to] / 1048576], total: st[:to] - st[:from] + 1, frequency: 2, head: '>')
|
119
|
+
when :finish_segment
|
120
|
+
subbar.finish
|
121
|
+
multibar.instance_variable_get('@bars').delete_at(1)
|
122
|
+
multibar.instance_variable_set('@rows', multibar.rows - 1)
|
123
|
+
print TTY::Cursor.up(1)
|
124
|
+
print TTY::Cursor.clear_line_after
|
125
|
+
when :progress
|
126
|
+
bar.current = st[:from] + st[:progress]
|
127
|
+
subbar.current = st[:progress]
|
128
|
+
when :retry
|
129
|
+
bar.current = st[:from]
|
130
|
+
subbar.reset
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
bar.finish
|
135
|
+
end
|
136
|
+
singleton_class.send(:alias_method, :cmd_up, :cmd_upload)
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Rb1drvTools
|
2
|
+
class Profile
|
3
|
+
attr_accessor *%w(name token created_at updated_at file)
|
4
|
+
def initialize(file=nil)
|
5
|
+
@file = file
|
6
|
+
if file && File.exist?(file)
|
7
|
+
hash_data = JSON.parse(File.read(file))
|
8
|
+
%w(name token created_at updated_at).each do |key|
|
9
|
+
instance_variable_set("@#{key}", hash_data[key])
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def update_token(access_token)
|
15
|
+
@created_at ||= Time.now.to_i
|
16
|
+
@updated_at = Time.now.to_i
|
17
|
+
@token = access_token.to_hash
|
18
|
+
save
|
19
|
+
end
|
20
|
+
|
21
|
+
def save
|
22
|
+
@file ||= File.join(self.class.config_home, "profile-#{@name}.json")
|
23
|
+
File.write @file, JSON.pretty_generate(
|
24
|
+
name: @name,
|
25
|
+
token: @token,
|
26
|
+
created_at: @created_at,
|
27
|
+
updated_at: @updated_at
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.all
|
32
|
+
@all ||= Dir.glob(File.join(config_home, "profile-*.json")).map do |file|
|
33
|
+
Profile.new(file)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.config_home
|
38
|
+
home = File.join(Dir.home, '.rb1drv')
|
39
|
+
ensure
|
40
|
+
FileUtils.mkdir(home) unless File.exist?(home)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.default_profile_file
|
44
|
+
File.join(config_home, 'default-profile')
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.default_profile_index
|
48
|
+
@default_profile_index ||=
|
49
|
+
if File.exist?(default_profile_file)
|
50
|
+
File.read(default_profile_file).strip
|
51
|
+
else
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.default_profile_index=value
|
57
|
+
return if value.empty?
|
58
|
+
@default_profile_index = value
|
59
|
+
File.write(default_profile_file, value)
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.profile_index
|
63
|
+
@profile_index
|
64
|
+
end
|
65
|
+
def self.profile_index=(name)
|
66
|
+
return unless name
|
67
|
+
@profile_index = name
|
68
|
+
@profile = all.select{ |p| p.name == name }.first
|
69
|
+
token = @profile.token
|
70
|
+
new_token = CLI.od.auth_load(token)
|
71
|
+
@profile.update_token(new_token) if new_token.token != token
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.profile
|
75
|
+
raise 'No profile available' if all.empty?
|
76
|
+
self.profile_index ||= all.first.name if all.size == 1
|
77
|
+
self.profile_index ||= default_profile_index
|
78
|
+
raise 'Invalid profile' unless @profile
|
79
|
+
@profile
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Rb1drvTools
|
2
|
+
module Utils
|
3
|
+
module_function
|
4
|
+
def sort_files(items, column, order)
|
5
|
+
if column
|
6
|
+
items = items.sort_by(&column)
|
7
|
+
items = items.reverse if order == :desc
|
8
|
+
end
|
9
|
+
items
|
10
|
+
end
|
11
|
+
def ls(items, column = :name, order = :asc, long = false, width=0)
|
12
|
+
return ll(items, column, order) if long
|
13
|
+
items = sort_files(items, column, order).map(&:name)
|
14
|
+
if width > 0
|
15
|
+
ls_format(items, width)
|
16
|
+
else
|
17
|
+
ls_simple(items)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def ls_simple(items)
|
22
|
+
items.join($/)
|
23
|
+
end
|
24
|
+
|
25
|
+
def ls_format(items, width)
|
26
|
+
buffer = []
|
27
|
+
lens = items.map(&:size)
|
28
|
+
row_length = []
|
29
|
+
rows = 1.upto(items.size) do |rows|
|
30
|
+
row_length = lens.each_slice(rows).map{ |col| col.max + 2 }
|
31
|
+
usage = row_length.sum
|
32
|
+
break rows if usage < width
|
33
|
+
end
|
34
|
+
items.each_slice(rows).reduce(&:zip).map(&:flatten).each do |row|
|
35
|
+
row.each_with_index do |item, idx|
|
36
|
+
buffer << item.ljust(row_length[idx]) if item
|
37
|
+
end
|
38
|
+
buffer << $/
|
39
|
+
end
|
40
|
+
buffer.join
|
41
|
+
end
|
42
|
+
|
43
|
+
def ll(items, column = :name, order = :asc)
|
44
|
+
items = sort_files(items, column, order)
|
45
|
+
items.map do |item|
|
46
|
+
if item.dir?
|
47
|
+
sprintf("d %-4d %-20s %6s %s %s/", item.child_count, item.muser, humanize_size(item.size), item.mtime.localtime.strftime('%Y-%m-%d %H:%M:%S'), item.name)
|
48
|
+
else
|
49
|
+
sprintf("f %-4d %-20s %6s %s %s", 0, item.muser, humanize_size(item.size), item.mtime.localtime.strftime('%Y-%m-%d %H:%M:%S'), item.name)
|
50
|
+
end
|
51
|
+
end.join($/)
|
52
|
+
end
|
53
|
+
|
54
|
+
def humanize_size(size)
|
55
|
+
units = ['', 'K', 'M', 'G']
|
56
|
+
unit_idx = 0
|
57
|
+
while size > 8192 && unit_idx < units.size - 1 do
|
58
|
+
size /= 1024
|
59
|
+
unit_idx += 1
|
60
|
+
end
|
61
|
+
"#{size}#{units[unit_idx]}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/rb1drv-tools/version.rb
CHANGED
data/rb1drv-tools.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Xinyue Lu"]
|
10
10
|
spec.email = ["i@7086.in"]
|
11
11
|
|
12
|
-
spec.summary = "Ruby OneDrive
|
12
|
+
spec.summary = "Ruby OneDrive Library Tools"
|
13
13
|
spec.homepage = "https://github.com/msg7086/rb1drv-tools"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
@@ -19,8 +19,12 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.bindir = "exe"
|
20
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ["lib"]
|
22
|
+
spec.required_ruby_version = '>= 2.5'
|
22
23
|
|
23
24
|
spec.add_dependency "rb1drv", "~> 0.1"
|
25
|
+
spec.add_dependency "tty-progressbar", "~> 0"
|
26
|
+
spec.add_dependency "tty-prompt", "~> 0"
|
27
|
+
spec.add_dependency "tty-screen", "~> 0"
|
24
28
|
spec.add_development_dependency "bundler", "~> 1.16"
|
25
29
|
spec.add_development_dependency "rake", "~> 10.0"
|
26
30
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rb1drv-tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Xinyue Lu
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-05-
|
11
|
+
date: 2018-05-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rb1drv
|
@@ -24,6 +24,48 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: tty-progressbar
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: tty-prompt
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: tty-screen
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
27
69
|
- !ruby/object:Gem::Dependency
|
28
70
|
name: bundler
|
29
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -55,12 +97,31 @@ dependencies:
|
|
55
97
|
description:
|
56
98
|
email:
|
57
99
|
- i@7086.in
|
58
|
-
executables:
|
100
|
+
executables:
|
101
|
+
- 1d
|
59
102
|
extensions: []
|
60
103
|
extra_rdoc_files: []
|
61
104
|
files:
|
105
|
+
- ".gitignore"
|
106
|
+
- ".travis.yml"
|
107
|
+
- Gemfile
|
108
|
+
- Gemfile.lock
|
62
109
|
- LICENSE.txt
|
63
110
|
- README.md
|
111
|
+
- bin/console
|
112
|
+
- bin/setup
|
113
|
+
- exe/1d
|
114
|
+
- lib/rb1drv-tools.rb
|
115
|
+
- lib/rb1drv-tools/cli.rb
|
116
|
+
- lib/rb1drv-tools/command/cd.rb
|
117
|
+
- lib/rb1drv-tools/command/common.rb
|
118
|
+
- lib/rb1drv-tools/command/help.rb
|
119
|
+
- lib/rb1drv-tools/command/info.rb
|
120
|
+
- lib/rb1drv-tools/command/ls.rb
|
121
|
+
- lib/rb1drv-tools/command/profile.rb
|
122
|
+
- lib/rb1drv-tools/command/upload.rb
|
123
|
+
- lib/rb1drv-tools/profile.rb
|
124
|
+
- lib/rb1drv-tools/utils.rb
|
64
125
|
- lib/rb1drv-tools/version.rb
|
65
126
|
- rb1drv-tools.gemspec
|
66
127
|
homepage: https://github.com/msg7086/rb1drv-tools
|
@@ -75,16 +136,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
75
136
|
requirements:
|
76
137
|
- - ">="
|
77
138
|
- !ruby/object:Gem::Version
|
78
|
-
version: '
|
139
|
+
version: '2.5'
|
79
140
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
141
|
requirements:
|
81
|
-
- - "
|
142
|
+
- - ">="
|
82
143
|
- !ruby/object:Gem::Version
|
83
|
-
version:
|
144
|
+
version: '0'
|
84
145
|
requirements: []
|
85
146
|
rubyforge_project:
|
86
147
|
rubygems_version: 2.7.6
|
87
148
|
signing_key:
|
88
149
|
specification_version: 4
|
89
|
-
summary: Ruby OneDrive
|
150
|
+
summary: Ruby OneDrive Library Tools
|
90
151
|
test_files: []
|