resync-client 0.1.2 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/CHANGES.md +10 -0
- data/lib/resync/client.rb +63 -0
- data/lib/resync/client/http_helper.rb +90 -90
- data/lib/resync/client/mixins.rb +1 -0
- data/lib/resync/client/mixins/bitstream_resource.rb +26 -0
- data/lib/resync/client/mixins/bitstream_resource_list.rb +29 -0
- data/lib/resync/client/mixins/client_delegator.rb +38 -0
- data/lib/resync/client/mixins/downloadable.rb +36 -0
- data/lib/resync/client/mixins/link_client_delegate.rb +19 -0
- data/lib/resync/client/mixins/resource_client_delegate.rb +19 -0
- data/lib/resync/client/mixins/zipped_resource.rb +20 -0
- data/lib/resync/client/mixins/zipped_resource_list.rb +26 -0
- data/lib/resync/client/version.rb +1 -1
- data/lib/resync/client/zip.rb +1 -0
- data/lib/resync/client/zip/bitstream.rb +85 -0
- data/lib/resync/client/zip/zip_package.rb +78 -0
- data/lib/resync/client/zip/zip_packages.rb +59 -0
- data/lib/resync/extensions.rb +36 -0
- data/resync-client.gemspec +1 -1
- data/spec/acceptance/example_spec.rb +46 -0
- data/spec/data/resourcedump/changedump.xml +16 -0
- data/spec/data/simulator/capability-list.xml +2 -0
- data/spec/data/simulator/change-list.xml +2 -0
- data/spec/data/simulator/source-description.xml +2 -0
- data/spec/data/simulator/update.txt +1 -0
- data/spec/unit/resync/client/bitstream_spec.rb +84 -80
- data/spec/unit/resync/client/client_spec.rb +64 -3
- data/spec/unit/resync/client/{resync_extensions_spec.rb → extensions_spec.rb} +1 -6
- data/spec/unit/resync/client/http_helper_spec.rb +187 -185
- data/spec/unit/resync/client/zip_package_spec.rb +47 -32
- data/spec/unit/resync/client/zip_packages_spec.rb +42 -38
- data/spec/unit/resync/client/zipped_resource_list_spec.rb +61 -0
- metadata +35 -16
- data/lib/resync/client/bitstream.rb +0 -79
- data/lib/resync/client/client.rb +0 -58
- data/lib/resync/client/downloadable.rb +0 -35
- data/lib/resync/client/dump.rb +0 -26
- data/lib/resync/client/resync_extensions.rb +0 -85
- data/lib/resync/client/zip_package.rb +0 -66
- data/lib/resync/client/zip_packages.rb +0 -51
- data/spec/unit/resync/client/dump_spec.rb +0 -26
data/lib/resync/client/client.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
require_relative 'version'
|
2
|
-
require_relative 'http_helper'
|
3
|
-
|
4
|
-
module Resync
|
5
|
-
|
6
|
-
# Utility class for retrieving HTTP content and parsing it as ResourceSync documents.
|
7
|
-
class Client
|
8
|
-
|
9
|
-
# ------------------------------------------------------------
|
10
|
-
# Initializer
|
11
|
-
|
12
|
-
# Creates a new +Client+
|
13
|
-
# @param helper [HTTPHelper] the HTTP helper. Defaults to a new HTTP helper with
|
14
|
-
# +resync-client VERSION+ as the User-Agent string.
|
15
|
-
def initialize(helper: HTTPHelper.new(user_agent: "resync-client #{VERSION}"))
|
16
|
-
@helper = helper
|
17
|
-
end
|
18
|
-
|
19
|
-
# ------------------------------------------------------------
|
20
|
-
# Public methods
|
21
|
-
|
22
|
-
# Gets the content of the specified URI and parses it as a ResourceSync document.
|
23
|
-
def get_and_parse(uri)
|
24
|
-
uri = Resync::XML.to_uri(uri)
|
25
|
-
raw_contents = get(uri)
|
26
|
-
doc = XMLParser.parse(raw_contents)
|
27
|
-
doc.client = self
|
28
|
-
doc
|
29
|
-
end
|
30
|
-
|
31
|
-
# Gets the content of the specified URI as a string.
|
32
|
-
# @param uri [URI, String] the URI to download
|
33
|
-
# @return [String] the content of the URI
|
34
|
-
def get(uri)
|
35
|
-
uri = Resync::XML.to_uri(uri)
|
36
|
-
@helper.fetch(uri: uri)
|
37
|
-
end
|
38
|
-
|
39
|
-
# Gets the content of the specified URI and saves it to a temporary file.
|
40
|
-
# @param uri [URI, String] the URI to download
|
41
|
-
# @return [String] the path to the downloaded file
|
42
|
-
def download_to_temp_file(uri)
|
43
|
-
uri = Resync::XML.to_uri(uri)
|
44
|
-
@helper.fetch_to_file(uri: uri)
|
45
|
-
end
|
46
|
-
|
47
|
-
# Gets the content of the specified URI and saves it to the specified file,
|
48
|
-
# overwriting it if it exists.
|
49
|
-
# @param uri [URI, String] the URI to download
|
50
|
-
# @param path [String] the path to save the download to
|
51
|
-
# @return [String] the path to the downloaded file
|
52
|
-
def download_to_file(uri:, path:)
|
53
|
-
uri = Resync::XML.to_uri(uri)
|
54
|
-
@helper.fetch_to_file(path: path, uri: uri)
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'resync'
|
2
|
-
|
3
|
-
module Resync
|
4
|
-
|
5
|
-
# Adds +get+, +get_raw+, and +get_file+ methods, delegating
|
6
|
-
# to the injected client.
|
7
|
-
#
|
8
|
-
# @see Augmented#client
|
9
|
-
module Downloadable
|
10
|
-
# Delegates to {Client#get_and_parse} to get the contents of
|
11
|
-
# +:uri+ as a ResourceSync document
|
12
|
-
def get_and_parse # rubocop:disable Style/AccessorMethodName
|
13
|
-
client.get_and_parse(uri)
|
14
|
-
end
|
15
|
-
|
16
|
-
# Delegates to {Client#get} to get the contents of this +:uri+
|
17
|
-
def get # rubocop:disable Style/AccessorMethodName
|
18
|
-
client.get(uri)
|
19
|
-
end
|
20
|
-
|
21
|
-
# Delegates to {Client#download_to_temp_file} to download the
|
22
|
-
# contents of +:uri+ to a file.
|
23
|
-
def download_to_temp_file # rubocop:disable Style/AccessorMethodName
|
24
|
-
client.download_to_temp_file(uri)
|
25
|
-
end
|
26
|
-
|
27
|
-
# Delegates to {Client#download_to_file} to download the
|
28
|
-
# contents of +:uri+ to the specified path.
|
29
|
-
# @param path [String] the path to download to
|
30
|
-
def download_to_file(path)
|
31
|
-
client.download_to_file(uri: uri, path: path)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
data/lib/resync/client/dump.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
require_relative 'zip_packages'
|
2
|
-
|
3
|
-
module Resync
|
4
|
-
# Extends {ChangeDump} and {ResourceDump} to provide
|
5
|
-
# transparent access to the linked bitstream packages
|
6
|
-
module Dump
|
7
|
-
# Injects a +:zip_package+ method into each resource,
|
8
|
-
# downloading the (presumed) bitstream package to a
|
9
|
-
# temp file and returning it as a {ZipPackage}
|
10
|
-
def resources=(value)
|
11
|
-
super
|
12
|
-
resources.each do |r|
|
13
|
-
def r.zip_package
|
14
|
-
@zip_package ||= ZipPackage.new(download_to_temp_file)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
# A list (downloaded lazily) of the {ZipPackage}s for each resource
|
20
|
-
# @return [ZipPackages] the zip packages for each resource
|
21
|
-
def zip_packages
|
22
|
-
@zip_packages ||= ZipPackages.new(resources)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
@@ -1,85 +0,0 @@
|
|
1
|
-
require 'resync'
|
2
|
-
require_relative 'downloadable'
|
3
|
-
require_relative 'dump'
|
4
|
-
|
5
|
-
# Extensions to the core Resync classes to simplify retrieval
|
6
|
-
module Resync
|
7
|
-
|
8
|
-
# ------------------------------------------------------------
|
9
|
-
# Base classes
|
10
|
-
|
11
|
-
# Injects a {Client} that subclasses can use to fetch
|
12
|
-
# resources and links
|
13
|
-
#
|
14
|
-
# @!attribute [rw] client
|
15
|
-
# @return [Client] the injected {Client}. Defaults to
|
16
|
-
# a new {Client} instance.
|
17
|
-
class Augmented
|
18
|
-
attr_writer :client
|
19
|
-
|
20
|
-
def client
|
21
|
-
@client ||= Client.new
|
22
|
-
end
|
23
|
-
|
24
|
-
alias_method :base_links=, :links=
|
25
|
-
private :base_links=
|
26
|
-
|
27
|
-
# Adds a +:client+ method to each link, delegating
|
28
|
-
# to {#client}
|
29
|
-
def links=(value)
|
30
|
-
self.base_links = value
|
31
|
-
self.base_links = value
|
32
|
-
parent = self
|
33
|
-
links.each do |l|
|
34
|
-
l.define_singleton_method(:client) do
|
35
|
-
parent.client
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
# Adds a +:client+ method to each resource, delegating
|
42
|
-
# to {Augmented#client}
|
43
|
-
class BaseResourceList
|
44
|
-
alias_method :base_resources=, :resources=
|
45
|
-
private :base_resources=
|
46
|
-
|
47
|
-
# Adds a +:client+ method to each resource, delegating
|
48
|
-
# to {Augmented#client}
|
49
|
-
def resources=(value)
|
50
|
-
self.base_resources = value
|
51
|
-
parent = self
|
52
|
-
resources.each do |r|
|
53
|
-
r.define_singleton_method(:client) do
|
54
|
-
parent.client
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
# ------------------------------------------------------------
|
61
|
-
# Resource and Link
|
62
|
-
|
63
|
-
# Includes the {Downloadable} module
|
64
|
-
class Resource
|
65
|
-
include Downloadable
|
66
|
-
end
|
67
|
-
|
68
|
-
# Includes the {Link} module
|
69
|
-
class Link
|
70
|
-
include Downloadable
|
71
|
-
end
|
72
|
-
|
73
|
-
# ------------------------------------------------------------
|
74
|
-
# ResourceDump and ChaneDump
|
75
|
-
|
76
|
-
# Includes the {Dump} module
|
77
|
-
class ResourceDump
|
78
|
-
include Dump
|
79
|
-
end
|
80
|
-
|
81
|
-
# Includes the {Dump} module
|
82
|
-
class ChangeDump
|
83
|
-
include Dump
|
84
|
-
end
|
85
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
require 'rexml/document'
|
2
|
-
require 'zip'
|
3
|
-
require_relative 'bitstream'
|
4
|
-
|
5
|
-
module Resync
|
6
|
-
# A ZIP package of resources or changes, providing access to individual
|
7
|
-
# bitstreams based on the included manifest file.
|
8
|
-
#
|
9
|
-
class ZipPackage
|
10
|
-
|
11
|
-
# ------------------------------------------------------------
|
12
|
-
# Attributes
|
13
|
-
|
14
|
-
# @return [Zip::File] the ZIP file wrapped by this package
|
15
|
-
attr_reader :zipfile
|
16
|
-
|
17
|
-
# @return [ResourceDumpManifest, ChangeDumpManifest] the manifest
|
18
|
-
# for the ZIP package
|
19
|
-
attr_reader :manifest
|
20
|
-
|
21
|
-
# ------------------------------------------------------------
|
22
|
-
# Initializer
|
23
|
-
|
24
|
-
# Creates a new +ZipPackage+ for the specified file.
|
25
|
-
#
|
26
|
-
# @param zipfile [Zip::File, String] the ZIP file, or a path to it.
|
27
|
-
def initialize(zipfile)
|
28
|
-
self.zipfile = zipfile
|
29
|
-
end
|
30
|
-
|
31
|
-
# ------------------------------------------------------------
|
32
|
-
# Public methods
|
33
|
-
|
34
|
-
# Gets the bitstream for the specified resource. (Note that this
|
35
|
-
# does no validation; if the resource is not in the manifest, or
|
36
|
-
# the corresponding entry is not in the ZIP file, the behavior of
|
37
|
-
# the returned {Bitstream} is undefined.)
|
38
|
-
#
|
39
|
-
# @return [Bitstream] a bitstream wrapping the ZIP entry for the
|
40
|
-
# specified resource.
|
41
|
-
def bitstream_for(resource)
|
42
|
-
Bitstream.new(zipfile: @zipfile, resource: resource)
|
43
|
-
end
|
44
|
-
|
45
|
-
# Gets all bitstreams declared in the package manifest.
|
46
|
-
# @return [Array<Bitstream>] a list of all bitstreams in the package
|
47
|
-
def bitstreams
|
48
|
-
manifest.resources.map { |r| bitstream_for(r) }
|
49
|
-
end
|
50
|
-
|
51
|
-
# ------------------------------------------------------------
|
52
|
-
# Private methods
|
53
|
-
|
54
|
-
private
|
55
|
-
|
56
|
-
def zipfile=(value)
|
57
|
-
zipfile = value.is_a?(Zip::File) ? value : Zip::File.open(value)
|
58
|
-
manifest_entry = zipfile.find_entry('manifest.xml')
|
59
|
-
fail "No manifest.xml found in zipfile #{zipfile.name}" unless manifest_entry
|
60
|
-
manifest_stream = manifest_entry.get_input_stream
|
61
|
-
@manifest = XMLParser.parse(manifest_stream)
|
62
|
-
@zipfile = zipfile
|
63
|
-
end
|
64
|
-
|
65
|
-
end
|
66
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
module Resync
|
2
|
-
# Lazily retrieves and caches the zip packages for the specified
|
3
|
-
# list of resources. The packages are cached to temporary files
|
4
|
-
# which are deleted on exit; if they are deleted while the
|
5
|
-
# interpreter is running, the behavior is undefined (but bad things
|
6
|
-
# are likely to happen).
|
7
|
-
class ZipPackages
|
8
|
-
include Enumerable
|
9
|
-
|
10
|
-
# Creates a new {ZipPackages} wrapper for the specified list
|
11
|
-
# of resources.
|
12
|
-
# @param resources [Array<Resource>] The list of resources to
|
13
|
-
# get zip packages for.
|
14
|
-
def initialize(resources)
|
15
|
-
@resources = resources
|
16
|
-
@packages = {}
|
17
|
-
end
|
18
|
-
|
19
|
-
# Gets the size of this list of packages.
|
20
|
-
# @return the size of the underlying array.
|
21
|
-
def size
|
22
|
-
@resources.size
|
23
|
-
end
|
24
|
-
|
25
|
-
# Gets the zip package at the specified index, downloading it
|
26
|
-
# if necessary.
|
27
|
-
#
|
28
|
-
# @return [ZipPackage] the zip package for the resource at the
|
29
|
-
# specified index in the underlying array.
|
30
|
-
def [](key)
|
31
|
-
resource = @resources[key]
|
32
|
-
package_for(resource)
|
33
|
-
end
|
34
|
-
|
35
|
-
# Gets the zip package for the specified resource, downloading it
|
36
|
-
# if necessary.
|
37
|
-
# @return [ZipPackage] the package for the resource
|
38
|
-
def package_for(resource)
|
39
|
-
@packages[resource] ||= resource.zip_package
|
40
|
-
end
|
41
|
-
|
42
|
-
# Lazily iterates the given block for each zip package, downloading
|
43
|
-
# as necessary.
|
44
|
-
# @param &block [Block] The block to iterate
|
45
|
-
def each
|
46
|
-
@resources.lazy.each do |resource|
|
47
|
-
yield package_for(resource)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Resync
|
4
|
-
describe Dump do
|
5
|
-
it 'transparently extracts bitstreams' do
|
6
|
-
package_uri = URI('http://example.com/resourcedump.zip')
|
7
|
-
client = instance_double(Client)
|
8
|
-
expect(client).to receive(:download_to_temp_file).once.with(package_uri).and_return('spec/data/resourcedump/resourcedump.zip')
|
9
|
-
|
10
|
-
resource_dump = XMLParser.parse(File.read('spec/data/resourcedump/resourcedump.xml'))
|
11
|
-
resource_dump.client = client
|
12
|
-
|
13
|
-
zip_packages = resource_dump.zip_packages
|
14
|
-
expect(zip_packages.size).to eq(1)
|
15
|
-
|
16
|
-
zip_package = zip_packages[0]
|
17
|
-
expect(zip_package).to be_a(ZipPackage)
|
18
|
-
|
19
|
-
bitstreams = zip_package.bitstreams
|
20
|
-
expect(bitstreams.size).to eq(2)
|
21
|
-
|
22
|
-
stream1 = bitstreams[0]
|
23
|
-
expect(stream1.content).to eq(File.read('spec/data/resourcedump/resources/res1'))
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|