Skip to content

Instantly share code, notes, and snippets.

@hellbunnie
Last active March 22, 2017 17:58
Show Gist options
  • Save hellbunnie/55d6dce0e026ce5f842ac81b8a9eb277 to your computer and use it in GitHub Desktop.
Save hellbunnie/55d6dce0e026ce5f842ac81b8a9eb277 to your computer and use it in GitHub Desktop.
Example using MOAB
# require the moab_versioning gem
require 'moab'
# Load an object to work with (in this case a Fedora object)
object = ActiveFedora::Base.find(your-object-id, {:cast => true})
# Set our version
version = 1
# Set up our MOAB directories
local_storage_dir = "/path/to/your/storage/directory"
version_string = 'v%04d' % version.to_s
version_path = File.join(local_storage_dir, object.id, version_string)
data_path = File.join(version_path, "data")
metadata_path = File.join(data_path, "metadata")
content_path = File.join(data_path, "content")
manifest_path = File.join(version_path, "manifests")
make_dir version_path
make_dir data_path
make_dir metadata_path
make_dir content_path
make_dir manifest_path
# Save the resource
File.write(File.join(metadata_path, 'resource.rdf'), object.resource.dump(:ttl) )
# Save the permissions
File.write(File.join(metadata_path, 'permissions.rdf'), object.permissions.inspect )
# Save any attached files
name = "descMetadata"
datastream = object.attached_files['name'])
data = datastream.content
File.write(File.join(metadata_path, "#{name.to_s}.xml"), data) unless data.nil?
# Now create the manifests
signature_catalog = Moab::SignatureCatalog.new(:digital_object_id => object.id, :version_id => 1)
version_inventory = Moab::FileInventory.new(:type => 'version', :version_id => version, :digital_object_id => object.id)
file_group = Moab::FileGroup.new(:group_id=>'metadata').group_from_directory(Pathname.new(metadata_path))
version_inventory.groups << file_group
file_group = Moab::FileGroup.new(:group_id=>'content').group_from_directory(Pathname.new(content_path))
version_inventory.groups << file_group
version_additions = signature_catalog.version_additions(version_inventory)
signature_catalog.update(version_inventory, Pathname.new( data_path ))
file_inventory_difference = Moab::FileInventoryDifference.new
file_inventory_difference.compare(Moab::FileInventory.new(), version_inventory)
signature_catalog.write_xml_file(Pathname.new(manifest_path))
version_inventory.write_xml_file(Pathname.new(manifest_path))
version_additions.write_xml_file(Pathname.new(manifest_path))
file_inventory_difference.write_xml_file(Pathname.new(manifest_path))
manifest_inventory = Moab::FileInventory.new(:type => 'manifests', :digital_object_id=>object.id, :version_id => version)
manifest_inventory.groups << Moab::FileGroup.new(:group_id=>'manifests').group_from_directory(manifest_path(object.id, recursive=false)
manifest_inventory.write_xml_file(Pathname.new(manifest_path))
# Updating manifests on subsequent versions
# Update the version number
new_version = version + 1
# Update the paths and create new MOAB directories
new_version_string = 'v%04d' % new_version.to_s
new_version_path = File.join(local_storage_dir, object.id, new_version_string)
new_data_path = File.join(new_version_path, "data")
new_metadata_path = File.join(new_data_path, "metadata")
new_content_path = File.join(new_data_path, "content")
new_manifest_path = File.join(new_version_path, "manifests")
make_dir new_version_path
make_dir new_data_path
make_dir new_metadata_path
make_dir new_content_path
make_dir new_manifest_path
# As for version 1 we should now save out all of our added or modified metadata and asset files
# Load the version inventory for the last version
last_version_inventory = Moab::FileInventory.new(:type => 'version', :version_id => last_version.to_i, :digital_object_id => object.id)
last_version_inventory.parse(Pathname.new(File.join(manifest_path, 'versionInventory.xml')).read)
# Create a new version inventory for the new version
# But beware! In order for it to know about files that were deleted, added, modified you need to first populate
# it with the information from the previous version of versionInventory.xml and then update it using the functions provided
version_inventory = Moab::FileInventory.new(:type => 'version', :version_id => last_version.to_i, :digital_object_id => object.id)
version_inventory.parse(Pathname.new(File.join(manifest_path,'versionInventory.xml')).read)
version_inventory.version_id = version_inventory.version_id + 1
# For each added file we must create a signature and a File Instances and add this to the version inventory manifest
file = "name-of-your-new-file"
path = new_content|metadata_path
file_signature = Moab::FileSignature.new()
file_signature.signature_from_file(Pathname.new(File.join(path, file)))
file_instance = Moab::FileInstance.new()
file_instance.instance_from_file(Pathname.new(File.join(path, file)), Pathname.new(path))
version_inventory.groups.find {|g| g.group_id == type.to_s }.add_file_instance(file_signature, file_instance)
# For each modified file we have to do the same, but remove the old version of the file first
file = "name-of-your-modified-file"
path = new_content|metadata_path
version_inventory.groups.find {|g| g.group_id == type.to_s }.remove_file_having_path(file)
file_signature = Moab::FileSignature.new()
file_signature.signature_from_file(Pathname.new(File.join(path, file)))
file_instance = Moab::FileInstance.new()
file_instance.instance_from_file(Pathname.new(File.join(path, file)), Pathname.new(path))
version_inventory.groups.find {|g| g.group_id == type.to_s }.add_file_instance(file_signature, file_instance)
# For each deleted file we just have to delete it
file = "name-of-the-file-to-delete"
version_inventory.groups.find {|g| g.group_id == type.to_s }.remove_file_having_path(file)
# Update the rest of the manifest files
signature_catalog = Moab::SignatureCatalog.new(:digital_object_id => object.id)
signature_catalog.parse(Pathname.new(File.join(manifest_path,'signatureCatalog.xml')).read) # parse the old catalog
signature_catalog.update(version_inventory, Pathname.new( new_data_path ))
version_additions = signature_catalog.version_additions(version_inventory)
file_inventory_difference = Moab::FileInventoryDifference.new
file_inventory_difference.compare(last_version_inventory, version_inventory)
signature_catalog.write_xml_file(Pathname.new(new_manifest_path))
version_inventory.write_xml_file(Pathname.new(new_manifest_path))
version_additions.write_xml_file(Pathname.new(new_manifest_path))
file_inventory_difference.write_xml_file(Pathname.new(new_manifest_path))
# And finally create the manifest inventory
manifest_inventory = Moab::FileInventory.new(:type => 'manifests', :digital_object_id=>object.id, :version_id => new_version)
manifest_inventory.groups << Moab::FileGroup.new(:group_id=>'manifests').group_from_directory(new_manifest_path, recursive=false)
manifest_inventory.write_xml_file(Pathname.new(new_manifest_path))
# We may also want to verify our manifests
aip_dir = File.join(local_storage_dir, object.id, version_string, "data") # Same as the data path above
storage_object = Moab::StorageObject.new(object.id, aip_dir)
storage_object_version = Moab::StorageObjectVersion.new(storage_object, version_id=version.to_i)
result = storage_object_version.verify_version_storage
result.verified.should be true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment