sdr-client 0.3.1 → 0.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4c634551367640a9eb3647e55fcac169a61b40af1a111582d3e857bc2cc1f020
4
- data.tar.gz: 75f3a024adf97dad2cf85a8e8b117a232c71b2f644655b98752c1320af005e17
3
+ metadata.gz: 85bf3bb61e2edeca3fd59c4bcb72e65c0ca8a6fa2555095059c774d6adbb5cd9
4
+ data.tar.gz: 29ef71e2e7778c28b8db875e7c910ee4f477857422d61d59774ab09b0fdb5852
5
5
  SHA512:
6
- metadata.gz: 04a14d2edbb8334fbcc13b7ae131d7bf1697869c580395c2ea8c2971c18b911d55b7b0128e0cdff25b7a5844333f11eb2af23bc435ab7c6e692e4951092e22ed
7
- data.tar.gz: 6c3369f015d8e3201ba1f58664c4d9b15208064eb5fdd24deca2de26ae7d4575889d22f7aa25eacb2e1232cfd2068d288771c6ba0c04737b7e5fc6c7508d2ba8
6
+ metadata.gz: 61cc5ce0d28aeddbcd20273a7086d9b4dc0482b76f91b19002496b80e4db7d32471f9b8e827ffc800c58172fb3cf7d1f2ccdf920ca11bd88f5ac141002406703
7
+ data.tar.gz: c2149a463c52831fee474f8c43e00982fce4ea9f56da629f8b87f1889bb59630419ed6c8c5296b56b6985324195ff1bb700277cbdfa91e9de89388319689b461
@@ -13,3 +13,9 @@ Layout/LineLength:
13
13
  Metrics/BlockLength:
14
14
  Exclude:
15
15
  - 'spec/**/*'
16
+ ExcludedMethods:
17
+ - 'OptionParser.new'
18
+
19
+ Naming/FileName:
20
+ Exclude:
21
+ - 'lib/sdr-client.rb'
@@ -14,8 +14,3 @@ Metrics/AbcSize:
14
14
  # Configuration parameters: CountComments, ExcludedMethods.
15
15
  Metrics/MethodLength:
16
16
  Max: 13
17
-
18
- # Offense count: 2
19
- # Configuration parameters: CountKeywordArgs.
20
- Metrics/ParameterLists:
21
- Max: 8
data/README.md CHANGED
@@ -8,6 +8,10 @@
8
8
  This is a CLI for interacting with the Stanford Digital Repository API.
9
9
  The code for the SDR API server is at https://github.com/sul-dlss/sdr-api
10
10
 
11
+ ## Install
12
+
13
+ `gem install sdr-client`
14
+
11
15
  ## Usage
12
16
 
13
17
  Log in:
data/exe/sdr CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  $LOAD_PATH.unshift 'lib'
5
5
  require 'optparse'
6
+ require 'sdr_client'
6
7
 
7
8
  options = {}
8
9
  global = OptionParser.new do |opts|
@@ -60,6 +61,20 @@ subcommands = {
60
61
  options[:source_id] = source_id
61
62
  end
62
63
 
64
+ opts.on('--strategy STRATEGY',
65
+ 'The strategy to use for distributing files into filesets. Either "default" or "filename"') do |strategy|
66
+ strategy_class = case strategy
67
+ when 'filename'
68
+ SdrClient::Deposit::MatchingFileGroupingStrategy
69
+ when 'default'
70
+ SdrClient::Deposit::SingleFileGroupingStrategy
71
+ else
72
+ warn "Unknown strategy #{strategy}"
73
+ exit(1)
74
+ end
75
+ options[:grouping_strategy] = strategy_class
76
+ end
77
+
63
78
  opts.on('-h', '--help', 'Display this screen') do
64
79
  puts opts
65
80
  exit
@@ -75,6 +90,5 @@ end
75
90
 
76
91
  subcommands[command].order!
77
92
 
78
- require 'sdr_client'
79
93
  options[:files] = ARGV unless ARGV.empty?
80
94
  SdrClient::CLI.start(command, options)
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sdr_client'
@@ -1,15 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'logger'
4
+
3
5
  module SdrClient
4
6
  # The namespace for the "deposit" command
5
7
  module Deposit
8
+ # rubocop:disable Metrics/ParameterLists
6
9
  def self.run(label: nil,
7
10
  type: 'http://cocina.sul.stanford.edu/models/book.jsonld',
8
11
  apo:,
9
12
  collection:,
10
13
  catkey: nil,
11
14
  source_id:,
12
- url:, files: [])
15
+ url:,
16
+ files: [],
17
+ files_metadata: {},
18
+ grouping_strategy: SingleFileGroupingStrategy,
19
+ logger: Logger.new(STDOUT))
13
20
  token = Credentials.read
14
21
 
15
22
  metadata = Request.new(label: label,
@@ -18,11 +25,15 @@ module SdrClient
18
25
  collection: collection,
19
26
  source_id: source_id,
20
27
  catkey: catkey)
21
- Process.new(metadata: metadata, url: url, token: token, files: files).run
28
+ Process.new(metadata: metadata, url: url, token: token, files: files,
29
+ files_metadata: files_metadata, grouping_strategy: grouping_strategy, logger: logger).run
22
30
  end
31
+ # rubocop:enable Metrics/ParameterLists
23
32
  end
24
33
  end
25
34
  require 'json'
35
+ require 'sdr_client/deposit/single_file_grouping_strategy'
36
+ require 'sdr_client/deposit/matching_file_grouping_strategy'
26
37
  require 'sdr_client/deposit/files/direct_upload_request'
27
38
  require 'sdr_client/deposit/files/direct_upload_response'
28
39
  require 'sdr_client/deposit/file'
@@ -4,15 +4,23 @@ module SdrClient
4
4
  module Deposit
5
5
  # This represents the File metadata that we send to the server for doing a deposit
6
6
  class File
7
- def initialize(external_identifier:, label:, filename:, access: 'dark', preserve: false, shelve: false)
7
+ # rubocop:disable Metrics/ParameterLists
8
+ def initialize(external_identifier:, label:, filename:,
9
+ access: 'dark', preserve: false, shelve: false,
10
+ mime_type: nil, md5: nil, sha1: nil)
8
11
  @external_identifier = external_identifier
9
12
  @label = label
10
13
  @filename = filename
11
14
  @access = access
12
15
  @preserve = preserve
13
16
  @shelve = shelve
17
+ @mime_type = mime_type
18
+ @md5 = md5
19
+ @sha1 = sha1
14
20
  end
21
+ # rubocop:enable Metrics/ParameterLists
15
22
 
23
+ # rubocop:disable Metrics/MethodLength
16
24
  def as_json
17
25
  {
18
26
  "type": 'http://cocina.sul.stanford.edu/models/file.jsonld',
@@ -26,6 +34,26 @@ module SdrClient
26
34
  sdrPreserve: @preserve,
27
35
  shelve: @shelve
28
36
  }
37
+ }.tap do |json|
38
+ json['hasMessageDigests'] = message_digests unless message_digests.empty?
39
+ json['hasMimeType'] = @mime_type if @mime_type
40
+ end
41
+ end
42
+ # rubocop:enable Metrics/MethodLength
43
+
44
+ private
45
+
46
+ def message_digests
47
+ @message_digests ||= [].tap do |message_digests|
48
+ message_digests << create_message_digest('md5', @md5) unless @md5.nil?
49
+ message_digests << create_message_digest('sha1', @sha1) unless @sha1.nil?
50
+ end
51
+ end
52
+
53
+ def create_message_digest(algorithm, digest)
54
+ {
55
+ "type": algorithm,
56
+ digest: digest
29
57
  }
30
58
  end
31
59
  end
@@ -4,11 +4,11 @@ module SdrClient
4
4
  module Deposit
5
5
  # This represents the FileSet metadata that we send to the server for doing a deposit
6
6
  class FileSet
7
- def initialize(uploads: [], files: [], label:)
7
+ def initialize(uploads: [], uploads_metadata: {}, files: [], label:)
8
8
  @label = label
9
9
  @files = if !uploads.empty?
10
10
  uploads.map do |upload|
11
- File.new(external_identifier: upload.signed_id, label: upload.filename, filename: upload.filename)
11
+ File.new(file_args(upload, uploads_metadata.fetch(upload.filename, {})))
12
12
  end
13
13
  else
14
14
  files
@@ -20,7 +20,7 @@ module SdrClient
20
20
  "type": 'http://cocina.sul.stanford.edu/models/fileset.jsonld',
21
21
  "label": label,
22
22
  structural: {
23
- hasMember: files.map(&:as_json)
23
+ contains: files.map(&:as_json)
24
24
  }
25
25
  }
26
26
  end
@@ -28,6 +28,15 @@ module SdrClient
28
28
  private
29
29
 
30
30
  attr_reader :files, :label
31
+
32
+ def file_args(upload, upload_metadata)
33
+ args = {
34
+ external_identifier: upload.signed_id,
35
+ label: upload.filename,
36
+ filename: upload.filename
37
+ }
38
+ args.merge(upload_metadata)
39
+ end
31
40
  end
32
41
  end
33
42
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SdrClient
4
+ module Deposit
5
+ # This strategy is for building one file set per set of similarly prefixed uploaded files
6
+ class MatchingFileGroupingStrategy
7
+ # @param [Array<SdrClient::Deposit::Files::DirectUploadResponse>] uploads the uploaded files to attach.
8
+ # @return [Array<Array<SdrClient::Deposit::Files::DirectUploadResponse>>] uploads the grouped uploaded files.
9
+ def self.run(uploads: [])
10
+ # Call `#values` on the result of the grouping operation because 1)
11
+ # `Process#build_filesets` expects an array of arrays, not an array of
12
+ # hashes, and 2) the keys aren't used anywhere
13
+ uploads.group_by { |ul| ::File.basename(ul.filename, '.*') }.values
14
+ end
15
+ end
16
+ end
17
+ end
@@ -9,30 +9,39 @@ module SdrClient
9
9
  BLOB_PATH = '/v1/direct_uploads'
10
10
  DRO_PATH = '/v1/resources'
11
11
  # @param [Request] metadata information about the object
12
+ # @param [Class] grouping_strategy class whose run method groups an array of uploads
12
13
  # @param [String] url the server to send to
13
14
  # @param [String] token the bearer auth token for the server
14
15
  # @param [Array<String>] files a list of file names to upload
16
+ # @param [Hash<String, Hash<String, String>>] files_metadata file name, hash of additional file metadata
17
+ # Additional metadata includes access, preserve, shelve, md5, sha1
15
18
  # @param [Logger] logger the logger to use
16
- def initialize(metadata:, url:, token:, files: [], logger: Logger.new(STDOUT))
19
+ # rubocop:disable Metrics/ParameterLists
20
+ def initialize(metadata:, grouping_strategy: SingleFileGroupingStrategy, url:,
21
+ token:, files: [], files_metadata: {}, logger: Logger.new(STDOUT))
17
22
  @files = files
18
23
  @url = url
19
24
  @token = token
20
25
  @metadata = metadata
21
26
  @logger = logger
27
+ @grouping_strategy = grouping_strategy
28
+ @files_metadata = files_metadata
22
29
  end
30
+ # rubocop:enable Metrics/ParameterLists
23
31
 
24
32
  def run
25
33
  check_files_exist
26
34
  file_metadata = collect_file_metadata
27
35
  upload_responses = upload_file_metadata(file_metadata)
28
36
  upload_files(upload_responses)
29
- request = metadata.with_uploads(upload_responses.values)
37
+ file_sets = build_filesets(uploads: upload_responses.values, files_metadata: files_metadata)
38
+ request = metadata.with_file_sets(file_sets)
30
39
  upload_metadata(request.as_json)
31
40
  end
32
41
 
33
42
  private
34
43
 
35
- attr_reader :metadata, :files, :url, :token, :logger
44
+ attr_reader :metadata, :files, :url, :token, :logger, :grouping_strategy, :files_metadata
36
45
 
37
46
  def check_files_exist
38
47
  logger.info('checking to see if files exist')
@@ -111,6 +120,18 @@ module SdrClient
111
120
  conn.adapter :net_http
112
121
  end
113
122
  end
123
+
124
+ # @param [Array<SdrClient::Deposit::Files::DirectUploadResponse>] uploads the uploaded files to attach.
125
+ # @param [Hash<String,Hash<String, String>>] files_metadata filename, hash of additional file metadata.
126
+ # @return [Array<SdrClient::Deposit::FileSet>] the uploads transformed to filesets
127
+ def build_filesets(uploads:, files_metadata:)
128
+ grouped_uploads = grouping_strategy.run(uploads: uploads)
129
+ grouped_uploads.map.with_index(1) do |upload_group, i|
130
+ metadata_group = {}
131
+ upload_group.each { |upload| metadata_group[upload.filename] = files_metadata.fetch(upload.filename, {}) }
132
+ FileSet.new(uploads: upload_group, uploads_metadata: metadata_group, label: "Object #{i}")
133
+ end
134
+ end
114
135
  end
