sdr-replication 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,33 @@
1
+ require File.join(File.dirname(__FILE__),'../libdir')
2
+ require 'sdr_replication'
3
+
4
+ module Replication
5
+
6
+ # A wrapper class around the systemu gem that is used for shelling out to the operating system
7
+ # and executing a command
8
+ #
9
+ # @note Copyright (c) 2014 by The Board of Trustees of the Leland Stanford Junior University.
10
+ # All rights reserved. See {file:LICENSE.rdoc} for details.
11
+ class OperatingSystem
12
+
13
+ # Executes a system command in a subprocess.
14
+ # The method will return stdout from the command if execution was successful.
15
+ # The method will raise an exception if if execution fails.
16
+ # The exception's message will contain the explaination of the failure.
17
+ # @param [String] command the command to be executed
18
+ # @return [String] stdout from the command if execution was successful
19
+ def OperatingSystem.execute(command)
20
+ status, stdout, stderr = systemu(command)
21
+ if (status.exitstatus != 0)
22
+ raise stderr
23
+ end
24
+ return stdout
25
+ rescue
26
+ msg = "Command failed to execute: [#{command}] caused by <STDERR = #{stderr.split($/).join('; ')}>"
27
+ msg << " STDOUT = #{stdout.split($/).join('; ')}" if (stdout && (stdout.length > 0))
28
+ raise msg
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,62 @@
1
+ require File.join(File.dirname(__FILE__),'../libdir')
2
+ require 'sdr_replication'
3
+
4
+ module Replication
5
+
6
+ # The metadata concerning the digital object/version that is the subject of replication.
7
+ #
8
+ # @note Copyright (c) 2014 by The Board of Trustees of the Leland Stanford Junior University.
9
+ # All rights reserved. See {file:LICENSE.rdoc} for details.
10
+ class Replica
11
+
12
+ @@replica_cache_pathname = nil
13
+
14
+ # @return [Pathname] The base location of the replica cache
15
+ def Replica.replica_cache_pathname
16
+ @@replica_cache_pathname
17
+ end
18
+
19
+ # @return [Pathname] Set the base location of the replica cache
20
+ # @param [Pathname,String] replica_cache_pathname The base location of the replica cache
21
+ def Replica.replica_cache_pathname=(replica_cache_pathname)
22
+ @@replica_cache_pathname = Pathname(replica_cache_pathname)
23
+ end
24
+
25
+ # @return [String] The unique identifier for the digital object replica
26
+ attr_accessor :replica_id
27
+
28
+ # @return [String] The original home location of the replica (sdr or dpn)
29
+ attr_accessor :home_repository
30
+
31
+ # @return [Time] The timestamp of the datetime at which the replica was created
32
+ attr_accessor :create_date
33
+
34
+ # @return [BagitBag] A bag containing a copy of the replica
35
+ attr_accessor :bagit_bag
36
+
37
+ # @return [Integer] The size (in bytes) of the replic bag's payload
38
+ attr_accessor :payload_size
39
+
40
+ # @return [String] The type of checksum/digest type (:sha1, :sha256)
41
+ attr_accessor :payload_fixity_type
42
+
43
+ # @return [String] The value of the checksum/digest
44
+ attr_accessor :payload_fixity
45
+
46
+ # @param [String] replica_id The unique identifier for the digital object replica
47
+ # @param [String] home_repository The original home location of the replica (sdr or dpn)
48
+ # @return [Replica] Initialize a new Replica object
49
+ def initialize(replica_id, home_repository)
50
+ @replica_id = replica_id
51
+ @home_repository = home_repository
52
+ end
53
+
54
+ # @return [Pathname] The location of the replica bag
55
+ def replica_pathname
56
+ @replica_pathname ||= @@replica_cache_pathname.join(home_repository,replica_id)
57
+ end
58
+
59
+ end
60
+ end
61
+
62
+
@@ -0,0 +1,63 @@
1
+ require File.join(File.dirname(__FILE__),'../libdir')
2
+ require 'sdr_replication'
3
+
4
+ module Replication
5
+
6
+ #
7
+ # @note Copyright (c) 2014 by The Board of Trustees of the Leland Stanford Junior University.
8
+ # All rights reserved. See {file:LICENSE.rdoc} for details.
9
+ class SdrObjectVersion
10
+
11
+ # @return [Moab::StorageObjectVersion] Represents the object version's storage location
12
+ attr_accessor :moab_object_version
13
+
14
+ # @param [Moab::StorageObjectVersion] object_version Represents the object version's storage location
15
+ # @return [SdrObjectVersion] Initialize a new SdrObjectVersion object
16
+ def initialize(object_version)
17
+ @moab_object_version = object_version
18
+ end
19
+
20
+ # @return [String] The digital object identifier (druid)
21
+ def sdr_object_id
22
+ @sdr_object_id ||= moab_object_version.storage_object.digital_object_id
23
+ end
24
+
25
+ # @return [Integer] The digital object version number
26
+ def sdr_version_id
27
+ @sdr_version_id ||= moab_object_version.version_id
28
+ end
29
+
30
+ # @return [Moab::FileInventory] The moab version manifest for the version
31
+ def version_inventory
32
+ @version_inventory ||= moab_object_version.file_inventory('version')
33
+ end
34
+
35
+ # @return [Moab::FileInventory] The moab version manifest for the version
36
+ def version_additions
37
+ @version_additions ||= moab_object_version.file_inventory('additions')
38
+ end
39
+
40
+ # @return [String] The unique identifier for the digital object replica
41
+ def replica_id
42
+ @replica_id ||= "#{sdr_object_id.split(':').last}-#{moab_object_version.version_name}"
43
+ end
44
+
45
+ # @return [Replica] The Replica of the object version that is archived to tape, etc
46
+ def replica
47
+ @replica ||= Replica.new(replica_id, 'sdr')
48
+ end
49
+
50
+ # @return [BagitBag] Copy the object version into a BagIt Bag in tarfile format
51
+ def moab_to_replica_bag
52
+ bag_dir = replica.replica_pathname
53
+ bag = BagitBag.create_bag(bag_dir)
54
+ bag.bag_checksum_types = [:sha256]
55
+ bag.add_payload_tarfile("#{replica_id}.tar",moab_object_version.version_pathname, moab_object_version.storage_object.object_pathname.parent)
56
+ bag.write_bag_info_txt
57
+ bag.write_manifest_checksums('tagmanifest', bag.generate_tagfile_checksums)
58
+ bag
59
+ end
60
+
61
+ end
62
+
63
+ end
@@ -0,0 +1,160 @@
1
+ require File.join(File.dirname(__FILE__),'../libdir')
2
+ require 'sdr_replication'
3
+
4
+ module Replication
5
+
6
+ # A tar archive file containing a set of digital object files
7
+ #
8
+ # @note Copyright (c) 2014 by The Board of Trustees of the Leland Stanford Junior University.
9
+ # All rights reserved. See {file:LICENSE.rdoc} for details.
10
+ class Tarfile
11
+
12
+ # @return [String] create archive of the specified format
13
+ # * gnu = GNU tar 1.13.x format
14
+ # * posix = POSIX 1003.1-2001 (pax) format
15
+ attr_accessor :format
16
+
17
+ # @return [Boolean] Follow symlinks and archive the files they point to
18
+ attr_accessor :dereference
19
+
20
+ # @return [Boolean] Verify that files were copied faithfully
21
+ attr_accessor :verify
22
+
23
+ # @return [Boolean] Create/list/extract multi-volume archive (not yet implemented)
24
+ attr_accessor :multi_volume
25
+
26
+ # @param [Hash<Symbol,Object>] options Key,Value pairs specifying initial values of attributes
27
+ # @return [Tarfile] Initialize a new Tarfile object
28
+ def initialize(options=nil)
29
+ options={} if options.nil?
30
+ # set defaults
31
+ @format=:posix
32
+ @dereference = true
33
+ @verify = false
34
+ @multi_volume = false
35
+ # override defaults
36
+ options.each do |key,value|
37
+ #instance_variable_set("@#{key}", value)
38
+ send "#{key}=", value
39
+ end
40
+ end
41
+
42
+ # @return [Pathname] The full path of the ancestor dir in which the tar file resides
43
+ def tarfile_basepath
44
+ raise "Tarfile basepath is nil" unless @tarfile_basepath
45
+ @tarfile_basepath
46
+ end
47
+
48
+ # @param [Pathname,String] basepath The full path of the ancestor dir in which the tar file resides
49
+ # @return [Void] Set the full path of the ancestor dir in which the tar file resides
50
+ def tarfile_basepath=(basepath)
51
+ raise "No pathname specified" unless basepath
52
+ @tarfile_basepath = Pathname(basepath).expand_path
53
+ end
54
+
55
+ # @return [Pathname] the full path of the tar archive file to be created or extracted from
56
+ def tarfile_fullpath
57
+ @tarfile_fullpath
58
+ end
59
+
60
+ # @param [Pathname,String] fullpath The full path of tar file
61
+ # @return [Void] Sets the full path of tar file
62
+ def tarfile_fullpath=(fullpath)
63
+ @tarfile_fullpath = Pathname(fullpath).expand_path
64
+ end
65
+
66
+ # @return [String] The id (path relative to basepath) of the tar file
67
+ def tarfile_relative_path
68
+ @tarfile_fullpath.relative_path_from(@tarfile_basepath).to_s
69
+ end
70
+
71
+ # @return [Pathname] The full path of the source file or directory being archived
72
+ def source_fullpath
73
+ raise "Source pathname is nil" unless @source_pathname
74
+ @source_pathname
75
+ end
76
+
77
+ # @param [Pathname,String] source The full path of the source file or directory being archived
78
+ # @return [Void] Set the full path of the source file or directory being archived
79
+ def source_fullpath=(source)
80
+ raise "No pathname specified" unless source
81
+ @source_pathname = Pathname(source).expand_path
82
+ end
83
+
84
+ # @return [Pathname] The directory that is the basis of relative paths
85
+ def source_basepath
86
+ @source_basepath
87
+ end
88
+
89
+ # @param [Pathname,String] base The directory that is the basis of relative paths
90
+ # @return [Void] Set the base path of the source file or directory being archived
91
+ def source_basepath=(base)
92
+ raise "No pathname specified" unless base
93
+ @source_basepath = Pathname(base).expand_path
94
+ end
95
+
96
+ # @return [Pathname] The relative path from the source base directory to the source directory
97
+ def source_relative_path
98
+ source_fullpath.relative_path_from(source_basepath)
99
+ end
100
+
101
+ # @return [String] The shell command string to be used to create the tarfile
102
+ def create_cmd
103
+ command = "tar --create --file=#{tarfile_fullpath} --format=#{@format} "
104
+ command << "--dereference " if @dereference
105
+ command << "--verify " if @verify
106
+ command << "--directory='#{source_basepath}' " if source_basepath
107
+ command << source_relative_path.to_s
108
+ command
109
+ end
110
+
111
+ # @return [Tarfile] Shell out to the operating system and create the tar archive file
112
+ def create_tarfile
113
+ command = create_cmd
114
+ OperatingSystem.execute(command)
115
+ self
116
+ end
117
+
118
+ # @return [String] The shell command that will list the tarfile's contents
119
+ def list_cmd
120
+ command = "tar --list --file=#{tarfile_fullpath} "
121
+ command
122
+ end
123
+
124
+ # @return [String] The list of the tarfile's contents
125
+ def list_tarfile
126
+ command = list_cmd
127
+ list = OperatingSystem.execute(command)
128
+ list
129
+ end
130
+
131
+ # @return [Pathname] The location of the directory into which the tarfile should be extracted
132
+ def target_pathname
133
+ raise "Target pathname is nil" unless @target_pathname
134
+ @target_pathname
135
+ end
136
+
137
+ # @param [Pathname,String] source The location of the directory into which the tarfile should be extracted
138
+ # @return [Void] Set the location of the directory into which the tarfile should be extracted
139
+ def target_pathname=(target)
140
+ raise "No target pathname specified" unless target
141
+ @target_pathname = Pathname(target).expand_path
142
+ end
143
+
144
+ # @return [String] The shell command that will extract the tarfile's contents # @return [Void]
145
+ def extract_cmd
146
+ command = "tar --extract --file=#{tarfile_fullpath} "
147
+ command << "--directory='#{target_pathname}' " if target_pathname
148
+ command
149
+ end
150
+
151
+ # @return [String] Shell out to the operating system and extract the tar archive file
152
+ def extract_tarfile
153
+ command = extract_cmd
154
+ stdout = OperatingSystem.execute(command)
155
+ stdout
156
+ end
157
+
158
+ end
159
+
160
+ end
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ Bundler.setup
4
+ require 'digest'
5
+ require 'find'
6
+ require 'json/pure'
7
+ require 'moab_stanford'
8
+ require 'pathname'
9
+ require 'rest-client'
10
+ require 'systemu'
11
+
12
+
13
+ # The classes used for SDR Replication workflows
14
+ module Replication
15
+ end
16
+
17
+ require 'replication/archive_catalog'
18
+ require 'replication/bagit_bag'
19
+ require 'replication/file_fixity'
20
+ require 'replication/fixity'
21
+ require 'replication/operating_system'
22
+ require 'replication/replica'
23
+ require 'replication/sdr_object_version'
24
+ require 'replication/tarfile'
25
+ include Replication
26
+
metadata ADDED
@@ -0,0 +1,198 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sdr-replication
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Richard Anderson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json_pure
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: moab-versioning
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: systemu
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rest-client
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: awesome_print
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: equivalent-xml
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: fakeweb
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 2.14.1
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 2.14.1
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.7.1
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.7.1
139
+ - !ruby/object:Gem::Dependency
140
+ name: yard
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ description: Contains classes to archive and retrieve digital object version content
154
+ and metadata
155
+ email:
156
+ - rnanders@stanford.edu
157
+ executables: []
158
+ extensions: []
159
+ extra_rdoc_files: []
160
+ files:
161
+ - lib/libdir.rb
162
+ - lib/replication/archive_catalog.rb
163
+ - lib/replication/bagit_bag.rb
164
+ - lib/replication/command_consumer.rb
165
+ - lib/replication/command_producer.rb
166
+ - lib/replication/dpn_check_rep.rb
167
+ - lib/replication/file_fixity.rb
168
+ - lib/replication/fixity.rb
169
+ - lib/replication/operating_system.rb
170
+ - lib/replication/replica.rb
171
+ - lib/replication/sdr_object_version.rb
172
+ - lib/replication/tarfile.rb
173
+ - lib/sdr_replication.rb
174
+ homepage:
175
+ licenses: []
176
+ metadata: {}
177
+ post_install_message:
178
+ rdoc_options: []
179
+ require_paths:
180
+ - lib
181
+ required_ruby_version: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ required_rubygems_version: !ruby/object:Gem::Requirement
187
+ requirements:
188
+ - - ">="
189
+ - !ruby/object:Gem::Version
190
+ version: 2.2.1
191
+ requirements: []
192
+ rubyforge_project:
193
+ rubygems_version: 2.2.1
194
+ signing_key:
195
+ specification_version: 4
196
+ summary: Core methods for support of SDR Preservation Core replication
197
+ test_files: []
198
+ has_rdoc: