resync-client 0.2.5 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +5 -0
- data/CHANGES.md +12 -0
- data/README.md +1 -1
- data/lib/resync/client/mixins/change_index.rb +6 -0
- data/lib/resync/client/mixins/dump.rb +32 -4
- data/lib/resync/client/mixins/dump_index.rb +40 -6
- data/lib/resync/client/mixins/list_index.rb +13 -1
- data/lib/resync/client/version.rb +1 -1
- data/resync-client.gemspec +3 -1
- data/spec/spec_helper.rb +6 -1
- data/spec/unit/resync/client/change_dump_index_spec.rb +99 -0
- data/spec/unit/resync/client/change_dump_spec.rb +56 -0
- data/spec/unit/resync/client/dump_index_spec.rb +10 -34
- data/spec/unit/resync/client/dump_spec.rb +182 -37
- data/spec/unit/resync/client/extensions_spec.rb +45 -0
- metadata +43 -8
- data/lib/resync/client/zip/zip_packages.rb +0 -69
- data/spec/unit/resync/client/zip_packages_spec.rb +0 -82
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f400045ef45597f5b91078336f0210322b58ff29
|
4
|
+
data.tar.gz: c6f10cbd9a55a03e7b2d9c7db1f5bd721189acff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 561e1fc1d2c34e59a31ace3f76ae1522839500a65a8b6f6a407654ee32b91f7ded1cba8b07e8550932b03e2f6dff983205b9d51ba7042689aca1f897772dbd9a
|
7
|
+
data.tar.gz: 327fe3b46728b19e6043f78f363df94d1d4a74b21c3363fa70d8f720c02ce500f5bf2e188bf96cb8c16bfdd3b61ed2ef0847d1888a1e9eb2279940cbae34cba8
|
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
# 0.3.0
|
2
|
+
|
3
|
+
- Update to depend on [resync](https://github.com/dmolesUC3/resync) 0.3.0
|
4
|
+
- Replace `ZipPackages` class with simple enumerable
|
5
|
+
|
6
|
+
# 0.2.6
|
7
|
+
|
8
|
+
- Added `#all_resources` (as alias for `#resources`) to `ChangeList`/`ResourceList` for transparent interoperability with `ChangeListIndex`/`ResourceListIndex`
|
9
|
+
- Added `#all_changes` (as alias for `#changes`) to `ChangeList`/`ChangeDump` for transparent interoperability with `ChangeListIndex`/`ChangeDumpIndex`
|
10
|
+
<!-- TODO: figure out what ChangeDump#all_changes should really do -->
|
11
|
+
- Added `#all_zip_packages` (as alias for `#zip_packages`) to `ChangeDump`/`ResourceDump` for transparent interoperability with `ChangeDumpIndex`/`ResourceDumpIndex`
|
12
|
+
|
1
13
|
# 0.2.5
|
2
14
|
|
3
15
|
- Added `#all_changes` to transparently download and flatten changes in `ChangeListIndex` and `ChangeDumpIndex` documents, with filtering by time and type
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# resync-client
|
1
|
+
# resync-client [![Build Status](https://travis-ci.org/dmolesUC3/resync-client.png?branch=master)](https://travis-ci.org/dmolesUC3/resync-client) [![Code Climate](https://codeclimate.com/github/dmolesUC3/resync-client.png)](https://codeclimate.com/github/dmolesUC3/resync-client) [![Inline docs](http://inch-ci.org/github/dmolesUC3/resync-client.png)](http://inch-ci.org/github/dmolesUC3/resync-client)
|
2
2
|
|
3
3
|
A gem providing a Ruby client for the [ResourceSync](http://www.openarchives.org/rs/1.0/resourcesync) web synchronization framework, based on the [resync](https://github.com/dmolesUC3/resync) gem and [Net::HTTP](http://ruby-doc.org/stdlib-2.2.2/libdoc/net/http/rdoc/Net/HTTP.html).
|
4
4
|
|
@@ -34,4 +34,10 @@ module Resync
|
|
34
34
|
class BaseChangeIndex
|
35
35
|
prepend Client::Mixins::ChangeIndex
|
36
36
|
end
|
37
|
+
|
38
|
+
class ChangeList
|
39
|
+
# Aliases +:changes+ as +:all_changes+ for transparent
|
40
|
+
# interoperability with +ChangeListIndex+
|
41
|
+
alias_method :all_changes, :changes
|
42
|
+
end
|
37
43
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'resync'
|
2
|
+
require 'lazy'
|
2
3
|
require_relative '../zip'
|
3
4
|
require_relative 'zipped_resource'
|
4
5
|
|
@@ -7,6 +8,8 @@ module Resync
|
|
7
8
|
module Mixins
|
8
9
|
# A list of resources each of which refers to a zipped bitstream package.
|
9
10
|
module Dump
|
11
|
+
|
12
|
+
# Makes each resource a {ZippedResource}
|
10
13
|
def resources=(value)
|
11
14
|
super
|
12
15
|
resources.each do |r|
|
@@ -17,11 +20,19 @@ module Resync
|
|
17
20
|
end
|
18
21
|
end
|
19
22
|
|
20
|
-
#
|
21
|
-
# @return [Resync::Client::Zip::
|
23
|
+
# The {Resync::Client::Zip::ZipPackage}s for each resource, downloaded lazily
|
24
|
+
# @return [Array<Lazy::Promise<Resync::Client::Zip::ZipPackage>>] the zip packages for each resource
|
22
25
|
def zip_packages
|
23
|
-
@zip_packages ||=
|
26
|
+
@zip_packages ||= resources.map { |r| Lazy.promise { r.zip_package } }
|
27
|
+
end
|
28
|
+
|
29
|
+
# Aliases +:zip_packages+ as +:all_zip_packages+ for transparent
|
30
|
+
# interoperability between +ResourceDump+ and +ResourceDumpIndex+,
|
31
|
+
# +ChangeDump+ and +ChangeDumpIndex+
|
32
|
+
def self.prepended(ext)
|
33
|
+
ext.send(:alias_method, :all_zip_packages, :zip_packages)
|
24
34
|
end
|
35
|
+
|
25
36
|
end
|
26
37
|
end
|
27
38
|
end
|
@@ -31,6 +42,23 @@ module Resync
|
|
31
42
|
end
|
32
43
|
|
33
44
|
class ChangeDump
|
34
|
-
|
45
|
+
include Client::Mixins::Dump
|
46
|
+
|
47
|
+
# A list (downloaded lazily) of the {Resync::Client::Zip::ZipPackage}s for each resource
|
48
|
+
# If a time range parameter is provided, the lists of packages is filtered by +from_time+
|
49
|
+
# and +until_time+, in non-strict mode (only excluding those lists provably not in the range,
|
50
|
+
# i.e., including packages without +from_time+ or +until_time+).
|
51
|
+
# @param in_range [Range<Time>] the range of times to filter by
|
52
|
+
# @return [Array<Lazy::Promise<Resync::Client::Zip::ZipPackage>>] the zip packages for each resource
|
53
|
+
def zip_packages(in_range: nil)
|
54
|
+
if in_range
|
55
|
+
change_lists = change_lists(in_range: in_range, strict: false)
|
56
|
+
change_lists.map { |r| Lazy.promise { r.zip_package } }
|
57
|
+
else
|
58
|
+
super()
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
alias_method :all_zip_packages, :zip_packages
|
35
63
|
end
|
36
64
|
end
|
@@ -11,20 +11,54 @@ module Resync
|
|
11
11
|
# Downloads and parses each resource list and returns a flattened enumeration
|
12
12
|
# of all zip packages in each contained list. Each contained list is only downloaded
|
13
13
|
# as needed, and only downloaded once.
|
14
|
-
# @return [Enumerator::Lazy<Resync::Client::Zip::
|
14
|
+
# @return [Enumerator::Lazy<Resync::Client::Zip::ZipPackage>] the flattened enumeration of resources
|
15
15
|
def all_zip_packages
|
16
|
-
|
17
|
-
|
18
|
-
@zipped_resource_lists[r] ||= r.get_and_parse
|
19
|
-
@zipped_resource_lists[r].respond_to?(:zip_packages) ? @zipped_resource_lists[r].zip_packages : []
|
16
|
+
resources.lazy.flat_map do |r|
|
17
|
+
package_for(r)
|
20
18
|
end
|
21
19
|
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def zipped_resource_list_for(r)
|
24
|
+
@zipped_resource_lists ||= {}
|
25
|
+
@zipped_resource_lists[r] ||= r.get_and_parse
|
26
|
+
end
|
27
|
+
|
28
|
+
def package_for(r)
|
29
|
+
zrl = zipped_resource_list_for(r)
|
30
|
+
zrl.respond_to?(:zip_packages) ? zrl.zip_packages : []
|
31
|
+
end
|
22
32
|
end
|
23
33
|
end
|
24
34
|
end
|
25
35
|
|
26
36
|
class ChangeDumpIndex
|
27
|
-
|
37
|
+
include Client::Mixins::DumpIndex
|
38
|
+
|
39
|
+
# Downloads and parses each resource list and returns a flattened enumeration
|
40
|
+
# of all zip packages in each contained list. Each contained list is only downloaded
|
41
|
+
# as needed, and only downloaded once.
|
42
|
+
# If a time range parameter is provided, the lists of packages is filtered by +from_time+
|
43
|
+
# and +until_time+, in non-strict mode (only excluding those lists provably not in the range,
|
44
|
+
# i.e., including packages without +from_time+ or +until_time+).
|
45
|
+
# @param in_range [Range<Time>] the range of times to filter by
|
46
|
+
# @return [Enumerator::Lazy<Resync::Client::Zip::ZipPackage>] the flattened enumeration of resources
|
47
|
+
def all_zip_packages(in_range: nil)
|
48
|
+
if in_range
|
49
|
+
dump_resources = change_lists(in_range: in_range, strict: false)
|
50
|
+
dump_resources.lazy.flat_map { |cl| package_for(cl, in_range: in_range) }
|
51
|
+
else
|
52
|
+
super()
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def package_for(r, in_range: nil)
|
59
|
+
zrl = zipped_resource_list_for(r)
|
60
|
+
in_range ? zrl.zip_packages(in_range: in_range) : super(r)
|
61
|
+
end
|
28
62
|
end
|
29
63
|
|
30
64
|
class ResourceDumpIndex
|
@@ -14,7 +14,7 @@ module Resync
|
|
14
14
|
# @return [Enumerator::Lazy<Resync::Resource>] the flattened enumeration of resources
|
15
15
|
def all_resources
|
16
16
|
@resource_lists ||= {}
|
17
|
-
resources.flat_map do |r|
|
17
|
+
resources.lazy.flat_map do |r|
|
18
18
|
@resource_lists[r] ||= r.get_and_parse
|
19
19
|
@resource_lists[r].resources
|
20
20
|
end
|
@@ -27,7 +27,19 @@ module Resync
|
|
27
27
|
prepend Client::Mixins::ListIndex
|
28
28
|
end
|
29
29
|
|
30
|
+
class ChangeList
|
31
|
+
# Aliases +:resources+ as +:all_resources+ for transparent
|
32
|
+
# interoperability with +ChangeListIndex+
|
33
|
+
alias_method :all_resources, :resources
|
34
|
+
end
|
35
|
+
|
30
36
|
class ResourceListIndex
|
31
37
|
prepend Client::Mixins::ListIndex
|
32
38
|
end
|
39
|
+
|
40
|
+
class ResourceList
|
41
|
+
# Aliases +:resources+ as +:all_resources+ for transparent
|
42
|
+
# interoperability with +ResourceListIndex+
|
43
|
+
alias_method :all_resources, :resources
|
44
|
+
end
|
33
45
|
end
|
data/resync-client.gemspec
CHANGED
@@ -22,7 +22,8 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
23
23
|
spec.require_paths = ['lib']
|
24
24
|
|
25
|
-
spec.add_dependency '
|
25
|
+
spec.add_dependency 'lazy', '~> 0.9', '>= 0.9.6'
|
26
|
+
spec.add_dependency 'resync', '~> 0.2', '>= 0.3.0'
|
26
27
|
spec.add_dependency 'rubyzip', '~> 1.1'
|
27
28
|
|
28
29
|
spec.add_development_dependency 'equivalent-xml', '~> 0.6.0'
|
@@ -32,4 +33,5 @@ Gem::Specification.new do |spec|
|
|
32
33
|
spec.add_development_dependency 'simplecov', '~> 0.9.2'
|
33
34
|
spec.add_development_dependency 'simplecov-console', '~> 0.2.0'
|
34
35
|
spec.add_development_dependency 'yard', '~> 0.8'
|
36
|
+
spec.add_development_dependency 'codeclimate-test-reporter', '~> 0'
|
35
37
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
# ------------------------------------------------------------
|
2
|
-
# SimpleCov setup
|
2
|
+
# SimpleCov/CodeClimate setup
|
3
3
|
|
4
4
|
if ENV['COVERAGE']
|
5
|
+
if ENV['CODECLIMATE_REPO_TOKEN']
|
6
|
+
require 'codeclimate-test-reporter'
|
7
|
+
CodeClimate::TestReporter.start
|
8
|
+
end
|
9
|
+
|
5
10
|
require 'simplecov'
|
6
11
|
require 'simplecov-console'
|
7
12
|
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Resync
|
4
|
+
describe ChangeDumpIndex do
|
5
|
+
before(:each) do
|
6
|
+
@change_dump_index = ChangeDumpIndex.load_from_xml(XML.element(
|
7
|
+
"<sitemapindex xmlns='http://www.sitemaps.org/schemas/sitemap/0.9' xmlns:rs='http://www.openarchives.org/rs/terms/'>
|
8
|
+
<rs:md capability='changedump'/>
|
9
|
+
<sitemap>
|
10
|
+
<loc>http://example.com/20130101-changedump.xml</loc>
|
11
|
+
<rs:md from='2013-01-01T00:00:00Z' until='2013-01-02T00:00:00Z'/>
|
12
|
+
</sitemap>
|
13
|
+
<sitemap>
|
14
|
+
<loc>http://example.com/20130102-changedump.xml</loc>
|
15
|
+
<rs:md from='2013-01-02T00:00:00Z' until='2013-01-03T00:00:00Z'/>
|
16
|
+
</sitemap>
|
17
|
+
<sitemap>
|
18
|
+
<loc>http://example.com/20130103-changedump.xml</loc>
|
19
|
+
<rs:md from='2013-01-03T00:00:00Z' until='2013-01-04T00:00:00Z'/>
|
20
|
+
</sitemap>
|
21
|
+
</sitemapindex>"))
|
22
|
+
|
23
|
+
@change_dumps = [
|
24
|
+
"<urlset xmlns='http://www.sitemaps.org/schemas/sitemap/0.9' xmlns:rs='http://www.openarchives.org/rs/terms/'>
|
25
|
+
<rs:md capability='changedump'/>
|
26
|
+
<url>
|
27
|
+
<loc>http://example.com/20130101-changedump-0.zip</loc>
|
28
|
+
<rs:md modified='2013-01-01T11:59:59Z' from='2013-01-01T00:00:00Z' until='2013-01-01T12:00:00Z'/>
|
29
|
+
</url>
|
30
|
+
<url>
|
31
|
+
<loc>http://example.com/20130101-changedump-1.zip</loc>
|
32
|
+
<rs:md modified='2013-01-01T23:59:59Z' from='2013-01-01T12:00:00Z' until='2013-01-02T00:00:00Z'/>
|
33
|
+
</url>
|
34
|
+
</urlset>",
|
35
|
+
"<urlset xmlns='http://www.sitemaps.org/schemas/sitemap/0.9' xmlns:rs='http://www.openarchives.org/rs/terms/'>
|
36
|
+
<rs:md capability='changedump'/>
|
37
|
+
<url>
|
38
|
+
<loc>http://example.com/20130102-changedump-0.zip</loc>
|
39
|
+
<rs:md modified='2013-01-02T11:59:59Z' from='2013-01-02T00:00:00Z' until='2013-01-02T12:00:00Z'/>
|
40
|
+
</url>
|
41
|
+
<url>
|
42
|
+
<loc>http://example.com/20130102-changedump-1.zip</loc>
|
43
|
+
<rs:md modified='2013-01-02T23:59:59Z' from='2013-01-02T12:00:00Z' until='2013-01-03T00:00:00Z'/>
|
44
|
+
</url>
|
45
|
+
</urlset>",
|
46
|
+
"<urlset xmlns='http://www.sitemaps.org/schemas/sitemap/0.9' xmlns:rs='http://www.openarchives.org/rs/terms/'>
|
47
|
+
<rs:md capability='changedump'/>
|
48
|
+
<url>
|
49
|
+
<loc>http://example.com/20130103-changedump-0.zip</loc>
|
50
|
+
<rs:md modified='2013-01-03T11:59:59Z' from='2013-01-03T00:00:00Z' until='2013-01-03T12:00:00Z'/>
|
51
|
+
</url>
|
52
|
+
<url>
|
53
|
+
<loc>http://example.com/20130103-changedump-1.zip</loc>
|
54
|
+
<rs:md modified='2013-01-03T23:59:59Z' from='2013-01-03T12:00:00Z' until='2013-01-04T00:00:00Z'/>
|
55
|
+
</url>
|
56
|
+
</urlset>"
|
57
|
+
].map { |xml| ChangeDump.load_from_xml(XML.element(xml)) }
|
58
|
+
|
59
|
+
@all_package_resources = []
|
60
|
+
@all_zip_packages = []
|
61
|
+
@change_dumps.each do |d|
|
62
|
+
d.resources.each do |r|
|
63
|
+
@all_package_resources << r
|
64
|
+
zp = instance_double(Resync::Client::Zip::ZipPackage)
|
65
|
+
allow(r).to receive(:zip_package) { zp }
|
66
|
+
@all_zip_packages << zp
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
@change_dump_resources = []
|
71
|
+
@change_dump_index.resources.each_with_index do |r, i|
|
72
|
+
@change_dump_resources << r
|
73
|
+
allow(r).to receive(:get_and_parse) { @change_dumps[i] }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#all_zip_packages' do
|
78
|
+
it 'should accept an optional time range' do
|
79
|
+
range = Time.utc(2013, 1, 1)..Time.utc(2013, 1, 2, 6)
|
80
|
+
all_packages = @change_dump_index.all_zip_packages(in_range: range).to_a
|
81
|
+
expect(all_packages).to eq(@all_zip_packages[0, 3])
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should not download unnecessary dumps or packages' do
|
85
|
+
expect(@change_dump_resources[2]).not_to receive(:get_and_parse)
|
86
|
+
@all_package_resources[3, 3].each do |r|
|
87
|
+
expect(r).not_to receive(:zip_package)
|
88
|
+
end
|
89
|
+
@change_dump_index.all_zip_packages(in_range: Time.utc(2013, 1, 1)..Time.utc(2013, 1, 2, 6)).to_a
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should not require a time range' do
|
93
|
+
all_packages = @change_dump_index.all_zip_packages.to_a
|
94
|
+
expect(all_packages).to eq(@all_zip_packages)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Resync
|
4
|
+
describe ChangeDump do
|
5
|
+
before(:each) do
|
6
|
+
@resources = [
|
7
|
+
Resource.new(
|
8
|
+
uri: URI('http://example.com/20130101-changedump.zip'),
|
9
|
+
modified_time: Time.utc(2013, 1, 1, 23, 59, 59),
|
10
|
+
metadata: Metadata.new(
|
11
|
+
from_time: Time.utc(2013, 1, 1),
|
12
|
+
until_time: Time.utc(2013, 1, 2))),
|
13
|
+
Resource.new(
|
14
|
+
uri: URI('http://example.com/20130102-changedump.zip'),
|
15
|
+
modified_time: Time.utc(2013, 1, 2, 23, 59, 59),
|
16
|
+
metadata: Metadata.new(
|
17
|
+
from_time: Time.utc(2013, 1, 2),
|
18
|
+
until_time: Time.utc(2013, 1, 3))),
|
19
|
+
Resource.new(
|
20
|
+
uri: URI('http://example.com/20130103-changedump.zip'),
|
21
|
+
modified_time: Time.utc(2013, 1, 3, 23, 59, 59),
|
22
|
+
metadata: Metadata.new(
|
23
|
+
from_time: Time.utc(2013, 1, 3),
|
24
|
+
until_time: Time.utc(2013, 1, 4)))
|
25
|
+
]
|
26
|
+
@dump = ChangeDump.new(resources: @resources)
|
27
|
+
|
28
|
+
@zip_packages = []
|
29
|
+
@resources.each_with_index do |r, i|
|
30
|
+
@zip_packages[i] = instance_double(Resync::Client::Zip::ZipPackage)
|
31
|
+
allow(r).to receive(:zip_package) { @zip_packages[i] }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#zip_packages' do
|
36
|
+
it 'should accept an optional time range' do
|
37
|
+
packages = @dump.zip_packages(in_range: Time.utc(2013, 1, 3)..Time.utc(2013, 1, 4))
|
38
|
+
expect(packages.size).to eq(2)
|
39
|
+
expect(packages.to_a).to eq([@zip_packages[1], @zip_packages[2]])
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should not require a time range' do
|
43
|
+
packages = @dump.zip_packages
|
44
|
+
expect(packages.to_a).to eq(@zip_packages)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#all_zip_packages' do
|
49
|
+
it 'should delegate to #zip_packages' do
|
50
|
+
packages = @dump.all_zip_packages
|
51
|
+
expect(packages.to_a).to eq(@zip_packages)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -51,10 +51,14 @@ module Resync
|
|
51
51
|
|
52
52
|
it 'is lazy enough not to download resources it doesn\'t need' do
|
53
53
|
resources = Array.new(3) { instance_double(ZippedResource) }
|
54
|
-
|
54
|
+
zip_packages = Array.new(3) { instance_double(Zip::ZipPackage) }
|
55
|
+
resources.each_with_index do |r, i|
|
55
56
|
allow(r).to receive(:client_delegate=)
|
56
|
-
|
57
|
-
|
57
|
+
if i <= 1
|
58
|
+
expect(r).to receive(:zip_package).once.and_return(zip_packages[i])
|
59
|
+
else
|
60
|
+
expect(r).not_to receive(:zip_package)
|
61
|
+
end
|
58
62
|
end
|
59
63
|
|
60
64
|
dump1 = ResourceDump.new(resources: resources[0, 3])
|
@@ -68,37 +72,9 @@ module Resync
|
|
68
72
|
expect(dump2_resource).not_to receive(:get_and_parse)
|
69
73
|
|
70
74
|
index = ResourceDumpIndex.new(resources: [dump1_resource, dump2_resource])
|
71
|
-
index.all_zip_packages.each_with_index do |
|
72
|
-
|
73
|
-
|
74
|
-
end
|
75
|
-
|
76
|
-
it 'caches downloaded resources' do
|
77
|
-
resources = Array.new(6) { instance_double(ZippedResource) }
|
78
|
-
resources.each do |r|
|
79
|
-
allow(r).to receive(:client_delegate=)
|
80
|
-
zip_package = instance_double(Zip::ZipPackage)
|
81
|
-
expect(r).to receive(:zip_package).once.and_return(zip_package)
|
82
|
-
end
|
83
|
-
|
84
|
-
dump1 = ResourceDump.new(resources: resources[0, 3])
|
85
|
-
dump2 = ResourceDump.new(resources: resources[3, 3])
|
86
|
-
|
87
|
-
dump1_resource = instance_double(Resource)
|
88
|
-
allow(dump1_resource).to receive(:client_delegate=)
|
89
|
-
expect(dump1_resource).to receive(:get_and_parse).once.and_return(dump1)
|
90
|
-
|
91
|
-
dump2_resource = instance_double(Resource)
|
92
|
-
allow(dump2_resource).to receive(:client_delegate=)
|
93
|
-
expect(dump2_resource).to receive(:get_and_parse).once.and_return(dump2)
|
94
|
-
|
95
|
-
index = ResourceDumpIndex.new(resources: [dump1_resource, dump2_resource])
|
96
|
-
all_packages = index.all_zip_packages
|
97
|
-
|
98
|
-
a1 = all_packages.to_a
|
99
|
-
a2 = all_packages.to_a
|
100
|
-
a1.each_with_index do |pkg, i|
|
101
|
-
expect(pkg).to be(a2[i])
|
75
|
+
index.all_zip_packages.each_with_index do |zp, i|
|
76
|
+
expect(zp).to be(zip_packages[i])
|
77
|
+
break if i >= 1
|
102
78
|
end
|
103
79
|
end
|
104
80
|
end
|
@@ -1,60 +1,205 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
module Resync
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
# TODO: introduce shared examples
|
5
|
+
describe ResourceDump do
|
6
|
+
describe '#zip_packages' do
|
7
|
+
it 'transparently exposes bitstreams' do
|
8
|
+
path = 'spec/data/resourcedump/resourcedump.xml'
|
9
|
+
package_uri = URI('http://example.com/resourcedump.zip')
|
10
|
+
|
11
|
+
client = instance_double(Client)
|
12
|
+
expect(client).to receive(:download_to_temp_file).once.with(package_uri).and_return('spec/data/resourcedump/resourcedump.zip')
|
13
|
+
|
14
|
+
dump = XMLParser.parse(File.read(path))
|
15
|
+
dump.client = client
|
16
|
+
|
17
|
+
zip_packages = dump.zip_packages
|
18
|
+
expect(zip_packages.size).to eq(1)
|
19
|
+
expect(zip_packages[0]).to be_a(Client::Zip::ZipPackage)
|
20
|
+
|
21
|
+
bitstreams = zip_packages[0].bitstreams
|
22
|
+
expect(bitstreams.size).to eq(2)
|
23
|
+
expect(bitstreams[0].content).to eq(File.read('spec/data/resourcedump/resources/res1'))
|
24
|
+
expect(bitstreams[1].content).to eq(File.read('spec/data/resourcedump/resources/res2'))
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'is lazy' do
|
28
|
+
resources = Array.new(3) { |i| Resource.new(uri: "http://example.org/res#{i}") }
|
29
|
+
dump = ResourceDump.new(resources: resources)
|
30
|
+
zip_packages = dump.zip_packages
|
31
|
+
zip_package = instance_double(Client::Zip::ZipPackage)
|
10
32
|
|
11
|
-
|
12
|
-
|
33
|
+
expect(resources[0]).not_to receive(:zip_package)
|
34
|
+
expect(resources[1]).not_to receive(:zip_package)
|
35
|
+
expect(resources[2]).to receive(:zip_package).and_return(zip_package)
|
13
36
|
|
14
|
-
|
15
|
-
|
37
|
+
expect(zip_packages[2]).to be(zip_package)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'flatmaps' do
|
41
|
+
resources = Array.new(6) { |i| Resource.new(uri: "http://example.org/res#{i}") }
|
42
|
+
all_packages = Array.new(6) do |i|
|
43
|
+
zip_package = instance_double(Client::Zip::ZipPackage)
|
44
|
+
expect(resources[i]).to receive(:zip_package).once.and_return(zip_package)
|
45
|
+
zip_package
|
46
|
+
end
|
16
47
|
|
17
|
-
|
18
|
-
|
48
|
+
zrl1 = ResourceDump.new(resources: resources[0, 3])
|
49
|
+
zrl2 = ResourceDump.new(resources: resources[3, 3])
|
19
50
|
|
20
|
-
|
21
|
-
|
51
|
+
flat_mapped = [zrl1, zrl2].flat_map(&:zip_packages)
|
52
|
+
expect(flat_mapped).to eq(all_packages)
|
22
53
|
|
23
|
-
|
24
|
-
|
54
|
+
lazy_flat_mapped = [zrl1, zrl2].lazy.flat_map(&:zip_packages).to_a
|
55
|
+
expect(lazy_flat_mapped).to eq(all_packages)
|
56
|
+
end
|
25
57
|
|
26
|
-
|
27
|
-
|
58
|
+
it 'supports lazy iteration 'do
|
59
|
+
manifests = Array.new(3) { instance_double(ChangeDumpManifest) }
|
60
|
+
all_packages = Array.new(3) do |index|
|
61
|
+
zip_package = instance_double(Client::Zip::ZipPackage)
|
62
|
+
allow(zip_package).to receive(:manifest).and_return(manifests[index])
|
63
|
+
zip_package
|
64
|
+
end
|
65
|
+
resources = Array.new(3) do |index|
|
66
|
+
resource = Resource.new(uri: "http://example.org/res#{index}")
|
67
|
+
if index > 1
|
68
|
+
expect(resource).not_to receive(:zip_package)
|
69
|
+
else
|
70
|
+
expect(resource).to receive(:zip_package).and_return(all_packages[index])
|
71
|
+
end
|
72
|
+
resource
|
73
|
+
end
|
28
74
|
|
29
|
-
|
30
|
-
|
75
|
+
zip_packages = ResourceDump.new(resources: resources).zip_packages
|
76
|
+
zip_packages.each_with_index do |zip_package, index|
|
77
|
+
expect(zip_package.manifest).to be(manifests[index])
|
78
|
+
break if index >= 1
|
31
79
|
end
|
80
|
+
end
|
81
|
+
end
|
32
82
|
|
33
|
-
|
34
|
-
|
35
|
-
|
83
|
+
describe '#all_zip_packages' do
|
84
|
+
it 'is an alias for #zip_packages' do
|
85
|
+
path = 'spec/data/resourcedump/resourcedump.xml'
|
86
|
+
package_uri = URI('http://example.com/resourcedump.zip')
|
36
87
|
|
37
|
-
|
38
|
-
|
88
|
+
client = instance_double(Client)
|
89
|
+
expect(client).to receive(:download_to_temp_file).once.with(package_uri).and_return('spec/data/resourcedump/resourcedump.zip')
|
39
90
|
|
40
|
-
|
41
|
-
|
91
|
+
dump = XMLParser.parse(File.read(path))
|
92
|
+
dump.client = client
|
42
93
|
|
43
|
-
|
44
|
-
|
94
|
+
all_zip_packages = dump.all_zip_packages
|
95
|
+
expect(all_zip_packages.size).to eq(1)
|
96
|
+
expect(all_zip_packages[0]).to be_a(Client::Zip::ZipPackage)
|
45
97
|
|
46
|
-
|
47
|
-
|
98
|
+
bitstreams = all_zip_packages[0].bitstreams
|
99
|
+
expect(bitstreams.size).to eq(2)
|
100
|
+
expect(bitstreams[0].content).to eq(File.read('spec/data/resourcedump/resources/res1'))
|
101
|
+
expect(bitstreams[1].content).to eq(File.read('spec/data/resourcedump/resources/res2'))
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe ChangeDump do
|
107
|
+
describe '#zip_packages' do
|
108
|
+
it 'transparently exposes bitstreams' do
|
109
|
+
path = 'spec/data/resourcedump/changedump.xml'
|
110
|
+
package_uri = URI('http://example.com/changedump.zip')
|
111
|
+
|
112
|
+
client = instance_double(Client)
|
113
|
+
expect(client).to receive(:download_to_temp_file).once.with(package_uri).and_return('spec/data/resourcedump/resourcedump.zip')
|
114
|
+
|
115
|
+
dump = XMLParser.parse(File.read(path))
|
116
|
+
dump.client = client
|
117
|
+
|
118
|
+
zip_packages = dump.zip_packages
|
119
|
+
expect(zip_packages.size).to eq(1)
|
120
|
+
expect(zip_packages[0]).to be_a(Client::Zip::ZipPackage)
|
121
|
+
|
122
|
+
bitstreams = zip_packages[0].bitstreams
|
123
|
+
expect(bitstreams.size).to eq(2)
|
124
|
+
expect(bitstreams[0].content).to eq(File.read('spec/data/resourcedump/resources/res1'))
|
125
|
+
expect(bitstreams[1].content).to eq(File.read('spec/data/resourcedump/resources/res2'))
|
126
|
+
end
|
48
127
|
|
49
|
-
|
50
|
-
|
128
|
+
it 'is lazy' do
|
129
|
+
resources = Array.new(3) { |i| Resource.new(uri: "http://example.org/res#{i}") }
|
130
|
+
dump = ChangeDump.new(resources: resources)
|
131
|
+
zip_packages = dump.zip_packages
|
132
|
+
zip_package = instance_double(Client::Zip::ZipPackage)
|
51
133
|
|
52
|
-
|
53
|
-
|
134
|
+
expect(resources[0]).not_to receive(:zip_package)
|
135
|
+
expect(resources[1]).not_to receive(:zip_package)
|
136
|
+
expect(resources[2]).to receive(:zip_package).and_return(zip_package)
|
54
137
|
|
55
|
-
|
56
|
-
|
138
|
+
expect(zip_packages[2]).to be(zip_package)
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'flatmaps' do
|
142
|
+
resources = Array.new(6) { |i| Resource.new(uri: "http://example.org/res#{i}") }
|
143
|
+
all_packages = Array.new(6) do |i|
|
144
|
+
zip_package = instance_double(Client::Zip::ZipPackage)
|
145
|
+
expect(resources[i]).to receive(:zip_package).once.and_return(zip_package)
|
146
|
+
zip_package
|
147
|
+
end
|
148
|
+
|
149
|
+
zrl1 = ChangeDump.new(resources: resources[0, 3])
|
150
|
+
zrl2 = ChangeDump.new(resources: resources[3, 3])
|
151
|
+
|
152
|
+
lazy_flat_mapped = [zrl1, zrl2].lazy.flat_map(&:zip_packages).to_a
|
153
|
+
expect(lazy_flat_mapped).to eq(all_packages)
|
154
|
+
|
155
|
+
flat_mapped = [zrl1, zrl2].flat_map(&:zip_packages)
|
156
|
+
expect(flat_mapped).to eq(all_packages)
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'supports lazy iteration 'do
|
160
|
+
manifests = Array.new(3) { instance_double(ChangeDumpManifest) }
|
161
|
+
all_packages = Array.new(3) do |index|
|
162
|
+
zip_package = instance_double(Client::Zip::ZipPackage)
|
163
|
+
allow(zip_package).to receive(:manifest).and_return(manifests[index])
|
164
|
+
zip_package
|
165
|
+
end
|
166
|
+
resources = Array.new(3) do |index|
|
167
|
+
resource = Resource.new(uri: "http://example.org/res#{index}")
|
168
|
+
if index > 1
|
169
|
+
expect(resource).not_to receive(:zip_package)
|
170
|
+
else
|
171
|
+
expect(resource).to receive(:zip_package).and_return(all_packages[index])
|
172
|
+
end
|
173
|
+
resource
|
57
174
|
end
|
175
|
+
|
176
|
+
zip_packages = ChangeDump.new(resources: resources).zip_packages
|
177
|
+
zip_packages.each_with_index do |zip_package, index|
|
178
|
+
expect(zip_package.manifest).to be(manifests[index])
|
179
|
+
break if index >= 1
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe '#all_zip_packages' do
|
185
|
+
it 'is an alias for #zip_packages' do
|
186
|
+
path = 'spec/data/resourcedump/changedump.xml'
|
187
|
+
package_uri = URI('http://example.com/changedump.zip')
|
188
|
+
|
189
|
+
client = instance_double(Client)
|
190
|
+
expect(client).to receive(:download_to_temp_file).once.with(package_uri).and_return('spec/data/resourcedump/resourcedump.zip')
|
191
|
+
|
192
|
+
dump = XMLParser.parse(File.read(path))
|
193
|
+
dump.client = client
|
194
|
+
|
195
|
+
zip_packages = dump.all_zip_packages
|
196
|
+
expect(zip_packages.size).to eq(1)
|
197
|
+
expect(zip_packages[0]).to be_a(Client::Zip::ZipPackage)
|
198
|
+
|
199
|
+
bitstreams = zip_packages[0].bitstreams
|
200
|
+
expect(bitstreams.size).to eq(2)
|
201
|
+
expect(bitstreams[0].content).to eq(File.read('spec/data/resourcedump/resources/res1'))
|
202
|
+
expect(bitstreams[1].content).to eq(File.read('spec/data/resourcedump/resources/res2'))
|
58
203
|
end
|
59
204
|
end
|
60
205
|
end
|
@@ -41,6 +41,51 @@ module Resync
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
+
describe ResourceList do
|
45
|
+
describe '#all_resources' do
|
46
|
+
it 'is an alias for #resources' do
|
47
|
+
resources = Array.new(3) do
|
48
|
+
resource = instance_double(Resource)
|
49
|
+
allow(resource).to receive(:client_delegate=)
|
50
|
+
resource
|
51
|
+
end
|
52
|
+
list = ResourceList.new(resources: resources)
|
53
|
+
expect(list.all_resources).to be(list.resources)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe ChangeList do
|
59
|
+
describe '#all_changes' do
|
60
|
+
describe '#all_resources' do
|
61
|
+
it 'is an alias for #resources' do
|
62
|
+
resources = []
|
63
|
+
resources[0] = Resource.new(uri: 'http://example.org/', modified_time: Time.utc(1999, 1, 1))
|
64
|
+
resources[1] = Resource.new(uri: 'http://example.org/', modified_time: Time.utc(2000, 1, 1))
|
65
|
+
resources[2] = Resource.new(uri: 'http://example.org/', modified_time: Time.utc(2001, 3, 1))
|
66
|
+
|
67
|
+
all_resources = ResourceList.new(resources: resources).all_resources
|
68
|
+
expect(all_resources.to_a).to eq(resources)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'is a proxy for #changes' do
|
73
|
+
resources = []
|
74
|
+
resources[0] = Resource.new(uri: 'http://example.org/', modified_time: Time.utc(1999, 1, 1), metadata: Metadata.new(change: Types::Change::CREATED))
|
75
|
+
resources[1] = Resource.new(uri: 'http://example.org/', modified_time: Time.utc(2000, 1, 1), metadata: Metadata.new(change: Types::Change::CREATED))
|
76
|
+
resources[2] = Resource.new(uri: 'http://example.org/', modified_time: Time.utc(1999, 3, 1), metadata: Metadata.new(change: Types::Change::UPDATED))
|
77
|
+
resources[3] = Resource.new(uri: 'http://example.org/', modified_time: Time.utc(1999, 6, 1), metadata: Metadata.new(change: Types::Change::UPDATED))
|
78
|
+
resources[4] = Resource.new(uri: 'http://example.org/', modified_time: Time.utc(2000, 3, 1), metadata: Metadata.new(change: Types::Change::UPDATED))
|
79
|
+
resources[5] = Resource.new(uri: 'http://example.org/', modified_time: Time.utc(2000, 6, 1), metadata: Metadata.new(change: Types::Change::UPDATED))
|
80
|
+
resources[6] = Resource.new(uri: 'http://example.org/', modified_time: Time.utc(1999, 9, 1), metadata: Metadata.new(change: Types::Change::DELETED))
|
81
|
+
resources[7] = Resource.new(uri: 'http://example.org/', modified_time: Time.utc(2000, 9, 1), metadata: Metadata.new(change: Types::Change::DELETED))
|
82
|
+
list = ChangeList.new(resources: resources)
|
83
|
+
all_changes = list.all_changes(of_type: Types::Change::UPDATED, in_range: Time.utc(1999, 4, 1)..Time.utc(2000, 4, 1))
|
84
|
+
expect(all_changes.to_a).to eq([resources[3], resources[4]])
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
44
89
|
describe BaseChangeIndex do
|
45
90
|
before(:each) do
|
46
91
|
@helper = instance_double(Client::HTTPHelper)
|
metadata
CHANGED
@@ -1,15 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resync-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 Moles
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: lazy
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.9'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.9.6
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.9'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.9.6
|
13
33
|
- !ruby/object:Gem::Dependency
|
14
34
|
name: resync
|
15
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -19,7 +39,7 @@ dependencies:
|
|
19
39
|
version: '0.2'
|
20
40
|
- - ">="
|
21
41
|
- !ruby/object:Gem::Version
|
22
|
-
version: 0.
|
42
|
+
version: 0.3.0
|
23
43
|
type: :runtime
|
24
44
|
prerelease: false
|
25
45
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,7 +49,7 @@ dependencies:
|
|
29
49
|
version: '0.2'
|
30
50
|
- - ">="
|
31
51
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0.
|
52
|
+
version: 0.3.0
|
33
53
|
- !ruby/object:Gem::Dependency
|
34
54
|
name: rubyzip
|
35
55
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,6 +162,20 @@ dependencies:
|
|
142
162
|
- - "~>"
|
143
163
|
- !ruby/object:Gem::Version
|
144
164
|
version: '0.8'
|
165
|
+
- !ruby/object:Gem::Dependency
|
166
|
+
name: codeclimate-test-reporter
|
167
|
+
requirement: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - "~>"
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
type: :development
|
173
|
+
prerelease: false
|
174
|
+
version_requirements: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - "~>"
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '0'
|
145
179
|
description: A Ruby client for the ResourceSync web synchronization framework
|
146
180
|
email:
|
147
181
|
- david.moles@ucop.edu
|
@@ -177,7 +211,6 @@ files:
|
|
177
211
|
- lib/resync/client/zip.rb
|
178
212
|
- lib/resync/client/zip/bitstream.rb
|
179
213
|
- lib/resync/client/zip/zip_package.rb
|
180
|
-
- lib/resync/client/zip/zip_packages.rb
|
181
214
|
- resync-client.gemspec
|
182
215
|
- spec/acceptance/example_spec.rb
|
183
216
|
- spec/data/examples/capability-list.xml
|
@@ -210,6 +243,8 @@ files:
|
|
210
243
|
- spec/spec_helper.rb
|
211
244
|
- spec/todo.rb
|
212
245
|
- spec/unit/resync/client/bitstream_spec.rb
|
246
|
+
- spec/unit/resync/client/change_dump_index_spec.rb
|
247
|
+
- spec/unit/resync/client/change_dump_spec.rb
|
213
248
|
- spec/unit/resync/client/client_spec.rb
|
214
249
|
- spec/unit/resync/client/dump_index_spec.rb
|
215
250
|
- spec/unit/resync/client/dump_spec.rb
|
@@ -217,7 +252,6 @@ files:
|
|
217
252
|
- spec/unit/resync/client/http_helper_spec.rb
|
218
253
|
- spec/unit/resync/client/list_index_spec.rb
|
219
254
|
- spec/unit/resync/client/zip_package_spec.rb
|
220
|
-
- spec/unit/resync/client/zip_packages_spec.rb
|
221
255
|
homepage: http://github.com/dmolesUC3/resync-client
|
222
256
|
licenses:
|
223
257
|
- MIT
|
@@ -238,7 +272,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
238
272
|
version: '0'
|
239
273
|
requirements: []
|
240
274
|
rubyforge_project:
|
241
|
-
rubygems_version: 2.4.
|
275
|
+
rubygems_version: 2.4.6
|
242
276
|
signing_key:
|
243
277
|
specification_version: 4
|
244
278
|
summary: Client library for ResourceSync
|
@@ -274,6 +308,8 @@ test_files:
|
|
274
308
|
- spec/spec_helper.rb
|
275
309
|
- spec/todo.rb
|
276
310
|
- spec/unit/resync/client/bitstream_spec.rb
|
311
|
+
- spec/unit/resync/client/change_dump_index_spec.rb
|
312
|
+
- spec/unit/resync/client/change_dump_spec.rb
|
277
313
|
- spec/unit/resync/client/client_spec.rb
|
278
314
|
- spec/unit/resync/client/dump_index_spec.rb
|
279
315
|
- spec/unit/resync/client/dump_spec.rb
|
@@ -281,5 +317,4 @@ test_files:
|
|
281
317
|
- spec/unit/resync/client/http_helper_spec.rb
|
282
318
|
- spec/unit/resync/client/list_index_spec.rb
|
283
319
|
- spec/unit/resync/client/zip_package_spec.rb
|
284
|
-
- spec/unit/resync/client/zip_packages_spec.rb
|
285
320
|
has_rdoc:
|
@@ -1,69 +0,0 @@
|
|
1
|
-
require 'resync'
|
2
|
-
require_relative '../mixins'
|
3
|
-
require_relative 'zip_package'
|
4
|
-
|
5
|
-
module Resync
|
6
|
-
class Client
|
7
|
-
module Zip
|
8
|
-
# Lazily retrieves and caches the zip packages for the specified
|
9
|
-
# list of resources. The packages are cached to temporary files
|
10
|
-
# which are deleted on exit; if they are deleted while the
|
11
|
-
# interpreter is running, the behavior is undefined (but bad things
|
12
|
-
# are likely to happen).
|
13
|
-
class ZipPackages
|
14
|
-
include Enumerable
|
15
|
-
|
16
|
-
# Creates a new {ZipPackages} wrapper for the specified list
|
17
|
-
# of resources.
|
18
|
-
# @param resources [Array<Resource>] The list of resources to
|
19
|
-
# get zip packages for.
|
20
|
-
def initialize(resources)
|
21
|
-
@resources = resources
|
22
|
-
@packages = {}
|
23
|
-
end
|
24
|
-
|
25
|
-
# Gets the size of this list of packages.
|
26
|
-
# @return the size of the underlying array.
|
27
|
-
def size
|
28
|
-
@resources.size
|
29
|
-
end
|
30
|
-
|
31
|
-
# Gets the zip package at the specified index, downloading it
|
32
|
-
# if necessary.
|
33
|
-
#
|
34
|
-
# @return [ZipPackage] the zip package for the resource at the
|
35
|
-
# specified index in the underlying array.
|
36
|
-
def [](key)
|
37
|
-
resource = @resources[key]
|
38
|
-
package_for(resource)
|
39
|
-
end
|
40
|
-
|
41
|
-
# Gets the zip package for the specified resource, downloading it
|
42
|
-
# if necessary.
|
43
|
-
# @return [ZipPackage] the package for the resource
|
44
|
-
def package_for(resource)
|
45
|
-
@packages[resource] ||= resource.zip_package
|
46
|
-
end
|
47
|
-
|
48
|
-
# Lazily iterates the given block for each zip package, downloading
|
49
|
-
# as necessary.
|
50
|
-
# @yield [ZipPackage] the zip package for each resource
|
51
|
-
def each
|
52
|
-
@resources.lazy.each do |resource|
|
53
|
-
yield package_for(resource)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# Eagerly gets the zip package for each resource, downloading
|
58
|
-
# as necessary. (For compatbility with {::Enumerator::Lazy#flat_map})
|
59
|
-
# @return [Array<ZipPackage>] the zip package for each resource
|
60
|
-
def force
|
61
|
-
@resources.map { |r| package_for(r) }.to_a
|
62
|
-
end
|
63
|
-
|
64
|
-
# Alias for {#force} (for compatbility with {::Enumerable#flat_map})
|
65
|
-
alias_method :to_ary, :force
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
@@ -1,82 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Resync
|
4
|
-
class Client
|
5
|
-
module Zip
|
6
|
-
describe ZipPackages do
|
7
|
-
it 'is lazy' do
|
8
|
-
resources = Array.new(3) { |i| Resource.new(uri: "http://example.org/res#{i}") }
|
9
|
-
|
10
|
-
zip_packages = ZipPackages.new(resources)
|
11
|
-
|
12
|
-
zip_package = instance_double(ZipPackage)
|
13
|
-
expect(resources[0]).not_to receive(:zip_package)
|
14
|
-
expect(resources[1]).not_to receive(:zip_package)
|
15
|
-
expect(resources[2]).to receive(:zip_package).and_return(zip_package)
|
16
|
-
|
17
|
-
expect(zip_packages[2]).to be(zip_package)
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'caches zip packages' do
|
21
|
-
resources = Array.new(3) { |i| Resource.new(uri: "http://example.org/res#{i}") }
|
22
|
-
|
23
|
-
zip_packages = ZipPackages.new(resources)
|
24
|
-
|
25
|
-
zip_package = instance_double(ZipPackage)
|
26
|
-
expect(resources[1]).to receive(:zip_package).once.and_return(zip_package)
|
27
|
-
|
28
|
-
expect(zip_packages[1]).to be(zip_package)
|
29
|
-
expect(zip_packages[1]).to be(zip_package)
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'flatmaps' do
|
33
|
-
resources = Array.new(6) { |i| Resource.new(uri: "http://example.org/res#{i}") }
|
34
|
-
all_packages = Array.new(6) do |i|
|
35
|
-
zip_package = instance_double(ZipPackage)
|
36
|
-
expect(resources[i]).to receive(:zip_package).once.and_return(zip_package)
|
37
|
-
zip_package
|
38
|
-
end
|
39
|
-
|
40
|
-
zip_packages_1 = ZipPackages.new(resources[0, 3])
|
41
|
-
zip_packages_2 = ZipPackages.new(resources[3, 3])
|
42
|
-
|
43
|
-
zrl1 = instance_double(Resync::Client::Mixins::Dump)
|
44
|
-
expect(zrl1).to receive(:zip_packages).twice.and_return(zip_packages_1)
|
45
|
-
|
46
|
-
zrl2 = instance_double(Resync::Client::Mixins::Dump)
|
47
|
-
expect(zrl2).to receive(:zip_packages).twice.and_return(zip_packages_2)
|
48
|
-
|
49
|
-
flat_mapped = [zrl1, zrl2].flat_map(&:zip_packages)
|
50
|
-
expect(flat_mapped).to eq(all_packages)
|
51
|
-
|
52
|
-
lazy_flat_mapped = [zrl1, zrl2].lazy.flat_map(&:zip_packages).to_a
|
53
|
-
expect(lazy_flat_mapped).to eq(all_packages)
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'supports lazy iteration' do
|
57
|
-
manifests = Array.new(3) { instance_double(ChangeDumpManifest) }
|
58
|
-
all_packages = Array.new(3) do |index|
|
59
|
-
zip_package = instance_double(ZipPackage)
|
60
|
-
allow(zip_package).to receive(:manifest).and_return(manifests[index])
|
61
|
-
zip_package
|
62
|
-
end
|
63
|
-
resources = Array.new(3) do |index|
|
64
|
-
resource = Resource.new(uri: "http://example.org/res#{index}")
|
65
|
-
if index > 1
|
66
|
-
expect(resource).not_to receive(:zip_package)
|
67
|
-
else
|
68
|
-
expect(resource).to receive(:zip_package).and_return(all_packages[index])
|
69
|
-
end
|
70
|
-
resource
|
71
|
-
end
|
72
|
-
|
73
|
-
zip_packages = ZipPackages.new(resources)
|
74
|
-
zip_packages.each_with_index do |zip_package, index|
|
75
|
-
expect(zip_package.manifest).to be(manifests[index])
|
76
|
-
break if index >= 1
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|