sdr-client 0.3.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 80a6d11a266d546eb1e0763b99b13b18d9f64c558ef21db50f3f509623a4f4bf
4
- data.tar.gz: 5ec2344617583af3322f0426e39328aee355ee4c12d7338d8734f529110e8da6
3
+ metadata.gz: bb3f20e21233ef1ef0f4d72f4d7dcd0e4bb52968b955152e62259e023b730b7b
4
+ data.tar.gz: ecbb08752fcd3c71b4868404bc48871eaba138c852304678a466cd85de3fe4bd
5
5
  SHA512:
6
- metadata.gz: 3a145ef20a1c42abaed33ab79746778844e922b530a6c48d1b7f6d6f50a0e5a2c3f23e15a804fc5b75b3baeaac6baa4e67b35391965b5bb5da34892b345c9805
7
- data.tar.gz: 2600c209c4f35f2ab7a8d7209189c690ec8f06de819666fd7bdd38f63290b997aa87355d54c7a5b5b2e4633ecfd02f75e908815923c2f44116373a999789bf68
6
+ metadata.gz: '08307c141dd01737019f40e1a999b8fd9aa41abca57379f655a9ac5773eba55f974c4d3c34c804e44cd7c8a8792c292e84f5d8c7bf62dd2021b32dd87832420b'
7
+ data.tar.gz: 928ba2d1377cf11bc1e1cfaff2891748ac916d3a3d9e83fca0ac07e0efdbd450ceb895a066bcc3c3a7a4355f186717efb4f5c4d6540867336a21095064f02cb2
@@ -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'
@@ -3,13 +3,17 @@
3
3
  module SdrClient
4
4
  # The namespace for the "deposit" command
5
5
  module Deposit
6
+ # rubocop:disable Metrics/ParameterLists
6
7
  def self.run(label: nil,
7
8
  type: 'http://cocina.sul.stanford.edu/models/book.jsonld',
8
9
  apo:,
9
10
  collection:,
10
11
  catkey: nil,
11
12
  source_id:,
12
- url:, files: [])
13
+ url:,
14
+ files: [],
15
+ files_metadata: {},
16
+ grouping_strategy: SingleFileGroupingStrategy)
13
17
  token = Credentials.read
14
18
 
15
19
  metadata = Request.new(label: label,
@@ -18,11 +22,15 @@ module SdrClient
18
22
  collection: collection,
19
23
  source_id: source_id,
20
24
  catkey: catkey)
21
- Process.new(metadata: metadata, url: url, token: token, files: files).run
25
+ Process.new(metadata: metadata, url: url, token: token,
26
+ files: files, files_metadata: files_metadata, grouping_strategy: grouping_strategy).run
22
27
  end
28
+ # rubocop:enable Metrics/ParameterLists
23
29
  end
24
30
  end
25
31
  require 'json'
32
+ require 'sdr_client/deposit/single_file_grouping_strategy'
33
+ require 'sdr_client/deposit/matching_file_grouping_strategy'
26
34
  require 'sdr_client/deposit/files/direct_upload_request'
27
35
  require 'sdr_client/deposit/files/direct_upload_response'
28
36
  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,10 +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: [])
7
+ def initialize(uploads: [], uploads_metadata: {}, files: [], label:)
8
+ @label = label
8
9
  @files = if !uploads.empty?
9
10
  uploads.map do |upload|
10
- File.new(external_identifier: upload.signed_id, label: upload.filename, filename: upload.filename)
11
+ File.new(file_args(upload, uploads_metadata.fetch(upload.filename, {})))
11
12
  end
12
13
  else
13
14
  files
@@ -17,15 +18,25 @@ module SdrClient
17
18
  def as_json
18
19
  {
19
20
  "type": 'http://cocina.sul.stanford.edu/models/fileset.jsonld',
21
+ "label": label,
20
22
  structural: {
21
- hasMember: files.map(&:as_json)
23
+ contains: files.map(&:as_json)
22
24
  }
23
25
  }
24
26
  end
25
27
 
26
28
  private
27
29
 
28
- attr_reader :files
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
29
40
  end
30
41
  end
31
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,11 +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.map { |upload| FileSet.new(uploads: [upload]) }
42
-
40
+ # @return [Request] a clone of this request with the file_sets added
41
+ def with_file_sets(file_sets)
43
42
  Request.new(label: label,
44
43
  apo: apo,
45
44
  collection: collection,
@@ -49,11 +48,6 @@ module SdrClient
49
48
  file_sets: file_sets)
50
49
  end
51
50
 
52
- # In this case there is a 1-1 mapping between Files and FileSets,
53
- # but this doesn't always have to be the case. We could change this in the
54
- # future so that we have one FileSet that has an Image and its OCR file.
55
- def add_uploads_each_as_resource(uploads); end
56
-
57
51
  private
58
52
 
59
53
  attr_reader :label, :file_sets, :source_id, :catkey, :apo, :collection, :type
@@ -73,7 +67,7 @@ module SdrClient
73
67
  def structural
74
68
  {
75
69
  isMemberOf: collection,
76
- hasMember: file_sets.map(&:as_json)
70
+ contains: file_sets.map(&:as_json)
77
71
  }
78
72
  end
79
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.0'
4
+ VERSION = '0.7.0'
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.0
4
+ version: 0.7.0
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