module Rb1drvTools::Command
Public Class Methods
cmd_cd(args)
click to toggle source
# File lib/rb1drv-tools/command/cd.rb, line 3 def self.cmd_cd(args) Profile.profile dir = args.first dir_obj = get_obj(dir) if dir_obj.is_a? OneDriveDir CLI.cwd = dir_obj else dir = File.join(CLI.cwd.absolute_path, dir) puts "cd: cannot access '#{dir}': No such file or directory" end end
cmd_help(args)
click to toggle source
# File lib/rb1drv-tools/command/help.rb, line 3 def self.cmd_help(args) cmd_version(args) me = File.basename($0, File.extname($0)) puts <<~EOF Usage: #{me} [:<profile>] <Command> [-,- <Command>]... Command: help Display this help profile new Create a new profile to access your files profile ls List profiles profile default Set chosen profile as default profile del Delete profile to revoke access ls [-ustrl] [<target>] List information about files ll [-ustrl] [<target>] Long listing format of ls -u Do not sort by name -s Sort by size, smallest first -t Sort by modified time, oldest first -r Reverse order while sorting -l Use a long listing format directory List contents of this directory file List information of this file cd <directory> Change current directory, only effective in single execution mkdir <directory> Create the directory recursively upload [-fs] <files> [@target] Upload files into directory recursively, skipping existing files download [-f] <r-files> [@target] Download files into directory recursively, skipping existing files -f Overwrite existing files regardless -s Overwrite existing files with different size or older date -t Reset last modified time if remote file has newer date and same size @directory/ Upload or download into directory as children, if: - target directory exists - target ends with a slash - multiple source files are given - wildcard matching multiple source files @file Upload or download as a single file, if: - target file exists - target does not end with a slash, and only one source file is given files Local source files to upload, wildcard accepted in Ruby glob syntax r-files Remote source files to download, wildcard accepted with limitations: - no ** matching - can only match names under current directory info Show information about this drive Examples: #{me} profile new student_account #{me} profile new personal #{me} :personal profile default -,- profile ls #{me} :student_account cd class101/slides -,- download slides-2\\*.pdf @slides/ #{me} upload slides -,- ls -l slides -,- info EOF end
cmd_info(args)
click to toggle source
# File lib/rb1drv-tools/command/info.rb, line 3 def self.cmd_info(args) Profile.profile format = '%10s: %s' CLI.od.request('drives').dig('value').each do |drive| total = drive.dig('quota', 'total').to_i used = drive.dig('quota', 'used').to_i deleted = drive.dig('quota', 'deleted').to_i remaining = drive.dig('quota', 'remaining').to_i lost = total - used - deleted - remaining { 'ID' => drive.dig('id'), 'Site' => drive.dig('webUrl'), 'Type' => drive.dig('driveType'), 'Owner' => '%s <%s>' % [drive.dig('owner', 'user', 'displayName'), drive.dig('owner', 'user', 'email')], 'Size' => Utils.humanize_size(total), 'Used' => Utils.humanize_size(used), 'Deleted' => Utils.humanize_size(deleted), 'Free' => Utils.humanize_size(remaining), 'Lost' => Utils.humanize_size(lost) # Lost in universe (Version History) }.each do |row| puts format % row end puts end end
cmd_ll(args)
click to toggle source
# File lib/rb1drv-tools/command/ls.rb, line 3 def self.cmd_ll(args) args.unshift('-l') cmd_ls(args) end
cmd_ls(args)
click to toggle source
# File lib/rb1drv-tools/command/ls.rb, line 7 def self.cmd_ls(args) Profile.profile column = :name order = :asc long = false dirs = [] args.each do |arg| next dirs << arg if arg[0] != '-' arg[1..-1].each_char do |flag| case flag when 'l' long = true when 'u' column = nil when 's' column = :size when 't' column = :mtime when 'r' order = :desc else puts "Warning: unknown flag '#{flag}'." end end end dirs << '.' if dirs.empty? dirs.each do |dir| dir_obj = get_obj(dir) if dir_obj.is_a? OneDrive404 dir = File.join(CLI.cwd.absolute_path, dir) puts "ls: cannot access '#{dir}': No such file or directory" elsif dir_obj.file? puts Utils.ls([dir_obj], column, order, long) else puts Utils.ls(dir_obj.children, column, order, long) puts "#{dir_obj.child_count} items" end end end
cmd_profile(args)
click to toggle source
# File lib/rb1drv-tools/command/profile.rb, line 4 def self.cmd_profile(args) request = args.shift case request when nil, 'ls' cmd_profile_ls(args) when 'new' cmd_profile_new(args) when 'default' cmd_profile_default(args) when 'del', 'delete', 'rm' cmd_profile_del(args) else puts "Unknown request #{request}" end end
cmd_profile_default(args)
click to toggle source
# File lib/rb1drv-tools/command/profile.rb, line 59 def self.cmd_profile_default(args) Profile.default_profile_index = Profile.profile_index end
cmd_profile_del(args)
click to toggle source
# File lib/rb1drv-tools/command/profile.rb, line 49 def self.cmd_profile_del(args) name = Profile.profile.name path = Profile.profile.file prompt = TTY::Prompt.new puts "You asked to delete your local profile #{name}." puts "Doing so will revoke our access to your files." puts "You can regain access by `profile add` later." File.unlink(path) if prompt.yes?("Proceed to delete?", convert: :bool, default: false) end
cmd_profile_ls(args)
click to toggle source
# File lib/rb1drv-tools/command/profile.rb, line 20 def self.cmd_profile_ls(args) Profile.all.map(&:name).each do |p| puts "Profile: #{p}" end puts "Default: #{Profile.default_profile_index || 'none'}" end
cmd_profile_new(args)
click to toggle source
# File lib/rb1drv-tools/command/profile.rb, line 27 def self.cmd_profile_new(args) name = args.first || SecureRandom.hex(4) print <<~EOF.chomp Creating profile #{name}. 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. #{CLI.od.auth_url} Paste your authorization code here: EOF auth_code = '' loop do auth_code = STDIN.gets.strip break unless auth_code.empty? end access_token = CLI.od.auth_access(auth_code) p = Profile.new p.name = name p.update_token(access_token) end
cmd_upload(args)
click to toggle source
# File lib/rb1drv-tools/command/upload.rb, line 3 def self.cmd_upload(args) Profile.profile return if args.empty? file_mode = true overwrite = false overwrite_smarter = false time_sync = false items = [] args.each do |arg| next items << arg if arg[0] != '-' arg[1..-1].each_char do |flag| case flag when 's' overwrite_smarter = true when 'f' overwrite = true when 't' time_sync = true else puts "Warning: unknown flag '#{flag}'." end end end if overwrite && overwrite_smarter puts "Error: -s and -f are mutually exclusive, make your decision first." return end target = '.' target = items.pop[1..-1] if items.last[0] == '@' target_obj = get_obj(target) return if items.empty? # p items # p target_obj # Directory mode if: # target directory exists file_mode = false if target_obj.dir? # target ends with a slash file_mode = false if target.end_with?('/') # multiple source files are given file_mode = false if items.size > 1 file_mode = false if File.directory?(items.first) # wildcard matching files on server file_mode = false if Dir[items.first].size > 1 overwrite_policy = if overwrite :overwrite elsif overwrite_smarter :overwrite_smarter else :skip end if file_mode target_dir = get_obj(File.dirname(target)) CLI.cwd.mkdir(File.dirname(target)) target_name = File.basename(target) upload(items.first, target_dir, File.basename(target), overwrite_policy: overwrite_policy, time_sync: time_sync) else items.each do |item| unless target_obj.dir? base = if target[0] == '/' CLI.root else CLI.cwd end target = File.expand_path('/./' + target) target_obj = base.mkdir(target) end Dir[item].each do |match| if File.directory?(match) traverse_dir(match, target_obj.mkdir(File.basename(match)), overwrite_policy: overwrite_policy, time_sync: time_sync) else upload(match, target_obj, File.basename(match), overwrite_policy: overwrite_policy, time_sync: time_sync) end end end end end
cmd_version(args)
click to toggle source
# File lib/rb1drv-tools/command/help.rb, line 62 def self.cmd_version(args) puts <<~EOF Ruby-OneDrive-Tools #{Rb1drvTools::VERSION}, SDK #{Rb1drv::VERSION} Copyright (c) 2018 Xinyue Lu, The MIT License. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. You may not hold the author liable. Check LICENSE.txt for Full Text. EOF end
get_obj(target)
click to toggle source
# File lib/rb1drv-tools/command/common.rb, line 3 def self.get_obj(target) if target == '.' CLI.cwd elsif target == '/' CLI.od.root elsif target[0] == '/' target = File.expand_path('/./' + target) CLI.root.get(target) else target = File.expand_path('/./' + target) CLI.cwd.get(target) end end
traverse_dir(source_directory, target_directory, overwrite_policy: :skip, time_sync: false)
click to toggle source
# File lib/rb1drv-tools/command/upload.rb, line 87 def self.traverse_dir(source_directory, target_directory, overwrite_policy: :skip, time_sync: false) Dir.entries(source_directory).sort.each do |child| next if child == '.' || child == '..' new_path = File.join(source_directory, child) if File.directory?(new_path) new_dir = target_directory.get_child(child) new_dir = target_directory.mkdir(child) unless new_dir.dir? traverse_dir(new_path, new_dir, overwrite_policy: overwrite_policy, time_sync: time_sync) else upload(new_path, target_directory, child, overwrite_policy: overwrite_policy, time_sync: time_sync) end end end
upload(source_file, target_directory, target_name, overwrite_policy: :skip, time_sync: false)
click to toggle source
# File lib/rb1drv-tools/command/upload.rb, line 101 def self.upload(source_file, target_directory, target_name, overwrite_policy: :skip, time_sync: false) return if source_file.include?('.1drv_upload') printf "%s => %s :: %s\n", source_file, target_directory.absolute_path, target_name target_obj = target_directory.get_child(target_name) return puts 'Target is a directory, skipped' if target_obj.dir? mtime = File.mtime(source_file) file_size = File.size(source_file) if overwrite_policy != :overwrite && target_obj.file? if time_sync && target_obj.size == file_size && target_obj.mtime - mtime > 2 target_obj.set_mtime(mtime) print '<sync mtime> ' end return puts 'Skipped' if overwrite_policy == :skip return puts 'Remote file is up to date, skipped' if target_obj.mtime >= File.mtime(source_file) - 2 end screen_width = TTY::Screen.width if STDOUT.tty? && screen_width >= 50 multibar = TTY::ProgressBar::Multi.new bar = multibar.register("%s :current_byte / :total_byte :byte_rate/s [:bar] :eta :percent" % source_file[0..29], total: file_size, frequency: 2, head: '>') bar.start end subbar = nil if file_size >= 524_288_000 # 500MiB fragment_size = 209_715_200 # 200MiB elsif file_size >= 209_715_200 # 200MiB fragment_size = 83_886_080 # 80MiB else fragment_size = 20_971_520 # 20MiB end target_directory.upload(source_file, target_name: target_name, overwrite: true, fragment_size: fragment_size) do |ev, st| case ev when :new_segment 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: '>') when :finish_segment subbar.finish multibar.instance_variable_get('@bars').delete_at(1) multibar.instance_variable_set('@rows', multibar.rows - 1) print TTY::Cursor.up(1) print TTY::Cursor.clear_line_after when :progress bar.current = st[:from] + st[:progress] subbar.current = st[:progress] when :retry bar.current = st[:from] subbar.reset end end bar.finish end