Class: Dor::DigitalStacksService

Inherits:
Object
  • Object
show all
Defined in:
lib/dor/services/digital_stacks_service.rb

Class Method Summary collapse

Class Method Details

.copy_file(workspace_pathname, stacks_pathname, moab_signature) ⇒ Boolean

Copy a file to stacks, but only if it does not yet exist with the expected signature

Parameters:

  • workspace_pathname (Pathname)

    The location of the file in the DOR workspace

  • stacks_pathname (Pathname)

    The location of the file in the stacks

  • moab_signature (Moab::FileSignature)

    The fixity values of the file

Returns:

  • (Boolean)

    true if file copied, false otherwise



103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/dor/services/digital_stacks_service.rb', line 103

def self.copy_file(workspace_pathname, stacks_pathname, moab_signature)
  if stacks_pathname.exist?
    file_signature = Moab::FileSignature.new.signature_from_file(stacks_pathname)
    stacks_pathname.delete if file_signature != moab_signature
  end
  unless stacks_pathname.exist?
    stacks_pathname.parent.mkpath
    FileUtils.cp workspace_pathname.to_s, stacks_pathname.to_s
    # Change permissions
    FileUtils.chmod 'u=rw,go=r', stacks_pathname.to_s
    return true
  end
  false
end

.delete_file(file_pathname, moab_signature) ⇒ Boolean

Delete a file, but only if it exists and matches the expected signature

Parameters:

  • file_pathname (Pathname)

    The location of the file to be deleted

  • moab_signature (Moab::FileSignature)

    The fixity values of the file

Returns:

  • (Boolean)

    true if file deleted, false otherwise



26
27
28
29
30
31
32
33
34
35
# File 'lib/dor/services/digital_stacks_service.rb', line 26

def self.delete_file(file_pathname, moab_signature)
  if file_pathname.exist? && (file_pathname.size == moab_signature.size)
    file_signature = Moab::FileSignature.new.signature_from_file(file_pathname)
    if file_signature == moab_signature
      file_pathname.delete
      return true
    end
  end
  false
end

.prune_stacks_dir(id) ⇒ Object

Assumes the digital stacks storage root is mounted to the local file system TODO: since this is delegating to the Druid, this method may not be necessary



120
121
122
123
# File 'lib/dor/services/digital_stacks_service.rb', line 120

def self.prune_stacks_dir(id)
  stacks_druid_tree = DruidTools::StacksDruid.new(id, Config.stacks.local_stacks_root)
  stacks_druid_tree.prune!
end

.remove_from_stacks(stacks_object_pathname, content_diff) ⇒ Object

Delete files from stacks that have change type ‘deleted’, ‘copydeleted’, or ‘modified’

Parameters:

  • stacks_object_pathname (Pathname)

    the stacks location of the digital object

  • content_diff (Moab::FileGroupDifference)

    the content file version differences report



11
12
13
14
15
16
17
18
19
20
# File 'lib/dor/services/digital_stacks_service.rb', line 11

def self.remove_from_stacks(stacks_object_pathname, content_diff)
  %i[deleted copydeleted modified].each do |change_type|
    subset = content_diff.subset(change_type) # {Moab::FileGroupDifferenceSubset}
    subset.files.each do |moab_file| # {Moab::FileInstanceDifference}
      moab_signature = moab_file.signatures.first # {Moab::FileSignature}
      file_pathname = stacks_object_pathname.join(moab_file.basis_path)
      delete_file(file_pathname, moab_signature)
    end
  end
end

.rename_file(old_pathname, new_pathname, moab_signature) ⇒ Boolean

Rename a file, but only if it exists and has the expected signature

Parameters:

  • old_pathname (Pathname)

    The original location/name of the file being renamed

  • new_pathname (Pathname)

    The new location/name of the file

  • moab_signature (Moab::FileSignature)

    The fixity values of the file

Returns:

  • (Boolean)

    true if file renamed, false otherwise



66
67
68
69
70
71
72
73
74
75
76
# File 'lib/dor/services/digital_stacks_service.rb', line 66

def self.rename_file(old_pathname, new_pathname, moab_signature)
  if old_pathname.exist? && (old_pathname.size == moab_signature.size)
    file_signature = Moab::FileSignature.new.signature_from_file(old_pathname)
    if file_signature == moab_signature
      new_pathname.parent.mkpath
      old_pathname.rename(new_pathname)
      return true
    end
  end
  false
end

.rename_in_stacks(stacks_object_pathname, content_diff) ⇒ Object

Rename files from stacks that have change type ‘renamed’ using an intermediate temp filename. The 2-step renaming allows chained or cyclic renames to occur without file collisions.

Parameters:

  • stacks_object_pathname (Pathname)

    the stacks location of the digital object

  • content_diff (Moab::FileGroupDifference)

    the content file version differences report



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/dor/services/digital_stacks_service.rb', line 41

def self.rename_in_stacks(stacks_object_pathname, content_diff)
  subset = content_diff.subset(:renamed) # {Moab::FileGroupDifferenceSubset

  # 1st Pass - rename files from original name to checksum-based name
  subset.files.each do |moab_file| # {Moab::FileInstanceDifference}
    moab_signature = moab_file.signatures.first # {Moab::FileSignature}
    original_pathname = stacks_object_pathname.join(moab_file.basis_path)
    temp_pathname = stacks_object_pathname.join(moab_signature.checksums.values.last)
    rename_file(original_pathname, temp_pathname, moab_signature)
  end

  # 2nd Pass - rename files from checksum-based name to new name
  subset.files.each do |moab_file| # {Moab::FileInstanceDifference}
    moab_signature = moab_file.signatures.first # {Moab::FileSignature}
    temp_pathname = stacks_object_pathname.join(moab_signature.checksums.values.last)
    new_pathname = stacks_object_pathname.join(moab_file.other_path)
    rename_file(temp_pathname, new_pathname, moab_signature)
  end
end

.shelve_to_stacks(workspace_content_pathname, stacks_object_pathname, content_diff) ⇒ Object

Add files to stacks that have change type ‘added’, ‘copyadded’ or ‘modified’.

Parameters:

  • workspace_content_pathname (Pathname)

    The dor workspace location of the digital object’s content fies

  • stacks_object_pathname (Pathname)

    the stacks location of the digital object’s shelved files

  • content_diff (Moab::FileGroupDifference)

    the content file version differences report



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/dor/services/digital_stacks_service.rb', line 82

def self.shelve_to_stacks(workspace_content_pathname, stacks_object_pathname, content_diff)
  return false if workspace_content_pathname.nil?

  %i[added copyadded modified].each do |change_type|
    subset = content_diff.subset(change_type) # {Moab::FileGroupDifferenceSubset
    subset.files.each do |moab_file| # {Moab::FileInstanceDifference}
      moab_signature = moab_file.signatures.last # {Moab::FileSignature}
      filename = change_type == :modified ? moab_file.basis_path : moab_file.other_path
      workspace_pathname = workspace_content_pathname.join(filename)
      stacks_pathname = stacks_object_pathname.join(filename)
      copy_file(workspace_pathname, stacks_pathname, moab_signature)
    end
  end
  true
end