duracloud-client 0.2.0 → 0.3.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/lib/duracloud/audit_log.rb +1 -5
- data/lib/duracloud/bit_integrity_report.rb +1 -1
- data/lib/duracloud/content.rb +18 -0
- data/lib/duracloud/manifest.rb +1 -1
- data/lib/duracloud/properties.rb +1 -1
- data/lib/duracloud/rest_methods.rb +3 -4
- data/lib/duracloud/tsv.rb +39 -17
- data/lib/duracloud/version.rb +1 -1
- data/spec/unit/audit_log_spec.rb +22 -9
- data/spec/unit/bit_integrity_report_spec.rb +22 -9
- data/spec/unit/client_spec.rb +7 -5
- data/spec/unit/content_spec.rb +37 -8
- data/spec/unit/manifest_spec.rb +22 -10
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 328f7556852dc8ca4dbdf2fed3314aa6ca2c160b
|
4
|
+
data.tar.gz: d10ae8810f1e964d495b8b88142246d42fc2c410
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: efa0688d30ec628915d6497422377c9edf95c06233af784947103ab110a4ea8925b7ff99854ccf829e024414eba6b370edd409dc525ff81b14c8707c1f6ccd93
|
7
|
+
data.tar.gz: 08bfcbd0b87934908c9b229b09400648699f90dd32e903b77d362033b8dcdbb1c737e3727e095b4a1343b32930dac68066895e5b5edc84f3d4e04c6e6a2db8e5
|
data/lib/duracloud/audit_log.rb
CHANGED
data/lib/duracloud/content.rb
CHANGED
@@ -107,6 +107,24 @@ module Duracloud
|
|
107
107
|
@md5
|
108
108
|
end
|
109
109
|
|
110
|
+
# @return [Duracloud::Content] the copied content
|
111
|
+
# The current instance still represents the original content.
|
112
|
+
def copy(target_space_id:, target_content_id:, target_store_id: nil)
|
113
|
+
copy_headers = {'x-dura-meta-copy-source'=>[space_id, content_id].join('/')}
|
114
|
+
copy_headers['x-dura-meta-copy-source-store'] = store_id if store_id
|
115
|
+
options = { storeID: target_store_id, headers: copy_headers }
|
116
|
+
Client.copy_content(target_space_id, target_content_id, **options)
|
117
|
+
Content.find(space_id: target_space_id, content_id: target_content_id, store_id: target_store_id, md5: md5)
|
118
|
+
end
|
119
|
+
|
120
|
+
# @return [Duracloud::Content] the moved content
|
121
|
+
# The current instance still represents the deleted content.
|
122
|
+
def move(**args)
|
123
|
+
copied = copy(**args)
|
124
|
+
delete
|
125
|
+
copied
|
126
|
+
end
|
127
|
+
|
110
128
|
private
|
111
129
|
|
112
130
|
def set_md5!(response)
|
data/lib/duracloud/manifest.rb
CHANGED
data/lib/duracloud/properties.rb
CHANGED
@@ -19,7 +19,7 @@ module Duracloud
|
|
19
19
|
SPACE_ACLS = /\A#{PREFIX}acl-/
|
20
20
|
|
21
21
|
# Copy Content headers
|
22
|
-
COPY_CONTENT = /\A#{PREFIX}copy-source(-store)
|
22
|
+
COPY_CONTENT = /\A#{PREFIX}copy-source(-store)?\z/
|
23
23
|
|
24
24
|
# DuraCloud internal content properties
|
25
25
|
INTERNAL = /\A#{PREFIX}content-(mimetype|size|checksum|modified)\z/
|
@@ -49,9 +49,8 @@ module Duracloud
|
|
49
49
|
durastore_content(:put, space_id, content_id, **options)
|
50
50
|
end
|
51
51
|
|
52
|
-
def copy_content(
|
53
|
-
|
54
|
-
"The API method 'Copy Content' has not yet been implemented."
|
52
|
+
def copy_content(target_space_id, target_content_id, **options)
|
53
|
+
durastore_content(:put, target_space_id, target_content_id, **options)
|
55
54
|
end
|
56
55
|
|
57
56
|
def delete_content(space_id, content_id, **options)
|
@@ -91,7 +90,7 @@ module Duracloud
|
|
91
90
|
end
|
92
91
|
|
93
92
|
def durastore_content(http_method, space_id, content_id, **options)
|
94
|
-
escaped_content_id = content_id.gsub(/%/, "%25")
|
93
|
+
escaped_content_id = content_id.gsub(/%/, "%25").gsub(/ /, "%20")
|
95
94
|
url = [ space_id, escaped_content_id ].join("/")
|
96
95
|
durastore(http_method, url, **options)
|
97
96
|
end
|
data/lib/duracloud/tsv.rb
CHANGED
@@ -2,31 +2,53 @@ require "csv"
|
|
2
2
|
|
3
3
|
module Duracloud
|
4
4
|
module TSV
|
5
|
-
|
5
|
+
|
6
6
|
def csv
|
7
|
-
@csv ||= CSV
|
8
|
-
header_line, rows = tsv.split(/\r?\n/, 2)
|
9
|
-
headers = header_line.split("\t").map { |h| h.downcase.gsub(/-/, "_") }
|
10
|
-
header_row = CSV::Row.new(headers, headers, true)
|
11
|
-
csv << header_row
|
12
|
-
rows.split(/\r?\n/).each do |row|
|
13
|
-
csv << row.split("\t")
|
14
|
-
end
|
15
|
-
end
|
7
|
+
@csv ||= CSV.new(tsv, csv_options)
|
16
8
|
end
|
17
9
|
|
18
|
-
# @return [Enumerator] rows as hashes
|
19
10
|
def rows
|
20
|
-
Enumerator.new do |e|
|
21
|
-
|
22
|
-
next if row.header_row?
|
23
|
-
e << row.to_hash
|
24
|
-
end
|
11
|
+
@rows ||= Enumerator.new do |e|
|
12
|
+
table.each { |row| e << row.to_hash }
|
25
13
|
end
|
26
14
|
end
|
27
15
|
|
16
|
+
def table
|
17
|
+
csv.rewind
|
18
|
+
csv.read
|
19
|
+
ensure
|
20
|
+
csv.rewind
|
21
|
+
end
|
22
|
+
|
28
23
|
def tsv
|
29
|
-
|
24
|
+
@tsv
|
25
|
+
end
|
26
|
+
|
27
|
+
def load_tsv(io_or_str)
|
28
|
+
@tsv = io_or_str
|
29
|
+
end
|
30
|
+
|
31
|
+
def load_tsv_file(path)
|
32
|
+
load_tsv(File.new(path, "rb"))
|
30
33
|
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
tsv.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def csv_options
|
42
|
+
{ col_sep: "\t",
|
43
|
+
quote_char: "`",
|
44
|
+
headers: true,
|
45
|
+
header_converters: header_converters,
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def header_converters
|
50
|
+
lambda { |h| h.downcase.gsub(/-/, "_") }
|
51
|
+
end
|
52
|
+
|
31
53
|
end
|
32
54
|
end
|
data/lib/duracloud/version.rb
CHANGED
data/spec/unit/audit_log_spec.rb
CHANGED
@@ -1,22 +1,35 @@
|
|
1
1
|
module Duracloud
|
2
2
|
RSpec.describe AuditLog do
|
3
3
|
|
4
|
-
let(:
|
5
|
-
|
6
|
-
before {
|
7
|
-
allow(subject).to receive(:tsv) { tsv }
|
8
|
-
}
|
4
|
+
let(:path) { File.expand_path('../../fixtures/audit_log.tsv', __FILE__) }
|
9
5
|
|
10
6
|
subject { described_class.new("myspace") }
|
11
7
|
|
12
|
-
describe "
|
8
|
+
describe "#csv" do
|
9
|
+
before {
|
10
|
+
allow(subject).to receive(:tsv) { File.read(path) }
|
11
|
+
subject.csv.read
|
12
|
+
}
|
13
13
|
specify {
|
14
14
|
expect(subject.csv.headers).to eq(%w(account store_id space_id content_id content_md5 content_size content_mimetype content_properties space_acls source_space_id source_content_id timestamp action username))
|
15
|
-
expect(subject.
|
16
|
-
expect(subject.
|
17
|
-
expect(subject.rows.next).to eq({"account"=>"example", "store_id"=>"1065", "space_id"=>"myspace", "content_id"=>"", "content_md5"=>"", "content_size"=>"", "content_mimetype"=>"", "content_properties"=>"", "space_acls"=>"", "source_space_id"=>"", "source_content_id"=>"", "timestamp"=>"2016-04-27T18:34:18.018", "action"=>"CREATE_SPACE", "username"=>"bob@example.com"})
|
15
|
+
expect(subject.rows.to_a.size).to eq(6)
|
16
|
+
expect(subject.rows.first).to eq({"account"=>"example", "store_id"=>"1065", "space_id"=>"myspace", "content_id"=>nil, "content_md5"=>nil, "content_size"=>nil, "content_mimetype"=>nil, "content_properties"=>nil, "space_acls"=>nil, "source_space_id"=>nil, "source_content_id"=>nil, "timestamp"=>"2016-04-27T18:34:18.018", "action"=>"CREATE_SPACE", "username"=>"bob@example.com"})
|
18
17
|
}
|
19
18
|
end
|
20
19
|
|
20
|
+
describe "#load_tsv" do
|
21
|
+
it "loads a string" do
|
22
|
+
tsv = File.read(path)
|
23
|
+
subject.load_tsv(tsv)
|
24
|
+
expect(subject.tsv).to eq(tsv)
|
25
|
+
end
|
26
|
+
it "loads an IO" do
|
27
|
+
tsv = File.read(path)
|
28
|
+
tsv_io = File.new(path, "rb")
|
29
|
+
subject.load_tsv(tsv)
|
30
|
+
expect(subject.tsv.to_s).to eq(tsv)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
21
34
|
end
|
22
35
|
end
|
@@ -1,22 +1,35 @@
|
|
1
1
|
module Duracloud
|
2
2
|
RSpec.describe BitIntegrityReport do
|
3
3
|
|
4
|
-
let(:
|
5
|
-
|
6
|
-
before {
|
7
|
-
allow(subject).to receive(:tsv) { tsv }
|
8
|
-
}
|
4
|
+
let(:path) { File.expand_path('../../fixtures/bit_integrity_report.tsv', __FILE__) }
|
9
5
|
|
10
6
|
subject { described_class.new("myspace") }
|
11
7
|
|
12
|
-
describe "
|
8
|
+
describe "#csv" do
|
9
|
+
before do
|
10
|
+
allow(subject).to receive(:tsv) { File.read(path) }
|
11
|
+
subject.csv.read
|
12
|
+
end
|
13
13
|
specify {
|
14
14
|
expect(subject.csv.headers).to eq(%w(date_checked account store_id store_type space_id content_id result content_checksum provider_checksum manifest_checksum details))
|
15
|
-
expect(subject.
|
16
|
-
expect(subject.
|
17
|
-
expect(subject.rows.next).to eq({"date_checked"=>"2016-05-15T04:11:14", "account"=>"example", "store_id"=>"1065", "store_type"=>"AMAZON_S3", "space_id"=>"myspace", "content_id"=>"BINARIES/00/00/e8/0000e819ac3e67d039d288adaab5b5e44c3c21d9", "result"=>"SUCCESS", "content_checksum"=>"27333f3c06a6d259863384799be68d30", "provider_checksum"=>"27333f3c06a6d259863384799be68d30", "manifest_checksum"=>"27333f3c06a6d259863384799be68d30", "details"=>"--"})
|
15
|
+
expect(subject.rows.to_a.size).to eq(3)
|
16
|
+
expect(subject.rows.first).to eq({"date_checked"=>"2016-05-15T04:11:14", "account"=>"example", "store_id"=>"1065", "store_type"=>"AMAZON_S3", "space_id"=>"myspace", "content_id"=>"BINARIES/00/00/e8/0000e819ac3e67d039d288adaab5b5e44c3c21d9", "result"=>"SUCCESS", "content_checksum"=>"27333f3c06a6d259863384799be68d30", "provider_checksum"=>"27333f3c06a6d259863384799be68d30", "manifest_checksum"=>"27333f3c06a6d259863384799be68d30", "details"=>"--"})
|
18
17
|
}
|
19
18
|
end
|
20
19
|
|
20
|
+
describe "#load_tsv" do
|
21
|
+
it "loads a string" do
|
22
|
+
tsv = File.read(path)
|
23
|
+
subject.load_tsv(tsv)
|
24
|
+
expect(subject.tsv).to eq(tsv)
|
25
|
+
end
|
26
|
+
it "loads an IO" do
|
27
|
+
tsv = File.read(path)
|
28
|
+
tsv_io = File.new(path, "rb")
|
29
|
+
subject.load_tsv(tsv)
|
30
|
+
expect(subject.tsv.to_s).to eq(tsv)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
21
34
|
end
|
22
35
|
end
|
data/spec/unit/client_spec.rb
CHANGED
@@ -130,9 +130,9 @@ module Duracloud
|
|
130
130
|
subject.get_content_properties("foo", "bar")
|
131
131
|
expect(stub).to have_been_requested
|
132
132
|
}
|
133
|
-
it "escapes percent signs in the content id" do
|
134
|
-
stub = stub_request(:head, "https://example.com/durastore/foo/z/z/bar%252Fbaz")
|
135
|
-
subject.get_content_properties("foo", "z/z/bar%2Fbaz")
|
133
|
+
it "escapes percent signs and spaces in the content id" do
|
134
|
+
stub = stub_request(:head, "https://example.com/durastore/foo/z/z/bar%252Fbaz%20spam%20eggs")
|
135
|
+
subject.get_content_properties("foo", "z/z/bar%2Fbaz spam eggs")
|
136
136
|
expect(stub).to have_been_requested
|
137
137
|
end
|
138
138
|
specify {
|
@@ -240,8 +240,10 @@ module Duracloud
|
|
240
240
|
|
241
241
|
describe "copy_content" do
|
242
242
|
specify {
|
243
|
-
|
244
|
-
|
243
|
+
stub = stub_request(:put, "https://example.com/durastore/spam/eggs")
|
244
|
+
.with(headers: {'x-dura-meta-copy-source'=>'foo/bar'})
|
245
|
+
subject.copy_content("spam", "eggs", headers: {'x-dura-meta-copy-source'=>'foo/bar'})
|
246
|
+
expect(stub).to have_been_requested
|
245
247
|
}
|
246
248
|
end
|
247
249
|
|
data/spec/unit/content_spec.rb
CHANGED
@@ -159,19 +159,48 @@ module Duracloud
|
|
159
159
|
end
|
160
160
|
|
161
161
|
describe "#properties" do
|
162
|
-
before
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
}
|
169
|
-
}
|
162
|
+
before do
|
163
|
+
stub_request(:head, url)
|
164
|
+
.to_return(headers: {'x-dura-meta-creator'=>'testuser',
|
165
|
+
'Content-Type'=>'text/plain',
|
166
|
+
'Content-MD5'=>'08a008a01d498c404b0c30852b39d3b8'})
|
167
|
+
end
|
170
168
|
specify {
|
169
|
+
pending "Research Webmock problem with return headers"
|
171
170
|
content = Content.find(space_id: "foo", content_id: "bar")
|
172
171
|
expect(content.properties.x_dura_meta_creator).to eq('testuser')
|
173
172
|
}
|
174
173
|
end
|
175
174
|
|
175
|
+
describe "#copy" do
|
176
|
+
let(:target) { "https://example.com/durastore/spam/eggs" }
|
177
|
+
subject { Content.new(space_id: "foo", content_id: "bar") }
|
178
|
+
specify {
|
179
|
+
stub1 = stub_request(:put, target)
|
180
|
+
.with(headers: {'x-dura-meta-copy-source'=>'foo/bar'})
|
181
|
+
stub2 = stub_request(:head, target)
|
182
|
+
copied = subject.copy(target_space_id: "spam", target_content_id: "eggs")
|
183
|
+
expect(copied).to be_a(Content)
|
184
|
+
expect(stub1).to have_been_requested
|
185
|
+
expect(stub2).to have_been_requested
|
186
|
+
}
|
187
|
+
end
|
188
|
+
|
189
|
+
describe "#move" do
|
190
|
+
let(:target) { "https://example.com/durastore/spam/eggs" }
|
191
|
+
subject { Content.new(space_id: "foo", content_id: "bar") }
|
192
|
+
specify {
|
193
|
+
stub1 = stub_request(:put, target)
|
194
|
+
.with(headers: {'x-dura-meta-copy-source'=>'foo/bar'})
|
195
|
+
stub2 = stub_request(:head, target)
|
196
|
+
stub3 = stub_request(:delete, "https://example.com/durastore/foo/bar")
|
197
|
+
moved = subject.move(target_space_id: "spam", target_content_id: "eggs")
|
198
|
+
expect(moved).to be_a(Content)
|
199
|
+
expect(stub1).to have_been_requested
|
200
|
+
expect(stub2).to have_been_requested
|
201
|
+
expect(stub3).to have_been_requested
|
202
|
+
}
|
203
|
+
end
|
204
|
+
|
176
205
|
end
|
177
206
|
end
|
data/spec/unit/manifest_spec.rb
CHANGED
@@ -1,22 +1,34 @@
|
|
1
1
|
module Duracloud
|
2
2
|
RSpec.describe Manifest do
|
3
3
|
|
4
|
-
let(:tsv) { File.read(File.expand_path('../../fixtures/manifest.tsv', __FILE__)) }
|
5
|
-
|
6
|
-
before {
|
7
|
-
allow(subject).to receive(:tsv) { tsv }
|
8
|
-
}
|
9
|
-
|
10
4
|
subject { described_class.new("myspace") }
|
5
|
+
let(:path) { File.expand_path('../../fixtures/manifest.tsv', __FILE__) }
|
11
6
|
|
12
|
-
describe "
|
7
|
+
describe "#csv" do
|
8
|
+
before do
|
9
|
+
allow(subject).to receive(:tsv) { File.read(path) }
|
10
|
+
subject.csv.read
|
11
|
+
end
|
13
12
|
specify {
|
14
13
|
expect(subject.csv.headers).to eq(%w(space_id content_id md5))
|
15
|
-
expect(subject.
|
16
|
-
expect(subject.
|
17
|
-
expect(subject.rows.next).to eq({"space_id"=>"myspace", "content_id"=>"METADATA/d6/42/0c/9c/d6420c9c-82f8-4f6a-baf7-37b9be7f4c5f/20160502_172925/manifest-md5.txt", "md5"=>"21fef474787860ccfb67bdd99ddee93a"})
|
14
|
+
expect(subject.rows.to_a.size).to eq(3)
|
15
|
+
expect(subject.rows.first).to eq({"space_id"=>"myspace", "content_id"=>"METADATA/d6/42/0c/9c/d6420c9c-82f8-4f6a-baf7-37b9be7f4c5f/20160502_172925/manifest-md5.txt", "md5"=>"21fef474787860ccfb67bdd99ddee93a"})
|
18
16
|
}
|
19
17
|
end
|
20
18
|
|
19
|
+
describe "#load_tsv" do
|
20
|
+
it "loads a string" do
|
21
|
+
tsv = File.read(path)
|
22
|
+
subject.load_tsv(tsv)
|
23
|
+
expect(subject.tsv).to eq(tsv)
|
24
|
+
end
|
25
|
+
it "loads an IO" do
|
26
|
+
tsv = File.read(path)
|
27
|
+
tsv_io = File.new(path, "rb")
|
28
|
+
subject.load_tsv(tsv)
|
29
|
+
expect(subject.tsv.to_s).to eq(tsv)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
21
33
|
end
|
22
34
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: duracloud-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Chandek-Stark
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hashie
|