dbox 0.6.7 → 0.6.8
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -0
- data/VERSION +1 -1
- data/dbox.gemspec +2 -2
- data/lib/dbox/api.rb +27 -13
- data/lib/dbox/db.rb +1 -3
- data/lib/dbox/syncer.rb +5 -7
- data/spec/dbox_spec.rb +8 -1
- metadata +4 -4
data/History.txt
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
== 0.6.8 / 2012-04-02
|
2
|
+
* Minor Enhancements
|
3
|
+
* Added retries after receiving HTTPServiceUnavailable from Dropbox API.
|
4
|
+
* Turned number of threads down to 3 (more than that triggers Dropbox rate limiting after a while).
|
5
|
+
|
1
6
|
== 0.6.7 / 2012-03-29
|
2
7
|
* Minor Enhancements
|
3
8
|
* Added timeout to SQLite operations to help with threads competing for db operations.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.6.
|
1
|
+
0.6.8
|
data/dbox.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "dbox"
|
8
|
-
s.version = "0.6.
|
8
|
+
s.version = "0.6.8"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Ken Pratt"]
|
12
|
-
s.date = "2012-03
|
12
|
+
s.date = "2012-04-03"
|
13
13
|
s.description = "An easy-to-use Dropbox client with fine-grained control over syncs."
|
14
14
|
s.email = "ken@kenpratt.net"
|
15
15
|
s.executables = ["dbox"]
|
data/lib/dbox/api.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
module Dbox
|
2
|
+
NUM_TRIES = 3
|
3
|
+
TIME_BETWEEN_TRIES = 3 # in seconds
|
4
|
+
|
2
5
|
class ConfigurationError < RuntimeError; end
|
3
6
|
class ServerError < RuntimeError; end
|
4
7
|
class RemoteMissing < RuntimeError; end
|
@@ -62,16 +65,24 @@ module Dbox
|
|
62
65
|
@client = DropboxClient.new(@session, 'dropbox')
|
63
66
|
end
|
64
67
|
|
65
|
-
def run(path)
|
68
|
+
def run(path, tries = NUM_TRIES, &proc)
|
66
69
|
begin
|
67
|
-
res =
|
70
|
+
res = proc.call
|
68
71
|
handle_response(path, res) { raise RuntimeError, "Unexpected result: #{res.inspect}" }
|
69
72
|
rescue DropboxNotModified => e
|
70
73
|
:not_modified
|
71
74
|
rescue DropboxAuthError => e
|
72
75
|
raise e
|
73
76
|
rescue DropboxError => e
|
74
|
-
|
77
|
+
if e.http_response.kind_of?(Net::HTTPServiceUnavailable) && tries > 0
|
78
|
+
log.info "Encountered 503 on #{path} (likely rate limiting). Sleeping #{TIME_BETWEEN_TRIES}s and trying again."
|
79
|
+
# TODO check for "Retry-After" header and use that for sleep instead of TIME_BETWEEN_TRIES
|
80
|
+
log.debug "Headers: #{e.http_response.to_hash.inspect}"
|
81
|
+
sleep TIME_BETWEEN_TRIES
|
82
|
+
run(path, tries - 1, &proc)
|
83
|
+
else
|
84
|
+
handle_response(path, e.http_response) { raise ServerError, "Server error -- might be a hiccup, please try your request again (#{e.message})" }
|
85
|
+
end
|
75
86
|
end
|
76
87
|
end
|
77
88
|
|
@@ -95,8 +106,8 @@ module Dbox
|
|
95
106
|
end
|
96
107
|
|
97
108
|
def metadata(path = "/", hash = nil, list=true)
|
98
|
-
log.debug "Fetching metadata for #{path}"
|
99
109
|
run(path) do
|
110
|
+
log.debug "Fetching metadata for #{path}"
|
100
111
|
res = @client.metadata(path, 10000, list, hash)
|
101
112
|
log.debug res.inspect
|
102
113
|
res
|
@@ -104,8 +115,8 @@ module Dbox
|
|
104
115
|
end
|
105
116
|
|
106
117
|
def create_dir(path)
|
107
|
-
log.info "Creating #{path}"
|
108
118
|
run(path) do
|
119
|
+
log.info "Creating #{path}"
|
109
120
|
begin
|
110
121
|
@client.file_create_folder(path)
|
111
122
|
rescue DropboxError => e
|
@@ -119,17 +130,19 @@ module Dbox
|
|
119
130
|
end
|
120
131
|
|
121
132
|
def delete_dir(path)
|
122
|
-
log.info "Deleting #{path}"
|
123
133
|
run(path) do
|
134
|
+
log.info "Deleting #{path}"
|
124
135
|
@client.file_delete(path)
|
125
136
|
end
|
126
137
|
end
|
127
138
|
|
128
139
|
def get_file(path, file_obj, stream=false)
|
129
|
-
log.info "Downloading #{path}"
|
130
140
|
unless stream
|
131
141
|
# just download directly using the get_file API
|
132
|
-
res = run(path)
|
142
|
+
res = run(path) do
|
143
|
+
log.info "Downloading #{path}"
|
144
|
+
@client.get_file(path)
|
145
|
+
end
|
133
146
|
if res.kind_of?(String)
|
134
147
|
file_obj << res
|
135
148
|
true
|
@@ -142,6 +155,7 @@ module Dbox
|
|
142
155
|
res = run(path) { @client.media(path) }
|
143
156
|
url = res[:url] if res && res.kind_of?(Hash)
|
144
157
|
if url
|
158
|
+
log.info "Downloading #{path}"
|
145
159
|
streaming_download(url, file_obj)
|
146
160
|
else
|
147
161
|
get_file(path, file_obj, false)
|
@@ -149,23 +163,23 @@ module Dbox
|
|
149
163
|
end
|
150
164
|
end
|
151
165
|
|
152
|
-
def put_file(path,
|
153
|
-
log.info "Uploading #{path}"
|
166
|
+
def put_file(path, local_path, previous_revision=nil)
|
154
167
|
run(path) do
|
155
|
-
|
168
|
+
log.info "Uploading #{path}"
|
169
|
+
File.open(local_path, "r") {|f| @client.put_file(path, f, false, previous_revision) }
|
156
170
|
end
|
157
171
|
end
|
158
172
|
|
159
173
|
def delete_file(path)
|
160
|
-
log.info "Deleting #{path}"
|
161
174
|
run(path) do
|
175
|
+
log.info "Deleting #{path}"
|
162
176
|
@client.file_delete(path)
|
163
177
|
end
|
164
178
|
end
|
165
179
|
|
166
180
|
def move(old_path, new_path)
|
167
|
-
log.info "Moving #{old_path} to #{new_path}"
|
168
181
|
run(old_path) do
|
182
|
+
log.info "Moving #{old_path} to #{new_path}"
|
169
183
|
begin
|
170
184
|
@client.file_move(old_path, new_path)
|
171
185
|
rescue DropboxError => e
|
data/lib/dbox/db.rb
CHANGED
data/lib/dbox/syncer.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Dbox
|
2
2
|
class Syncer
|
3
|
-
MAX_PARALLEL_DBOX_OPS =
|
3
|
+
MAX_PARALLEL_DBOX_OPS = 3
|
4
4
|
MIN_BYTES_TO_STREAM_DOWNLOAD = 1024 * 100 # 100kB
|
5
5
|
|
6
6
|
include Loggable
|
@@ -620,12 +620,10 @@ module Dbox
|
|
620
620
|
def upload_file(file)
|
621
621
|
local_path = relative_to_local_path(file[:path])
|
622
622
|
remote_path = relative_to_remote_path(file[:path])
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
process_basic_remote_props(res)
|
628
|
-
end
|
623
|
+
db_entry = database.find_by_path(file[:path])
|
624
|
+
last_revision = db_entry ? db_entry[:revision] : nil
|
625
|
+
res = api.put_file(remote_path, local_path, last_revision)
|
626
|
+
process_basic_remote_props(res)
|
629
627
|
end
|
630
628
|
|
631
629
|
def force_metadata_update_from_server(entry)
|
data/spec/dbox_spec.rb
CHANGED
@@ -377,7 +377,14 @@ describe Dbox do
|
|
377
377
|
Dbox.push(@local).should eql(:created => [], :deleted => [], :updated => ["hello.txt"], :failed => [])
|
378
378
|
|
379
379
|
make_file "#{@alternate}/hello.txt"
|
380
|
-
Dbox.push(@alternate)
|
380
|
+
res = Dbox.push(@alternate)
|
381
|
+
res[:created].should eql([])
|
382
|
+
res[:updated].should eql([])
|
383
|
+
res[:deleted].should eql([])
|
384
|
+
res[:failed].should eql([])
|
385
|
+
res[:conflicts].size.should eql(1)
|
386
|
+
res[:conflicts][0][:original].should eql("hello.txt")
|
387
|
+
res[:conflicts][0][:renamed].should match(/hello \(.* conflicted copy\).txt/)
|
381
388
|
end
|
382
389
|
end
|
383
390
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dbox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 6
|
9
|
-
-
|
10
|
-
version: 0.6.
|
9
|
+
- 8
|
10
|
+
version: 0.6.8
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ken Pratt
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-03
|
18
|
+
date: 2012-04-03 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: multipart-post
|