googledrive-easy 0.1.5 → 0.1.7
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/bin/googledrive +1 -1
- data/lib/googledrive-easy-test.rb +130 -47
- data/lib/googledrive-easy.rb +92 -93
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 980d20ae39d421ac858a8ccceabd2d6d7ba95ea9e8e0181ffbf96d068d217b99
|
4
|
+
data.tar.gz: 1593952ec9b4d4a4746a95039816eee6cd6cbda6c86757fbeea28688caf84423
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d2b9e15ea96f2a7eecd9c510463ce4dc5628515aec068c06cc6360260bbb030fe636bfc11f8202f5bf69a9abf48c71d7d705235675c4b5d720f101c0a9b501d
|
7
|
+
data.tar.gz: 682e5cf1e0e3ca41518ea3ef55c1b47351519bf1132999418950ea2689c71b8fdf8947b0f0b691456d8fef17e26c332de0a17749f5e4bacb7d6fd7b4fffc5717
|
data/bin/googledrive
CHANGED
@@ -46,7 +46,7 @@ def print_hash_for_env_use(keys)
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def handle_auth(options)
|
49
|
-
drive = GoogleDrive::new(raise_error:
|
49
|
+
drive = GoogleDrive::new(raise_error: true, loglevel: Logger::ERROR)
|
50
50
|
|
51
51
|
# Handle special service mode cases
|
52
52
|
case options[:authmode]
|
@@ -57,11 +57,16 @@ class GoogleDriveEasyTest < Test::Unit::TestCase
|
|
57
57
|
def test_loading_api_vars_from_env_success
|
58
58
|
configure_environment
|
59
59
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
60
|
+
2.times do |i|
|
61
|
+
result = @drive.load_api_keys_from_env
|
62
|
+
assert(result, "load_api_keys_from_env should return true")
|
63
|
+
assert_equal(@client_id, @drive.instance_variable_get(:@client_id), "Client ID should be loaded")
|
64
|
+
assert_equal(@client_secret, @drive.instance_variable_get(:@client_secret), "Client Secret should be loaded")
|
65
|
+
assert_equal(@refresh_token, @drive.instance_variable_get(:@refresh_token), "Refresh Token should be loaded")
|
66
|
+
|
67
|
+
# Enable raise error for second run.
|
68
|
+
@drive.set_raise_error
|
69
|
+
end
|
65
70
|
end
|
66
71
|
|
67
72
|
def test_loading_api_vars_from_env_missing_fail
|
@@ -74,6 +79,10 @@ class GoogleDriveEasyTest < Test::Unit::TestCase
|
|
74
79
|
assert_equal(nil, @drive.instance_variable_get(:@client_id), "Client ID should not be loaded")
|
75
80
|
assert_equal(nil, @drive.instance_variable_get(:@client_secret), "Client Secret should not be loaded")
|
76
81
|
assert_equal(nil, @drive.instance_variable_get(:@refresh_token), "Refresh Token should not be loaded")
|
82
|
+
|
83
|
+
@drive.set_raise_error
|
84
|
+
exception = assert_raise(RuntimeError) { @drive.load_api_keys_from_env }
|
85
|
+
assert_equal("DRIVEAPI_CLIENT_SECRET export variable not set.", exception.message)
|
77
86
|
end
|
78
87
|
|
79
88
|
def test_loading_api_vars_from_file_success
|
@@ -82,13 +91,16 @@ class GoogleDriveEasyTest < Test::Unit::TestCase
|
|
82
91
|
|
83
92
|
# Override default key file
|
84
93
|
# @drive.instance_variable_set(:@api_key_file, @env_file.path)
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
94
|
+
2.times do |i|
|
95
|
+
# Attempt load
|
96
|
+
result = @drive.load_api_keys_from_file(path:@env_file.path)
|
97
|
+
assert(result, "load_api_keys_from_file should return true")
|
98
|
+
assert_equal(@client_id, @drive.instance_variable_get(:@client_id), "Client ID should be loaded")
|
99
|
+
assert_equal(@client_secret, @drive.instance_variable_get(:@client_secret), "Client Secret should be loaded")
|
100
|
+
assert_equal(@refresh_token, @drive.instance_variable_get(:@refresh_token), "Refresh Token should be loaded")
|
101
|
+
# Enable raise error for second run.
|
102
|
+
@drive.set_raise_error
|
103
|
+
end
|
92
104
|
end
|
93
105
|
|
94
106
|
def test_loading_api_vars_from_file_not_found
|
@@ -101,6 +113,10 @@ class GoogleDriveEasyTest < Test::Unit::TestCase
|
|
101
113
|
assert_equal(nil, @drive.instance_variable_get(:@client_id), "Client ID should be loaded")
|
102
114
|
assert_equal(nil, @drive.instance_variable_get(:@client_secret), "Client Secret should be loaded")
|
103
115
|
assert_equal(nil, @drive.instance_variable_get(:@refresh_token), "Refresh Token should be loaded")
|
116
|
+
|
117
|
+
@drive.set_raise_error
|
118
|
+
exception = assert_raise(RuntimeError) { @drive.load_api_keys_from_file }
|
119
|
+
assert_equal("Cannot find /tmp/bogons", exception.message)
|
104
120
|
end
|
105
121
|
|
106
122
|
###########################
|
@@ -111,9 +127,12 @@ class GoogleDriveEasyTest < Test::Unit::TestCase
|
|
111
127
|
@drive.instance_variable_set(:@client_id, @client_id)
|
112
128
|
@drive.instance_variable_set(:@client_secret, @client_secret)
|
113
129
|
|
114
|
-
|
115
|
-
|
116
|
-
|
130
|
+
2.times do
|
131
|
+
api_hash = @drive.generate_api_secret_hash
|
132
|
+
assert_equal(@client_id, api_hash['installed']['client_id'], 'Hash should contain client id')
|
133
|
+
assert_equal(@client_secret, api_hash['installed']['client_secret'], 'Hash should contain client secret')
|
134
|
+
@drive.set_raise_error
|
135
|
+
end
|
117
136
|
end
|
118
137
|
|
119
138
|
def test_generate_token_yaml_success
|
@@ -123,11 +142,13 @@ class GoogleDriveEasyTest < Test::Unit::TestCase
|
|
123
142
|
@drive.instance_variable_set(:@refresh_token, @refresh_token)
|
124
143
|
token_file_user = @drive.instance_variable_get(:@token_file_user)
|
125
144
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
145
|
+
2.times do
|
146
|
+
yaml_string = @drive.generate_token_yaml
|
147
|
+
assert(yaml_string.include?(token_file_user), "Result should contain token_file_user")
|
148
|
+
assert(yaml_string.include?(@client_id), "Result should contain client_id")
|
149
|
+
assert(yaml_string.include?(@refresh_token), "Result should contain refresh_token")
|
150
|
+
@drive.set_raise_error
|
151
|
+
end
|
131
152
|
end
|
132
153
|
|
133
154
|
def test_generate_token_yaml_fail
|
@@ -135,6 +156,9 @@ class GoogleDriveEasyTest < Test::Unit::TestCase
|
|
135
156
|
# @drive_wrapper.instance_variable_set(:@client_id, @client_id)
|
136
157
|
@drive.instance_variable_set(:@refresh_token, @refresh_token)
|
137
158
|
assert(!@drive.generate_token_yaml, "Generation of token yaml should fail with partial config")
|
159
|
+
|
160
|
+
@drive.set_raise_error
|
161
|
+
assert_raise(RuntimeError) { @drive.generate_token_yaml }
|
138
162
|
end
|
139
163
|
|
140
164
|
def test_generate_temp_token_file
|
@@ -143,11 +167,14 @@ class GoogleDriveEasyTest < Test::Unit::TestCase
|
|
143
167
|
@drive.instance_variable_set(:@refresh_token, @refresh_token)
|
144
168
|
token_file_user = @drive.instance_variable_get(:@token_file_user)
|
145
169
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
170
|
+
2.times do
|
171
|
+
tmp_file_path = @drive.generate_temp_token_file
|
172
|
+
tmp_file_contents = File.read(tmp_file_path)
|
173
|
+
assert(tmp_file_contents.include?(token_file_user), "Result should contain token_file_user")
|
174
|
+
assert(tmp_file_contents.include?(@client_id), "Result should contain client_id")
|
175
|
+
assert(tmp_file_contents.include?(@refresh_token), "Result should contain refresh_token")
|
176
|
+
@drive.set_raise_error
|
177
|
+
end
|
151
178
|
end
|
152
179
|
|
153
180
|
#########################################
|
@@ -162,34 +189,43 @@ class GoogleDriveEasyTest < Test::Unit::TestCase
|
|
162
189
|
# Use this, or just set the path directly.
|
163
190
|
@drive.load_api_keys_from_file(path:@env_file.path)
|
164
191
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
192
|
+
2.times do
|
193
|
+
# Authorize
|
194
|
+
result = @drive.create_service(mode: 'manual')
|
195
|
+
assert(result, "Authorization from configured environment should succeed.")
|
196
|
+
assert(@drive.instance_variable_get(:@credentials), "Credentials should be set")
|
197
|
+
assert_instance_of(Google::Apis::DriveV3::DriveService, result, "Should return instance of Google Drive Service")
|
198
|
+
@drive.set_raise_error
|
199
|
+
end
|
170
200
|
end
|
171
201
|
|
172
202
|
def test_create_service_environment
|
173
203
|
omit("Test Environment not correctly configured for live tests") unless @test_env_vars_defined
|
174
204
|
configure_environment
|
175
205
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
206
|
+
2.times do
|
207
|
+
# Authorize
|
208
|
+
result = @drive.create_service(mode: 'environment')
|
209
|
+
assert(result, "Authorization from configured environment should succeed.")
|
210
|
+
assert(@drive.instance_variable_get(:@credentials), "Credentials should be set")
|
211
|
+
puts @drive.instance_variable_get(:@credentials)
|
212
|
+
assert_instance_of(Google::Apis::DriveV3::DriveService, result, "Should return instance of Google Drive Service")
|
213
|
+
@drive.set_raise_error
|
214
|
+
end
|
182
215
|
end
|
183
216
|
|
184
217
|
def test_create_service_manual
|
185
218
|
omit("Test Environment not correctly configured for live tests") unless @test_env_vars_defined
|
186
219
|
@drive.set_api_keys(client_id: @client_id, client_secret: @client_secret, refresh_token: @refresh_token)
|
187
220
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
221
|
+
2.times do
|
222
|
+
# Authorize
|
223
|
+
result = @drive.create_service(mode: 'manual')
|
224
|
+
assert(result, "Authorization from manual configuration should succeed.")
|
225
|
+
assert(@drive.instance_variable_get(:@credentials), "Credentials should be set")
|
226
|
+
assert_instance_of(Google::Apis::DriveV3::DriveService, result, "Should return instance of Google Drive Service")
|
227
|
+
@drive.set_raise_error
|
228
|
+
end
|
193
229
|
end
|
194
230
|
|
195
231
|
###########################################
|
@@ -216,18 +252,65 @@ class GoogleDriveEasyTest < Test::Unit::TestCase
|
|
216
252
|
|
217
253
|
@drive.set_api_keys(client_id: @client_id, client_secret: @client_secret, refresh_token: @refresh_token)
|
218
254
|
@drive.create_service(mode:'manual')
|
219
|
-
|
220
|
-
|
255
|
+
|
256
|
+
2.times do
|
257
|
+
res = @drive.get_all_files(name: "rxgos*")
|
258
|
+
assert_instance_of(Array, res, "Returns list")
|
259
|
+
@drive.set_raise_error
|
260
|
+
end
|
221
261
|
end
|
222
262
|
|
223
263
|
def test_get_file_info
|
224
264
|
omit("Test Environment not correctly configured for live tests") unless @test_env_vars_defined
|
225
265
|
@drive.set_api_keys(client_id: @client_id, client_secret: @client_secret, refresh_token: @refresh_token)
|
226
266
|
@drive.create_service(mode:'manual')
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
267
|
+
|
268
|
+
2.times do
|
269
|
+
res = @drive.get_file_info("10l2ahCetnm1_147rRcuaObTwrntqQuRz")
|
270
|
+
assert_instance_of(Hash, res, 'Should return a Hash')
|
271
|
+
assert_equal("rxg", res[:name], "Name should be 'rxg'")
|
272
|
+
# assert_instance_of(Google::Apis::DriveV3::File, res, 'Should be instance of Google::Apis::DriveV3::File')
|
273
|
+
@drive.set_raise_error
|
274
|
+
end
|
231
275
|
end
|
232
276
|
|
277
|
+
def test_get_file_info_nofile
|
278
|
+
omit("Test Environment not correctly configured for live tests") unless @test_env_vars_defined
|
279
|
+
@drive.set_api_keys(client_id: @client_id, client_secret: @client_secret, refresh_token: @refresh_token)
|
280
|
+
@drive.create_service(mode:'manual')
|
281
|
+
|
282
|
+
res = @drive.get_file_info("10l2ahCetnm1_147rRcuaObTwrntqQZZZ")
|
283
|
+
assert_false(res, "Result should be false")
|
284
|
+
|
285
|
+
# Doesn't raise on not-found
|
286
|
+
end
|
287
|
+
|
288
|
+
def test_find_directory_id
|
289
|
+
omit("Test Environment not correctly configured for live tests") unless @test_env_vars_defined
|
290
|
+
@drive.set_api_keys(client_id: @client_id, client_secret: @client_secret, refresh_token: @refresh_token)
|
291
|
+
@drive.create_service(mode:'manual')
|
292
|
+
|
293
|
+
2.times do
|
294
|
+
res = @drive.find_directory_id("rxg")
|
295
|
+
assert_equal("10l2ahCetnm1_147rRcuaObTwrntqQuRz", res)
|
296
|
+
# assert_instance_of(Google::Apis::DriveV3::File, res, 'Should be instance of Google::Apis::DriveV3::File')
|
297
|
+
res = @drive.get_file_info("10l2ahCetnm1_147rRcuaObTwrntqQuRz")
|
298
|
+
@drive.set_raise_error
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def test_find_directory_id_nodir
|
303
|
+
omit("Test Environment not correctly configured for live tests") unless @test_env_vars_defined
|
304
|
+
@drive.set_api_keys(client_id: @client_id, client_secret: @client_secret, refresh_token: @refresh_token)
|
305
|
+
@drive.create_service(mode:'manual')
|
306
|
+
|
307
|
+
res = @drive.find_directory_id("nonexistantdirectory")
|
308
|
+
assert_false(res, "Result should be false")
|
309
|
+
|
310
|
+
@drive.set_raise_error
|
311
|
+
assert_raise(RuntimeError) { res = @drive.find_directory_id("nonexistantdirectory") }
|
312
|
+
# Doesn't raise on not-found
|
313
|
+
end
|
314
|
+
|
315
|
+
|
233
316
|
end
|
data/lib/googledrive-easy.rb
CHANGED
@@ -85,16 +85,20 @@ class GoogleDrive
|
|
85
85
|
TEXT
|
86
86
|
end
|
87
87
|
|
88
|
-
def
|
88
|
+
def set_raise_error(raise_error=true)
|
89
|
+
@raise_error = raise_error
|
90
|
+
end
|
91
|
+
|
92
|
+
def log_error_and_raise(msg, raise_error=@raise_error)
|
89
93
|
@logger.error(msg)
|
90
|
-
raise "msg" if
|
94
|
+
raise "#{msg}" if raise_error
|
95
|
+
false
|
91
96
|
end
|
92
97
|
|
93
|
-
def set_api_keys(client_id:nil, client_secret:nil, refresh_token:nil, access_token:nil, require_refresh_token:true)
|
98
|
+
def set_api_keys(client_id:nil, client_secret:nil, refresh_token:nil, access_token:nil, require_refresh_token:true, raise_error: @raise_error )
|
94
99
|
# Recommended service mode if manually called: manual
|
95
100
|
unless client_id && client_secret && (refresh_token || !require_refresh_token)
|
96
|
-
log_error_and_raise("Not all tokens provided.")
|
97
|
-
return false
|
101
|
+
return log_error_and_raise("Not all tokens provided.", raise_error)
|
98
102
|
end
|
99
103
|
@client_id = client_id if client_id
|
100
104
|
@client_secret = client_secret if client_secret
|
@@ -103,15 +107,14 @@ class GoogleDrive
|
|
103
107
|
return true
|
104
108
|
end
|
105
109
|
|
106
|
-
def load_api_keys_from_file(path:nil, require_refresh_token:true)
|
110
|
+
def load_api_keys_from_file(path:nil, require_refresh_token:true, raise_error: @raise_error)
|
107
111
|
@loaded_api_key_file = path ? path : @api_key_file
|
108
112
|
if(File.exist?(@loaded_api_key_file))
|
109
113
|
@logger.info("API key file #{@loaded_api_key_file} exists")
|
110
114
|
begin
|
111
115
|
api_hash = JSON.parse(File.read(@loaded_api_key_file))
|
112
116
|
rescue => error
|
113
|
-
log_error_and_raise("Error opening api key file: " + error.inspect)
|
114
|
-
return false
|
117
|
+
return log_error_and_raise("Error opening api key file: " + error.inspect, raise_error)
|
115
118
|
end
|
116
119
|
|
117
120
|
@logger.debug("api_hash: " + api_hash.inspect)
|
@@ -124,38 +127,41 @@ class GoogleDrive
|
|
124
127
|
client_id:api_hash["CLIENT_ID"],
|
125
128
|
client_secret:api_hash["CLIENT_SECRET"],
|
126
129
|
refresh_token:api_hash["REFRESH_TOKEN"],
|
127
|
-
require_refresh_token:require_refresh_token
|
130
|
+
require_refresh_token:require_refresh_token,
|
131
|
+
raise_error: false
|
128
132
|
)
|
129
133
|
@logger.info("Using Google Drive API information from #{@loaded_api_key_file}")
|
130
134
|
else
|
131
|
-
log_error_and_raise("Not all API keys were in file #{@loaded_api_key_file}.")
|
132
|
-
return false
|
135
|
+
return log_error_and_raise("Not all API keys were in file #{@loaded_api_key_file}.", raise_error)
|
133
136
|
end
|
134
137
|
else
|
135
|
-
log_error_and_raise("Cannot find #{@loaded_api_key_file}")
|
136
|
-
return false
|
138
|
+
return log_error_and_raise("Cannot find #{@loaded_api_key_file}", raise_error)
|
137
139
|
end
|
138
140
|
true
|
139
141
|
end
|
140
142
|
|
141
|
-
def load_api_keys_from_env(require_refresh_token:true)
|
143
|
+
def load_api_keys_from_env(require_refresh_token:true, raise_error: @raise_error)
|
142
144
|
# Google Drive Credentials from ENV if not derived from JSON file in home.
|
143
145
|
vars = [ENV_KEYS[:id], ENV_KEYS[:secret]]
|
144
146
|
vars << ENV_KEYS[:refresh] if require_refresh_token
|
145
147
|
vars.each do |v|
|
146
148
|
if ENV[v].nil?
|
147
|
-
log_error_and_raise("#{v} export variable not set.")
|
148
|
-
return false
|
149
|
+
return log_error_and_raise("#{v} export variable not set.", raise_error)
|
149
150
|
end
|
150
151
|
end
|
151
152
|
|
152
153
|
# Set
|
153
|
-
|
154
|
+
if set_api_keys(
|
154
155
|
client_id:ENV[ENV_KEYS[:id]],
|
155
156
|
client_secret:ENV[ENV_KEYS[:secret]],
|
156
157
|
refresh_token:ENV[ENV_KEYS[:refresh]],
|
157
|
-
require_refresh_token:require_refresh_token
|
158
|
+
require_refresh_token:require_refresh_token,
|
159
|
+
raise_error: raise_error
|
158
160
|
)
|
161
|
+
@logger.info("Using Google Drive API information from environment.")
|
162
|
+
else
|
163
|
+
return log_error_and_raise("Not all API keys were in environment.", raise_error)
|
164
|
+
end
|
159
165
|
end
|
160
166
|
|
161
167
|
def generate_api_secret_hash
|
@@ -182,12 +188,11 @@ class GoogleDrive
|
|
182
188
|
end
|
183
189
|
|
184
190
|
# Generates token yaml
|
185
|
-
def generate_token_yaml
|
191
|
+
def generate_token_yaml(raise_error: @raise_error)
|
186
192
|
unless @client_id && @refresh_token
|
187
193
|
api_config = {"client_id" => @client_id, "refresh_token" => @refresh_token }
|
188
194
|
@logger.debug("API Config: #{api_config}")
|
189
|
-
log_error_and_raise("Some required API config for token hasn't been configured yet")
|
190
|
-
return false
|
195
|
+
return log_error_and_raise("Some required API config for token hasn't been configured yet", raise_error)
|
191
196
|
end
|
192
197
|
|
193
198
|
drive_token_hash = {
|
@@ -201,12 +206,10 @@ class GoogleDrive
|
|
201
206
|
end
|
202
207
|
|
203
208
|
# Generates temp token file and return path to it
|
204
|
-
def generate_temp_token_file
|
209
|
+
def generate_temp_token_file(raise_error: @raise_error)
|
205
210
|
tmpfile = Tempfile.new('drive_token')
|
206
|
-
token_yaml = generate_token_yaml
|
207
|
-
unless token_yaml
|
208
|
-
return false
|
209
|
-
end
|
211
|
+
token_yaml = generate_token_yaml(raise_error: raise_error)
|
212
|
+
return false unless token_yaml
|
210
213
|
tmpfile.write(token_yaml)
|
211
214
|
tmpfile.flush # flush file contents before continuing.
|
212
215
|
return @drive_token_path = File.expand_path(tmpfile.path)
|
@@ -226,7 +229,6 @@ class GoogleDrive
|
|
226
229
|
# from the machine running the authenticating browser to the machine running this script,
|
227
230
|
# likely via `ssh user@host -L @oauth_port:@oauth_address:@oauth_port`
|
228
231
|
def get_oauth_credentials_via_loopback(authorizer)
|
229
|
-
# TODO: This a raw copy, refactor
|
230
232
|
# Print instructions and URL for user to click
|
231
233
|
# TODO: Should this be puts or @logger? it's a user interaction...
|
232
234
|
puts "Listening on #{@oauth_address}:#{@oauth_port}."
|
@@ -270,7 +272,6 @@ class GoogleDrive
|
|
270
272
|
end
|
271
273
|
|
272
274
|
def get_oauth_credentials_via_input(authorizer)
|
273
|
-
# TODO: This a raw copy, refactor
|
274
275
|
puts 'Follow this url and complete the sign-in process. The login will result in an error, do not close it.'
|
275
276
|
puts 'Instead, copy and paste the value of the `code` parameter (begins with 4/)'
|
276
277
|
puts authorizer.get_authorization_url(base_url: "http://localhost:1")
|
@@ -289,8 +290,7 @@ class GoogleDrive
|
|
289
290
|
@logger.debug("Passed authorization mode: #{mode}")
|
290
291
|
|
291
292
|
unless %w(environment loopback input manual).include?(mode)
|
292
|
-
log_error_and_raise("Unknown authorization mode")
|
293
|
-
return false
|
293
|
+
return log_error_and_raise("Unknown authorization mode")
|
294
294
|
end
|
295
295
|
|
296
296
|
# TODO: Figure out balance between always requiring env config and just reading from the token store if it already exists
|
@@ -301,7 +301,10 @@ class GoogleDrive
|
|
301
301
|
if mode == "manual"
|
302
302
|
key_load_result = false
|
303
303
|
else
|
304
|
-
key_load_result = (
|
304
|
+
key_load_result = (
|
305
|
+
load_api_keys_from_env(require_refresh_token:!interactive_mode, raise_error: false) ||
|
306
|
+
load_api_keys_from_file(require_refresh_token:!interactive_mode, raise_error: false)
|
307
|
+
)
|
305
308
|
end
|
306
309
|
|
307
310
|
if interactive_mode && !key_load_result
|
@@ -311,22 +314,19 @@ class GoogleDrive
|
|
311
314
|
# If environment, we need key load to have succeeded completely
|
312
315
|
# If manual, it should pull from memory.
|
313
316
|
if %w(environment manual).include?(mode)
|
314
|
-
tmp_token_path = generate_temp_token_file
|
317
|
+
tmp_token_path = generate_temp_token_file(raise_error: false)
|
315
318
|
unless tmp_token_path
|
316
|
-
log_error_and_raise("Failed to generate temporary token file")
|
317
|
-
return false
|
319
|
+
return log_error_and_raise("Failed to generate temporary token file")
|
318
320
|
end
|
319
321
|
@logger.debug(File.read(tmp_token_path))
|
320
322
|
unless key_load_result || mode=='manual'
|
321
|
-
log_error_and_raise("Unable to load api keys from environment")
|
322
|
-
return false
|
323
|
+
return log_error_and_raise("Unable to load api keys from environment")
|
323
324
|
end
|
324
325
|
token_store = Google::Auth::Stores::FileTokenStore.new(file: tmp_token_path)
|
325
326
|
else
|
326
327
|
# Otherwise, just the ID and secret are enough
|
327
328
|
unless @client_secret && @client_id
|
328
|
-
log_error_and_raise("Client Secret or ID missing.")
|
329
|
-
return false
|
329
|
+
return log_error_and_raise("Client Secret or ID missing.")
|
330
330
|
end
|
331
331
|
token_store = Google::Auth::Stores::FileTokenStore.new(file: @drive_token_path)
|
332
332
|
end
|
@@ -352,8 +352,7 @@ class GoogleDrive
|
|
352
352
|
|
353
353
|
# Final cred check
|
354
354
|
if @credentials.nil?
|
355
|
-
@logger.error('Unable to retrieve credentials')
|
356
|
-
return false
|
355
|
+
return log_error_and_raise(@logger.error('Unable to retrieve credentials') )
|
357
356
|
end
|
358
357
|
|
359
358
|
# Update internal credentials based on credentials loaded
|
@@ -380,11 +379,8 @@ class GoogleDrive
|
|
380
379
|
# parentfolderid: "root" gets the root directory. Not all folders are under the root. Has to do with permissions
|
381
380
|
# and how Google Drive works.
|
382
381
|
# https://developers.google.com/drive/api/v3/reference/query-ref
|
383
|
-
def get_all_files(justfiles: false, justfolders: false, parentfolderid: nil, name: nil)
|
384
|
-
unless @drive_service
|
385
|
-
log_error_and_raise("Drive service not initialized.")
|
386
|
-
return false
|
387
|
-
end
|
382
|
+
def get_all_files(justfiles: false, justfolders: false, parentfolderid: nil, name: nil, raise_error: @raise_error)
|
383
|
+
return log_error_and_raise("Drive service not initialized.") unless @drive_service
|
388
384
|
|
389
385
|
# Number of files/directories to be returned each call to /files.
|
390
386
|
# multiple page sizes are handled with the pageToken return value.
|
@@ -401,16 +397,36 @@ class GoogleDrive
|
|
401
397
|
# parent folder has to be surrounded by single quotes in query
|
402
398
|
query += " and ('#{parentfolderid}' in parents)" if parentfolderid
|
403
399
|
# filename has to be surrounded by single quotes in query
|
404
|
-
|
400
|
+
|
401
|
+
if name
|
402
|
+
name.split("*").each_with_index do |part, idx|
|
403
|
+
if idx == 0 and name =~ /\*/ and part.size > 0
|
404
|
+
# If the above are true, this is the first piece, and it was followed by a *, so we should pass it in the
|
405
|
+
# format for prefix matching
|
406
|
+
query += " and (name contains '#{part}*')"
|
407
|
+
elsif idx == 0 and !(name =~ /\*/ )
|
408
|
+
# If the above is true, this is a literal equivalence search, no wildcards should be used.
|
409
|
+
query += " and (name = '#{part}')"
|
410
|
+
else
|
411
|
+
# If we're here, either we had a wildcard prefix, or we're on a later part of the search term. Do a contains.
|
412
|
+
query += " and (name contains '#{part}')" if part.size > 0
|
413
|
+
end
|
414
|
+
end
|
415
|
+
end
|
416
|
+
@logger.debug("Searching with query: #{query}")
|
405
417
|
|
406
418
|
files = [ ]
|
407
419
|
next_page_token = nil
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
420
|
+
begin
|
421
|
+
loop do
|
422
|
+
# TODO: Should this be converted to block form and then use that to gracefully handle failure and errors?
|
423
|
+
files_page = @drive_service.list_files(page_size: page_size, q: query, page_token: next_page_token, fields: fields)
|
424
|
+
files_page.files.each {|f| files << f}
|
425
|
+
next_page_token = files_page.next_page_token
|
426
|
+
break unless next_page_token
|
427
|
+
end
|
428
|
+
rescue => e
|
429
|
+
return log_error_and_raise("Error retrieving files: #{e}", raise_error)
|
414
430
|
end
|
415
431
|
|
416
432
|
# Process the returned files
|
@@ -420,7 +436,6 @@ class GoogleDrive
|
|
420
436
|
processed_files << process_file(file)
|
421
437
|
end
|
422
438
|
|
423
|
-
# Todo: Is this still really necessary? I think the list_files function can do this server-side. Need to research.
|
424
439
|
# we have additional processing to do it a wildcard character was passed. Because Google Drive "contains" returns all portions of it.
|
425
440
|
# so we need to filter here
|
426
441
|
if name =~ /\*/ # if name contains wildcard
|
@@ -437,45 +452,40 @@ class GoogleDrive
|
|
437
452
|
end
|
438
453
|
|
439
454
|
# returns all files by default in all folders
|
440
|
-
def find_files(name = "*", parentfolderid: nil)
|
441
|
-
return get_all_files(justfiles: true, parentfolderid: parentfolderid, name: name)
|
455
|
+
def find_files(name = "*", parentfolderid: nil, raise_error: @raise_error)
|
456
|
+
return get_all_files(justfiles: true, parentfolderid: parentfolderid, name: name, raise_error: raise_error)
|
442
457
|
end
|
443
458
|
|
444
|
-
def get_file_info(file_id)
|
445
|
-
unless @drive_service
|
446
|
-
|
447
|
-
|
459
|
+
def get_file_info(file_id, raise_error: @raise_error)
|
460
|
+
return log_error_and_raise("Drive service not initialized.") unless @drive_service
|
461
|
+
begin
|
462
|
+
# TODO: Maybe convert this to block format and handle errors like in other places
|
463
|
+
file = @drive_service.get_file(file_id, fields: "#{@file_fields}")
|
464
|
+
return process_file(file)
|
465
|
+
rescue => e
|
466
|
+
return log_error_and_raise("Error getting file info: #{e}.", raise_error)
|
448
467
|
end
|
449
|
-
|
450
|
-
# TODO: Maybe convert this to block format and handle errors like in other places
|
451
|
-
file = @drive_service.get_file(file_id, fields: "#{@file_fields}")
|
452
|
-
return process_file(file)
|
453
468
|
end
|
454
469
|
|
455
|
-
def find_directory_id(directory_name, parentfolderid: nil)
|
456
|
-
file_list = get_all_files(justfolders: true, name: directory_name, parentfolderid: parentfolderid)
|
470
|
+
def find_directory_id(directory_name, parentfolderid: nil, raise_error: @raise_error)
|
471
|
+
file_list = get_all_files(justfolders: true, name: directory_name, parentfolderid: parentfolderid, raise_error: raise_error)
|
457
472
|
|
458
473
|
if !file_list || (file_list.count == 0)
|
459
|
-
log_error_and_raise("Directory not found.")
|
460
|
-
return false
|
474
|
+
return log_error_and_raise("Directory not found.", raise_error)
|
461
475
|
end
|
462
476
|
|
463
477
|
return file_list.first[:id]
|
464
478
|
end
|
465
479
|
|
466
480
|
def upload_file(file, directory_id: nil)
|
467
|
-
unless @drive_service
|
468
|
-
log_error_and_raise("Drive service not initialized.")
|
469
|
-
return false
|
470
|
-
end
|
481
|
+
return log_error_and_raise("Drive service not initialized.") unless @drive_service
|
471
482
|
|
472
483
|
file_basename = File.basename(file)
|
473
484
|
# TODO: If no parent directory is passed, it will deny upload if a file by that name exists in any visible folder on any visible drive. How to fix?
|
474
485
|
# see if file exists on Drive
|
475
486
|
file_list = self.get_all_files(justfiles: true, parentfolderid: directory_id, name: file_basename)
|
476
487
|
if file_list.count > 0
|
477
|
-
log_error_and_raise("ERROR: File '#{file_basename}' already exists.")
|
478
|
-
return false
|
488
|
+
return log_error_and_raise("ERROR: File '#{file_basename}' already exists.")
|
479
489
|
end
|
480
490
|
|
481
491
|
file_obj = Google::Apis::DriveV3::File.new(name: file_basename)
|
@@ -486,24 +496,19 @@ class GoogleDrive
|
|
486
496
|
fields: @file_fields
|
487
497
|
) do |resfile, err|
|
488
498
|
if err
|
489
|
-
log_error_and_raise("Error: #{err}.")
|
490
|
-
return false
|
499
|
+
return log_error_and_raise("Error uploading file: #{err}.")
|
491
500
|
end
|
492
501
|
|
493
502
|
# check that name = filename
|
494
503
|
# check that kind = drive#file
|
495
504
|
if !resfile.name # name key does not exist
|
496
|
-
log_error_and_raise("no name key specified in response.")
|
497
|
-
return false
|
505
|
+
return log_error_and_raise("no name key specified in response.")
|
498
506
|
elsif !resfile.kind # kind key does not exist
|
499
|
-
log_error_and_raise("no kind key specified in response.")
|
500
|
-
return false
|
507
|
+
return log_error_and_raise("no kind key specified in response.")
|
501
508
|
elsif resfile.kind != "drive#file" # Not of file type
|
502
|
-
log_error_and_raise("kind is of non-file type.")
|
503
|
-
return false
|
509
|
+
return log_error_and_raise("kind is of non-file type.")
|
504
510
|
elsif resfile.name != file_basename # file name mismatch
|
505
|
-
log_error_and_raise("file name mismatch.")
|
506
|
-
return false
|
511
|
+
return log_error_and_raise("file name mismatch.")
|
507
512
|
end
|
508
513
|
# TODO: Add MD5 check, since we're now capable.
|
509
514
|
end
|
@@ -512,15 +517,11 @@ class GoogleDrive
|
|
512
517
|
|
513
518
|
# returns full path of downloaded file
|
514
519
|
def download_file(file_name_or_id, parentfolderid: nil, file_path: nil)
|
515
|
-
unless @drive_service
|
516
|
-
log_error_and_raise("Drive service not initialized.")
|
517
|
-
return false
|
518
|
-
end
|
520
|
+
return log_error_and_raise("Drive service not initialized.") unless @drive_service
|
519
521
|
|
520
522
|
# if file path passed, check it is valid.
|
521
523
|
if file_path && !Dir.exist?(file_path)
|
522
|
-
log_error_and_raise("File path '#{file_path}' does not exist.")
|
523
|
-
return false
|
524
|
+
return log_error_and_raise("File path '#{file_path}' does not exist.")
|
524
525
|
elsif !file_path # no path passed, use current directory
|
525
526
|
file_path = Dir.getwd
|
526
527
|
end
|
@@ -533,13 +534,11 @@ class GoogleDrive
|
|
533
534
|
if files && (files.count == 1)
|
534
535
|
file_info = files.first
|
535
536
|
elsif files && (files.count > 1)
|
536
|
-
log_error_and_raise("Multiple files with name '#{file_name_or_id}' exist. download_file() can only handle a single filename.")
|
537
|
-
return false
|
537
|
+
return log_error_and_raise("Multiple files with name '#{file_name_or_id}' exist. download_file() can only handle a single filename.")
|
538
538
|
else # either files is false or count is 0. assume file_name_or_id is an id.
|
539
539
|
file_info = get_file_info(file_name_or_id)
|
540
540
|
if !file_info
|
541
|
-
log_error_and_raise("No file with ID '#{file_name_or_id}' exist.")
|
542
|
-
return false
|
541
|
+
return log_error_and_raise("No file with ID '#{file_name_or_id}' exist.")
|
543
542
|
end
|
544
543
|
end
|
545
544
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: googledrive-easy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Bullock
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2022-10-
|
12
|
+
date: 2022-10-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: googleauth
|