resync-client 0.2.5 → 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/.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 [](https://travis-ci.org/dmolesUC3/resync-client) [](https://codeclimate.com/github/dmolesUC3/resync-client) [](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
|