resync-client 0.1.2 → 0.2.1

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/CHANGES.md +10 -0
  4. data/lib/resync/client.rb +63 -0
  5. data/lib/resync/client/http_helper.rb +90 -90
  6. data/lib/resync/client/mixins.rb +1 -0
  7. data/lib/resync/client/mixins/bitstream_resource.rb +26 -0
  8. data/lib/resync/client/mixins/bitstream_resource_list.rb +29 -0
  9. data/lib/resync/client/mixins/client_delegator.rb +38 -0
  10. data/lib/resync/client/mixins/downloadable.rb +36 -0
  11. data/lib/resync/client/mixins/link_client_delegate.rb +19 -0
  12. data/lib/resync/client/mixins/resource_client_delegate.rb +19 -0
  13. data/lib/resync/client/mixins/zipped_resource.rb +20 -0
  14. data/lib/resync/client/mixins/zipped_resource_list.rb +26 -0
  15. data/lib/resync/client/version.rb +1 -1
  16. data/lib/resync/client/zip.rb +1 -0
  17. data/lib/resync/client/zip/bitstream.rb +85 -0
  18. data/lib/resync/client/zip/zip_package.rb +78 -0
  19. data/lib/resync/client/zip/zip_packages.rb +59 -0
  20. data/lib/resync/extensions.rb +36 -0
  21. data/resync-client.gemspec +1 -1
  22. data/spec/acceptance/example_spec.rb +46 -0
  23. data/spec/data/resourcedump/changedump.xml +16 -0
  24. data/spec/data/simulator/capability-list.xml +2 -0
  25. data/spec/data/simulator/change-list.xml +2 -0
  26. data/spec/data/simulator/source-description.xml +2 -0
  27. data/spec/data/simulator/update.txt +1 -0
  28. data/spec/unit/resync/client/bitstream_spec.rb +84 -80
  29. data/spec/unit/resync/client/client_spec.rb +64 -3
  30. data/spec/unit/resync/client/{resync_extensions_spec.rb → extensions_spec.rb} +1 -6
  31. data/spec/unit/resync/client/http_helper_spec.rb +187 -185
  32. data/spec/unit/resync/client/zip_package_spec.rb +47 -32
  33. data/spec/unit/resync/client/zip_packages_spec.rb +42 -38
  34. data/spec/unit/resync/client/zipped_resource_list_spec.rb +61 -0
  35. metadata +35 -16
  36. data/lib/resync/client/bitstream.rb +0 -79
  37. data/lib/resync/client/client.rb +0 -58
  38. data/lib/resync/client/downloadable.rb +0 -35
  39. data/lib/resync/client/dump.rb +0 -26
  40. data/lib/resync/client/resync_extensions.rb +0 -85
  41. data/lib/resync/client/zip_package.rb +0 -66
  42. data/lib/resync/client/zip_packages.rb +0 -51
  43. data/spec/unit/resync/client/dump_spec.rb +0 -26
@@ -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
@@ -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