sdr-client 0.96.0 → 1.0.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: 74e0b90a6bacfc70362321764e79a26db88ca6b17bb37debcdfbafbba4cf117c
4
- data.tar.gz: 512f7e341236bcfd30fba4b45cf8844b851c62335abc39139185913dbca375e1
3
+ metadata.gz: a66643c6ea7e08e14f529c7e5396a5037ab39cae895fa65bb7ddf7a6d98ca93c
4
+ data.tar.gz: 7a7986eb90c7de9eb1f4b0335e4bae0981fe2679ac2317de2f66daaee92f141f
5
5
  SHA512:
6
- metadata.gz: fff091c59cf01f92fb978987e123814916ce791e9d965007a82641cf7a7ceb41011e34854ad7efed3afc454c31ffa6515de77dbfa3f2f1f55226213787f2b041
7
- data.tar.gz: f3273189c211b9c82141aa7e10b76387d6a6a2105bca12b7d5867363ea6b2c35e136ab2dd5b72586c63f7ff9123c322db31f6741e57dc0883a7254735fcd5a4e
6
+ metadata.gz: 8fc2bb28ace65e03d8cf5336b080924a7ed6d2899cf5d2d54459b38b3d2849738cdaf9bee4fb8021a5b174f3062410748e20345cba9e10e42690995d4e0cd9f9
7
+ data.tar.gz: 4a3dcc3903a17266469c3ad2ca18c2d3fbb7ff57b1711b5753993a5202361d7cb9b526fbef9806a31daabcebc307cae4ba052b5f185bd6a34bfb75e694fbfd11
data/.rubocop.yml CHANGED
@@ -27,6 +27,9 @@ Naming/FileName:
27
27
  Exclude:
28
28
  - 'lib/sdr-client.rb'
29
29
 
30
+ RSpec/MultipleMemoizedHelpers:
31
+ Enabled: false
32
+
30
33
  Gemspec/DeprecatedAttributeAssignment: # new in 1.10
31
34
  Enabled: true
32
35
  Gemspec/RequireMFA: # new in 1.23
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sdr-client (0.96.0)
4
+ sdr-client (1.0.0)
5
5
  activesupport
6
6
  cocina-models (~> 0.86.0)
7
7
  dry-monads
@@ -18,7 +18,7 @@ GEM
18
18
  addressable (2.8.1)
19
19
  public_suffix (>= 2.0.2, < 6.0)
20
20
  ast (2.4.2)
21
- attr_extras (6.2.5)
21
+ attr_extras (7.0.0)
22
22
  byebug (11.1.3)
23
23
  cocina-models (0.86.0)
24
24
  activesupport
@@ -43,35 +43,37 @@ GEM
43
43
  activesupport
44
44
  diff-lcs (1.5.0)
45
45
  docile (1.4.0)
46
- dry-container (0.11.0)
46
+ dry-core (1.0.0)
47
47
  concurrent-ruby (~> 1.0)
48
- dry-core (0.8.1)
48
+ zeitwerk (~> 2.6)
49
+ dry-inflector (1.0.0)
50
+ dry-logic (1.4.0)
49
51
  concurrent-ruby (~> 1.0)
50
- dry-inflector (0.3.0)
51
- dry-logic (1.2.0)
52
+ dry-core (~> 1.0, < 2)
53
+ zeitwerk (~> 2.6)
54
+ dry-monads (1.6.0)
52
55
  concurrent-ruby (~> 1.0)
53
- dry-core (~> 0.5, >= 0.5)
54
- dry-monads (1.4.0)
55
- concurrent-ruby (~> 1.0)
56
- dry-core (~> 0.7)
57
- dry-struct (1.4.0)
58
- dry-core (~> 0.5, >= 0.5)
59
- dry-types (~> 1.5)
56
+ dry-core (~> 1.0, < 2)
57
+ zeitwerk (~> 2.6)
58
+ dry-struct (1.6.0)
59
+ dry-core (~> 1.0, < 2)
60
+ dry-types (>= 1.7, < 2)
60
61
  ice_nine (~> 0.11)
61
- dry-types (1.5.1)
62
+ zeitwerk (~> 2.6)
63
+ dry-types (1.7.0)
62
64
  concurrent-ruby (~> 1.0)
63
- dry-container (~> 0.3)
64
- dry-core (~> 0.5, >= 0.5)
65
- dry-inflector (~> 0.1, >= 0.1.2)
66
- dry-logic (~> 1.0, >= 1.0.2)
65
+ dry-core (~> 1.0, < 2)
66
+ dry-inflector (~> 1.0, < 2)
67
+ dry-logic (>= 1.4, < 2)
68
+ zeitwerk (~> 2.6)
67
69
  edtf (3.1.0)
68
70
  activesupport (>= 3.0, < 8.0)
69
71
  equivalent-xml (0.6.0)
70
72
  nokogiri (>= 1.4.3)
71
- faraday (2.5.2)
73
+ faraday (2.7.0)
72
74
  faraday-net_http (>= 2.0, < 3.1)
73
75
  ruby2_keywords (>= 0.0.4)
74
- faraday-net_http (3.0.0)
76
+ faraday-net_http (3.0.2)
75
77
  hashdiff (1.0.1)
76
78
  i18n (1.12.0)
77
79
  concurrent-ruby (~> 1.0)
@@ -81,9 +83,9 @@ GEM
81
83
  multi_json
82
84
  minitest (5.16.3)
83
85
  multi_json (1.15.0)
84
- nokogiri (1.13.8-x86_64-darwin)
86
+ nokogiri (1.13.9-x86_64-darwin)
85
87
  racc (~> 1.4)
86
- nokogiri (1.13.8-x86_64-linux)
88
+ nokogiri (1.13.9-x86_64-linux)
87
89
  racc (~> 1.4)
88
90
  openapi3_parser (0.9.2)
89
91
  commonmarker (~> 0.17)
@@ -98,40 +100,40 @@ GEM
98
100
  racc (1.6.0)
99
101
  rainbow (3.1.1)
100
102
  rake (13.0.6)
101
- regexp_parser (2.5.0)
103
+ regexp_parser (2.6.0)
102
104
  rexml (3.2.5)
103
- rspec (3.11.0)
104
- rspec-core (~> 3.11.0)
105
- rspec-expectations (~> 3.11.0)
106
- rspec-mocks (~> 3.11.0)
107
- rspec-core (3.11.0)
108
- rspec-support (~> 3.11.0)
109
- rspec-expectations (3.11.1)
105
+ rspec (3.12.0)
106
+ rspec-core (~> 3.12.0)
107
+ rspec-expectations (~> 3.12.0)
108
+ rspec-mocks (~> 3.12.0)
109
+ rspec-core (3.12.0)
110
+ rspec-support (~> 3.12.0)
111
+ rspec-expectations (3.12.0)
110
112
  diff-lcs (>= 1.2.0, < 2.0)
111
- rspec-support (~> 3.11.0)
112
- rspec-mocks (3.11.1)
113
+ rspec-support (~> 3.12.0)
114
+ rspec-mocks (3.12.0)
113
115
  diff-lcs (>= 1.2.0, < 2.0)
114
- rspec-support (~> 3.11.0)
115
- rspec-support (3.11.1)
116
- rspec_junit_formatter (0.5.1)
116
+ rspec-support (~> 3.12.0)
117
+ rspec-support (3.12.0)
118
+ rspec_junit_formatter (0.6.0)
117
119
  rspec-core (>= 2, < 4, != 2.12.0)
118
120
  rss (0.2.9)
119
121
  rexml
120
- rubocop (1.36.0)
122
+ rubocop (1.39.0)
121
123
  json (~> 2.3)
122
124
  parallel (~> 1.10)
123
125
  parser (>= 3.1.2.1)
124
126
  rainbow (>= 2.2.2, < 4.0)
125
127
  regexp_parser (>= 1.8, < 3.0)
126
128
  rexml (>= 3.2.5, < 4.0)
127
- rubocop-ast (>= 1.20.1, < 2.0)
129
+ rubocop-ast (>= 1.23.0, < 2.0)
128
130
  ruby-progressbar (~> 1.7)
129
131
  unicode-display_width (>= 1.4.0, < 3.0)
130
- rubocop-ast (1.21.0)
132
+ rubocop-ast (1.23.0)
131
133
  parser (>= 3.1.1.0)
