gdrive-cli 0.0.2
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/Gemfile +3 -0
- data/Gemfile.lock +63 -0
- data/README.md +0 -0
- data/bin/gdrive +41 -0
- data/gdrive-cli.gemspec +12 -0
- data/lib/gdrive-lib.rb +186 -0
- metadata +49 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3b610f46c0797a2e97953ff318408e96203192319e9ac0993a8b74bb1b46b0d1
|
4
|
+
data.tar.gz: 6ddf89868fc9c6b742111b43bbaa64da68cc17bc0dacd2b8259ef0c69b559467
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1aec88e81e6feba4c09e73d03c449f38c628aa4d605f9e8885f78431cfa971fe0d0c9badef2c294a2f7a1679a490443eefdd0bca11ef6322add036dcb1917f6b
|
7
|
+
data.tar.gz: e81da2d9c099714b8ca2ea8545eff776900fd1d5160eba7a1ff559d043ece522dc7ed4cffc6736202472c214c3a585ed5037ad7ddf4c67173983dc05cbd67920
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
addressable (2.7.0)
|
5
|
+
public_suffix (>= 2.0.2, < 5.0)
|
6
|
+
declarative (0.0.20)
|
7
|
+
declarative-option (0.1.0)
|
8
|
+
faraday (1.1.0)
|
9
|
+
multipart-post (>= 1.2, < 3)
|
10
|
+
ruby2_keywords
|
11
|
+
google-api-client (0.50.0)
|
12
|
+
addressable (~> 2.5, >= 2.5.1)
|
13
|
+
googleauth (~> 0.9)
|
14
|
+
httpclient (>= 2.8.1, < 3.0)
|
15
|
+
mini_mime (~> 1.0)
|
16
|
+
representable (~> 3.0)
|
17
|
+
retriable (>= 2.0, < 4.0)
|
18
|
+
rexml
|
19
|
+
signet (~> 0.12)
|
20
|
+
google_drive (3.0.5)
|
21
|
+
google-api-client (>= 0.11.0, < 1.0.0)
|
22
|
+
googleauth (>= 0.5.0, < 1.0.0)
|
23
|
+
nokogiri (>= 1.5.3, < 2.0.0)
|
24
|
+
googleauth (0.14.0)
|
25
|
+
faraday (>= 0.17.3, < 2.0)
|
26
|
+
jwt (>= 1.4, < 3.0)
|
27
|
+
memoist (~> 0.16)
|
28
|
+
multi_json (~> 1.11)
|
29
|
+
os (>= 0.9, < 2.0)
|
30
|
+
signet (~> 0.14)
|
31
|
+
httpclient (2.8.3)
|
32
|
+
jwt (2.2.2)
|
33
|
+
memoist (0.16.2)
|
34
|
+
mini_mime (1.0.2)
|
35
|
+
mini_portile2 (2.4.0)
|
36
|
+
multi_json (1.15.0)
|
37
|
+
multipart-post (2.1.1)
|
38
|
+
nokogiri (1.10.10)
|
39
|
+
mini_portile2 (~> 2.4.0)
|
40
|
+
os (1.1.1)
|
41
|
+
public_suffix (4.0.6)
|
42
|
+
representable (3.0.4)
|
43
|
+
declarative (< 0.1.0)
|
44
|
+
declarative-option (< 0.2.0)
|
45
|
+
uber (< 0.2.0)
|
46
|
+
retriable (3.1.2)
|
47
|
+
rexml (3.2.4)
|
48
|
+
ruby2_keywords (0.0.2)
|
49
|
+
signet (0.14.0)
|
50
|
+
addressable (~> 2.3)
|
51
|
+
faraday (>= 0.17.3, < 2.0)
|
52
|
+
jwt (>= 1.5, < 3.0)
|
53
|
+
multi_json (~> 1.10)
|
54
|
+
uber (0.1.0)
|
55
|
+
|
56
|
+
PLATFORMS
|
57
|
+
ruby
|
58
|
+
|
59
|
+
DEPENDENCIES
|
60
|
+
google_drive
|
61
|
+
|
62
|
+
BUNDLED WITH
|
63
|
+
2.1.4
|
data/README.md
ADDED
File without changes
|
data/bin/gdrive
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'pry'
|
4
|
+
require 'json'
|
5
|
+
begin
|
6
|
+
require_relative '../lib/gdrive-lib'
|
7
|
+
rescue LoadError
|
8
|
+
abort "You need to install the google_drive gem first."
|
9
|
+
end
|
10
|
+
|
11
|
+
CREDENTIALS_FILE_PATH = File.expand_path('~/.gdrive.json')
|
12
|
+
CLI.ensure_credentials_file(CREDENTIALS_FILE_PATH)
|
13
|
+
|
14
|
+
cli = CLI.build(CREDENTIALS_FILE_PATH)
|
15
|
+
|
16
|
+
case ARGV.shift
|
17
|
+
when 'list', 'ls' then cli.command_list(ARGV.first)
|
18
|
+
when 'find' then cli.command_find(ARGV.first)
|
19
|
+
when 'search' then cli.command_search(ARGV.first)
|
20
|
+
when 'cat' then cli.command_cat(ARGV.first)
|
21
|
+
when 'download' then cli.command_download(*ARGV[0..2])
|
22
|
+
when 'upload' then cli.command_upload(*ARGV)
|
23
|
+
when 'mkdir' then cli.command_mkdir(ARGV.first)
|
24
|
+
when 'remove', 'rm' then cli.command_remove(ARGV.first)
|
25
|
+
else
|
26
|
+
puts eval("\"#{DATA.read}\"")
|
27
|
+
end
|
28
|
+
|
29
|
+
__END__
|
30
|
+
#{`tput setaf 9`}Usage:#{`tput sgr0`}
|
31
|
+
|
32
|
+
#{`tput setaf 10`}#{File.basename($0)} ls [path]#{`tput sgr0`} List given path. If no path is given, root is assummed.
|
33
|
+
#{`tput setaf 10`}#{File.basename($0)} find [path]#{`tput sgr0`} List given path recursively. If no path is given, root is assummed.
|
34
|
+
#{`tput setaf 10`}#{File.basename($0)} search [title]#{`tput sgr0`} Look for file title.
|
35
|
+
|
36
|
+
#{`tput setaf 11`}#{File.basename($0)} mkdir [path]#{`tput sgr0`} Create a directory.
|
37
|
+
#{`tput setaf 11`}#{File.basename($0)} download [path]#{`tput sgr0`} Download a file.
|
38
|
+
#{`tput setaf 11`}#{File.basename($0)} upload [local paths] [remote path]#{`tput sgr0`} Upload file(s) into a remote path. Remote path doesn't have to exist yet, but its dirname has to exist.
|
39
|
+
#{`tput setaf 11`}#{File.basename($0)} cat [path]#{`tput sgr0`} Print out remote file.
|
40
|
+
|
41
|
+
#{`tput setaf 9`}#{File.basename($0)} remove [remote path]#{`tput sgr0`} Delete remote file.
|
data/gdrive-cli.gemspec
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
Gem::Specification.new do |spec|
|
2
|
+
spec.name = 'gdrive-cli'
|
3
|
+
spec.version = '0.0.2'
|
4
|
+
spec.license = 'MIT' # Just so gem build would shut up. Use it however you like.
|
5
|
+
|
6
|
+
spec.summary = "Manage your Google Drive from command line"
|
7
|
+
spec.author = "Jakub Šťastný"
|
8
|
+
spec.homepage = 'https://github.com/jakub-stastny/gdrive-cli'
|
9
|
+
|
10
|
+
spec.files = Dir["{lib,spec}/**/*.rb"] + Dir["bin/*"] + ['Gemfile', 'Gemfile.lock', 'README.md', 'gdrive-cli.gemspec']
|
11
|
+
spec.executables << 'gdrive'
|
12
|
+
end
|
data/lib/gdrive-lib.rb
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'google_drive'
|
2
|
+
|
3
|
+
# TODO: double upload shouldn't be possible (same file name), but is is now.
|
4
|
+
class CLI
|
5
|
+
class InvalidPathError < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
class ErrorNotDirectory < StandardError
|
9
|
+
attr_reader :file
|
10
|
+
def initialize(file)
|
11
|
+
@file = file
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# This has to be a file, so it can be updated with scope and refresh token (automatically).
|
16
|
+
def self.ensure_credentials_file(credentials_file_path)
|
17
|
+
unless File.file?(credentials_file_path)
|
18
|
+
id = ENV.fetch('GDRIVE_CLIENT_ID')
|
19
|
+
secret = ENV.fetch('GDRIVE_CLIENT_SECRET')
|
20
|
+
|
21
|
+
File.open(credentials_file_path, 'w') do |file|
|
22
|
+
file.puts({client_id: id, client_secret: secret}.to_json)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Creates a session. This will prompt the credential via command line for the
|
28
|
+
# first time and save it to config.json file for later usages.
|
29
|
+
# See this document to learn how to create config.json:
|
30
|
+
# https://github.com/gimite/google-drive-ruby/blob/master/doc/authorization.md
|
31
|
+
def self.build(credentials_file_path)
|
32
|
+
self.new(GoogleDrive::Session.from_config(credentials_file_path))
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(session)
|
36
|
+
@session = session
|
37
|
+
end
|
38
|
+
|
39
|
+
def command_list(destination)
|
40
|
+
collection = self.get_collection(destination)
|
41
|
+
collection.files.uniq(&:title).sort_by(&:title).each do |file|
|
42
|
+
puts file.is_a?(GoogleDrive::Collection) ? "#{`tput setaf 4`}#{file.title}#{`tput sgr0`}" : file.title
|
43
|
+
end
|
44
|
+
rescue ErrorNotDirectory => error # If given path points to a file, show more details.
|
45
|
+
p error.file
|
46
|
+
rescue Interrupt
|
47
|
+
puts
|
48
|
+
end
|
49
|
+
|
50
|
+
def command_find(destination)
|
51
|
+
self.find(self.get_collection(destination))
|
52
|
+
rescue ErrorNotDirectory => error # If given path points to a file, show more details.
|
53
|
+
p error.file
|
54
|
+
rescue Interrupt
|
55
|
+
puts
|
56
|
+
end
|
57
|
+
|
58
|
+
# FIXME: Doesn't work.
|
59
|
+
def command_search(title)
|
60
|
+
drive_service = @session.instance_variable_get(:@fetcher).drive
|
61
|
+
query = "title contains '#{ARGV.first}'"
|
62
|
+
puts "Query: #{query}"
|
63
|
+
files = drive_service.list_files(q: query)
|
64
|
+
files.items.each do |file|
|
65
|
+
puts file.title
|
66
|
+
end
|
67
|
+
rescue Interrupt
|
68
|
+
puts
|
69
|
+
end
|
70
|
+
|
71
|
+
def command_cat(remote_path)
|
72
|
+
remote_path, local_path = ARGV
|
73
|
+
local_path ||= File.basename(remote_path)
|
74
|
+
file = self.find_file(remote_path)
|
75
|
+
file || abort("File #{remote_path} not found")
|
76
|
+
if file.is_a?(GoogleDrive::Collection)
|
77
|
+
abort "File #{remote_path} is a directory"
|
78
|
+
else
|
79
|
+
puts file.download_to_string
|
80
|
+
end
|
81
|
+
rescue Interrupt
|
82
|
+
puts
|
83
|
+
end
|
84
|
+
|
85
|
+
def command_download(remote_path, local_path = File.basename(remote_path))
|
86
|
+
puts "~ Downloading '#{remote_path}' to #{local_path}"
|
87
|
+
download(remote_path, local_path)
|
88
|
+
rescue Interrupt
|
89
|
+
puts
|
90
|
+
end
|
91
|
+
|
92
|
+
# Upload to WIP:
|
93
|
+
# upload song.mp3 song2.mp3
|
94
|
+
# upload song.mp3 song2.mp3 -- songs
|
95
|
+
def command_upload(*args)
|
96
|
+
if separator_index = args.index('--')
|
97
|
+
local_paths = args[0..(separator_index - 1)]
|
98
|
+
remote_paths = args[(separator_index + 1)..-1]
|
99
|
+
if remote_path.length != 1
|
100
|
+
abort "x"
|
101
|
+
end
|
102
|
+
remote_path = remote_paths.first
|
103
|
+
else
|
104
|
+
local_paths = args
|
105
|
+
remote_path = local_paths.length == 1 ? local_paths.first : 'WIP'
|
106
|
+
end
|
107
|
+
require 'pry'; binding.pry ###
|
108
|
+
local_path, remote_path = "/#{File.basename(local_path)}"
|
109
|
+
# If path is given as relative, File.dirname(remote_path) returns '.' and
|
110
|
+
# self.find_file returns nil.
|
111
|
+
remote_path = "/#{remote_path}" unless remote_path.start_with?('/')
|
112
|
+
|
113
|
+
puts "~ Uploading '#{local_path}' to #{remote_path}"
|
114
|
+
file = @session.upload_from_file(local_path, File.basename(remote_path), convert: false)
|
115
|
+
|
116
|
+
# File is always uploaded to the root_collection by default.
|
117
|
+
# https://github.com/gimite/google-drive-ruby/issues/260
|
118
|
+
unless self.find_file(File.dirname(remote_path)) == @session.root_collection
|
119
|
+
require 'pry'; binding.pry ###
|
120
|
+
self.find_file(File.dirname(remote_path)).add(file)
|
121
|
+
@session.root_collection.remove(file)
|
122
|
+
end
|
123
|
+
rescue Interrupt
|
124
|
+
puts
|
125
|
+
end
|
126
|
+
|
127
|
+
def command_mkdir(remote_path)
|
128
|
+
*dirnames, basename = ARGV.first.split('/')
|
129
|
+
collection = dirnames.empty? ? @session.root_collection : self.find_file(dirnames.join('/'))
|
130
|
+
collection.create_subcollection(ARGV.first.split('/').last)
|
131
|
+
rescue Interrupt
|
132
|
+
puts
|
133
|
+
end
|
134
|
+
|
135
|
+
def command_remove(remote_path)
|
136
|
+
puts "~ Deleting '#{ARGV.first}'"
|
137
|
+
file = self.find_file(ARGV.first)
|
138
|
+
file.delete(true)
|
139
|
+
rescue Interrupt
|
140
|
+
puts
|
141
|
+
end
|
142
|
+
|
143
|
+
protected
|
144
|
+
def get_collection(destination)
|
145
|
+
result = destination.nil? || destination == '/' ? @session.root_collection : self.find_file(destination.sub(/^\//, ''))
|
146
|
+
raise InvalidPathError if result.nil?
|
147
|
+
raise ErrorNotDirectory.new(result) unless result.respond_to?(:create_subcollection)
|
148
|
+
result
|
149
|
+
end
|
150
|
+
|
151
|
+
def find_file(full_path)
|
152
|
+
full_path.split('/').reduce(@session.root_collection) do |parent, file_name|
|
153
|
+
parent.file_by_title(file_name)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def download(remote_path, local_path)
|
158
|
+
file = self.find_file(remote_path)
|
159
|
+
file || abort("File #{remote_path} not found")
|
160
|
+
if file.is_a?(GoogleDrive::Collection)
|
161
|
+
Dir.mkdir(local_path)
|
162
|
+
Dir.chdir(local_path) do
|
163
|
+
file.files.each do |file|
|
164
|
+
download(file)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
else
|
168
|
+
file.download_to_file(local_path)
|
169
|
+
end
|
170
|
+
rescue NotImplementedError
|
171
|
+
# This will want the format to be specified most likely.
|
172
|
+
#
|
173
|
+
# file.export_as_file(local_path)
|
174
|
+
binding.pry
|
175
|
+
end
|
176
|
+
|
177
|
+
def find(collection, dirname = nil)
|
178
|
+
collection.files.uniq(&:title).sort_by(&:title).each do |file|
|
179
|
+
if file.is_a?(GoogleDrive::Collection)
|
180
|
+
self.find(file, [dirname, file.title].compact.join('/'))
|
181
|
+
else
|
182
|
+
puts [dirname, file.title].compact.join('/')
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
metadata
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gdrive-cli
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jakub Šťastný
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-12-03 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email:
|
15
|
+
executables:
|
16
|
+
- gdrive
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- Gemfile
|
21
|
+
- Gemfile.lock
|
22
|
+
- README.md
|
23
|
+
- bin/gdrive
|
24
|
+
- gdrive-cli.gemspec
|
25
|
+
- lib/gdrive-lib.rb
|
26
|
+
homepage: https://github.com/jakub-stastny/gdrive-cli
|
27
|
+
licenses:
|
28
|
+
- MIT
|
29
|
+
metadata: {}
|
30
|
+
post_install_message:
|
31
|
+
rdoc_options: []
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ">="
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
requirements: []
|
45
|
+
rubygems_version: 3.1.2
|
46
|
+
signing_key:
|
47
|
+
specification_version: 4
|
48
|
+
summary: Manage your Google Drive from command line
|
49
|
+
test_files: []
|