115
136
  end
116
137
  end
@@ -7,6 +7,7 @@ module SdrClient
7
7
  # @param [String] label the required object label
8
8
  # @param [String] type (http://cocina.sul.stanford.edu/models/object.jsonld) the required object type.
9
9
  # @param [Array<FileSet>] file_sets the file sets to attach.
10
+ # rubocop:disable Metrics/ParameterLists
10
11
  def initialize(label: nil,
11
12
  apo:,
12
13
  collection:,
@@ -22,6 +23,7 @@ module SdrClient
22
23
  @apo = apo
23
24
  @file_sets = file_sets
24
25
  end
26
+ # rubocop:enable Metrics/ParameterLists
25
27
 
26
28
  def as_json
27
29
  {
@@ -35,13 +37,8 @@ module SdrClient
35
37
  end
36
38
  end
37
39
 
38
- # @param [Array<SdrClient::Deposit::Files::DirectUploadResponse>] uploads the uploaded files to attach.
39
- # @return [Request] a clone of this request with the uploads added
40
- def with_uploads(uploads)
41
- file_sets = uploads.each_with_index.map do |upload, i|
42
- FileSet.new(uploads: [upload], label: "Object #{i + 1}")
43
- end
44
-
40
+ # @return [Request] a clone of this request with the file_sets added
41
+ def with_file_sets(file_sets)
45
42
  Request.new(label: label,
46
43
  apo: apo,
47
44
  collection: collection,
@@ -51,11 +48,6 @@ module SdrClient
51
48
  file_sets: file_sets)
52
49
  end
53
50
 
54
- # In this case there is a 1-1 mapping between Files and FileSets,
55
- # but this doesn't always have to be the case. We could change this in the
56
- # future so that we have one FileSet that has an Image and its OCR file.
57
- def add_uploads_each_as_resource(uploads); end
58
-
59
51
  private
60
52
 
61
53
  attr_reader :label, :file_sets, :source_id, :catkey, :apo, :collection, :type
@@ -75,7 +67,7 @@ module SdrClient
75
67
  def structural
76
68
  {
77
69
  isMemberOf: collection,
78
- hasMember: file_sets.map(&:as_json)
70
+ contains: file_sets.map(&:as_json)
79
71
  }
80
72
  end
81
73
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SdrClient
4
+ module Deposit
5
+ # This strategy is for building one file set per uploaded file
6
+ class SingleFileGroupingStrategy
7
+ # @param [Array<SdrClient::Deposit::Files::DirectUploadResponse>] uploads the uploaded files to attach.
8
+ # @return [Array<Array<SdrClient::Deposit::Files::DirectUploadResponse>>] uploads the grouped uploaded files.
9
+ def self.run(uploads: [])
10
+ uploads.map { |upload| [upload] }
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SdrClient
4
- VERSION = '0.3.1'
4
+ VERSION = '0.7.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sdr-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Coyne
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-01-23 00:00:00.000000000 Z
11
+ date: 2020-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-monads
@@ -158,6 +158,7 @@ files:
158
158
  - bin/console
159
159
  - bin/setup
160
160
  - exe/sdr
161
+ - lib/sdr-client.rb
161
162
  - lib/sdr_client.rb
162
163
  - lib/sdr_client/cli.rb
163
164
  - lib/sdr_client/credentials.rb
@@ -166,8 +167,10 @@ files:
166
167
  - lib/sdr_client/deposit/file_set.rb
167
168
  - lib/sdr_client/deposit/files/direct_upload_request.rb
168
169
  - lib/sdr_client/deposit/files/direct_upload_response.rb
170
+ - lib/sdr_client/deposit/matching_file_grouping_strategy.rb
169
171
  - lib/sdr_client/deposit/process.rb
170
172
  - lib/sdr_client/deposit/request.rb
173
+ - lib/sdr_client/deposit/single_file_grouping_strategy.rb
171
174
  - lib/sdr_client/login.rb
172
175
  - lib/sdr_client/login_prompt.rb
173
176
  - lib/sdr_client/version.rb
@@ -193,7 +196,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
193
196
  - !ruby/object:Gem::Version
194
197
  version: '0'
195
198
  requirements: []
196
- rubygems_version: 3.0.3
199
+ rubygems_version: 3.1.2
197
200
  signing_key:
198
201
  specification_version: 4
199
202
  summary: The CLI for https://github.com/sul-dlss/sdr-api