132
134
  rubocop-rake (0.6.0)
133
135
  rubocop (~> 1.0)
134
- rubocop-rspec (2.13.2)
136
+ rubocop-rspec (2.15.0)
135
137
  rubocop (~> 1.33)
136
138
  ruby-progressbar (1.11.0)
137
139
  ruby2_keywords (0.0.5)
@@ -153,7 +155,7 @@ GEM
153
155
  addressable (>= 2.8.0)
154
156
  crack (>= 0.3.2)
155
157
  hashdiff (>= 0.4.0, < 2.0.0)
156
- zeitwerk (2.6.0)
158
+ zeitwerk (2.6.6)
157
159
 
158
160
  PLATFORMS
159
161
  x86_64-darwin-19
data/README.md CHANGED
@@ -11,9 +11,10 @@ This provides a way for consumers to easily and correctly deposit files to the S
11
11
 
12
12
  ## Install
13
13
 
14
- We recommend using the latest 3.x release of Ruby.
14
+ Ruby 3 is required. The latest 3.x release is recommended.
15
15
 
16
16
  `gem install sdr-client`
17
+ Note that some commands require the lastest version of the client. Use this command to update the client as necessary.
17
18
 
18
19
  ## Usage
19
20
 
@@ -35,6 +36,7 @@ Log in:
35
36
  ```
36
37
  sdr login --url https://sdr-api-server:3000
37
38
  ```
39
+ You will be prompted for an email and password. Note that this is for an SDR API account, not SUNET account.
38
40
 
39
41
  Display version of sdr-client:
40
42
  ```
@@ -72,6 +72,7 @@ module SdrClient
72
72
  option :cdl, type: :boolean, default: false, desc: 'Controlled digital lending'
73
73
  option :cocina_file, desc: 'Path to a file containing Cocina JSON'
74
74
  option :cocina_pipe, type: :boolean, default: false, desc: 'Indicate Cocina JSON is being piped in'
75
+ option :basepath, default: Dir.getwd, desc: 'Base path for the files'
75
76
  def update(druid)
76
77
  validate_druid!(druid)
77
78
  job_id = SdrClient::Update.run(druid, **options)
@@ -95,6 +96,7 @@ module SdrClient
95
96
  option :view, enum: %w[world stanford location-based citation-only dark], desc: 'Access view level for the object'
96
97
  option :files_metadata, desc: 'JSON string representing per-file metadata'
97
98
  option :grouping_strategy, enum: %w[default filename], desc: 'Strategy for grouping files into filesets'
99
+ option :basepath, default: Dir.getwd, desc: 'Base path for the files'
98
100
  def deposit(*files)
99
101
  register_or_deposit(files: files, accession: true)
100
102
  end
@@ -113,6 +115,7 @@ module SdrClient
113
115
  option :view, enum: %w[world stanford location-based citation-only dark], desc: 'Access view level for the object'
114
116
  option :files_metadata, desc: 'JSON string representing per-file metadata'
115
117
  option :grouping_strategy, enum: %w[default filename], desc: 'Strategy for grouping files into filesets'
118
+ option :basepath, default: Dir.getwd, desc: 'Base path for the files'
116
119
  def register(*files)
117
120
  register_or_deposit(files: files, accession: false)
118
121
  end
@@ -18,26 +18,26 @@ module SdrClient
18
18
 
19
19
  # @param (see #initialize)
20
20
  # @return (see #build)
21
- def self.build(files:, files_metadata:)
22
- new(files: files, files_metadata: files_metadata.dup).build
21
+ def self.build(files:, files_metadata:, basepath:)
22
+ new(files: files, files_metadata: files_metadata.dup, basepath: basepath).build
23
23
  end
24
24
 
25
- # @param [Array<String>] files the list of files for which to generate metadata
26
- def initialize(files:, files_metadata:)
25
+ # @param [Array<String>] files the list of relative filepaths for which to generate metadata
26
+ def initialize(files:, files_metadata:, basepath:)
27
27
  @files = files
28
28
  @files_metadata = files_metadata
29
+ @basepath = basepath
29
30
  end
30
31
 
31
- # @return [Hash<String, Hash<String, String>>]
32
+ # @return [Hash<String, Hash<String, String>>] a map of relative filepaths to a map of metadata
32
33
  def build
33
- files.each do |file_path|
34
- file_key = ::File.basename(file_path)
34
+ files.each do |filepath|
35
35
  OPERATIONS.each do |operation|
36
- result = operation.for(file_path: file_path)
36
+ result = operation.for(filepath: absolute_filepath_for(filepath))
37
37
  next if result.nil?
38
38
 
39
- files_metadata[file_key] ||= {}
40
- files_metadata[file_key][operation::NAME] = result
39
+ files_metadata[filepath] ||= {}
40
+ files_metadata[filepath][operation::NAME] = result
41
41
  end
42
42
  end
43
43
  files_metadata
@@ -45,7 +45,11 @@ module SdrClient
45
45
 
46
46
  private
47
47
 
48
- attr_reader :files, :files_metadata
48
+ attr_reader :files, :files_metadata, :basepath
49
+
50
+ def absolute_filepath_for(filepath)
51
+ ::File.join(basepath, filepath)
52
+ end
49
53
  end
50
54
  end
51
55
  end
@@ -8,8 +8,8 @@ module SdrClient
8
8
  # MD5 for this file.
9
9
  class MD5
10
10
  NAME = 'md5'
11
- def self.for(file_path:, **)
12
- Digest::MD5.file(file_path).hexdigest
11
+ def self.for(filepath:, **)
12
+ Digest::MD5.file(filepath).hexdigest
13
13
  end
14
14
  end
15
15
  end
@@ -8,8 +8,8 @@ module SdrClient
8
8
  # Mime-type for this file.
9
9
  class MimeType
10
10
  NAME = 'mime_type'
11
- def self.for(file_path:, **)
12
- argv = Shellwords.escape(file_path)
11
+ def self.for(filepath:, **)
12
+ argv = Shellwords.escape(filepath)
13
13
  `file --mime-type -b #{argv}`.chomp
14
14
  end
15
15
  end
@@ -8,8 +8,8 @@ module SdrClient
8
8
  # SHA1 for this file.
9
9
  class SHA1
10
10
  NAME = 'sha1'
11
- def self.for(file_path:, **)
12
- Digest::SHA1.file(file_path).hexdigest
11
+ def self.for(filepath:, **)
12
+ Digest::SHA1.file(filepath).hexdigest
13
13
  end
14
14
  end
15
15
  end
@@ -41,7 +41,7 @@ module SdrClient
41
41
  def file_args(upload, upload_metadata)
42
42
  args = {
43
43
  external_identifier: upload.signed_id,
44
- label: upload.filename,
44
+ label: ::File.basename(upload.filename),
45
45
  filename: upload.filename
46
46
  }
47
47
  args.merge!(upload_metadata)
@@ -10,7 +10,7 @@ module SdrClient
10
10
  # Call `#values` on the result of the grouping operation because 1)
11
11
  # `Process#build_filesets` expects an array of arrays, not an array of
12
12
  # hashes, and 2) the keys aren't used anywhere
13
- uploads.group_by { |ul| ::File.basename(ul.filename, '.*') }.values
13
+ uploads.group_by { |ul| ::File.join(::File.dirname(ul.filename), ::File.basename(ul.filename, '.*')) }.values
14
14
  end
15
15
  end
16
16
  end
@@ -11,17 +11,20 @@ module SdrClient
11
11
  # @param [Boolean] accession should the accessionWF be started
12
12
  # @param [String] priority (nil) what processing priority should be used
13
13
  # either 'low' or 'default'
14
- # @param [Array<String>] files a list of file names to upload
14
+ # @param [Array<String>] files a list of relative filepaths to upload
15
+ # @param [String] basepath filepath to which filepaths are relative
15
16
  # @param [Boolean] assign_doi should a DOI be assigned to this item
16
17
  # @param [Logger] logger the logger to use
17
18
  def initialize(request_dro:, # rubocop:disable Metrics/ParameterLists
18
19
  connection:,
19
20
  accession:,
21
+ basepath:,
20
22
  priority: nil,
21
23
  files: [],
22
24
  assign_doi: false,
23
25
  logger: Logger.new($stdout))
24
26
  @files = files
27
+ @basepath = basepath
25
28
  @connection = connection
26
29
  @request_dro = request_dro
27
30
  @logger = logger
@@ -34,10 +37,14 @@ module SdrClient
34
37
  check_files_exist
35
38
  child_files_match
36
39
 
37
- file_metadata = UploadFilesMetadataBuilder.build(files: files, mime_types: mime_types)
40
+ # file_metadata is a map of relative filepaths to Files::DirectUploadRequests
41
+ file_metadata = UploadFilesMetadataBuilder.build(files: files, mime_types: mime_types, basepath: basepath)
42
+ # upload_response is an array of Files::DirectUploadResponse
38
43
  upload_responses = UploadFiles.upload(file_metadata: file_metadata,
44
+ filepath_map: filepath_map,
39
45
  logger: logger,
40
46
  connection: connection)
47
+
41
48
  new_request_dro = UpdateDroWithFileIdentifiers.update(request_dro: request_dro, upload_responses: upload_responses)
42
49
  CreateResource.run(accession: @accession,
43
50
  priority: @priority,
@@ -49,31 +56,28 @@ module SdrClient
49
56
 
50
57
  private
51
58
 
52
- attr_reader :request_dro, :files, :logger, :connection
59
+ attr_reader :request_dro, :files, :logger, :connection, :basepath
53
60
 
54
61
  def check_files_exist
55
62
  logger.info('checking to see if files exist')
56
- files.each do |file_name|
57
- raise Errno::ENOENT, file_name unless ::File.exist?(file_name)
63
+ files.each do |filepath|
64
+ raise Errno::ENOENT, filepath unless ::File.exist?(absolute_filepath_for(filepath))
58
65
  end
59
66
  end
60
67
 
61
68
  def child_files_match
62
69
  # Files without request files.
63
70
  files.each do |filepath|
64
- filename = ::File.basename(filepath)
65
-
66
- raise "Request file not provided for #{filepath}" if request_files[filename].nil?
71
+ raise "Request file not provided for #{filepath}" if request_files[filepath].nil?
67
72
  end
68
73
 
69
74
  # Request files without files
70
- filenames = files.map { |filepath| ::File.basename(filepath) }
71
75
  request_files.each_key do |request_filename|
72
- raise "File not provided for request file #{request_filename}" unless filenames.include?(request_filename)
76
+ raise "File not provided for request file #{request_filename}" unless files.include?(request_filename)
73
77
  end
74
78
  end
75
79
 
76
- # Map of filenames to mimetypes
80
+ # Map of relative filepaths to mimetypes
77
81
  def mime_types
78
82
  @mime_types ||=
79
83
  request_files.transform_values do |file|
@@ -81,7 +85,7 @@ module SdrClient
81
85
  end
82
86
  end
83
87
 
84
- # Map of filenames to request files
88
+ # Map of absolute filepaths to Cocina::Models::RequestFiles
85
89
  def request_files
86
90
  @request_files ||= begin
87
91
  return {} unless request_dro.structural
@@ -93,6 +97,16 @@ module SdrClient
93
97
  end.flatten(1).to_h
94
98
  end
95
99
  end
100
+
101
+ def absolute_filepath_for(filename)
102
+ ::File.join(basepath, filename)
103
+ end
104
+
105
+ def filepath_map
106
+ @filepath_map ||= files.each_with_object({}) do |filepath, obj|
107
+ obj[filepath] = absolute_filepath_for(filepath)
108
+ end
109
+ end
96
110
  end
97
111
  end
98
112
  end
@@ -13,7 +13,8 @@ module SdrClient
13
13
  # either 'low' or 'default'
14
14
  # @param [Class] grouping_strategy class whose run method groups an array of uploads
15
15
  # @param [Class] file_set_type_strategy class whose run method determines file_set type
16
- # @param [Array<String>] files a list of file names to upload
16
+ # @param [Array<String>] files a list of relative filepaths to upload
17
+ # @param [String] basepath filepath to which filepaths are relative
17
18
  # @param [Boolean] assign_doi should a DOI be assigned to this item
18
19
  # @param [Logger] logger the logger to use
19
20
  #
@@ -21,6 +22,7 @@ module SdrClient
21
22
  def initialize(metadata:,
22
23
  connection:,
23
24
  accession:,
25
+ basepath:,
24
26
  priority: nil,
25
27
  grouping_strategy: SingleFileGroupingStrategy,
26
28
  file_set_type_strategy: FileTypeFileSetStrategy,
@@ -36,6 +38,7 @@ module SdrClient
36
38
  @accession = accession
37
39
  @priority = priority
38
40
  @assign_doi = assign_doi
41
+ @basepath = basepath
39
42
  end
40
43
  # rubocop:enable Metrics/ParameterLists
41
44
 
@@ -44,8 +47,9 @@ module SdrClient
44
47
  def run
45
48
  check_files_exist
46
49
 
47
- file_metadata = UploadFilesMetadataBuilder.build(files: files, mime_types: mime_types)
50
+ file_metadata = UploadFilesMetadataBuilder.build(files: files, mime_types: mime_types, basepath: basepath)
48
51
  upload_responses = UploadFiles.upload(file_metadata: file_metadata,
52
+ filepath_map: filepath_map,
49
53
  logger: logger,
50
54
  connection: connection)
51
55
  metadata_builder = MetadataBuilder.new(metadata: metadata,
@@ -65,22 +69,31 @@ module SdrClient
65
69
 
66
70
  private
67
71
 
68
- attr_reader :metadata, :files, :connection, :logger, :grouping_strategy, :file_set_type_strategy
72
+ attr_reader :metadata, :files, :connection, :logger, :grouping_strategy, :file_set_type_strategy, :basepath
69
73
 
70
74
  def check_files_exist
71
75
  logger.info('checking to see if files exist')
72
- files.each do |file_name|
73
- raise Errno::ENOENT, file_name unless ::File.exist?(file_name)
76
+ files.each do |filepath|
77
+ raise Errno::ENOENT, filepath unless ::File.exist?(absolute_filepath_for(filepath))
74
78
  end
75
79
  end
76
80
 
77
81
  def mime_types
78
82
  @mime_types ||=
79
83
  files.to_h do |filepath|
80
- filename = ::File.basename(filepath)
81
- [filename, metadata.for(filename)['mime_type']]
84
+ [filepath, metadata.for(filepath)['mime_type']]
82
85
  end
83
86
  end
87
+
88
+ def filepath_map
89
+ @filepath_map ||= files.each_with_object({}) do |filepath, obj|
90
+ obj[filepath] = absolute_filepath_for(filepath)
91
+ end
92
+ end
93
+
94
+ def absolute_filepath_for(filepath)
95
+ ::File.join(basepath, filepath)
96
+ end
84
97
  end
85
98
  end
86
99
  end
@@ -8,38 +8,43 @@ module SdrClient
8
8
  class UploadFiles
9
9
  BLOB_PATH = '/v1/direct_uploads'
10
10
 
11
- # @param [Hash<String,Files::DirectUploadRequest>] the metadata for uploading the files
11
+ # @param [Hash<String,Files::DirectUploadRequest>] file_metadata map of relative filepaths to file metadata
12
+ # @param [Hash<String,String>] filepath_map map of relative filepaths to absolute filepaths
12
13
  # @param [Logger] logger the logger to use
13
14
  # @param [Connection] connection
14
- def self.upload(file_metadata:, logger:, connection:)
15
- new(file_metadata: file_metadata, logger: logger, connection: connection).run
15
+ def self.upload(file_metadata:, filepath_map:, logger:, connection:)
16
+ new(file_metadata: file_metadata, filepath_map: filepath_map, logger: logger, connection: connection).run
16
17
  end
17
18
 
18
- # @param [Hash<String,Files::DirectUploadRequest>] the metadata for uploading the files
19
+ # @param [Hash<String,Files::DirectUploadRequest>] file_metadata map of relative filepaths to file metadata
20
+ # @param [Hash<String,String>] filepath_map map of relative filepaths to absolute filepaths
19
21
  # @param [Logger] logger the logger to use
20
22
  # @param [Connection] connection
21
- def initialize(file_metadata:, logger:, connection:)
23
+ def initialize(file_metadata:, filepath_map:, logger:, connection:)
22
24
  @file_metadata = file_metadata
25
+ @filepath_map = filepath_map
23
26
  @logger = logger
24
27
  @connection = connection
25
28
  end
26
29
 
27
30
  # @return [Array<Files::DirectUploadResponse>] the responses from the server for the uploads
28
31
  def run
29
- file_metadata.map do |filename, metadata|
32
+ file_metadata.map do |filepath, metadata|
30
33
  direct_upload(metadata.to_json).tap do |response|
31
- upload_file(filename: filename,
34
+ # ActiveStorage modifies the filename provided in response, so setting here with the relative filename
35
+ response.filename = filepath
36
+ upload_file(filename: filepath,
32
37
  url: response.direct_upload.fetch('url'),
33
38
  content_type: response.content_type,
34
39
  content_length: response.byte_size)
35
- logger.info("Upload of #{filename} complete")
40
+ logger.info("Upload of #{filepath} complete")
36
41
  end
37
42
  end
38
43
  end
39
44
 
40
45
  private
41
46
 
42
- attr_reader :logger, :connection, :file_metadata
47
+ attr_reader :logger, :connection, :file_metadata, :filepath_map
43
48
 
44
49
  def direct_upload(metadata_json)
45
50
  logger.info("Starting an upload request: #{metadata_json}")
@@ -61,7 +66,7 @@ module SdrClient
61
66
  logger.info("Uploading `#{filename}' to #{url}")
62
67
 
63
68
  upload_response = connection.put(url) do |req|
64
- req.body = ::File.open(filename)
69
+ req.body = ::File.open(filepath_map[filename])
65
70
  req.headers['Content-Type'] = content_type
66
71
  req.headers['Content-Length'] = content_length.to_s
67
72
  end
@@ -6,39 +6,36 @@ module SdrClient
6
6
  module Deposit
7
7
  # Collecting all the metadata about the files for a deposit
8
8
  class UploadFilesMetadataBuilder
9
- # @param [Array<String>] files a list of filepaths to upload
9
+ # @param [Array<String>] files a list of relative filepaths to upload
10
10
  # @param [Hash<String,String>] mime_types a map of filenames to mime types
11
+ # @param [String] basepath path to which files are relative
11
12
  # @return [Hash<String, Files::DirectUploadRequest>] the metadata for uploading the files
12
- def self.build(files:, mime_types:)
13
- new(files: files, mime_types: mime_types).build
13
+ def self.build(files:, mime_types:, basepath:)
14
+ new(files: files, mime_types: mime_types, basepath: basepath).build
14
15
  end
15
16
 
16
- # @param [Array<String>] files a list of filepaths to upload
17
+ # @param [Array<String>] files a list of absolute filepaths to upload
17
18
  # @param [Hash<String,String>] mime_types a map of filenames to mime types
18
- def initialize(files:, mime_types:)
19
+ # @param [String] basepath path to which files are relative
20
+ def initialize(files:, mime_types:, basepath:)
19
21
  @files = files
20
22
  @mime_types = mime_types
23
+ @basepath = basepath
21
24
  end
22
25
 
23
- attr_reader :files, :mime_types
26
+ attr_reader :files, :mime_types, :basepath
24
27
 
25
28
  # @return [Hash<String, Files::DirectUploadRequest>] the metadata for uploading the files
26
29
  def build
27
- files.each_with_object({}) do |path, obj|
28
- obj[path] = Files::DirectUploadRequest.from_file(path,
29
- file_name: filename_for(path),
30
- content_type: mime_type_for(path))
30
+ files.each_with_object({}) do |filepath, obj|
31
+ obj[filepath] = Files::DirectUploadRequest.from_file(absolute_filepath_for(filepath),
32
+ file_name: filepath,
33
+ content_type: mime_types[filepath])
31
34
  end
32
35
  end
33
36
 
34
- # This can be overridden in the case that the file on disk has a different
35
- # name than we want to repo to know about.
36
- def filename_for(file_path)
37
- ::File.basename(file_path)
38
- end
39
-
40
- def mime_type_for(file_path)
41
- mime_types[filename_for(file_path)]
37
+ def absolute_filepath_for(filepath)
38
+ ::File.join(basepath, filepath)
42
39
  end
43
40
  end
44
41
  end
@@ -8,6 +8,9 @@ module SdrClient
8
8
  BOOK_TYPE = Cocina::Models::ObjectType.book
9
9
  # rubocop:disable Metrics/ParameterLists
10
10
  # rubocop:disable Metrics/MethodLength
11
+ # params [Array<String>] files a list of relative filepaths to upload
12
+ # params [String] basepath filepath to which filepaths are relative, defaults to current directory
13
+ # params [Hash<String,Hash>] file_metadata relative filepath, hash of metadata per-file metadata
11
14
  # @return [String] job id for the background job result
12
15
  def self.run(label: nil,
13
16
  type: BOOK_TYPE,
@@ -26,29 +29,34 @@ module SdrClient
26
29
  url:,
27
30
  files: [],
28
31
  files_metadata: {},
32
+ basepath: Dir.getwd,
29
33
  accession: false,
30
34
  priority: nil,
31
35
  grouping_strategy: SingleFileGroupingStrategy,
32
36
  file_set_type_strategy: FileTypeFileSetStrategy,
33
37
  logger: Logger.new($stdout))
34
- augmented_metadata = FileMetadataBuilder.build(files: files, files_metadata: files_metadata)
35
- metadata = Request.new(label: label,
36
- type: type,
37
- view: view,
38
- download: download,
39
- apo: apo,
40
- use_and_reproduction: use_and_reproduction,
41
- copyright: copyright,
42
- collection: collection,
43
- source_id: source_id,
44
- catkey: catkey,
45
- embargo_release_date: embargo_release_date,
46
- embargo_access: embargo_access,
47
- embargo_download: embargo_download,
48
- viewing_direction: viewing_direction,
49
- files_metadata: augmented_metadata)
38
+ # augmented_metadata is a map of relative filepaths to file metadata
39
+ augmented_metadata = FileMetadataBuilder.build(files: files, files_metadata: files_metadata, basepath: basepath)
40
+ request = Request.new(label: label,
41
+ type: type,
42
+ view: view,
43
+ download: download,
44
+ apo: apo,
45
+ use_and_reproduction: use_and_reproduction,
46
+ copyright: copyright,
47
+ collection: collection,
48
+ source_id: source_id,
49
+ catkey: catkey,
50
+ embargo_release_date: embargo_release_date,
51
+ embargo_access: embargo_access,
52
+ embargo_download: embargo_download,
53
+ viewing_direction: viewing_direction,
54
+ files_metadata: augmented_metadata)
50
55
  connection = Connection.new(url: url)
51
- Process.new(metadata: metadata, connection: connection, files: files,
56
+ Process.new(metadata: request,
57
+ connection: connection,
58
+ files: files,
59
+ basepath: basepath,
52
60
  grouping_strategy: grouping_strategy,
53
61
  file_set_type_strategy: file_set_type_strategy,
54
62
  accession: accession,
@@ -57,9 +65,11 @@ module SdrClient
57
65
  end
58
66
  # rubocop:enable Metrics/MethodLength
59
67
 
60
- # @param [Array<String>] files absolute paths to files
68
+ # @param [Array<String>] files relative paths to files
69
+ # @params [String] basepath path to which files are relative
61
70
  def self.model_run(request_dro:,
62
71
  files: [],
72
+ basepath: Dir.getwd,
63
73
  url:,
64
74
  accession:,
65
75
  priority: nil,
@@ -68,6 +78,7 @@ module SdrClient
68
78
  ModelProcess.new(request_dro: request_dro,
69
79
  connection: connection,
70
80
  files: files,
81
+ basepath: basepath,
71
82
  logger: logger,
72
83
  accession: accession,
73
84
  priority: priority).run
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SdrClient
4
- VERSION = '0.96.0'
4
+ VERSION = '1.0.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.96.0
4
+ version: 1.0.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: 2022-09-27 00:00:00.000000000 Z
11
+ date: 2022-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -274,7 +274,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
274
274
  - !ruby/object:Gem::Version
275
275
  version: '0'
276
276
  requirements: []
277
- rubygems_version: 3.2.32
277
+ rubygems_version: 3.3.7
278
278
  signing_key:
279
279
  specification_version: 4
280
280
  summary: The CLI for https://github.com/sul-dlss/sdr-api